summaryrefslogtreecommitdiffabout
path: root/src/dudki.cc
Side-by-side diff
Diffstat (limited to 'src/dudki.cc') (more/less context) (show whitespace changes)
-rw-r--r--src/dudki.cc5
1 files changed, 5 insertions, 0 deletions
diff --git a/src/dudki.cc b/src/dudki.cc
index 9562079..c966695 100644
--- a/src/dudki.cc
+++ b/src/dudki.cc
@@ -1,87 +1,89 @@
#include <unistd.h>
#include <signal.h>
#include <syslog.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#include <stdexcept>
using namespace std;
#include "configuration.h"
#include "util.h"
#include "config.h"
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif
#ifndef DEFAULT_CONF_FILE
# define DEFAULT_CONF_FILE "/etc/dudki.conf"
#endif
#define PHEADER PACKAGE " Version " VERSION
#define PCOPY "Copyright (c) 2004 Klever Group"
bool finishing = false;
bool restarting = false;
static char **_argv = NULL;
static void lethal_signal_handler(int signum) {
syslog(LOG_NOTICE,"Lethal signal received. Terminating.");
finishing = true;
}
static void sighup_handler(int signum) {
syslog(LOG_NOTICE,"SUGHUP received, reloading.");
restarting = finishing = true;
}
void check_herd(configuration& config) {
+ process::prepare_herd();
for(processes_t::iterator i=config.processes.begin();i!=config.processes.end();++i)
i->second.check(i->first,config);
+ process::unprepare_herd();
}
void signal_self(const configuration& config,int signum) {
ifstream pids(config.pidfile.c_str(),ios::in);
if(!pids)
throw runtime_error("Can't detect running instance");
pid_t pid = 0;
pids >> pid;
if(!pid)
throw runtime_error("Can't detect running instance");
if(pid==getpid())
throw 0;
if(kill(pid,signum))
throw runtime_error("Failed to signal running instance");
}
int main(int argc,char **argv) {
try {
_argv = new char*[argc+1];
if(!_argv)
throw runtime_error("memory allocation problem at the very start");
memmove(_argv,argv,sizeof(*_argv)*(argc+1));
string config_file = DEFAULT_CONF_FILE;
enum {
op_default,
op_work,
op_signal,
op_ensure,
op_test
} op = op_default;
int op_signum = 0;
while(true) {
#define SHORTOPTSTRING "f:hVLrkcets:"
#ifdef HAVE_GETOPT_LONG
static struct option opts[] = {
{ "help", no_argument, 0, 'h' },
{ "usage", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'V' },
{ "license", no_argument, 0, 'L' },
{ "config", required_argument, 0, 'f' },
{ "kill", no_argument, 0, 'k' },
{ "reload", no_argument, 0, 'r' },
{ "signal", required_argument, 0, 's' },
{ "check", no_argument, 0, 'c' },
{ "ensure", no_argument, 0, 'e' },
{ "test", no_argument, 0, 't' },
{ NULL, 0, 0, 0 }
};
@@ -175,97 +177,100 @@ int main(int argc,char **argv) {
if(op!=op_default) {
cerr << "Can't obey two or more orders at once" << endl;
exit(1);
}
op = op_test;
break;
case 's':
if(op!=op_default) {
cerr << "Can't obey two or more orders at once" << endl;
exit(1);
}
op = op_signal;
errno = 0;
op_signum = strtol(optarg,NULL,0);
if(errno) {
cerr << "Can't obtain the signal value" << endl;
exit(1);
}
break;
default:
cerr << "Huh??" << endl;
exit(1);
break;
}
}
const char *sid = *argv;
const char *t;
while(t = index(sid,'/')) {
sid = t; sid++;
}
openlog(sid,LOG_CONS|LOG_PERROR|LOG_PID,LOG_DAEMON);
configuration config;
config.parse(config_file);
switch(op) {
case op_test:
cerr << "Configuration OK" << endl;
break;
case op_signal:
try {
if(optind>=argc) {
signal_self(config,op_signum);
}else{
int failures = 0;
for(int narg=optind;narg<argc;narg++) {
try {
processes_t::const_iterator i = config.processes.find(argv[narg]);
if(i==config.processes.end())
throw runtime_error("no such process configured");
+ if(op_signum)
i->second.signal(op_signum);
+ else
+ i->second.check();
}catch(exception& e) {
cerr << "dudki(" << argv[narg] << "): " << e.what() << endl;
failures++;
}
}
if(failures)
throw runtime_error("not all processes have been successfully signaled");
}
if(!op_signum)
exit(0);
}catch(exception& e) {
if(!op_signum)
exit(1);
}
case op_ensure:
try {
signal_self(config,0);
break;
}catch(exception& e) {
syslog(LOG_NOTICE,"The dudki process is down, taking its place");
config.daemonize = true;
}catch(int zero) {
// we throw zero in case we're ensuring that this very process is running.
// we don't have to daemonize if we're daemonic.
config.daemonize = false;
}
case op_default:
case op_work:
{
if(config.daemonize) {
pid_t pf = fork();
if(pf<0)
throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to fork()");
if(pf) {
_exit(0);
}
}
pid_file pidfile;
pidfile.set(config.pidfile);
signal(SIGINT,lethal_signal_handler);
signal(SIGABRT,lethal_signal_handler);
signal(SIGTERM,lethal_signal_handler);
signal(SIGHUP,sighup_handler);
sigset_t sset;
sigemptyset(&sset);
sigaddset(&sset,SIGINT); sigaddset(&sset,SIGABRT);
sigaddset(&sset,SIGTERM); sigaddset(&sset,SIGHUP);
sigprocmask(SIG_UNBLOCK,&sset,NULL);