MythTV  0.26-pre
main.cpp
Go to the documentation of this file.
00001 
00002 #include <iostream>
00003 #include <cstdlib>
00004 using namespace std;
00005 #include <unistd.h>
00006 
00007 #include <QCoreApplication>
00008 #include <QFile>
00009 
00010 #include "exitcodes.h"
00011 #include "mythcontext.h"
00012 #include "mythdb.h"
00013 #include "mythsystem.h"
00014 #include "mythversion.h"
00015 #include "jobqueue.h"
00016 #include "tv.h"
00017 #include "remoteutil.h"
00018 #include "tvremoteutil.h"
00019 #include "compat.h"
00020 #include "mythlogging.h"
00021 #include "commandlineparser.h"
00022 #include "programinfo.h"
00023 
00024 static void setGlobalSetting(const QString &key, const QString &value)
00025 {
00026     MSqlQuery query(MSqlQuery::InitCon());
00027     if (query.isConnected())
00028     {
00029         query.prepare("DELETE FROM settings WHERE value = :KEY;");
00030         query.bindValue(":KEY", key);
00031 
00032         if (!query.exec() || !query.isActive())
00033             MythDB::DBError("Clear setting", query);
00034 
00035         query.prepare("INSERT INTO settings ( value, data ) "
00036                 "VALUES ( :VALUE, :DATA );");
00037         query.bindValue(":VALUE", key);
00038         query.bindValue(":DATA", value);
00039 
00040         if (!query.exec() || !query.isActive())
00041             MythDB::DBError("Save new global setting", query);
00042     }
00043     else
00044     {
00045         LOG(VB_GENERAL, LOG_ERR,
00046             QString("Database not open while trying to save setting: %1")
00047                 .arg(key));
00048     }
00049 }
00050 
00051 static QString getGlobalSetting(const QString &key, const QString &defaultval)
00052 {
00053     QString value = defaultval;
00054 
00055     MSqlQuery query(MSqlQuery::InitCon());
00056     if (query.isConnected())
00057     {
00058         query.prepare("SELECT data FROM settings WHERE value = :KEY AND "
00059                       "hostname IS NULL;");
00060         query.bindValue(":KEY", key);
00061         if (query.exec() && query.next())
00062             value = query.value(0).toString();
00063     }
00064     else
00065     {
00066         LOG(VB_GENERAL, LOG_ERR,
00067             QString("Database not open while trying to load setting: %1")
00068                 .arg(key));
00069     }
00070 
00071     return value;
00072 }
00073 
00074 static int lockShutdown()
00075 {
00076     LOG(VB_GENERAL, LOG_INFO, "Mythshutdown: --lock");
00077 
00078     MSqlQuery query(MSqlQuery::InitCon());
00079 
00080     // lock setting table
00081     int tries = 0;
00082     while (!query.exec("LOCK TABLE settings WRITE;") && tries < 5)
00083     {
00084         LOG(VB_GENERAL, LOG_INFO, "Waiting for lock on setting table");
00085         sleep(1);
00086         tries++;
00087     }
00088 
00089     if (tries >= 5)
00090     {
00091         LOG(VB_GENERAL, LOG_ERR,
00092             "Waited too long to obtain lock on setting table");
00093         return 1;
00094     }
00095 
00096     // does the setting already exist?
00097     query.prepare("SELECT * FROM settings "
00098                   "WHERE value = 'MythShutdownLock' AND hostname IS NULL;");
00099     if (!query.exec())
00100         MythDB::DBError("lockShutdown -- select", query);
00101 
00102     if (query.size() < 1)
00103     {
00104         // add the lock setting
00105         query.prepare("INSERT INTO settings (value, data) "
00106                       "VALUES ('MythShutdownLock', '1');");
00107         if (!query.exec())
00108             MythDB::DBError("lockShutdown -- insert", query);
00109     }
00110     else
00111     {
00112         // update the lock setting
00113         query.prepare("UPDATE settings SET data = data + 1 "
00114                       "WHERE value = 'MythShutdownLock' "
00115                       "AND hostname IS NULL;");
00116         if (!query.exec())
00117             MythDB::DBError("lockShutdown -- update", query);
00118     }
00119 
00120     // unlock settings table
00121     if (!query.exec("UNLOCK TABLES;"))
00122         MythDB::DBError("lockShutdown -- unlock", query);
00123 
00124     return 0;
00125 }
00126 
00127 static int unlockShutdown()
00128 {
00129     LOG(VB_GENERAL, LOG_INFO, "Mythshutdown: --unlock");
00130 
00131     MSqlQuery query(MSqlQuery::InitCon());
00132 
00133     // lock setting table
00134     int tries = 0;
00135     while (!query.exec("LOCK TABLE settings WRITE;") && tries < 5)
00136     {
00137         LOG(VB_GENERAL, LOG_INFO, "Waiting for lock on setting table");
00138         sleep(1);
00139         tries++;
00140     }
00141 
00142     if (tries >= 5)
00143     {
00144         LOG(VB_GENERAL, LOG_ERR,
00145             "Waited too long to obtain lock on setting table");
00146         return 1;
00147     }
00148 
00149     // does the setting exist?
00150     query.prepare("SELECT * FROM settings "
00151                   "WHERE value = 'MythShutdownLock' AND hostname IS NULL;");
00152     if (!query.exec())
00153         MythDB::DBError("unlockShutdown -- select", query);
00154 
00155     if (query.size() < 1)
00156     {
00157         // add the lock setting
00158         query.prepare("INSERT INTO settings (value, data) "
00159                       "VALUES ('MythShutdownLock', '0');");
00160         if (!query.exec())
00161             MythDB::DBError("unlockShutdown -- insert", query);
00162     }
00163     else
00164     {
00165         // update lock setting
00166         query.prepare("UPDATE settings SET data = GREATEST(0,  data - 1) "
00167                       "WHERE value = 'MythShutdownLock' "
00168                       "AND hostname IS NULL;");
00169         if (!query.exec())
00170             MythDB::DBError("unlockShutdown -- update", query);
00171     }
00172 
00173     // unlock table
00174     if (!query.exec("UNLOCK TABLES;"))
00175         MythDB::DBError("unlockShutdown -- unlock", query);
00176 
00177     // tell the master BE to reset its idle time
00178     gCoreContext->SendMessage("RESET_IDLETIME");
00179 
00180     return 0;
00181 }
00182 
00196 static bool isRunning(const char *program)
00197 {
00198     QString command = QString("ps ch -C %1 -o pid > /dev/null").arg(program);
00199     return (myth_system(command) == GENERIC_EXIT_OK);
00200 }
00201 
00202 static QDateTime getDailyWakeupTime(QString sPeriod)
00203 {
00204     QString sTime = getGlobalSetting(sPeriod, "00:00");
00205     QTime tTime = QTime::fromString(sTime, "hh:mm");
00206     QDateTime dtDateTime = QDateTime(QDate::currentDate(), tTime);
00207 
00208     return dtDateTime;
00209 }
00210 
00211 static bool isRecording()
00212 {
00213     if (!gCoreContext->IsConnectedToMaster())
00214     {
00215         LOG(VB_GENERAL, LOG_NOTICE,
00216                 "isRecording: Attempting to connect to master server...");
00217         if (!gCoreContext->ConnectToMasterServer(false))
00218         {
00219             LOG(VB_GENERAL, LOG_ERR,
00220                     "isRecording: Could not connect to master server!");
00221             return false;
00222         }
00223     }
00224 
00225     return RemoteGetRecordingStatus(NULL, false);
00226 }
00227 
00228 static int getStatus(bool bWantRecStatus)
00229 {
00230     LOG(VB_GENERAL, LOG_INFO, "Mythshutdown: --status");
00231 
00232     int res = 0;
00233 
00234     if (isRunning("mythtranscode"))
00235     {
00236         LOG(VB_GENERAL, LOG_NOTICE, "Transcoding in progress...");
00237         res |= 1;
00238     }
00239 
00240     if (isRunning("mythcommflag"))
00241     {
00242         LOG(VB_GENERAL, LOG_NOTICE, "Commercial Detection in progress...");
00243         res |= 2;
00244     }
00245 
00246     if (isRunning("mythfilldatabase"))
00247     {
00248         LOG(VB_GENERAL, LOG_NOTICE, "Grabbing EPG data in progress...");
00249         res |= 4;
00250     }
00251 
00252     if (bWantRecStatus && isRecording())
00253     {
00254         LOG(VB_GENERAL, LOG_NOTICE, "Recording in progress...");
00255         res |= 8;
00256     }
00257 
00258     if (getGlobalSetting("MythShutdownLock", "0") != "0")
00259     {
00260         LOG(VB_GENERAL, LOG_NOTICE, "Shutdown is locked");
00261         res |= 16;
00262     }
00263 
00264     if (JobQueue::HasRunningOrPendingJobs(15))
00265     {
00266         LOG(VB_GENERAL, LOG_NOTICE, "Has queued or pending jobs");
00267         res |= 32;
00268     }
00269 
00270     QDateTime dtPeriod1Start = getDailyWakeupTime("DailyWakeupStartPeriod1");
00271     QDateTime dtPeriod1End = getDailyWakeupTime("DailyWakeupEndPeriod1");
00272     QDateTime dtPeriod2Start = getDailyWakeupTime("DailyWakeupStartPeriod2");
00273     QDateTime dtPeriod2End = getDailyWakeupTime("DailyWakeupEndPeriod2");
00274     QDateTime dtCurrent = QDateTime::currentDateTime();
00275 
00276     // Check for time periods that cross midnight
00277     if (dtPeriod1End < dtPeriod1Start)
00278     {
00279         if (dtCurrent > dtPeriod1End)
00280             dtPeriod1End = dtPeriod1End.addDays(1);
00281         else
00282             dtPeriod1Start = dtPeriod1Start.addDays(-1);
00283     }
00284 
00285     if (dtPeriod2End < dtPeriod2Start)
00286     {
00287         if (dtCurrent > dtPeriod2End)
00288             dtPeriod2End = dtPeriod2End.addDays(1);
00289         else
00290             dtPeriod2Start = dtPeriod2Start.addDays(-1);
00291     }
00292 
00293     // Check for one of the daily wakeup periods
00294     if (dtPeriod1Start != dtPeriod1End)
00295     {
00296         if (dtCurrent >= dtPeriod1Start && dtCurrent <= dtPeriod1End)
00297         {
00298             LOG(VB_GENERAL, LOG_NOTICE, "In a daily wakeup period (1).");
00299             res |= 64;
00300         }
00301     }
00302 
00303     if (dtPeriod2Start != dtPeriod2End)
00304     {
00305         if (dtCurrent >= dtPeriod2Start && dtCurrent <= dtPeriod2End)
00306         {
00307             LOG(VB_GENERAL, LOG_NOTICE, "In a daily wakeup period (2).");
00308             res |= 64;
00309         }
00310     }
00311 
00312     // Are we about to start a daily wakeup period
00313     // allow for a 15 minute window
00314     if (dtPeriod1Start != dtPeriod1End)
00315     {
00316         int delta = dtCurrent.secsTo(dtPeriod1Start);
00317         if (delta >= 0 && delta <= 15 * 60)
00318         {
00319             LOG(VB_GENERAL, LOG_NOTICE,
00320                 "About to start daily wakeup period (1)");
00321             res |= 128;
00322         }
00323     }
00324 
00325     if (dtPeriod2Start != dtPeriod2End)
00326     {
00327         int delta = dtCurrent.secsTo(dtPeriod2Start);
00328         if (delta >= 0 && delta <= 15 * 60)
00329         {
00330             LOG(VB_GENERAL, LOG_NOTICE,
00331                 "About to start daily wakeup period (2)");
00332             res |= 128;
00333         }
00334     }
00335 
00336     if (isRunning("mythtv-setup"))
00337     {
00338         LOG(VB_GENERAL, LOG_NOTICE, "Setup is running...");
00339         res = 255;
00340     }
00341 
00342     LOG(VB_GENERAL, LOG_INFO,
00343         QString("Mythshutdown: --status returned: %1").arg(res));
00344 
00345     return res;
00346 }
00347 
00348 static int checkOKShutdown(bool bWantRecStatus)
00349 {
00350     // mythbackend wants 0=ok to shutdown,
00351     // 1=reset idle count, 2=wait for frontend
00352 
00353     LOG(VB_GENERAL, LOG_INFO, "Mythshutdown: --check");
00354 
00355     int res = getStatus(bWantRecStatus);
00356 
00357     if (res > 0)
00358     {
00359         LOG(VB_GENERAL, LOG_NOTICE, "Not OK to shutdown");
00360         res = 1;
00361     }
00362     else
00363     {
00364         LOG(VB_GENERAL, LOG_NOTICE, "OK to shutdown");
00365         res = 0;
00366     }
00367 
00368     LOG(VB_GENERAL, LOG_INFO,
00369         QString("Mythshutdown: --check returned: %1").arg(res));
00370 
00371     return res;
00372 }
00373 
00374 static int setWakeupTime(QString sWakeupTime)
00375 {
00376     LOG(VB_GENERAL, LOG_INFO, "Mythshutdown: --setwakeup");
00377 
00378     LOG(VB_GENERAL, LOG_NOTICE,
00379         QString("Mythshutdown: wakeup time given is: %1").arg(sWakeupTime));
00380 
00381     // check time given is valid
00382     QDateTime dtWakeupTime;
00383     dtWakeupTime = QDateTime::fromString(sWakeupTime, Qt::ISODate);
00384 
00385     if (!dtWakeupTime.isValid())
00386     {
00387         LOG(VB_GENERAL, LOG_ERR,
00388             QString("Mythshutdown: --setwakeup invalid date "
00389                                       "format (%1)\n\t\t\t"
00390                                       "must be yyyy-MM-ddThh:mm:ss")
00391                                       .arg(sWakeupTime));
00392         return 1;
00393     }
00394 
00395     setGlobalSetting("MythShutdownNextScheduled",
00396                      dtWakeupTime.toString(Qt::ISODate));
00397 
00398     return 0;
00399 }
00400 
00401 static int setScheduledWakeupTime()
00402 {
00403     if (!gCoreContext->IsConnectedToMaster())
00404     {
00405         LOG(VB_GENERAL, LOG_NOTICE,
00406             "setScheduledWakeupTime: "
00407             "Attempting to connect to master server...");
00408         if (!gCoreContext->ConnectToMasterServer(false))
00409         {
00410             LOG(VB_GENERAL, LOG_NOTICE,
00411                 "setScheduledWakeupTime: "
00412                 "Could not connect to master server!");
00413             return 1;
00414         }
00415     }
00416 
00417     QDateTime nextRecordingStart;
00418     GetNextRecordingList(nextRecordingStart);
00419 
00420     // set the wakeup time for the next scheduled recording
00421     if (!nextRecordingStart.isNull())
00422     {
00423         int m_preRollSeconds = gCoreContext->GetNumSetting("RecordPreRoll");
00424         QDateTime restarttime = nextRecordingStart
00425             .addSecs((-1) * m_preRollSeconds);
00426 
00427         int add = gCoreContext->GetNumSetting("StartupSecsBeforeRecording", 240);
00428         if (add)
00429             restarttime = restarttime.addSecs((-1) * add);
00430 
00431         setWakeupTime(restarttime.toString(Qt::ISODate));
00432 
00433         return 0;
00434     }
00435     return 1;
00436 }
00437 
00438 static int shutdown()
00439 {
00440     LOG(VB_GENERAL, LOG_INFO, "Mythshutdown: --shutdown");
00441 
00442     // get next daily wakeup times if any are set
00443     QDateTime dtPeriod1Start = getDailyWakeupTime("DailyWakeupStartPeriod1");
00444     QDateTime dtPeriod1End = getDailyWakeupTime("DailyWakeupEndPeriod1");
00445     QDateTime dtPeriod2Start = getDailyWakeupTime("DailyWakeupStartPeriod2");
00446     QDateTime dtPeriod2End = getDailyWakeupTime("DailyWakeupEndPeriod2");
00447     QDateTime dtCurrent = QDateTime::currentDateTime();
00448     QDateTime dtNextDailyWakeup = QDateTime();
00449 
00450     // Make sure Period1 is before Period2
00451     if (dtPeriod2Start < dtPeriod1Start)
00452     {
00453         QDateTime temp = dtPeriod1Start;
00454         dtPeriod1Start = dtPeriod2Start;
00455         dtPeriod2Start = temp;
00456         temp = dtPeriod1End;
00457         dtPeriod1End = dtPeriod2End;
00458         dtPeriod2End = temp;
00459     }
00460 
00461     // Check for time periods that cross midnight
00462     if (dtPeriod1End < dtPeriod1Start)
00463     {
00464         if (dtCurrent > dtPeriod1End)
00465             dtPeriod1End = dtPeriod1End.addDays(1);
00466         else
00467             dtPeriod1Start = dtPeriod1Start.addDays(-1);
00468     }
00469 
00470     if (dtPeriod2End < dtPeriod2Start)
00471     {
00472         if (dtCurrent > dtPeriod2End)
00473             dtPeriod2End = dtPeriod2End.addDays(1);
00474         else
00475             dtPeriod2Start = dtPeriod2Start.addDays(-1);
00476     }
00477 
00478     // have we passed the first wakeup time today
00479     if (dtPeriod1Start != dtPeriod1End)
00480     {
00481         if (dtCurrent < dtPeriod1Start)
00482         {
00483             LOG(VB_GENERAL, LOG_NOTICE,
00484                 "daily wakeup today at " + dtPeriod1Start.toString("hh:mm:ss"));
00485             dtNextDailyWakeup = dtPeriod1Start;
00486         }
00487     }
00488 
00489     // have we passed the second wakeup time today
00490     if (!dtNextDailyWakeup.isValid() && dtPeriod2Start != dtPeriod2End)
00491     {
00492         if (dtCurrent < dtPeriod2Start)
00493         {
00494             LOG(VB_GENERAL, LOG_NOTICE,
00495                 "daily wakeup today at " + dtPeriod2Start.toString("hh:mm:ss"));
00496             dtNextDailyWakeup = dtPeriod2Start;
00497         }
00498     }
00499 
00500     // if we have at least one valid daily wakeup time
00501     // and dtNextDailyWakeup is still not valid
00502     // then next daily wakeup is tomorrow
00503     if (!dtNextDailyWakeup.isValid())
00504     {
00505         if (dtPeriod1Start != dtPeriod1End)
00506             dtNextDailyWakeup = dtPeriod1Start;
00507         else if (dtPeriod2Start != dtPeriod2End)
00508             dtNextDailyWakeup = dtPeriod2Start;
00509 
00510         if (dtNextDailyWakeup.isValid())
00511         {
00512             dtNextDailyWakeup = dtNextDailyWakeup.addDays(1);
00513 
00514             LOG(VB_GENERAL, LOG_NOTICE, "next daily wakeup is tomorrow at " +
00515                 dtNextDailyWakeup.toString("hh:mm:ss"));
00516         }
00517     }
00518 
00519     // if dtNextDailyWakeup is still not valid then no daily wakeups are set
00520     if (!dtNextDailyWakeup.isValid())
00521         LOG(VB_GENERAL, LOG_ERR, "no daily wakeup times are set");
00522 
00523     // get next scheduled wake up for a recording if any
00524     QDateTime dtNextRecordingStart = QDateTime();
00525     QString s = getGlobalSetting("MythShutdownNextScheduled", "");
00526     if (!s.isEmpty())
00527         dtNextRecordingStart = QDateTime::fromString(s, Qt::ISODate);
00528 
00529     if (!dtNextRecordingStart.isValid())
00530         LOG(VB_GENERAL, LOG_ERR, "no recording time is set");
00531     else 
00532         LOG(VB_GENERAL, LOG_NOTICE, "recording scheduled at: " +
00533                     dtNextRecordingStart.toString(Qt::ISODate));
00534 
00535     // check if scheduled recording time has already passed
00536     if (dtNextRecordingStart.isValid())
00537     {
00538         int delta = dtCurrent.secsTo(dtNextRecordingStart);
00539 
00540         if (delta < 0)
00541         {
00542             LOG(VB_GENERAL, LOG_NOTICE,
00543                 "Scheduled recording time has already passed. "
00544                 "Schedule deleted");
00545 
00546             dtNextRecordingStart = QDateTime();
00547             setGlobalSetting("MythShutdownNextScheduled", "");
00548         }
00549     }
00550 
00551     QDateTime dtWakeupTime = QDateTime();
00552 
00553     // simple case
00554     // no daily wakeup set
00555     // no scheduled program set
00556     // just shut down
00557     if (!dtNextRecordingStart.isValid() && !dtNextDailyWakeup.isValid())
00558     {
00559         dtWakeupTime = QDateTime();
00560         LOG(VB_GENERAL, LOG_ERR,
00561             "no wake up time set and no scheduled program");
00562     }
00563 
00564     // no daily wakeup set
00565     // scheduled program is set
00566     if (dtNextRecordingStart.isValid() && !dtNextDailyWakeup.isValid())
00567     {
00568         dtWakeupTime = dtNextRecordingStart;
00569         LOG(VB_GENERAL, LOG_NOTICE, "will wake up at next scheduled program");
00570     }
00571 
00572     // daily wakeup is set
00573     // no scheduled program is set
00574     if (!dtNextRecordingStart.isValid() && dtNextDailyWakeup.isValid())
00575     {
00576         dtWakeupTime = dtNextDailyWakeup;
00577         LOG(VB_GENERAL, LOG_NOTICE, "will wake up at next daily wakeup");
00578     }
00579 
00580     // daily wakeup is set
00581     // scheduled program is set
00582     // wake up at which ever is the earliest
00583     if (dtNextRecordingStart.isValid() && dtNextDailyWakeup.isValid())
00584     {
00585         if (dtNextDailyWakeup < dtNextRecordingStart)
00586         {
00587             LOG(VB_GENERAL, LOG_NOTICE,
00588                 "program is scheduled but will wake up at next daily wakeup");
00589             dtWakeupTime = dtNextDailyWakeup;
00590         }
00591         else
00592         {
00593             LOG(VB_GENERAL, LOG_NOTICE, "daily wakeup is set but will wake up "
00594                                         "at next scheduled program");
00595             dtWakeupTime = dtNextRecordingStart;
00596         }
00597     }
00598 
00599     // save the next wakuptime in the db
00600     setGlobalSetting("MythShutdownWakeupTime",
00601                      dtWakeupTime.toString(Qt::ISODate));
00602 
00603     // stop here to debug
00604     //return 0;
00605 
00606     int shutdownmode = 0; // default to poweroff no reboot
00607     QString nvramRestartCmd =
00608             gCoreContext->GetSetting("MythShutdownNvramRestartCmd", "");
00609 
00610     if (dtWakeupTime.isValid())
00611     {
00612         // dont't shutdown if we are within 15 mins of the next wakeup time
00613         if (dtCurrent.secsTo(dtWakeupTime) > 15 * 60)
00614         {
00615             QString nvramCommand =
00616                 gCoreContext->GetSetting("MythShutdownNvramCmd",
00617                      "/usr/bin/nvram-wakeup --settime $time");
00618 
00619             QString wakeup_timeformat = gCoreContext->GetSetting(
00620                 "MythShutdownWakeupTimeFmt", "time_t");
00621 
00622             if (wakeup_timeformat == "time_t")
00623             {
00624                 QString time_ts;
00625                 nvramCommand.replace(
00626                     "$time", time_ts.setNum(dtWakeupTime.toTime_t()));
00627             }
00628             else
00629                 nvramCommand.replace(
00630                     "$time", dtWakeupTime.toString(wakeup_timeformat));
00631 
00632             LOG(VB_GENERAL, LOG_NOTICE, "sending command to set time in bios" +
00633                 nvramCommand);
00634 
00635             shutdownmode = myth_system(nvramCommand);
00636 
00637             LOG(VB_GENERAL, LOG_NOTICE, (nvramCommand + " exited with code %2")
00638                     .arg(shutdownmode));
00639 
00640             if (shutdownmode == 2)
00641             {
00642                 LOG(VB_GENERAL, LOG_ERR,
00643                     "nvram-wakeup failed to set time in bios");
00644                 return 1;
00645             }
00646 
00647             // we don't trust the return code from nvram-wakeup so only reboot
00648             // if the user has set a restart command
00649             if (nvramRestartCmd.isEmpty())
00650                 shutdownmode = 0;
00651             else
00652                 shutdownmode = 1;
00653         }
00654         else
00655         {
00656             LOG(VB_GENERAL, LOG_NOTICE, "The next wakeup time is less than "
00657                                         "15 mins away, not shutting down");
00658             return 0;
00659         }
00660     }
00661 
00662     int res = 0;
00663 
00664     switch (shutdownmode)
00665     {
00666         case 0:
00667         {
00668             LOG(VB_GENERAL, LOG_NOTICE,
00669                 "everything looks fine, shutting down ...");
00670             QString poweroffCmd = gCoreContext->GetSetting(
00671                 "MythShutdownPoweroff", "/sbin/poweroff");
00672             LOG(VB_GENERAL, LOG_NOTICE, "..");
00673             LOG(VB_GENERAL, LOG_NOTICE, ".");
00674             LOG(VB_GENERAL, LOG_NOTICE, "shutting down ...");
00675 
00676             myth_system(poweroffCmd);
00677             res = 0;
00678             break;
00679         }
00680         case 1:
00681         {
00682             LOG(VB_GENERAL, LOG_NOTICE,
00683                 "everything looks fine, but reboot is needed");
00684             LOG(VB_GENERAL, LOG_NOTICE, "sending command to bootloader ...");
00685             LOG(VB_GENERAL, LOG_NOTICE, nvramRestartCmd);
00686 
00687             myth_system(nvramRestartCmd);
00688 
00689             LOG(VB_GENERAL, LOG_NOTICE, "..");
00690             LOG(VB_GENERAL, LOG_NOTICE, ".");
00691             LOG(VB_GENERAL, LOG_NOTICE, "rebooting ...");
00692 
00693             QString rebootCmd =
00694                 gCoreContext->GetSetting("MythShutdownReboot", "/sbin/reboot");
00695             myth_system(rebootCmd);
00696             res = 0;
00697             break;
00698         }
00699         default:
00700             LOG(VB_GENERAL, LOG_ERR,
00701                 "panic. invalid shutdown mode, do nothing");
00702             res = 1;
00703             break;
00704     }
00705 
00706     return res;
00707 }
00708 
00709 static int startup()
00710 {
00711     LOG(VB_GENERAL, LOG_INFO, "Mythshutdown: --startup");
00712 
00713     int res = 0;
00714     QDateTime startupTime = QDateTime();
00715     QString s = getGlobalSetting("MythshutdownWakeupTime", "");
00716     if (!s.isEmpty())
00717         startupTime = QDateTime::fromString(s, Qt::ISODate);
00718 
00719     // if we don't have a valid startup time assume we were started manually
00720     if (!startupTime.isValid())
00721         res = 1;
00722     else
00723     {
00724         // if we started within 15mins of the saved wakeup time assume we started
00725         // automatically to record or for a daily wakeup/shutdown period
00726 
00727         int delta = startupTime.secsTo(QDateTime::currentDateTime());
00728         if (delta < 0)
00729             delta = -delta;
00730 
00731         if (delta < 15 * 60)
00732             res = 0;
00733         else
00734             res = 1;
00735     }
00736 
00737     if (res)
00738         LOG(VB_GENERAL, LOG_INFO,
00739             QString("looks like we were started manually: %1").arg(res));
00740     else
00741         LOG(VB_GENERAL, LOG_INFO,
00742             QString("looks like we were started automatically: %1").arg(res));
00743 
00744 
00745     LOG(VB_GENERAL, LOG_INFO,
00746         QString("Mythshutdown: --startup returned: %1").arg(res));
00747 
00748     return res;
00749 }
00750 
00751 int main(int argc, char **argv)
00752 {
00753     MythShutdownCommandLineParser cmdline;
00754     if (!cmdline.Parse(argc, argv))
00755     {
00756         cmdline.PrintHelp();
00757         return GENERIC_EXIT_INVALID_CMDLINE;
00758     }
00759 
00760     if (cmdline.toBool("showhelp"))
00761     {
00762         cmdline.PrintHelp();
00763         return GENERIC_EXIT_OK;
00764     }
00765 
00766     if (cmdline.toBool("showversion"))
00767     {
00768         cmdline.PrintVersion();
00769         return GENERIC_EXIT_OK;
00770     }
00771 
00772     QCoreApplication a(argc, argv);
00773     QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHSHUTDOWN);
00774 
00775     int retval;
00776     QString mask("none");
00777     if ((retval = cmdline.ConfigureLogging(mask)) != GENERIC_EXIT_OK)
00778         return retval;
00779 
00780     gContext = new MythContext(MYTH_BINARY_VERSION);
00781     if (!gContext->Init(false))
00782     {
00783         LOG(VB_GENERAL, LOG_ERR,
00784             "mythshutdown: Could not initialize MythContext. Exiting.");
00785         return GENERIC_EXIT_NO_MYTHCONTEXT;
00786     }
00787 
00788     int res = 0;
00789 
00790     if (cmdline.toBool("lock"))
00791         res = lockShutdown();
00792     else if (cmdline.toBool("unlock"))
00793         res = unlockShutdown();
00794     else if (cmdline.toBool("check"))
00795         res = checkOKShutdown((bool)(cmdline.toInt("check") == 1));
00796     else if (cmdline.toBool("setschedwakeup"))
00797         res = setScheduledWakeupTime();
00798     else if (cmdline.toBool("startup"))
00799         res = startup();
00800     else if (cmdline.toBool("shutdown"))
00801         res = shutdown();
00802     else if (cmdline.toBool("status"))
00803         res = getStatus((bool)(cmdline.toInt("status") == 1));
00804     else if (cmdline.toBool("setwakeup"))
00805         res = setWakeupTime(cmdline.toString("setwakeup"));
00806     else if (cmdline.toBool("safeshutdown"))
00807     { 
00808         res = checkOKShutdown(true);
00809         if (res == 0)
00810         {
00811              // Nothing to stop a shutdown (eg. recording in progress).
00812              res = setScheduledWakeupTime();
00813              res = shutdown();
00814         }
00815 
00816     }
00817     else
00818         cmdline.PrintHelp();
00819 
00820     delete gContext;
00821 
00822     return res;
00823 }
00824 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends