28 #define NEED_PACKAGE_INFO
37 # include <iostream.h>
41 #ifdef HAVE_STD_IOSTREAM
52 #ifdef HAVE_SYS_TYPES_H
53 # include <sys/types.h>
56 #ifdef HAVE_SYS_STAT_H
57 # include <sys/stat.h>
85 #define STRERR_FILE_LINE strerror(errno)<<" "<<__FILE__<<":"<<__LINE__
96 Daemon::Daemon(
int&,
char**&)
119 DaemonImpl::DaemonImpl(){}
122 DaemonImpl::~DaemonImpl()
131 void DaemonImpl::tracefile(
const char* val)
133 _tracefile=::strdup(val);
137 void DaemonImpl::foreground(
bool val)
143 void DaemonImpl::pidfile(
const char* val)
145 string pidfileStr =val;
146 if(pidfileStr[0]!=
'/')
147 pidfileStr=string(
"/var/run/")+pidfileStr;
148 DaemonImpl::_pidfile=::strdup(pidfileStr.c_str());
152 void DaemonImpl::initialize(
int&,
char**&)
158 void DaemonImpl::daemonize()
167 cerr<<
"Failed to set exit handler."<<endl;
178 checkPidfileOrShutdown();
192 if(_tracefile && _tracefile[0]!=
'\0')
194 redirectStreamsTo(_tracefile);
198 #ifndef HAVE_OMNIORB3
200 ::openlog(
PACKAGE_NAME ": ",LOG_PID|LOG_PERROR,LOG_DAEMON);
207 cerr<<
"You must use option -t to set the file for trace messages."
208 "\n(This is because omniORB3 cannot redirect messages to syslog.)"<<endl;
215 void DaemonImpl::runningOk()
231 redirectStreamsTo(
"/dev/null");
236 void DaemonImpl::shutdown(
int status)
239 if(_havePidfile && _pidfile && 0!=::unlink(_pidfile))
241 cerr<<
"Failed to remove pidfile '"<<_pidfile<<
"': "
258 notifyParent(status);
265 void DaemonImpl::log(
const char* message)
267 int priority =LOG_INFO;
271 const char* mPos( message );
272 const char* pPos(
"omniEvents: " );
273 while(*mPos && (*mPos==*pPos || *pPos==
':'))
281 case '!': priority=LOG_ERR;
282 case ':': message=mPos;
288 ::syslog(priority,
"%s",message);
293 cerr<<message<<flush;
298 void DaemonImpl::checkPidfileOrShutdown()
304 pid_t pidFromFile =0;
306 if(0==::stat(_pidfile,&buf))
308 if(!S_ISREG(buf.st_mode))
310 cerr<<
"Pidfile '"<<_pidfile<<
"' is not a regular file."<<endl;
315 ifstream infile(_pidfile);
321 cerr<<
"Failed to read pidfile'"<<_pidfile<<
"'."<<endl;
325 else if(errno!=ENOENT)
327 cerr<<
"Failed to stat pidfile '"<<_pidfile<<
"': "
335 if(0==::kill(pidFromFile,0))
337 cerr<<
"Quitting because process "<<pidFromFile
338 <<
" defined in pidfile '"<<_pidfile<<
"'"
339 <<
" is already running."<<endl;
342 else if(errno!=ESRCH)
344 cerr<<
"Failed to test for process "<<pidFromFile
345 <<
" defined in pidfile '"<<_pidfile<<
"': "
353 void DaemonImpl::writePidfile()
359 #ifdef FSTREAM_OPEN_PROT
360 ofstream outfile(_pidfile,ios::out|ios::trunc,0644);
362 ofstream outfile(_pidfile,ios::out|ios::trunc);
364 outfile<<::getpid()<<endl;
371 cerr<<
"Failed to write pidfile '"<<_pidfile<<
"'."<<endl;
378 void DaemonImpl::fork()
380 if( ::pipe(_pipe) <0)
403 ::_exit(waitForChild());
417 pid_t sid =::setsid();
426 void DaemonImpl::redirectStreamsTo(
const char* filename)
433 if(openFileFor(
STDOUT_FILENO,filename,O_WRONLY|O_CREAT|O_APPEND)<0)
438 if(openFileFor(STDERR_FILENO,filename,O_WRONLY|O_CREAT|O_APPEND)<0)
446 int DaemonImpl::openFileFor(
int fd,
const char* filename,
int flags)
448 int newfd =::open(filename,flags,0644);
453 if(::dup2(newfd,fd)<0)
460 int DaemonImpl::waitForChild()
463 ssize_t bytes =::read(_pipe[
PIPE_READ],&status,
sizeof(status));
464 if(bytes<
sizeof(status))
477 void DaemonImpl::notifyParent(
int status)
479 ssize_t r =::write(_pipe[
PIPE_WRITE],&status,
sizeof(status));
483 cerr<<
"read() failed while writing return value to pipe: "
486 cerr<<
"write() too short while writing return value from pipe: "
DaemonImpl daemon
Singleton - only at file scope.
void shutdown2(int s, void *)
Param to on_exit().
void shutdown0(void)
Param to atexit().
void setLogFunction(void(*logFunction)(const char *))
Utility class that contains various methods for running omniEvents as a Unix daemon.
void runningOk()
Called to signal that all startup operations have completed OK.
void foreground(bool val)
Set _foreground.
void tracefile(const char *val)
Set _tracefile.
int _pipe[2]
Unnamed pipe for child->parent comms.
void pidfile(const char *val)
Set _pidfile.
char * _tracefile
The tracefile name (if any).
bool _foreground
TRUE for debug mode (run in foreground)
void daemonize()
Puts the current process into the background.
bool _haveSyslog
Should we close syslog before quitting?
char * _pidfile
The pidfile name (if any).
void shutdown(int status)
Exit handler called (indirectly) by ::on_exit() - shuts down the daemon.
bool _haveParent
Is there a parent for us to clean up?
bool _havePidfile
Is there a pidfile for us to clean up?