69 |
/* -------------------------------------------------------------- Prototypes */ |
/* -------------------------------------------------------------- Prototypes */ |
70 |
|
|
71 |
|
|
72 |
static void do_free(); |
static void exec_alert_mail(Service_T s, Command_T c); |
73 |
static Command_T copy_command(Command_T); |
static void set_monit_environment(Service_T s, Command_T c); |
|
static Mail_T create_exec_alert_list(Service_T, Command_T); |
|
74 |
|
|
75 |
|
|
76 |
/* ------------------------------------------------------------------ Public */ |
/* ------------------------------------------------------------------ Public */ |
90 |
|
|
91 |
ASSERT(S); |
ASSERT(S); |
92 |
ASSERT(C); |
ASSERT(C); |
93 |
|
|
94 |
/* |
/* |
95 |
* Block SIGCHLD |
* Block SIGCHLD |
96 |
*/ |
*/ |
118 |
|
|
119 |
} else { |
} else { |
120 |
|
|
|
Command_T c= copy_command(C); |
|
|
Mail_T alert_list= create_exec_alert_list(S, C); |
|
121 |
|
|
122 |
/* |
/* |
123 |
* Reset all signals, so the child process is |
* Reset all signals, so the child process is |
131 |
signal(SIGUSR1, SIG_DFL); |
signal(SIGUSR1, SIG_DFL); |
132 |
signal(SIGPIPE, SIG_DFL); |
signal(SIGPIPE, SIG_DFL); |
133 |
|
|
|
/* Garbage collect */ |
|
|
do_free(); |
|
|
|
|
134 |
/* |
/* |
135 |
* Reset to the original umask so programs will inherit the |
* Reset to the original umask so programs will inherit the |
136 |
* same file creation mask monit was started with |
* same file creation mask monit was started with |
145 |
/* |
/* |
146 |
* Switch uid and gid if requested |
* Switch uid and gid if requested |
147 |
*/ |
*/ |
148 |
if(c->has_gid) { |
if(C->has_gid) { |
149 |
if(0 != setgid(c->gid)) { |
if(0 != setgid(C->gid)) { |
150 |
log("Failed to change gid to '%d' for '%s'\n", |
log("Failed to change gid to '%d' for '%s'\n", |
151 |
c->gid, c->arg[0]); |
C->gid, C->arg[0]); |
152 |
} |
} |
153 |
} |
} |
154 |
if(c->has_uid) { |
if(C->has_uid) { |
155 |
if(0 != setuid(c->uid)) { |
if(0 != setuid(C->uid)) { |
156 |
log("Failed to change uid to '%d' for '%s'\n", |
log("Failed to change uid to '%d' for '%s'\n", |
157 |
c->uid, c->arg[0]); |
C->uid, C->arg[0]); |
158 |
} |
} |
159 |
} |
} |
160 |
|
|
161 |
|
/* |
162 |
|
* Set the MONIT_xxx environment variables |
163 |
|
*/ |
164 |
|
set_monit_environment(S, C); |
165 |
|
|
166 |
/* |
/* |
167 |
* The exec statement done by the second child |
* The exec statement done by the second child |
168 |
*/ |
*/ |
169 |
(void) execv(c->arg[0], c->arg); |
(void) execv(C->arg[0], C->arg); |
170 |
sendmail(alert_list); |
exec_alert_mail(S, C); |
171 |
log("Could not execute %s\n", c->arg[0]); |
log("Could not execute %s\n", C->arg[0]); |
|
gc_mail_list(&alert_list); |
|
172 |
_exit(1); |
_exit(1); |
173 |
|
|
174 |
} |
} |
199 |
|
|
200 |
|
|
201 |
/* |
/* |
202 |
* Free memory for the child process |
* Send an exec failed alert mail to those mail objects that has |
203 |
|
* registred interest for restart notification. |
204 |
*/ |
*/ |
205 |
static void do_free() { |
static void exec_alert_mail(Service_T s, Command_T c) { |
|
|
|
|
gc(); |
|
|
destroy_hosts_allow(); |
|
|
free(Run.controlfile); |
|
|
free(Run.pidfile); |
|
|
free(Run.statefile); |
|
|
free(Run.logfile); |
|
|
free(Run.localhostname); |
|
|
free(Run.Env.user); |
|
|
free(Run.Env.home); |
|
|
free(Run.Env.cwd); |
|
|
free(Run.Auth.uname); |
|
|
free(Run.Auth.passwd); |
|
|
free(Run.MailFormat.from); |
|
|
free(Run.MailFormat.subject); |
|
|
free(Run.MailFormat.message); |
|
|
free(Run.bind_addr); |
|
|
/* Run.mailserver is not freed since it's used in exec alert */ |
|
206 |
|
|
207 |
|
Mail_T a= s->maillist; |
208 |
|
|
209 |
|
for(; a; a= a->next) |
210 |
|
if(a->alert_on_restart) { |
211 |
|
struct mymail m; |
212 |
|
char message[STRLEN]; |
213 |
|
|
214 |
|
m.to= a->to; |
215 |
|
m.from= "monit@localhost"; |
216 |
|
m.subject= "monit alert -- exec error"; |
217 |
|
snprintf(message, STRLEN, |
218 |
|
"Could not execute program '%s' for service %s\n\n" |
219 |
|
"Your faithful employee,\nmonit", |
220 |
|
c->arg[0]?c->arg[0]:"null", s->name); |
221 |
|
m.message= message; |
222 |
|
sendmail(&m); |
223 |
|
} |
224 |
|
|
225 |
} |
} |
226 |
|
|
227 |
|
|
228 |
/* |
/* |
229 |
* Return a deep copy of the given command object |
* Setup the environment with special MONIT_xxx variables. The program |
230 |
|
* executed may use such variable for various purposes. |
231 |
*/ |
*/ |
232 |
static Command_T copy_command(Command_T C) { |
static void set_monit_environment(Service_T s, Command_T c) { |
233 |
|
|
234 |
int i; |
int i; |
235 |
Command_T P= NEW(P); |
char buf[10][STRLEN]; |
236 |
|
|
237 |
for(i= 0; C->arg[i]; i++) |
snprintf(buf[0], STRLEN, "MONIT_PROGRAM_PID=%d", is_process_running(s)); |
238 |
P->arg[i]= xstrdup(C->arg[i]); |
snprintf(buf[1], STRLEN, "MONIT_PROGRAM=%s", c->arg[0]); |
239 |
P->arg[i]= NULL; |
snprintf(buf[2], STRLEN, "MONIT_DATE=%s", get_RFC822date(NULL)); |
240 |
|
snprintf(buf[3], STRLEN, "MONIT_HOST=%s", Run.localhostname); |
241 |
P->uid= C->uid; |
snprintf(buf[4], STRLEN, "MONIT_PROGRAM_MEMORY=%ld", s->procinfo->mem_kbyte); |
242 |
P->gid= C->gid; |
snprintf(buf[5], STRLEN, "MONIT_PROGRAM_CHILDREN=%d", s->procinfo->children); |
243 |
P->has_uid= C->has_uid; |
snprintf(buf[6], STRLEN, "MONIT_PROGRAM_CPU_PERCENT=%d", |
244 |
P->has_gid= C->has_gid; |
s->procinfo->cpu_percent); |
|
|
|
|
return P; |
|
245 |
|
|
246 |
} |
buf[7][0]= 0; |
|
|
|
|
|
|
|
/* |
|
|
* Create a list of mail addresses to send mail to in case the exec |
|
|
* fails. Only mail objects that has registred interest for restart |
|
|
* notification is used. |
|
|
*/ |
|
|
static Mail_T create_exec_alert_list(Service_T s, Command_T c) { |
|
247 |
|
|
248 |
Mail_T l= NULL; |
for(i= 0; *buf[i]; i++) |
249 |
Mail_T h= s->maillist; |
putenv(buf[i]); |
|
|
|
|
for(; h; h= h->next) |
|
|
if(h->alert_on_restart) { |
|
|
|
|
|
Mail_T n= NEW(n); |
|
|
char *message= xmalloc(STRLEN); |
|
|
|
|
|
n->to= xstrdup(h->to); |
|
|
n->from= xstrdup("monit@localhost"); |
|
|
n->subject= xstrdup("monit alert -- exec error"); |
|
|
snprintf(message, STRLEN, |
|
|
"NOTE, THIS EMAIL TAKES PRECEDENCE OVER SUBSEQUENT RESTART ALERTS\n\n" |
|
|
"Could not execute program '%s' for service %s\n\n" |
|
|
"Your faithful employee,\nmonit", |
|
|
c->arg[0]?c->arg[0]:"null", s->name); |
|
|
n->message= message; |
|
|
n->next= l; |
|
|
l= n; |
|
|
|
|
|
} |
|
250 |
|
|
|
return l; |
|
|
|
|
251 |
} |
} |