/** * Check to see if we should try to start/stop service * @param S A service name as stated in the config file * @param A A string describing the action to execute * @return FALSE for error, otherwise TRUE */ int control_service_string(const char *S, const char *A) { int a; ASSERT(S); ASSERT(A); if ((a = Util_getAction(A)) == ACTION_IGNORE) { LogError("%s: service '%s' -- invalid action %s\n", prog, S, A); return FALSE; } return control_service(S, a); }
/** * Pass on to methods in http/cervlet.c to start/stop services * @param S A service name as stated in the config file * @param action A string describing the action to execute * @return FALSE for error, otherwise TRUE */ int control_service_daemon(const char *S, const char *action) { int rv = FALSE; int status, content_length = 0; Socket_T socket; char *auth; char buf[STRLEN]; ASSERT(S); ASSERT(action); if (Util_getAction(action) == ACTION_IGNORE) { LogError("Cannot %s service '%s' -- invalid action %s\n", action, S, action); return FALSE; } socket = socket_create_t(Run.bind_addr ? Run.bind_addr : "localhost", Run.httpdport, SOCKET_TCP, (Ssl_T){.use_ssl = Run.httpdssl, .clientpemfile = Run.httpsslclientpem}, NET_TIMEOUT);
/** * Pass on to methods in http/cervlet.c to start/stop services * @param S A service name as stated in the config file * @param action A string describing the action to execute * @return FALSE for error, otherwise TRUE */ int control_service_daemon(const char *S, const char *action) { int rv = FALSE; int status, content_length = 0; Socket_T s; char *auth; char buf[STRLEN]; ASSERT(S); ASSERT(action); if (Util_getAction(action) == ACTION_IGNORE) { LogError("%s: Cannot %s service '%s' -- invalid action %s\n", prog, action, S, action); return FALSE; } s = socket_new(Run.bind_addr ? Run.bind_addr : "localhost", Run.httpdport, SOCKET_TCP, Run.httpdssl, NET_TIMEOUT); if (!s) { LogError("%s: Cannot connect to the monit daemon. Did you start it with http support?\n", prog); return FALSE; } /* Send request */ auth = Util_getBasicAuthHeaderMonit(); if (socket_print(s, "POST /%s HTTP/1.0\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %d\r\n" "%s" "\r\n" "action=%s", S, strlen("action=") + strlen(action), auth ? auth : "", action) < 0) { LogError("%s: Cannot send the command '%s' to the monit daemon -- %s", prog, action ? action : "null", STRERROR); goto err1; } /* Process response */ if (! socket_readln(s, buf, STRLEN)) { LogError("%s: error receiving data -- %s\n", prog, STRERROR); goto err1; } Util_chomp(buf); if (! sscanf(buf, "%*s %d", &status)) { LogError("%s: cannot parse status in response: %s\n", prog, buf); goto err1; } if (status >= 300) { char *message = NULL; /* Skip headers */ while (socket_readln(s, buf, STRLEN)) { if (! strncmp(buf, "\r\n", sizeof(buf))) break; if(Util_startsWith(buf, "Content-Length") && ! sscanf(buf, "%*s%*[: ]%d", &content_length)) goto err1; } if (content_length > 0 && content_length < 1024 && socket_readln(s, buf, STRLEN)) { char token[] = "</h2>"; char *p = strstr(buf, token); if (strlen(p) <= strlen(token)) goto err2; p += strlen(token); message = xcalloc(sizeof(unsigned char), content_length + 1); snprintf(message, content_length + 1, "%s", p); p = strstr(message, "<p>"); if (p) *p = 0; } err2: LogError("%s: action failed -- %s\n", prog, message ? message : "unable to parse response"); FREE(message); } else rv = TRUE; err1: FREE(auth); socket_free(&s); return rv; }
/** * Pass on to methods in http/cervlet.c to start/stop services * @param S A service name as stated in the config file * @param action A string describing the action to execute * @param attempts Number of attemps (in case of "already action already in progres...") * @return a string starting with "ERR" in for error, otherwise return "OK" */ char *control_service_daemon_message(const char *S, const char *action, int attempts, int check_exit_status /* ignored */) { char *rv = NULL; int status, content_length = 0; Socket_T s; char *auth; char buf[STRLEN]; ASSERT(S); ASSERT(action); if (Util_getAction(action) == ACTION_IGNORE) { return xstrdup("ERR1: invalid action"); } auth = Util_getBasicAuthHeaderMonit(); retry: /* Try with the socket first */ if (Run.bind_path) { s = socket_new(Run.bind_path, 0, SOCKET_TCP, Run.httpdssl, NET_TIMEOUT); } /* Try network connection */ if (!s) { if(!(s = socket_new(Run.bind_addr ? Run.bind_addr : "localhost", Run.httpdport, SOCKET_TCP, Run.httpdssl, NET_TIMEOUT))) { FREE(auth); return xstrdup("ERR2: cannot connect to the monit daemon"); } } /* Send request */ if (socket_print(s, "POST /%s HTTP/1.0\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %d\r\n" "%s" "\r\n" "action=%s", S, strlen("action=") + strlen(action), auth ? auth : "", action) < 0) { return xstrdup("ERR3: cannot send the command"); goto err1; } /* Process response */ if (! socket_readln(s, buf, STRLEN)) { rv = xstrdup("ERR4: error receiving data"); goto err1; } Util_chomp(buf); if (! sscanf(buf, "%*s %d", &status)) { rv = xstrdup("ERR5: cannot parse status in response"); goto err1; } if (status >= 300) { /* Skip headers */ while (socket_readln(s, buf, STRLEN)) { if (! strncmp(buf, "\r\n", sizeof(buf))) break; if(Util_startsWith(buf, "Content-Length") && ! sscanf(buf, "%*s%*[: ]%d", &content_length)) { rv = xstrdup("ERR6: error parsing headers"); goto err1; } } if (content_length > 0 && content_length < 1024 && socket_readln(s, buf, STRLEN)) { char token[] = "</h2>"; char *p = strstr(buf, token); if (strlen(p) <= strlen(token)) { rv = xstrdup("ERR7: error parsing body"); goto err1; } p += strlen(token); rv = xcalloc(sizeof(unsigned char), content_length + 1 + 6); snprintf(rv, content_length + 1 + 6, "ERR8: %s", p); p = strstr(rv, "<p>"); if (p) *p = 0; attempts--; if ((attempts > 0) && (strstr(rv, "please try again later") != NULL)) { socket_free(&s); /*LogInfo("%s: retrying %s %s (%s)\n", prog, action, S, rv);*/ LogInfo("%s: retrying %s %s\n", prog, action, S); FREE(rv); sleep(1); goto retry; } } } else rv = xstrdup("OK"); err1: FREE(auth); socket_free(&s); return rv; }