summaryrefslogtreecommitdiff
path: root/orkbasecxx/Daemon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'orkbasecxx/Daemon.cpp')
-rw-r--r--orkbasecxx/Daemon.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/orkbasecxx/Daemon.cpp b/orkbasecxx/Daemon.cpp
new file mode 100644
index 0000000..8a07f2d
--- /dev/null
+++ b/orkbasecxx/Daemon.cpp
@@ -0,0 +1,284 @@
+/*
+ * Oreka -- A media capture and retrieval platform
+ *
+ * Copyright (C) 2005, orecx LLC
+ *
+ * http://www.orecx.com
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License.
+ * Please refer to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#define _WINSOCKAPI_ // prevents the inclusion of winsock.h
+
+#include "ace/OS_NS_dirent.h"
+#include "Utils.h"
+#ifdef WIN32
+#include <windows.h>
+#include <tchar.h>
+SERVICE_STATUS serviceStatus;
+SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
+HANDLE stopServiceEvent = 0;
+#endif
+#include "ace/OS_NS_signal.h"
+#include "Daemon.h"
+
+void handle_signal(int sig_num)
+{
+ signal(SIGUSR1, handle_signal);
+ Daemon::Singleton()->Stop();
+}
+
+#ifdef WIN32
+void WINAPI ServiceControlHandler( DWORD controlCode )
+{
+ switch ( controlCode )
+ {
+ case SERVICE_CONTROL_INTERROGATE:
+ break;
+
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
+ SetServiceStatus( serviceStatusHandle, &serviceStatus );
+ Daemon::Singleton()->Stop();
+ return;
+
+ case SERVICE_CONTROL_PAUSE:
+ break;
+
+ case SERVICE_CONTROL_CONTINUE:
+ break;
+
+ default:
+ ;
+ }
+
+ SetServiceStatus( serviceStatusHandle, &serviceStatus );
+}
+#endif
+
+Daemon* Daemon::m_singleton;
+
+Daemon::Daemon()
+{
+}
+
+Daemon* Daemon::Singleton()
+{
+ return m_singleton;
+}
+
+void Daemon::Initialize(CStdString serviceName, DaemonHandler runHandler, DaemonHandler stopHandler)
+{
+ m_singleton = new Daemon();
+
+ m_singleton->m_runHandler = runHandler;
+ m_singleton->m_stopHandler = stopHandler;
+ m_singleton->m_serviceName = serviceName;
+
+ m_singleton->m_stopping = false;
+ m_singleton->m_shortLived = false;
+}
+
+void Daemon::Start()
+{
+#ifdef WIN32
+ // change current directory to service location (default for NT services is system32)
+ CStdString workingDirectory;
+
+ TCHAR path[ _MAX_PATH + 1 ];
+ if ( GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0 )
+ {
+ CStdString pathString = path;
+ int lastBackSlashPosition = pathString.ReverseFind("\\");
+ if (lastBackSlashPosition != -1)
+ {
+ workingDirectory = pathString.Left(lastBackSlashPosition);
+ chdir((PCSTR)workingDirectory);
+ }
+ }
+
+ SERVICE_TABLE_ENTRY serviceTable[] =
+ {
+ { (char *)(PCSTR)m_serviceName, Daemon::Run },
+ { 0, 0 }
+ };
+
+ StartServiceCtrlDispatcher( serviceTable );
+#else
+ signal(SIGUSR1, handle_signal);
+ Daemon::Run();
+#endif
+}
+
+#ifdef WIN32
+void WINAPI Daemon::Run( DWORD /*argc*/, TCHAR* /*argv*/[] )
+#else
+void Daemon::Run()
+#endif
+{
+#ifdef WIN32
+ // initialise service status
+ serviceStatus.dwServiceType = SERVICE_WIN32;
+ serviceStatus.dwCurrentState = SERVICE_START_PENDING;
+ serviceStatus.dwControlsAccepted = 0;
+ serviceStatus.dwWin32ExitCode = NO_ERROR;
+ serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
+ serviceStatus.dwCheckPoint = 0;
+ serviceStatus.dwWaitHint = 0;
+
+ serviceStatusHandle = RegisterServiceCtrlHandler( (PCSTR)Daemon::Singleton()->m_serviceName, ServiceControlHandler );
+ if ( serviceStatusHandle )
+ {
+ // service is starting
+ serviceStatus.dwCurrentState = SERVICE_START_PENDING;
+ SetServiceStatus( serviceStatusHandle, &serviceStatus );
+
+ // running
+ serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
+ serviceStatus.dwCurrentState = SERVICE_RUNNING;
+ SetServiceStatus( serviceStatusHandle, &serviceStatus );
+ }
+#else // non WIN32
+ int i,lfp;
+ char str[10];
+ if(getppid()==1) return; /* already a daemon */
+ i=fork();
+ if (i<0) exit(1); /* fork error */
+ if (i>0) exit(0); /* parent exits */
+ /* child (daemon) continues */
+ setsid(); /* obtain a new process group */
+ for (i=getdtablesize();i>=0;--i) close(i); /* close all descriptors */
+ i=open("/dev/null",O_RDWR); dup(i); dup(i); /* handle standart I/O */
+ umask(027); /* set newly created file permissions */
+ //chdir(RUNNING_DIR); /* change running directory */
+
+ char *loggingPath = NULL;
+ CStdString lockFile = CStdString("");
+
+ loggingPath = ACE_OS::getenv("ORKAUDIO_LOGGING_PATH");
+ if(loggingPath) {
+ ACE_DIR* dir = ACE_OS::opendir(loggingPath);
+ if(dir) {
+ ACE_OS::closedir(dir);
+ lockFile.Format("%s/orkaudio.lock", loggingPath);
+ }
+ }
+
+ if(!lockFile.size()) {
+ lfp=open("/var/log/orkaudio/orkaudio.lock",O_RDWR|O_CREAT,0640);
+ } else {
+ lfp=open(lockFile.c_str(),O_RDWR|O_CREAT,0640);
+ }
+
+ if (lfp<0)
+ {
+ lfp=open("orkaudio.lock",O_RDWR|O_CREAT,0640);
+ }
+ if (lfp<0)
+ {
+ exit(1); /* can not open */
+ }
+ if (lockf(lfp,F_TLOCK,0)<0) exit(0); /* can not lock */
+ /* first instance continues */
+ sprintf(str,"%d\n",getpid());
+ write(lfp,str,strlen(str)); /* record pid to lockfile */
+
+ //signal(SIGCHLD,SIG_IGN); /* ignore child */
+ //signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
+ //signal(SIGTTOU,SIG_IGN);
+ //signal(SIGTTIN,SIG_IGN);
+ //signal(SIGHUP,signal_handler); /* catch hangup signal */
+#endif
+
+ Daemon::Singleton()->m_runHandler();
+
+#ifdef WIN32
+ // service was stopped
+ serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
+ SetServiceStatus( serviceStatusHandle, &serviceStatus );
+
+ // do cleanup here
+ CloseHandle( stopServiceEvent );
+ stopServiceEvent = 0;
+
+ // service is now stopped
+ serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
+ serviceStatus.dwCurrentState = SERVICE_STOPPED;
+ SetServiceStatus( serviceStatusHandle, &serviceStatus );
+#endif
+}
+
+void Daemon::Stop()
+{
+ m_stopping = true;
+ m_stopHandler();
+}
+
+void Daemon::Install()
+{
+#ifdef WIN32
+ SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CREATE_SERVICE );
+
+ if ( serviceControlManager )
+ {
+ TCHAR path[ _MAX_PATH + 1 ];
+ if ( GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0 )
+ {
+ SC_HANDLE service = CreateService( serviceControlManager,
+ (PCSTR)m_serviceName, (PCSTR)m_serviceName,
+ SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path,
+ 0, 0, 0, 0, 0 );
+ if ( service )
+ CloseServiceHandle( service );
+ }
+
+ CloseServiceHandle( serviceControlManager );
+ }
+#endif
+}
+
+void Daemon::Uninstall()
+{
+#ifdef WIN32
+ SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CONNECT );
+
+ if ( serviceControlManager )
+ {
+ SC_HANDLE service = OpenService( serviceControlManager,
+ (PCSTR)m_serviceName, SERVICE_QUERY_STATUS | DELETE );
+ if ( service )
+ {
+ SERVICE_STATUS serviceStatus;
+ if ( QueryServiceStatus( service, &serviceStatus ) )
+ {
+ if ( serviceStatus.dwCurrentState == SERVICE_STOPPED )
+ DeleteService( service );
+ }
+
+ CloseServiceHandle( service );
+ }
+
+ CloseServiceHandle( serviceControlManager );
+ }
+#endif
+}
+
+bool Daemon::IsStopping()
+{
+ return m_stopping;
+}
+
+void Daemon::SetShortLived()
+{
+ m_shortLived = true;
+}
+
+bool Daemon::GetShortLived()
+{
+ return m_shortLived;
+}