00001 /* $Id: vosdaemon.hh,v 1.8 2003/07/22 05:09:56 tetron Exp $ */ 00002 00003 00004 /** @file vosdaemon.cc 00005 @author Reed Hedges (reed@zerohour.net) 00006 00007 TODO: 00008 * use site callbacks for periodic save state instead of SIGALRM 00009 * Special option spit out Docbook <cmdsynopsis> text for help: 00010 also change <foo> to <replacable>foo</replacable> in output. 00011 00012 Copyright 2003 Reed Hedges 00013 00014 This program is free software; you can redistribute it and/or modify 00015 it under the terms of the GNU General Public License as published by 00016 the Free Software Foundation; either version 2 of the License, or 00017 (at your option) any later version. 00018 00019 This program is distributed in the hope that it will be useful, 00020 but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License 00025 along with this program; if not, write to the Free Software 00026 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00027 */ 00028 00029 #ifndef VOSDAEMON_HH 00030 00031 #include <vos/corelibs/vos/vos.hh> 00032 #include <fstream> 00033 00034 /** 00035 This class contains many convenient features useful for running a 00036 background service, a.k.a. a daemon. 00037 00038 @ingroup applibs 00039 @ingroup vosdaemon 00040 00041 It will fork and run in the background automatically. 00042 To use it for your daemon, simply subclass this class, and instantiate 00043 it from your program. 00044 You can add and check for command-line arguments with addArg, addFlag, getArg 00045 and getFlag. 00046 You can also turn on automatic saving, loading and periodic saving by 00047 enabling the Save and Load built in command line parameters. 00048 Then call checkArgs, and run. 00049 You can override loop() to do something every program loop, or you can use 00050 a site callback. Other virtual methods may be overridden, but be sure 00051 to call the method in the parent class (VOSDaemon::) from your method. 00052 00053 VOSDaemon will automatically handle the following arguments: 00054 <dl> 00055 <dt>--help, -h and -?</dt> <dd>Print help message and quit</dd> 00056 <dt>--log, -L</dt> <dd>Set log file</dd> 00057 <dt>--loglevel, -E</dt> <dd>Set log level</dd> 00058 <dt>--save, -s</dt> <dd>Reserved for a future autosave feature</dd> 00059 <dt>--safe-feq, -S</dt> <dd>Reserved for a future autosave feature</dd> 00060 <dt>--load, -l</dt> <dd>Reserved for a future COD loading feature</dd> 00061 <dt>--name</dt> <dd>Reserved for a future COD loading feature</dd> 00062 </dl> 00063 00064 00065 Here is an example of use: 00066 00067 @code 00068 #include <iostream> // for cerr 00069 #include <vos/corelibs/vos/vos.hh> 00070 #include <vos/metaobjects/property/property.hh> 00071 #include <vosdaemon.hh> 00072 00073 class MyDaemon : public virtual VOSDaemon { 00074 public: 00075 MyDaemon() : VOSDaemon("example") { 00076 } 00077 00078 void setup() { 00079 addArg("example", "value", "Example argument. <value> is any string.", 'e', "VOSDAEMON_EXAMPLE"); 00080 addFlag("test", "Test flag.", 't', "VOSDAEMON_TEST_FLAG"); 00081 } 00082 00083 void preRun() { 00084 if(argGiven("example")) 00085 cerr << "example arg is: " << getArg("example") << endl; 00086 if(argGiven("test")) 00087 cerr << "test flag was given.\n"; 00088 else 00089 cerr << "test flag was not given.\n"; 00090 } 00091 00092 virtual void loop() { 00093 cerr << "loop!\n"; 00094 } 00095 }; 00096 00097 int main(int argc, char** argv) { 00098 Property::registerExtenders(); 00099 MyDaemon myDaemon("mydaemon"); 00100 myDaemon->setup(); 00101 myDaemon->checkArgs(argc, argv); 00102 myDaemon->preRun(); 00103 cerr << "Now running in the background...\n"; 00104 myDaemon->run(); 00105 } 00106 @endcode 00107 00108 00109 */ 00110 class VOSDaemon { 00111 00112 00113 private: 00114 vRef<LocalSite> site; 00115 char* saveFile; 00116 int saveFreq; 00117 Vobject* rootObj; 00118 char* programName; 00119 char* rootName; 00120 char* logFile; 00121 bool mayLoad, maySave, mayNameRoot; 00122 ofstream* logStream; 00123 00124 char* loadfile; 00125 bool dontFork; 00126 00127 typedef struct { 00128 string argName; 00129 string valueLabel; 00130 string value; 00131 char argChar; 00132 bool isFlag; 00133 string description; 00134 bool given; 00135 string envVar; 00136 } ArgInfo; 00137 typedef map <string, ArgInfo> ArgMap; 00138 typedef map <char, ArgInfo*> ShortArgMap; 00139 ArgMap args; 00140 ShortArgMap shortArgs; 00141 00142 bool checkBuiltinArgs(char o, char* val); 00143 00144 public: 00145 00146 /** Constructor. If site is omitted, a LocalSlocketSite 00147 * will be created with select timeout -1. (You can dynamic_cast 00148 * the LocalSite (returned by getSite()) to LocalSocketSite) once its created */ 00149 VOSDaemon(char* progName, LocalSite* site = 0); 00150 00151 /** Destructor */ 00152 virtual ~VOSDaemon(); 00153 00154 /** Get the site. */ 00155 LocalSite* getSite() { 00156 return &site; 00157 } 00158 00159 /** Set the save file. Must be called before run. */ 00160 void setSaveFile(char* savefile); 00161 00162 /** Set the save frequency. Must be called before run. */ 00163 void setSaveFrequency(int freq); 00164 00165 /** Set the root object (for saving). Must be called before run. */ 00166 void setRootObject(Vobject* rood); 00167 00168 /** Set the name of the root object (for loading). Must be called before 00169 * run. */ 00170 void setRootName(char* name); 00171 00172 /** Set the log level */ 00173 void setLogLevel(int lev); 00174 00175 /** Log to the named file. Must be called before run. */ 00176 void setLogFile(char* file); 00177 00178 /** Parse the command line arguments. Some built in arguments may 00179 * override any previously set settings. Any arguments you added 00180 * with addArg will also be recognized, and after a call to this 00181 * function, will be available from getArg. 00182 * 00183 * The following built in command line arguments may override some settings: 00184 * -L Log file 00185 * -E Log level 00186 * -s Save file (if enabled) 00187 * -S Save Frequency (if save is enabled) 00188 * -l Load state from this file (if enabled) 00189 * -N don't fork (if fork is available on this platform) 00190 */ 00191 virtual void checkArgs(int argc, char** argv); 00192 00193 /** Start running the daemon in the background. */ 00194 virtual void run(); 00195 00196 /** Virtual method called right after flushIncomingBuffers. Subclasses can 00197 * use this to perform actions during the run loop. Note that the frequency 00198 * with which this gets called depends on the select timeout (see 00199 * setTimeoutOnSelect()). 00200 */ 00201 virtual void loop() {} 00202 00203 00204 /* Enable or disable availability of some of the built in command-line arguments */ 00205 //@{ 00206 //void enableArg_load(bool p); 00207 //void enableArg_save(bool p); 00208 //void enableArg_nameRoot(bool p); 00209 //@} 00210 00211 /** Add command line arguments. If found, they will be available 00212 * by calling getArg or getFlag(). This functiow must 00213 * be called before calling run(). 00214 * @param argName long name of argument. 00215 * @param valueLabel label for the argument's value (used in help text). 00216 * @param description A description of the argument (used in help text). 00217 * @param defaultValue If supplied, then use this value if argument is not given. 00218 * @param argChar short one-character name of argument. (note that long arguments are 00219 * unavailable on some platforms, so always give a non-empty char for this) 00220 * @param envVar If supplied, then an environment variable with this name 00221 * may be used to supply a default value. (Command-line arguments always 00222 * override environment variables) 00223 * 00224 * @example addArg("example", "value", "An example", 'x'); // for --example or -x 00225 * @example addArg("example", "value", "An example"); 00226 * @example addArg("example", "value", "An example", "default value", 'e', "VOSDAEMON_EXAMPLE"); 00227 * @example addArg("example", "value", "An example", "default"); 00228 * @note The built in options are: 00229 * <ul> 00230 * <li>"help" or 'h' to generate help text</li> 00231 * <li>"loglevel" or 'E' to set the log level</li> 00232 * <li>"log" or 'L' to set the log file</li> 00233 * <li>"name" or 'n' to set the root object name (if enabled)</li> 00234 * <li>"load" or 'l' to load a saved file (if enabled)</li> 00235 * <li>"save" or 's' to set save-file name (if enabled)</li> 00236 * <li>"save-freq" or 'S' to set save frequency (if enabled and possible on this platform)</li> 00237 * </ul> 00238 * 00239 */ 00240 00241 //@{ 00242 void addArg(string argName, string valueLabel, string description, char argChar, string envVar = ""); 00243 void addArg(string argName, string valueLabel, string description, string defaultValue, char argChar, string envVar = ""); 00244 //@} 00245 00246 00247 00248 /** Add flag argument . This function must be called before calling 00249 * run(). 00250 */ 00251 void addFlag(string flagName, string description, char flagChar, string envVar); 00252 00253 00254 /** Get value of a command line argument. If it wasn't given then 00255 * the default value is returned. If it wasn't added using addArg(), or it 00256 * was added using addFlag(), then 00257 * a runtime_error exception will be thrown. */ 00258 string getArg(string argName); 00259 00260 /** Get presence of a command line option with no argiment (ie, a flag). 00261 * If it was given, true will be returned. If it wasn't then false 00262 * will be returned. If it wasn't added using addArg, then a 00263 * runtime_error exception will be thrown. 00264 */ 00265 bool argGiven(string argName); 00266 00267 /** Same as argGiven */ 00268 inline bool getFlag(string argName) { 00269 return argGiven(argName); 00270 } 00271 00272 /** Print out help for command-line arguments. */ 00273 virtual void printHelp(); 00274 00275 /** Save current state of the site and it's objects to the file previously 00276 set by setSaveFile or command line arguments. */ 00277 virtual void save(); 00278 00279 00280 /** Print the internal command-line argument map to stderr. */ 00281 void debugArgs(); 00282 }; 00283 00284 #endif //VOSDAEMON_HH