00001
00002
00003 #ifndef BASE_DAEMON_H
00004 #define BASE_DAEMON_H
00005
00006 #include <iostream>
00007 #include <ctime>
00008 #include "Config.h"
00009 #include "Global.h"
00010 #include "Log.h"
00011 #include "Mutex.h"
00012 #include "Process.h"
00013 #include "Socket.h"
00014
00015 template<class T> int daemon_main(int argc, const char **argv, const char *domain = NULL) {
00016 int ret;
00017
00018 if (domain && *domain)
00019 base::Global::setDomain(domain);
00020 else
00021 base::Global::setDomainFromExecutable(*argv);
00022 try {
00023 T daemon(*argv);
00024 base::Socket::init();
00025 if (daemon.readArguments(argc, argv))
00026 ret = daemon.service(argv);
00027 else
00028 ret = 1;
00029 base::Socket::finit();
00030 } catch (const base::Exception &ex) {
00031 std::cerr << *argv << ": " << ex << std::endl;
00032 ret = 4;
00033 } catch (const std::exception &ex) {
00034 std::cerr << *argv << ": " << (ex.what() ? ex.what() : "(null)") << std::endl;
00035 ret = 4;
00036 }
00037 return ret;
00038 }
00039
00040 namespace base {
00042
00046 class PPBASE_EXPORT Daemon: public Mutex {
00047 public:
00049 virtual ~Daemon();
00050
00052
00055 Log *getLog();
00056
00058 Config *getConfig();
00059
00061
00064 bool getForeground() const;
00065
00067
00070 const String &getName() const;
00071
00073
00076 Process::pid_type getPid() const;
00077
00079
00082 time_t getTime() const;
00083
00085
00088 void getUptime(String &s);
00089
00091
00097 void log(Log::levels level, const char *func, const char *fmt, ...)
00098 #ifdef __GNUC__
00099 __attribute__((format(printf, 4, 5)))
00100 #endif
00101 ;
00102
00104
00110 bool readArguments(int argc, const char **argv, const char *args =
00111 #ifdef _WIN32
00112 "c:d:fhqsvV"
00113 #else
00114 "c:d:fhqsvVw"
00115 #endif
00116 );
00117
00119
00122 int service(const char **argv);
00123
00124 protected:
00125 #ifdef _WIN32
00126 enum srvE {
00127 srvNone = 0,
00128 srvInstall,
00129 srvStart,
00130 srvStop,
00131 srvUninstall
00132 };
00133 #endif
00134
00136
00139 Daemon(const String &name);
00140
00142 virtual void config();
00143
00145 virtual void createThreads(bool init);
00146
00147 #ifndef _WIN32
00148
00149
00154 Process::pid_type daemonize(bool createpid = true, bool exitparent = true);
00155
00157 void dropRootPrivileges();
00158 #endif
00159
00161
00166 virtual bool dumpState(bool force);
00167
00168 #ifndef _WIN32
00169
00170
00173 gid_t getGroupID() const;
00174
00176
00179 uid_t getUserID() const;
00180 #endif
00181
00183
00187 virtual bool handleArgument(int arg);
00188
00190
00193 bool hasExplicitUGID() const;
00194
00196
00199 virtual int loop() = 0;
00200
00202
00205 virtual bool needRootPrivileges();
00206
00208 int serviceMain();
00209
00214 virtual void shutdown();
00215
00220 virtual void startup();
00221
00223 virtual void terminateThreads();
00224
00226
00230 virtual void usage(const char *pgm, bool err) const;
00231
00233
00239 virtual void vlog(Log::levels level, const char *func, const char *fmt, va_list ap);
00240
00241 #ifdef _WIN32
00242 int win32Service();
00243 static void WINAPI win32ServiceHandler(DWORD opcode);
00244 void win32ServiceMain(DWORD, LPWSTR *);
00245 static void WINAPI win32ServiceMainS(DWORD dw, LPWSTR *lpstr);
00246 void win32SetServiceStatus(DWORD status);
00247 #endif
00248
00249 Config _cfg;
00250 String _cfgfile;
00251 bool _foreground;
00252 u_longlong_t _laststatedump;
00253 Log *_log;
00254 bool _logstderr;
00255 int _maxopenfiles;
00256 String _name;
00257 Process::pid_type _pid;
00258 time_t _t_now;
00259 time_t _t_start;
00260 int _fdreserve;
00261
00262 #ifdef _WIN32
00263 enum srvE _srvact;
00264 WString _srvname;
00265 String _srvprefix;
00266 SERVICE_STATUS_HANDLE _srvsh;
00267 SERVICE_STATUS _srvst;
00268 #else
00269 String _pidfile;
00270 bool _watcher;
00271 #endif
00272 };
00273 }
00274
00275 #endif