/* * Copyright (C), 2000-2002 by Contributors to the monit codebase. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #ifdef HAVE_SYS_TYPES_H #include #endif #include #include #ifdef HAVE_STRING_H #include #endif #include "monitor.h" #include "net.h" /** * Methods for controlling processes managed by monit. * * @author Jan-Henrik Haukeland, * @author Rory Toma, * * @version \$Id: control.c,v 1.1 2002/09/26 02:39:27 rory Exp $ * * @file */ /* ------------------------------------------------------------------ Public */ /** * Start all processes in the process list */ void start() { Process_T p; for(p= processlist; p; p= p->next) { if(p->start) dstart_process(p->name); } } /** * Start all processes in the group */ void start_group(char *G) { Process_T p; for(p= processlist; p; p= p->next) { if(is(p->group, G) ) { if(p->start) dstart_process(p->name); } } } /** * Start the given process * @param p A Process_T object */ void start_process(Process_T p) { pid_t pid= -1; if(!p->start) { error("Start: '%s' the start program is not defined\n", p->name); return; } if((pid= is_process_running(p))) { error("Start: '%s' is already started with pid=%d\n", p->name, (int)pid); return; } log("Start: (%s) %s\n", p->name, p->start->arg[0]); spawn(p, p->start); } /** * Request the monit deamon to start the process P * @param P A process name as stated in the config file */ void dstart_process(char *P) { Process_T p; int pid; if ( ! exist_process(P) ) { error("%s: Cannot start program '%s' -- not found in %s\n", prog, P, Run.controlfile); return; } p= get_process(P); if ( (pid= is_process_running(p))) { error("%s: '%s' is already running with pid=%d\n", prog, P, pid); return; } control_process(P, PSTART); } /** * Stop all processes in the process list */ void stop() { Process_T p; for(p= processlist; p; p= p->next) { if(p->stop) dstop_process(p->name); } } /** * Stop all processes in the group */ void stop_group(char *G) { Process_T p; for(p= processlist; p; p= p->next) { if(is(p->group, G)) { if(p->stop) dstop_process(p->name); } } } /** * stop the process * @param p A Process_T object */ void stop_process(Process_T p) { pid_t pid= -1; if(!p->stop) { error("Stop: '%s' the stop program is not defined\n", p->name); return; } if(!(pid= is_process_running(p))) { error("Stop: '%s' is not running\n", p->name); return; } log("Stop: (%s) %s\n", p->name, p->stop->arg[0]); spawn(p, p->stop); } /** * Request the monit deamon to stop the process P * @param P A process name as stated in the config file */ void dstop_process(char *P) { Process_T p; if ( ! exist_process(P) ) { error("%s: Cannot stop program '%s' -- not found in %s\n", prog, P, Run.controlfile); return; } p= get_process(P); if ( ! is_process_running(p) ) { error("%s: '%s' is not running\n", prog, P); return; } control_process(P, PSTOP); } /* Start/stop processes with dependency code */ void control_process(char *P, int action) { Process_T p; Dependant_T d; p= get_process(P); if ( exist_daemon() ) { /* If a monit daemon exist we request that the daemon start the program in case the daemon timed out the program. This way any process timeout lock in the daemon is removed */ /* stop dependant processes - we do this no matter what */ for(d= p->dependantlist; d; d= p->dependantlist->next) { if(d->dependant == NULL) { break; } dcontrol_process(d->dependant, PSTOP); if(d->next == NULL) { break; } } /* Now start/stop the process we asked for */ dcontrol_process(P, action); /* Start dependant processes again */ if(action == PSTART) { for(d= p->dependantlist; d; d= p->dependantlist->next) { if(d->dependant == NULL) { break; } dcontrol_process(d->dependant, PSTART); if(d->next == NULL) { break; } } } } else { /* No monit daemon */ force_process(p, action); } } /* Just start/stop the programs */ void force_process(Process_T p, int action) { Dependant_T d; /* stop dependant processes - we need to do this no matter what*/ for(d= p->dependantlist; d; d= p->dependantlist->next) { if(d->dependant == NULL) { break; } stop_process(get_process(d->dependant)); if(d->next == NULL) { break; } } /* Now start/stop the process we asked for */ if(action == PSTART) { start_process(p); } else { stop_process(p); } /* Restart dependant processes */ if(action == PSTART) { for(d= p->dependantlist; d; d= p->dependantlist->next) { if(d->dependant == NULL) { break; } start_process(get_process(d->dependant)); if(d->next == NULL) { break; } } } } /* Start/stop processes via monit http interface */ void dcontrol_process(char *P, int action) { int s; char req[2*STRLEN]; char command[8]; char *auth= get_basic_authentication_header(); Process_T p; p= get_process(P); if(action == PSTOP) { snprintf(command, sizeof(command), "stop"); } else { snprintf(command, sizeof(command), "start"); } s= create_socket(Run.bind_addr?Run.bind_addr:"localhost", Run.httpdport, SOCK_STREAM); if(s<0) { error("%s: Cannot connect to the monit daemon. " "Did you start it with http support?\n", prog); return; } else { snprintf(req, sizeof(req), "GET /%s?action=%s HTTP/1.0\r\n%s\r\n", P, command, auth); sock_send(s, req, sizeof(req), 0); close_socket(s); free(auth); } }