-rw-r--r-- | src/dudki.cc | 2 | ||||
-rw-r--r-- | src/process.cc | 3 |
2 files changed, 4 insertions, 1 deletions
diff --git a/src/dudki.cc b/src/dudki.cc index 91a3342..1f95be4 100644 --- a/src/dudki.cc +++ b/src/dudki.cc @@ -1,55 +1,57 @@ #include <unistd.h> #include <signal.h> #include <syslog.h> #include <errno.h> #include <iostream> #include <fstream> #include <stdexcept> +#include <cstring> +#include <stdlib.h> 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-2006 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"); diff --git a/src/process.cc b/src/process.cc index 4807b98..3e9cc2b 100644 --- a/src/process.cc +++ b/src/process.cc @@ -1,57 +1,58 @@ #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <signal.h> #include <pwd.h> #include <grp.h> #include <dirent.h> #include <sys/wait.h> #include <syslog.h> +#include <stdlib.h> #include <errno.h> #include <iostream> #include <fstream> #include <sstream> #include <stdexcept> #include <string> #include <vector> using namespace std; #include "process.h" #include "configuration.h" static multimap<string,pid_t> procpids; void process::check() const { if(!pidfile.empty()) { signal(0); }else if(!process_name.empty()) { if(procpids.empty()) gather_proc_info(); if(procpids.find(process_name)==procpids.end()) throw runtime_error("no such process"); } // XXX: or else? } void process::check(const string& id,configuration& config) { try { check(); patience = 0; }catch(exception& e) { if(patience>60) { // TODO: configurable patience = 0; }else{ if(patience<10) { // TODO: configurable syslog(LOG_NOTICE,"The process '%s' is down, trying to launch.",id.c_str()); do_notify(id,"Starting up", "The named process seems to be down. Dudki will try\n" "to revive it by running the specified command.\n", config); try { launch(id,config); }catch(exception& e) { syslog(LOG_ERR,"Error trying to launch process '%s': %s",id.c_str(),e.what()); } }else if(patience==10){ // TODO: configurable like the above syslog(LOG_NOTICE,"Giving up on process '%s' for a while",id.c_str()); do_notify(id,"Giving up", "After a number of attempts to relaunch the named process\n" "It still seems to be down. Dudki is giving up attempts\n" "to revive the process for a while.\n", @@ -67,97 +68,97 @@ void process::launch(const string& id,configuration& config) { gid_t gid = (gid_t)-1; if(!user.empty()) { struct passwd *ptmp = getpwnam(user.c_str()); if(ptmp) { uid = ptmp->pw_uid; gid = ptmp->pw_gid; }else{ errno=0; uid = strtol(user.c_str(),NULL,0); if(errno) throw runtime_error("Failed to resolve User value to uid"); } } if(!group.empty()) { struct group *gtmp = getgrnam(group.c_str()); if(gtmp) { gid = gtmp->gr_gid; }else{ errno = 0; gid = strtol(group.c_str(),NULL,0); if(errno) throw runtime_error("Failed to reslove Group value to gid"); } } pid_t p = fork(); if(p<0) throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to fork()"); if(!p) { // child try { setsid(); if(!group.empty()) { if(user.empty()) { if((getgid()!=gid) && setgid(gid)) throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to setgid()"); }else{ if(initgroups(user.c_str(),gid)) throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to initgroups()"); } } if(!chroot.empty()) { if(::chroot(chroot.c_str())) throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to chroot()"); } if(!user.empty()) { if((getuid()!=uid) && setuid(uid)) throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to setuid()"); } - char *argv[] = { "/bin/sh", "-c", (char*)restart_cmd.c_str(), NULL }; + char *argv[] = { const_cast<char*>("/bin/sh"), const_cast<char*>("-c"), (char*)restart_cmd.c_str(), NULL }; close(0); close(1); close(2); execv("/bin/sh",argv); }catch(exception& e) { syslog(LOG_ERR,"Error trying to launch process '%s': %s",id.c_str(),e.what()); } _exit(-1); } // parent int rv; if(waitpid(p,&rv,0)<0) throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to waitpid()"); } void process::do_notify(const string& id,const string& event,const string& description,configuration& config) { string the_notify; if(!notify.empty()) the_notify=notify; else if(!config.notify.empty()) the_notify=config.notify; else return; try { string::size_type colon = the_notify.find(':'); if(colon==string::npos) throw runtime_error("invalid notify action specification"); string nschema = the_notify.substr(0,colon); string ntarget = the_notify.substr(colon+1); if(nschema=="mailto") { notify_mailto(ntarget,id,event,description,config); }else throw runtime_error("unrecognized notification schema"); }catch(exception& e) { syslog(LOG_ERR,"Notification error: %s",e.what()); } } void process::notify_mailto(const string& email,const string& id,const string& event,const string& description,configuration& config) { int files[2]; if(pipe(files)) throw runtime_error("Failed to pipe()"); pid_t pid = vfork(); if(pid==-1) { close(files[0]); close(files[1]); throw runtime_error("Failed to vfork()"); } if(!pid) { // child |