summaryrefslogtreecommitdiffabout
path: root/src/process.cc
authorMichael Krelin <hacker@klever.net>2004-07-15 04:13:35 (UTC)
committer Michael Krelin <hacker@klever.net>2004-07-15 04:13:35 (UTC)
commit5e437102c59f4544e3803598eabcb643d403272d (patch) (unidiff)
tree7703657f2dac2fd9fb2b2a1f453ca2f30227efa1 /src/process.cc
parent4f8a6f291a231410a03c438bc9d63a7beb861e7b (diff)
downloaddudki-5e437102c59f4544e3803598eabcb643d403272d.zip
dudki-5e437102c59f4544e3803598eabcb643d403272d.tar.gz
dudki-5e437102c59f4544e3803598eabcb643d403272d.tar.bz2
initgroups() call added when changing uid
Diffstat (limited to 'src/process.cc') (more/less context) (show whitespace changes)
-rw-r--r--src/process.cc17
1 files changed, 10 insertions, 7 deletions
diff --git a/src/process.cc b/src/process.cc
index fda35e8..bfab311 100644
--- a/src/process.cc
+++ b/src/process.cc
@@ -13,136 +13,139 @@
13using namespace std; 13using namespace std;
14#include "process.h" 14#include "process.h"
15#include "configuration.h" 15#include "configuration.h"
16 16
17void process::check(const string& id,configuration& config) { 17void process::check(const string& id,configuration& config) {
18 bool running = false; 18 bool running = false;
19 ifstream pids(pidfile.c_str(),ios::in); 19 ifstream pids(pidfile.c_str(),ios::in);
20 if(pids) { 20 if(pids) {
21 pid_t pid = 0; 21 pid_t pid = 0;
22 pids >> pid; 22 pids >> pid;
23 pids.close(); 23 pids.close();
24 if(pid) { 24 if(pid) {
25 if(!kill(pid,0)) { 25 if(!kill(pid,0)) {
26 running = true; 26 running = true;
27 } 27 }
28 } 28 }
29 } 29 }
30 if(running){ 30 if(running){
31 patience = 0; 31 patience = 0;
32 }else{ 32 }else{
33 if(patience>60) { // TODO: configurable 33 if(patience>60) { // TODO: configurable
34 patience = 0; 34 patience = 0;
35 }else{ 35 }else{
36 if(patience<10) { // TODO: configurable 36 if(patience<10) { // TODO: configurable
37 syslog(LOG_NOTICE,"The process '%s' is down, trying to launch.",id.c_str()); 37 syslog(LOG_NOTICE,"The process '%s' is down, trying to launch.",id.c_str());
38 do_notify(id,"Starting up", 38 do_notify(id,"Starting up",
39 "The named process seems to be down. Dudki will try\n" 39 "The named process seems to be down. Dudki will try\n"
40 "to revive it by running the specified command.\n", 40 "to revive it by running the specified command.\n",
41 config); 41 config);
42 try { 42 try {
43 launch(id,config); 43 launch(id,config);
44 }catch(exception& e) { 44 }catch(exception& e) {
45 syslog(LOG_ERR,"Error trying to launch process '%s': %s",id.c_str(),e.what()); 45 syslog(LOG_ERR,"Error trying to launch process '%s': %s",id.c_str(),e.what());
46 } 46 }
47 }else if(patience==10){ // TODO: configurable like the above 47 }else if(patience==10){ // TODO: configurable like the above
48 syslog(LOG_NOTICE,"Giving up on process '%s' for a while",id.c_str()); 48 syslog(LOG_NOTICE,"Giving up on process '%s' for a while",id.c_str());
49 do_notify(id,"Giving up", 49 do_notify(id,"Giving up",
50 "After a number of attempts to relaunch the named process\n" 50 "After a number of attempts to relaunch the named process\n"
51 "It still seems to be down. Dudki is giving up attempts\n" 51 "It still seems to be down. Dudki is giving up attempts\n"
52 "to revive the process for a while.\n", 52 "to revive the process for a while.\n",
53 config); 53 config);
54 } 54 }
55 patience++; 55 patience++;
56 } 56 }
57 } 57 }
58} 58}
59 59
60void process::launch(const string& id,configuration& config) { 60void process::launch(const string& id,configuration& config) {
61 uid_t uid = 0; 61 uid_t uid = (uid_t)-1;
62 gid_t gid = (gid_t)-1;
62 if(!user.empty()) { 63 if(!user.empty()) {
63 struct passwd *ptmp = getpwnam(user.c_str()); 64 struct passwd *ptmp = getpwnam(user.c_str());
64 if(ptmp) { 65 if(ptmp) {
65 uid = ptmp->pw_uid; 66 uid = ptmp->pw_uid;
67 gid = ptmp->pw_gid;
66 }else{ 68 }else{
67 errno=0; 69 errno=0;
68 uid = strtol(user.c_str(),NULL,0); 70 uid = strtol(user.c_str(),NULL,0);
69 if(errno) 71 if(errno)
70 throw runtime_error("Failed to resolve User value to uid"); 72 throw runtime_error("Failed to resolve User value to uid");
71 } 73 }
72 } 74 }
73 gid_t gid = 0;
74 if(!group.empty()) { 75 if(!group.empty()) {
75 struct group *gtmp = getgrnam(group.c_str()); 76 struct group *gtmp = getgrnam(group.c_str());
76 if(gtmp) { 77 if(gtmp) {
77 gid = gtmp->gr_gid; 78 gid = gtmp->gr_gid;
78 }else{ 79 }else{
79 errno = 0; 80 errno = 0;
80 gid = strtol(group.c_str(),NULL,0); 81 gid = strtol(group.c_str(),NULL,0);
81 if(errno) 82 if(errno)
82 throw runtime_error("Failed to reslove Group value to gid"); 83 throw runtime_error("Failed to reslove Group value to gid");
83 } 84 }
84 } 85 }
85 pid_t p = fork(); 86 pid_t p = fork();
86 if(p<0) 87 if(p<0)
87 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to fork()"); 88 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to fork()");
88 if(!p) { 89 if(!p) {
89 // child 90 // child
90 try { 91 try {
91 setsid(); 92 setsid();
93 if(user.empty()) {
94 if((getgid()!=gid) && setgid(gid))
95 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to setgid()");
96 }else{
97 if(initgroups(user.c_str(),gid))
98 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to initgroups()");
99 }
92 if(!chroot.empty()) { 100 if(!chroot.empty()) {
93 if(::chroot(chroot.c_str())) 101 if(::chroot(chroot.c_str()))
94 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to chroot()"); 102 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to chroot()");
95 } 103 }
96 if(!group.empty()) {
97 // TODO: initgroups()?
98 if((getgid()!=gid) && setgid(gid))
99 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to setgid()");
100 }
101 if(!user.empty()) { 104 if(!user.empty()) {
102 if((getuid()!=uid) && setuid(uid)) 105 if((getuid()!=uid) && setuid(uid))
103 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to setuid()"); 106 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to setuid()");
104 } 107 }
105 char *argv[] = { "/bin/sh", "-c", (char*)restart_cmd.c_str(), NULL }; 108 char *argv[] = { "/bin/sh", "-c", (char*)restart_cmd.c_str(), NULL };
106 close(0); close(1); close(2); 109 close(0); close(1); close(2);
107 execv("/bin/sh",argv); 110 execv("/bin/sh",argv);
108 }catch(exception& e) { 111 }catch(exception& e) {
109 syslog(LOG_ERR,"Error trying to launch process '%s': %s",id.c_str(),e.what()); 112 syslog(LOG_ERR,"Error trying to launch process '%s': %s",id.c_str(),e.what());
110 } 113 }
111 _exit(-1); 114 _exit(-1);
112 } 115 }
113 // parent 116 // parent
114 int rv; 117 int rv;
115 if(waitpid(p,&rv,0)<0) 118 if(waitpid(p,&rv,0)<0)
116 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to waitpid()"); 119 throw runtime_error(string(__PRETTY_FUNCTION__)+": failed to waitpid()");
117} 120}
118 121
119void process::do_notify(const string& id,const string& event,const string& description,configuration& config) { 122void process::do_notify(const string& id,const string& event,const string& description,configuration& config) {
120 string the_notify; 123 string the_notify;
121 if(!notify.empty()) 124 if(!notify.empty())
122 the_notify=notify; 125 the_notify=notify;
123 else if(!config.notify.empty()) 126 else if(!config.notify.empty())
124 the_notify=config.notify; 127 the_notify=config.notify;
125 else 128 else
126 return; 129 return;
127 try { 130 try {
128 string::size_type colon = the_notify.find(':'); 131 string::size_type colon = the_notify.find(':');
129 if(colon==string::npos) 132 if(colon==string::npos)
130 throw runtime_error("invalid notify action specification"); 133 throw runtime_error("invalid notify action specification");
131 string nschema = the_notify.substr(0,colon); 134 string nschema = the_notify.substr(0,colon);
132 string ntarget = the_notify.substr(colon+1); 135 string ntarget = the_notify.substr(colon+1);
133 if(nschema=="mailto") { 136 if(nschema=="mailto") {
134 notify_mailto(ntarget,id,event,description,config); 137 notify_mailto(ntarget,id,event,description,config);
135 }else 138 }else
136 throw runtime_error("unrecognized notification schema"); 139 throw runtime_error("unrecognized notification schema");
137 }catch(exception& e) { 140 }catch(exception& e) {
138 syslog(LOG_ERR,"Notification error: %s",e.what()); 141 syslog(LOG_ERR,"Notification error: %s",e.what());
139 } 142 }
140} 143}
141 144
142void process::notify_mailto(const string& email,const string& id,const string& event,const string& description,configuration& config) { 145void process::notify_mailto(const string& email,const string& id,const string& event,const string& description,configuration& config) {
143 int files[2]; 146 int files[2];
144 if(pipe(files)) 147 if(pipe(files))
145 throw runtime_error("Failed to pipe()"); 148 throw runtime_error("Failed to pipe()");
146 pid_t pid = vfork(); 149 pid_t pid = vfork();
147 if(pid==-1) { 150 if(pid==-1) {
148 close(files[0]); 151 close(files[0]);