-rw-r--r-- | NEWS.xml | 1 | ||||
-rw-r--r-- | src/process.cc | 32 |
2 files changed, 22 insertions, 11 deletions
@@ -1,18 +1,19 @@ <?xml version="1.0" encoding="us-ascii"?> <news> <version version="0.2.1"> <ni>do not act -e when doing -r</ni> + <ni>proper handling of <kbd>ProcessName</kbd> on <kbd>FreeBSD</kbd></ni> </version> <version version="0.2" date="July 24th, 2004"> <ni>now dudki sends arbitrary signals to the processes being monitored from the command line</ni> <ni>detection of running processes which do not keep pidfiles, using process name</ni> </version> <version version="0.1" date="July 21st, 2004"> <ni><kbd>initgroups()</kbd> called before executing <kbd>RestartCommand</kbd></ni> <ni>more civilized way of restarting on <kbd>SIGHUP</kbd></ni> <ni>minor changes to build process</ni> </version> <version version="0.0" date="July 11th, 2004"> <ni>Initial release</ni> </version> </news> diff --git a/src/process.cc b/src/process.cc index 8a5b5d2..96c874f 100644 --- a/src/process.cc +++ b/src/process.cc @@ -156,130 +156,140 @@ void process::notify_mailto(const string& email,const string& id,const string& e close(files[0]); close(files[1]); throw runtime_error("Failed to vfork()"); } if(!pid) { // child if(dup2(files[0],0)!=0) _exit(-1); close(1); close(files[0]); close(files[1]); execl("/usr/sbin/sendmail","usr/sbin/sendmail","-i",email.c_str(),NULL); _exit(-1); } // parent close(files[0]); FILE *mta = fdopen(files[1],"w"); for(headers_t::const_iterator i=mailto_headers.begin();i!=mailto_headers.end();++i) { fprintf(mta,"%s: %s\n",i->first.c_str(),i->second.c_str()); } for(headers_t::const_iterator i=config.mailto_headers.begin();i!=config.mailto_headers.end();++i) { if(mailto_headers.find(i->first)!=mailto_headers.end()) continue; fprintf(mta,"%s: %s\n",i->first.c_str(),i->second.c_str()); } fprintf(mta, "Subject: [%s] %s\n\n" "%s\n" "---\n" "This message was sent automatically by the 'dudki' daemon\n", id.c_str(), event.c_str(), description.c_str() ); fclose(mta); int status; waitpid(pid,&status,0); // TODO: check the return code } void process::signal(int signum) const { if(!pidfile.empty()) { ifstream pids(pidfile.c_str(),ios::in); if(!pids) throw runtime_error("no pidfile found"); pid_t pid = 0; pids >> pid; pids.close(); if(!pid) throw runtime_error("no pid in pidfile"); if(kill(pid,signum)) throw runtime_error("failed to signal process"); }else if(!process_name.empty()) { if(procpids.empty()) gather_proc_info(); pair<multimap<string,pid_t>::const_iterator,multimap<string,pid_t>::const_iterator> range = procpids.equal_range(process_name); int count = 0; for(multimap<string,pid_t>::const_iterator i=range.first;i!=range.second;++i) { pid_t pid = i->second; if(kill(i->second,signum)) throw runtime_error("failed to signal process"); count++; } if(!count) throw runtime_error("no running instance detected"); }else throw runtime_error("nothing is known about the process"); } void process::prepare_herd() { procpids.clear(); } void process::unprepare_herd() { procpids.clear(); } void process::gather_proc_info() { vector<pid_t> allpids; DIR *pd = opendir("/proc"); if(!pd) throw runtime_error("failed to open /proc"); struct dirent *pde; pid_t selfpid = getpid(); while(pde=readdir(pd)) { errno=0; pid_t pid = atoi(pde->d_name); if((!pid) || pid==selfpid) continue; allpids.push_back(pid); } closedir(pd); char s[256]; procpids.clear(); for(vector<pid_t>::const_iterator i=allpids.begin();i!=allpids.end();++i) { int r = snprintf(s,sizeof(s),"/proc/%d/stat",*i); if(r>=sizeof(s) || r<1) continue; string cmd; ifstream ss(s,ios::in); - if(!ss) - continue; - getline(ss,cmd); - string::size_type op = cmd.find('('); - if(op==string::npos) - continue; - cmd.erase(0,op+1); - string::size_type cp = cmd.find(')'); - if(cp==string::npos) - continue; - cmd.erase(cp); + if(ss) { + getline(ss,cmd); + string::size_type op = cmd.find('('); + if(op==string::npos) + continue; + cmd.erase(0,op+1); + string::size_type cp = cmd.find(')'); + if(cp==string::npos) + continue; + cmd.erase(cp); + }else{ + r = snprintf(s,sizeof(s),"/proc/%d/status",*i); + if(r>=sizeof(s) || r<1) + continue; + ifstream ss(s,ios::in); + if(!ss) + continue; + ss >> cmd; + if(cmd.empty()) + continue; + } r = snprintf(s,sizeof(s),"/proc/%d/cmdline",*i); if(r>=sizeof(s) || r<1) continue; ifstream cs(s,ios::binary); if(!cs) continue; string command; while(cs) { string cl; getline(cs,cl,(char)0); string::size_type lsl = cl.rfind('/'); if(lsl!=string::npos) cl.erase(0,lsl+1); if(cl.substr(0,cmd.length())==cmd) { command = cl; break; } } procpids.insert(pair<string,pid_t>(cmd,*i)); if((!command.empty()) && cmd!=command) procpids.insert(pair<string,pid_t>(command,*i)); } } |