void Command_vSetEnv(T C, const char *env, ...) { assert(C); if (STR_DEF(env)) { va_list ap; char *s, *n, *v, *t; va_start(ap, env); n = s = Str_vcat(env, ap); va_end(ap); while ((v = strchr(n, '='))) { *(v++) = 0; t = strchr(v, ';'); if (t) *(t++) = 0; Command_setEnv(C, Str_trim(n), Str_trim(v)); if (t) n = t; else break; } FREE(s); } }
static int _commandExecute(Service_T S, command_t c, char *msg, int msglen, int64_t *timeout) { ASSERT(S); ASSERT(c); ASSERT(msg); msg[0] = 0; int status = -1; Command_T C = NULL; TRY { // May throw exception if the program doesn't exist (was removed while Monit was up) C = Command_new(c->arg[0], NULL); } ELSE { snprintf(msg, msglen, "Program %s failed: %s", c->arg[0], Exception_frame.message); } END_TRY; if (C) { for (int i = 1; i < c->length; i++) Command_appendArgument(C, c->arg[i]); if (c->has_uid) Command_setUid(C, c->uid); if (c->has_gid) Command_setGid(C, c->gid); Command_setEnv(C, "MONIT_DATE", Time_string(Time_now(), (char[26]){})); Command_setEnv(C, "MONIT_SERVICE", S->name); Command_setEnv(C, "MONIT_HOST", Run.system->name); Command_setEnv(C, "MONIT_EVENT", c == S->start ? "Started" : c == S->stop ? "Stopped" : "Restarted"); Command_setEnv(C, "MONIT_DESCRIPTION", c == S->start ? "Started" : c == S->stop ? "Stopped" : "Restarted"); if (S->type == Service_Process) { Command_vSetEnv(C, "MONIT_PROCESS_PID", "%d", Util_isProcessRunning(S, false)); Command_vSetEnv(C, "MONIT_PROCESS_MEMORY", "%ld", S->inf->priv.process.mem_kbyte); Command_vSetEnv(C, "MONIT_PROCESS_CHILDREN", "%d", S->inf->priv.process.children); Command_vSetEnv(C, "MONIT_PROCESS_CPU_PERCENT", "%d", S->inf->priv.process.cpu_percent); } Process_T P = Command_execute(C); Command_free(&C); if (P) { do { Time_usleep(RETRY_INTERVAL); *timeout -= RETRY_INTERVAL; } while ((status = Process_exitStatus(P)) < 0 && *timeout > 0 && ! (Run.flags & Run_Stopped)); if (*timeout <= 0) snprintf(msg, msglen, "Program %s timed out", c->arg[0]); int n, total = 0; char buf[STRLEN]; do { if ((n = _getOutput(Process_getErrorStream(P), buf, sizeof(buf))) <= 0) n = _getOutput(Process_getInputStream(P), buf, sizeof(buf)); if (n > 0) { buf[n] = 0; DEBUG("%s", buf); // Report the first message (override existing plain timeout message if some program output is available) if (! total) snprintf(msg, msglen, "%s: %s%s", c->arg[0], *timeout <= 0 ? "Program timed out -- " : "", buf); total += n; } } while (n > 0 && Run.debug && total < 2048); // Limit the debug output (if the program will have endless output, such as 'yes' utility, we have to stop at some point to not spin here forever) Process_free(&P); // Will kill the program if still running } }