📄 manager.c
字号:
/* * Changes: * Jul 22, 2005: Created (Jorrit N. Herder) */#include "inc.h"#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#include <minix/dmap.h>/* Allocate variables. */struct rproc rproc[NR_SYS_PROCS]; /* system process table */struct rproc *rproc_ptr[NR_PROCS]; /* mapping for fast access */int nr_in_use; /* number of services */extern int errno; /* error status *//* Prototypes for internal functions that do the hard work. */FORWARD _PROTOTYPE( int start_service, (struct rproc *rp) );FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp,int how) );PRIVATE int shutting_down = FALSE;#define EXEC_FAILED 49 /* recognizable status *//*===========================================================================* * do_up * *===========================================================================*/PUBLIC int do_up(m_ptr)message *m_ptr; /* request message pointer */{/* A request was made to start a new system service. Dismember the request * message and gather all information needed to start the service. Starting * is done by a helper routine. */ register struct rproc *rp; /* system process table */ int slot_nr; /* local table entry */ int arg_count; /* number of arguments */ char *cmd_ptr; /* parse command string */ enum dev_style dev_style; /* device style */ int s; /* status variable */ /* See if there is a free entry in the table with system processes. */ if (nr_in_use >= NR_SYS_PROCS) return(EAGAIN); for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) { rp = &rproc[slot_nr]; /* get pointer to slot */ if (! rp->r_flags & RS_IN_USE) /* check if available */ break; } nr_in_use ++; /* update administration */ /* Obtain command name and parameters. This is a space-separated string * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional. */ if (m_ptr->RS_CMD_LEN > MAX_COMMAND_LEN) return(E2BIG); if (OK!=(s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR, SELF, (vir_bytes) rp->r_cmd, m_ptr->RS_CMD_LEN))) return(s); rp->r_cmd[m_ptr->RS_CMD_LEN] = '\0'; /* ensure it is terminated */ if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */ /* Build argument vector to be passed to execute call. The format of the * arguments vector is: path, arguments, NULL. */ arg_count = 0; /* initialize arg count */ rp->r_argv[arg_count++] = rp->r_cmd; /* start with path */ cmd_ptr = rp->r_cmd; /* do some parsing */ while(*cmd_ptr != '\0') { /* stop at end of string */ if (*cmd_ptr == ' ') { /* next argument */ *cmd_ptr = '\0'; /* terminate previous */ while (*++cmd_ptr == ' ') ; /* skip spaces */ if (*cmd_ptr == '\0') break; /* no arg following */ if (arg_count>MAX_NR_ARGS+1) break; /* arg vector full */ rp->r_argv[arg_count++] = cmd_ptr; /* add to arg vector */ } cmd_ptr ++; /* continue parsing */ } rp->r_argv[arg_count] = NULL; /* end with NULL pointer */ rp->r_argc = arg_count; /* Initialize some fields. */ rp->r_period = m_ptr->RS_PERIOD; rp->r_dev_nr = m_ptr->RS_DEV_MAJOR; rp->r_dev_style = STYLE_DEV; rp->r_restarts = -1; /* will be incremented */ /* All information was gathered. Now try to start the system service. */ return(start_service(rp));}/*===========================================================================* * do_down * *===========================================================================*/PUBLIC int do_down(message *m_ptr){ register struct rproc *rp; pid_t pid = (pid_t) m_ptr->RS_PID; for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { if (rp->r_flags & RS_IN_USE && rp->r_pid == pid) {#if VERBOSE printf("stopping %d (%d)\n", pid, m_ptr->RS_PID);#endif stop_service(rp,RS_EXITING); return(OK); } }#if VERBOSE printf("not found %d (%d)\n", pid, m_ptr->RS_PID);#endif return(ESRCH);}/*===========================================================================* * do_refresh * *===========================================================================*/PUBLIC int do_refresh(message *m_ptr){ register struct rproc *rp; pid_t pid = (pid_t) m_ptr->RS_PID; for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { if (rp->r_flags & RS_IN_USE && rp->r_pid == pid) {#if VERBOSE printf("refreshing %d (%d)\n", pid, m_ptr->RS_PID);#endif stop_service(rp,RS_REFRESHING); return(OK); } }#if VERBOSE printf("not found %d (%d)\n", pid, m_ptr->RS_PID);#endif return(ESRCH);}/*===========================================================================* * do_rescue * *===========================================================================*/PUBLIC int do_rescue(message *m_ptr){ char rescue_dir[MAX_RESCUE_DIR_LEN]; int s; /* Copy rescue directory from user. */ if (m_ptr->RS_CMD_LEN > MAX_RESCUE_DIR_LEN) return(E2BIG); if (OK!=(s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR, SELF, (vir_bytes) rescue_dir, m_ptr->RS_CMD_LEN))) return(s); rescue_dir[m_ptr->RS_CMD_LEN] = '\0'; /* ensure it is terminated */ if (rescue_dir[0] != '/') return(EINVAL); /* insist on absolute path */ /* Change RS' directory to the rescue directory. Provided that the needed * binaries are in the rescue dir, this makes recovery possible even if the * (root) file system is no longer available, because no directory lookups * are required. Thus if an absolute path fails, we can try to strip the * path an see if the command is in the rescue dir. */ if (chdir(rescue_dir) != 0) return(errno); return(OK);}/*===========================================================================* * do_shutdown * *===========================================================================*/PUBLIC int do_shutdown(message *m_ptr){ /* Set flag so that RS server knows services shouldn't be restarted. */ shutting_down = TRUE; return(OK);}/*===========================================================================* * do_exit * *===========================================================================*/PUBLIC void do_exit(message *m_ptr){ register struct rproc *rp; pid_t exit_pid; int exit_status;#if VERBOSE printf("RS: got SIGCHLD signal, doing wait to get exited child.\n");#endif /* See which child exited and what the exit status is. This is done in a * loop because multiple childs may have exited, all reported by one * SIGCHLD signal. The WNOHANG options is used to prevent blocking if, * somehow, no exited child can be found. */ while ( (exit_pid = waitpid(-1, &exit_status, WNOHANG)) != 0 ) {#if VERBOSE printf("RS: proc %d, pid %d, ", rp->r_proc_nr, exit_pid); if (WIFSIGNALED(exit_status)) { printf("killed, signal number %d\n", WTERMSIG(exit_status)); } else if (WIFEXITED(exit_status)) { printf("normal exit, status %d\n", WEXITSTATUS(exit_status)); }#endif /* Search the system process table to see who exited. * This should always succeed. */ for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { if ((rp->r_flags & RS_IN_USE) && rp->r_pid == exit_pid) { rproc_ptr[rp->r_proc_nr] = NULL; /* invalidate */ if ((rp->r_flags & RS_EXITING) || shutting_down) { rp->r_flags = 0; /* release slot */ rproc_ptr[rp->r_proc_nr] = NULL; } else if(rp->r_flags & RS_REFRESHING) { rp->r_restarts = -1; /* reset counter */ start_service(rp); /* direct restart */ } else if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == EXEC_FAILED) { rp->r_flags = 0; /* release slot */ } else {#if VERBOSE printf("Unexpected exit. Restarting %s\n", rp->r_cmd);#endif /* Determine what to do. If this is the first unexpected * exit, immediately restart this service. Otherwise use
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -