void signal_handler(int sig_num) { switch(sig_num) { #ifndef WIN32 case SIGHUP: if (logfile!="") { _log.SetOutputFile(logfile.c_str()); } break; #endif case SIGINT: case SIGTERM: #ifndef WIN32 if ((g_bRunAsDaemon)||(g_bUseSyslog)) syslog(LOG_INFO, "Domoticz is exiting..."); #endif g_bStopApplication = true; break; case SIGSEGV: case SIGILL: case SIGABRT: case SIGFPE: if (fatal_handling) { _log.Log(LOG_ERROR, "Domoticz received fatal signal %d while backtracing !...", sig_num); exit(EXIT_FAILURE); } fatal_handling = 1; _log.Log(LOG_ERROR, "Domoticz received fatal signal %d !...", sig_num); dumpstack(); // re-raise signal to enforce core dump signal(sig_num, SIG_DFL); raise(sig_num); break; } }
int main(int argc, char**argv) #endif { #if defined WIN32 #ifndef _DEBUG CreateMutexA(0, FALSE, "Local\\Domoticz"); if(GetLastError() == ERROR_ALREADY_EXISTS) { MessageBox(HWND_DESKTOP,"Another instance of Domoticz is already running!","Domoticz",MB_OK); return 1; } #endif //_DEBUG bool bStartWebBrowser = true; RedirectIOToConsole(); #endif //WIN32 szStartupFolder = ""; szWWWFolder = ""; szWebRoot = ""; CCmdLine cmdLine; // parse argc,argv #if defined WIN32 cmdLine.SplitLine(__argc, __argv); #else cmdLine.SplitLine(argc, argv); //ignore pipe errors signal(SIGPIPE, SIG_IGN); #endif if (cmdLine.HasSwitch("-log")) { if (cmdLine.GetArgumentCount("-log") != 1) { _log.Log(LOG_ERROR, "Please specify an output log file"); return 1; } logfile = cmdLine.GetSafeArgument("-log", 0, "domoticz.log"); _log.SetOutputFile(logfile.c_str()); } if (cmdLine.HasSwitch("-loglevel")) { if (cmdLine.GetArgumentCount("-loglevel") != 1) { _log.Log(LOG_ERROR, "Please specify logfile output level (0=All, 1=Status+Error, 2=Error)"); return 1; } int Level = atoi(cmdLine.GetSafeArgument("-loglevel", 0, "").c_str()); _log.SetVerboseLevel((_eLogFileVerboseLevel)Level); } if (cmdLine.HasSwitch("-notimestamps")) { _log.EnableLogTimestamps(false); } if (cmdLine.HasSwitch("-approot")) { if (cmdLine.GetArgumentCount("-approot") != 1) { _log.Log(LOG_ERROR, "Please specify a APP root path"); return 1; } std::string szroot = cmdLine.GetSafeArgument("-approot", 0, ""); if (szroot.size() != 0) szStartupFolder = szroot; } if (szStartupFolder == "") { #if !defined WIN32 char szStartupPath[255]; getExecutablePathName((char*)&szStartupPath,255); szStartupFolder=szStartupPath; if (szStartupFolder.find_last_of('/')!=std::string::npos) szStartupFolder=szStartupFolder.substr(0,szStartupFolder.find_last_of('/')+1); #else #ifndef _DEBUG char szStartupPath[255]; char * p; GetModuleFileName(NULL, szStartupPath, sizeof(szStartupPath)); p = szStartupPath + strlen(szStartupPath); while (p >= szStartupPath && *p != '\\') p--; if (++p >= szStartupPath) *p = 0; szStartupFolder=szStartupPath; size_t start_pos = szStartupFolder.find("\\Release\\"); if(start_pos != std::string::npos) { szStartupFolder.replace(start_pos, 9, "\\domoticz\\"); _log.Log(LOG_STATUS,"%s",szStartupFolder.c_str()); } #endif #endif } GetAppVersion(); _log.Log(LOG_STATUS, "Domoticz V%s (c)2012-%d GizMoCuz", szAppVersion.c_str(), ActYear); _log.Log(LOG_STATUS, "Build Hash: %s, Date: %s", szAppHash.c_str(), szAppDate.c_str()); #if !defined WIN32 //Check if we are running on a RaspberryPi std::string sLine = ""; std::ifstream infile; infile.open("/proc/cpuinfo"); if (infile.is_open()) { while (!infile.eof()) { getline(infile, sLine); if ( (sLine.find("BCM2708")!=std::string::npos)|| (sLine.find("BCM2709")!=std::string::npos) ) { //Core temperature of BCM2835 SoC _log.Log(LOG_STATUS,"System: Raspberry Pi"); szInternalTemperatureCommand="/opt/vc/bin/vcgencmd measure_temp"; bHasInternalTemperature=true; break; } } infile.close(); } if (!bHasInternalTemperature) { if (file_exist("/sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/temp1_input")) { _log.Log(LOG_STATUS,"System: Cubieboard/Cubietruck"); szInternalTemperatureCommand="cat /sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/temp1_input | awk '{ printf (\"temp=%0.2f\\n\",$1/1000); }'"; bHasInternalTemperature = true; } else if (file_exist("/sys/devices/virtual/thermal/thermal_zone0/temp")) { //_log.Log(LOG_STATUS,"System: ODroid"); szInternalTemperatureCommand="cat /sys/devices/virtual/thermal/thermal_zone0/temp | awk '{ printf (\"temp=%0.2f\\n\",$1/1000); }'"; bHasInternalTemperature = true; } } if (file_exist("/sys/class/power_supply/ac/voltage_now")) { szInternalVoltageCommand = "cat /sys/class/power_supply/ac/voltage_now | awk '{ printf (\"volt=%0.2f\\n\",$1/1000000); }'"; bHasInternalVoltage = true; } if (file_exist("/sys/class/power_supply/ac/current_now")) { szInternalCurrentCommand = "cat /sys/class/power_supply/ac/current_now | awk '{ printf (\"curr=%0.2f\\n\",$1/1000000); }'"; bHasInternalCurrent = true; } _log.Log(LOG_STATUS,"Startup Path: %s", szStartupFolder.c_str()); #endif szWWWFolder = szStartupFolder + "www"; if ((cmdLine.HasSwitch("-h")) || (cmdLine.HasSwitch("--help")) || (cmdLine.HasSwitch("/?"))) { _log.Log(LOG_NORM, szHelp); return 0; } szUserDataFolder=szStartupFolder; if (cmdLine.HasSwitch("-userdata")) { if (cmdLine.GetArgumentCount("-userdata") != 1) { _log.Log(LOG_ERROR, "Please specify a path for user data to be stored"); return 1; } std::string szroot = cmdLine.GetSafeArgument("-userdata", 0, ""); if (szroot.size() != 0) szUserDataFolder = szroot; } if (cmdLine.HasSwitch("-startupdelay")) { if (cmdLine.GetArgumentCount("-startupdelay") != 1) { _log.Log(LOG_ERROR, "Please specify a startupdelay"); return 1; } int DelaySeconds = atoi(cmdLine.GetSafeArgument("-startupdelay", 0, "").c_str()); _log.Log(LOG_STATUS, "Startup delay... waiting %d seconds...", DelaySeconds); sleep_seconds(DelaySeconds); } if (cmdLine.HasSwitch("-wwwbind")) { if (cmdLine.GetArgumentCount("-wwwbind") != 1) { _log.Log(LOG_ERROR, "Please specify an address"); return 1; } std::string wwwbind = cmdLine.GetSafeArgument("-wwwbind", 0, "0.0.0.0"); m_mainworker.SetWebserverAddress(wwwbind); } if (cmdLine.HasSwitch("-www")) { if (cmdLine.GetArgumentCount("-www") != 1) { _log.Log(LOG_ERROR, "Please specify a port"); return 1; } std::string wwwport = cmdLine.GetSafeArgument("-www", 0, "8080"); if (wwwport == "0") wwwport.clear();//HTTP server disabled m_mainworker.SetWebserverPort(wwwport); } #ifdef NS_ENABLE_SSL if (cmdLine.HasSwitch("-sslwww")) { if (cmdLine.GetArgumentCount("-sslwww") != 1) { _log.Log(LOG_ERROR, "Please specify a port"); return 1; } std::string wwwport = cmdLine.GetSafeArgument("-sslwww", 0, "443"); if (wwwport == "0") wwwport.clear();//HTTPS server disabled m_mainworker.SetSecureWebserverPort(wwwport); } if (cmdLine.HasSwitch("-sslcert")) { if (cmdLine.GetArgumentCount("-sslcert") != 1) { _log.Log(LOG_ERROR, "Please specify the file path"); return 1; } std::string ca_cert = cmdLine.GetSafeArgument("-sslcert", 0, "./server_cert.pem"); m_mainworker.SetSecureWebserverCert(ca_cert); } if (cmdLine.HasSwitch("-sslpass")) { if (cmdLine.GetArgumentCount("-sslpass") != 1) { _log.Log(LOG_ERROR, "Please specify a passphrase for your certificate file"); return 1; } std::string ca_passphrase = cmdLine.GetSafeArgument("-sslpass", 0, ""); m_mainworker.SetSecureWebserverPass(ca_passphrase); } #endif if (cmdLine.HasSwitch("-nowwwpwd")) { m_mainworker.m_bIgnoreUsernamePassword = true; } if (cmdLine.HasSwitch("-nocache")) { g_bDontCacheWWW = true; } std::string dbasefile = szUserDataFolder + "domoticz.db"; #ifdef WIN32 #ifndef _DEBUG if (!IsUserAnAdmin()) { char szPath[MAX_PATH]; HRESULT hr = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath); if (SUCCEEDED(hr)) { std::string sPath = szPath; sPath += "\\Domoticz"; DWORD dwAttr = GetFileAttributes(sPath.c_str()); BOOL bDirExists = (dwAttr != 0xffffffff && (dwAttr & FILE_ATTRIBUTE_DIRECTORY)); if (!bDirExists) { BOOL bRet = CreateDirectory(sPath.c_str(), NULL); if (bRet == FALSE) { MessageBox(0, "Error creating Domoticz directory in program data folder (%ProgramData%)!!", "Error:", MB_OK); } } sPath += "\\domoticz.db"; dbasefile = sPath; } } #endif #endif if (cmdLine.HasSwitch("-dbase")) { if (cmdLine.GetArgumentCount("-dbase") != 1) { _log.Log(LOG_ERROR, "Please specify a Database Name"); return 1; } dbasefile = cmdLine.GetSafeArgument("-dbase", 0, "domoticz.db"); } m_sql.SetDatabaseName(dbasefile); if (cmdLine.HasSwitch("-wwwroot")) { if (cmdLine.GetArgumentCount("-wwwroot") != 1) { _log.Log(LOG_ERROR, "Please specify a WWW root path"); return 1; } std::string szroot = cmdLine.GetSafeArgument("-wwwroot", 0, ""); if (szroot.size() != 0) szWWWFolder = szroot; } if (cmdLine.HasSwitch("-webroot")) { if (cmdLine.GetArgumentCount("-webroot") != 1) { _log.Log(LOG_ERROR, "Please specify a web root path"); return 1; } std::string szroot = cmdLine.GetSafeArgument("-webroot", 0, ""); if (szroot.size() != 0) szWebRoot = szroot; } if (cmdLine.HasSwitch("-verbose")) { if (cmdLine.GetArgumentCount("-verbose") != 1) { _log.Log(LOG_ERROR, "Please specify a verbose level"); return 1; } int Level = atoi(cmdLine.GetSafeArgument("-verbose", 0, "").c_str()); m_mainworker.SetVerboseLevel((eVerboseLevel)Level); } #if defined WIN32 if (cmdLine.HasSwitch("-nobrowser")) { bStartWebBrowser = false; } //Init WinSock WSADATA data; WORD version; version = (MAKEWORD(2, 2)); int ret = WSAStartup(version, &data); if (ret != 0) { ret = WSAGetLastError(); if (ret == WSANOTINITIALISED) { _log.Log(LOG_ERROR, "Error: Winsock could not be initialized!"); } } CoInitializeEx(0, COINIT_MULTITHREADED); CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); #endif #ifndef WIN32 if (cmdLine.HasSwitch("-daemon")) { g_bRunAsDaemon = true; } std::string daemonname = DAEMON_NAME; if (cmdLine.HasSwitch("-daemonname")) { daemonname = cmdLine.GetSafeArgument("-daemonname", 0, DAEMON_NAME); } std::string pidfile = PID_FILE; if (cmdLine.HasSwitch("-pidfile")) { pidfile = cmdLine.GetSafeArgument("-pidfile", 0, PID_FILE); } if ((g_bRunAsDaemon)||(g_bUseSyslog)) { setlogmask(LOG_UPTO(LOG_INFO)); openlog(daemonname.c_str(), LOG_CONS | LOG_PERROR, LOG_USER); syslog(LOG_INFO, "Domoticz is starting up...."); } if (g_bRunAsDaemon) { /* Deamonize */ daemonize(szStartupFolder.c_str(), pidfile.c_str()); } if ((g_bRunAsDaemon) || (g_bUseSyslog)) { syslog(LOG_INFO, "Domoticz running..."); } #endif if (!g_bRunAsDaemon) { signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); } if (!m_mainworker.Start()) { return 1; } m_StartTime = time(NULL); /* now, lets get into an infinite loop of doing nothing. */ #if defined WIN32 #ifndef _DEBUG RedirectIOToConsole(); //hide console #endif InitWindowsHelper(hInstance, hPrevInstance, nShowCmd, m_mainworker.GetWebserverAddress(), atoi(m_mainworker.GetWebserverPort().c_str()), bStartWebBrowser); MSG Msg; while (!g_bStopApplication) { if (PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE)) { if (GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } } else sleep_milliseconds(100); } TrayMessage(NIM_DELETE, NULL); #else while ( !g_bStopApplication ) { sleep_seconds(1); } #endif _log.Log(LOG_STATUS, "Closing application!..."); fflush(stdout); _log.Log(LOG_STATUS, "Stopping worker..."); try { m_mainworker.Stop(); } catch (...) { } #ifndef WIN32 if (g_bRunAsDaemon) { syslog(LOG_INFO, "Domoticz stopped..."); daemonShutdown(); // Delete PID file remove(pidfile.c_str()); } #else // Release WinSock WSACleanup(); CoUninitialize(); #endif return 0; }
void daemonize(const char *rundir, const char *pidfile) { int pid, sid, i; char str[10]; struct sigaction newSigAction; sigset_t newSigSet; /* Check if parent process id is set */ if (getppid() == 1) { /* PPID exists, therefore we are already a daemon */ return; } /* Set signal mask - signals we want to block */ sigemptyset(&newSigSet); sigaddset(&newSigSet, SIGCHLD); /* ignore child - i.e. we don't need to wait for it */ sigaddset(&newSigSet, SIGTSTP); /* ignore Tty stop signals */ sigaddset(&newSigSet, SIGTTOU); /* ignore Tty background writes */ sigaddset(&newSigSet, SIGTTIN); /* ignore Tty background reads */ sigprocmask(SIG_BLOCK, &newSigSet, NULL); /* Block the above specified signals */ /* Set up a signal handler */ newSigAction.sa_handler = signal_handler; sigemptyset(&newSigAction.sa_mask); newSigAction.sa_flags = 0; /* Signals to handle */ sigaction(SIGTERM, &newSigAction, NULL); // catch term signal sigaction(SIGINT, &newSigAction, NULL); // catch interrupt signal sigaction(SIGSEGV, &newSigAction, NULL); // catch segmentation fault signal sigaction(SIGABRT, &newSigAction, NULL); // catch abnormal termination signal sigaction(SIGILL, &newSigAction, NULL); // catch invalid program image #ifndef WIN32 sigaction(SIGHUP, &newSigAction, NULL); // catch HUP, for logrotation #endif /* Fork*/ pid = fork(); if (pid < 0) { /* Could not fork */ exit(EXIT_FAILURE); } if (pid > 0) { /* Child created ok, so exit parent process */ exit(EXIT_SUCCESS); } /* Ensure only one copy */ pidFilehandle = open(pidfile, O_RDWR | O_CREAT, 0600); if (pidFilehandle == -1) { /* Couldn't open lock file */ syslog(LOG_INFO, "Could not open PID lock file %s, exiting", pidfile); exit(EXIT_FAILURE); } /* Try to lock file */ if (lockf(pidFilehandle, F_TLOCK, 0) == -1) { /* Couldn't get lock on lock file */ syslog(LOG_INFO, "Could not lock PID lock file %s, exiting", pidfile); exit(EXIT_FAILURE); } /* Get and format PID */ sprintf(str, "%d\n", getpid()); /* write pid to lockfile */ int twrite=write(pidFilehandle, str, strlen(str)); if (twrite != strlen(str)) { syslog(LOG_INFO, "Could not write to lockfile %s, exiting", pidfile); exit(EXIT_FAILURE); } /* Child continues */ umask(027); /* Set file permissions 750 */ if (logfile!="") { _log.SetOutputFile(logfile.c_str()); } /* Get a new process group */ sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); } /* Close out the standard file descriptors */ close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); /* Route I/O connections */ /* Open STDIN */ i = open("/dev/null", O_RDWR); /* STDOUT */ int dret = dup(i); if (dret == -1) { _log.Log(LOG_ERROR, "Could not set STDOUT descriptor !"); } /* STDERR */ dret = dup(i); if (dret == -1) { _log.Log(LOG_ERROR, "Could not set STDERR descriptor !"); } int cdret = chdir(rundir); /* change running directory */ if (dret == -1) { _log.Log(LOG_ERROR, "Could not change running directory !"); } }
int main(int argc, char**argv) #endif { #if defined WIN32 CreateMutexA(0, FALSE, "Local\\Domoticz"); if(GetLastError() == ERROR_ALREADY_EXISTS) { MessageBox(HWND_DESKTOP,"Another instance of Domoticz is already running!","Domoticz",MB_OK); return -1; } bool bStartWebBrowser=true; RedirectIOToConsole(); #endif szStartupFolder=""; szWWWFolder=""; #if !defined WIN32 char szStartupPath[255]; getExecutablePathName((char*)&szStartupPath,255); szStartupFolder=szStartupPath; if (szStartupFolder.find_last_of('/')!=std::string::npos) szStartupFolder=szStartupFolder.substr(0,szStartupFolder.find_last_of('/')+1); #else #ifndef _DEBUG char szStartupPath[255]; char * p; GetModuleFileName(NULL, szStartupPath, sizeof(szStartupPath)); p = szStartupPath + strlen(szStartupPath); while(p >= szStartupPath && *p != '\\') p--; if(++p >= szStartupPath) *p = 0; szStartupFolder=szStartupPath; size_t start_pos = szStartupFolder.find("\\Release\\"); if(start_pos != std::string::npos) { szStartupFolder.replace(start_pos, 9, "\\domoticz\\"); _log.Log(LOG_NORM,"%s",szStartupFolder.c_str()); } #endif #endif GetAppVersion(); _log.Log(LOG_NORM,"Domoticz V%s (c)2012-2014 GizMoCuz",szAppVersion.c_str()); #if !defined WIN32 //Check if we are running on a RaspberryPi std::string sLine = ""; std::ifstream infile; infile.open("/proc/cpuinfo"); if (infile.is_open()) { while (!infile.eof()) { getline(infile, sLine); if (sLine.find("BCM2708")!=std::string::npos) { _log.Log(LOG_NORM,"System: Raspberry Pi"); bIsRaspberryPi=true; break; } } infile.close(); } _log.Log(LOG_NORM,"Startup Path: %s", szStartupFolder.c_str()); #endif szWWWFolder=szStartupFolder+"www"; CCmdLine cmdLine; // parse argc,argv #if defined WIN32 cmdLine.SplitLine(__argc, __argv); #else cmdLine.SplitLine(argc, argv); #endif if ((cmdLine.HasSwitch("-h"))||(cmdLine.HasSwitch("--help"))||(cmdLine.HasSwitch("/?"))) { _log.Log(LOG_NORM,szHelp); return 0; } if (cmdLine.HasSwitch("-startupdelay")) { if (cmdLine.GetArgumentCount("-startupdelay")!=1) { _log.Log(LOG_ERROR,"Please specify a startupdelay"); return 0; } int DelaySeconds=atoi(cmdLine.GetSafeArgument("-startupdelay",0,"").c_str()); _log.Log(LOG_NORM,"Startup delay... waiting %d seconds...",DelaySeconds); sleep_seconds(DelaySeconds); } if (cmdLine.HasSwitch("-www")) { if (cmdLine.GetArgumentCount("-www")!=1) { _log.Log(LOG_ERROR,"Please specify a port"); return 0; } std::string wwwport=cmdLine.GetSafeArgument("-www",0,"8080"); _mainworker.SetWebserverPort(wwwport); } if (cmdLine.HasSwitch("-nowwwpwd")) { _mainworker.m_bIgnoreUsernamePassword=true; } std::string dbasefile=szStartupFolder + "domoticz.db"; #ifdef WIN32 if (!IsUserAnAdmin()) { char szPath[MAX_PATH]; HRESULT hr = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath); if (SUCCEEDED(hr)) { std::string sPath=szPath; sPath+="\\Domoticz"; DWORD dwAttr = GetFileAttributes(sPath.c_str()); BOOL bDirExists=(dwAttr != 0xffffffff && (dwAttr & FILE_ATTRIBUTE_DIRECTORY)); if (!bDirExists) { BOOL bRet=CreateDirectory(sPath.c_str(),NULL); if (bRet==FALSE) { MessageBox(0,"Error creating Domoticz directory in program data folder (%ProgramData%)!!","Error:",MB_OK); } } sPath+="\\domoticz.db"; dbasefile=sPath; } } #endif if (cmdLine.HasSwitch("-dbase")) { if (cmdLine.GetArgumentCount("-dbase")!=1) { _log.Log(LOG_ERROR,"Please specify a Database Name"); return 0; } dbasefile=cmdLine.GetSafeArgument("-dbase",0,"domoticz.db"); } _mainworker.m_sql.SetDatabaseName(dbasefile); if (cmdLine.HasSwitch("-wwwroot")) { if (cmdLine.GetArgumentCount("-wwwroot")!=1) { _log.Log(LOG_ERROR,"Please specify a WWW root path"); return 0; } std::string szroot=cmdLine.GetSafeArgument("-wwwroot",0,""); if (szroot.size()!=0) szWWWFolder=szroot; } if (cmdLine.HasSwitch("-verbose")) { if (cmdLine.GetArgumentCount("-verbose")!=1) { _log.Log(LOG_ERROR,"Please specify a verbose level"); return 0; } int Level=atoi(cmdLine.GetSafeArgument("-verbose",0,"").c_str()); _mainworker.SetVerboseLevel((eVerboseLevel)Level); } #if defined WIN32 if (cmdLine.HasSwitch("-nobrowser")) { bStartWebBrowser=false; } #endif if (cmdLine.HasSwitch("-log")) { if (cmdLine.GetArgumentCount("-log")!=1) { _log.Log(LOG_ERROR,"Please specify an output log file"); return 0; } std::string logfile=cmdLine.GetSafeArgument("-log",0,"domoticz.log"); _log.SetOutputFile(logfile.c_str()); } if (!_mainworker.Start()) { return 0; } signal(SIGINT, catch_intterm); signal(SIGTERM,catch_intterm); /* now, lets get into an infinite loop of doing nothing. */ #if defined WIN32 #ifndef _DEBUG RedirectIOToConsole(); //hide console #endif InitWindowsHelper(hInstance,hPrevInstance,nShowCmd,DQuitFunction,atoi(_mainworker.GetWebserverPort().c_str()),bStartWebBrowser); MSG Msg; while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } #else for ( ;; ) sleep_seconds(1); #endif return 0; }