removed or optionalized verbose/debugging messages
[minix3.git] / servers / rs / manager.c
blob42449205bd2c703d404a9df79a13dae247955901
1 /*
2 * Changes:
3 * Jul 22, 2005: Created (Jorrit N. Herder)
4 */
6 #include "inc.h"
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <sys/wait.h>
12 #include <minix/dmap.h>
13 #include <minix/endpoint.h>
14 #include <minix/rs.h>
15 #include <lib.h>
17 #include <timers.h> /* For priv.h */
18 #include "../../kernel/priv.h"
20 /* Allocate variables. */
21 struct rproc rproc[NR_SYS_PROCS]; /* system process table */
22 struct rproc *rproc_ptr[NR_PROCS]; /* mapping for fast access */
24 /* Prototypes for internal functions that do the hard work. */
25 FORWARD _PROTOTYPE( int start_service, (struct rproc *rp, int flags,
26 endpoint_t *ep) );
27 FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp,int how) );
28 FORWARD _PROTOTYPE( int fork_nb, (void) );
29 FORWARD _PROTOTYPE( int read_exec, (struct rproc *rp) );
30 FORWARD _PROTOTYPE( void run_script, (struct rproc *rp) );
31 FORWARD _PROTOTYPE( void init_privs, (struct rproc *rp, struct priv *privp) );
32 FORWARD _PROTOTYPE( void init_pci, (struct rproc *rp, int endpoint) );
34 PRIVATE int shutting_down = FALSE;
36 #define EXEC_FAILED 49 /* recognizable status */
38 extern int rs_verbose;
40 /*===========================================================================*
41 * do_up *
42 *===========================================================================*/
43 PUBLIC int do_up(m_ptr, do_copy, flags)
44 message *m_ptr; /* request message pointer */
45 int do_copy; /* keep copy in memory */
46 int flags; /* extra flags, if any */
48 /* A request was made to start a new system service. Dismember the request
49 * message and gather all information needed to start the service. Starting
50 * is done by a helper routine.
52 register struct rproc *rp; /* system process table */
53 int slot_nr; /* local table entry */
54 int arg_count; /* number of arguments */
55 char *cmd_ptr; /* parse command string */
56 char *label; /* unique name of command */
57 enum dev_style dev_style; /* device style */
58 int s; /* status variable */
59 int len; /* length of string */
60 int r;
61 endpoint_t ep; /* new endpoint no. */
63 /* See if there is a free entry in the table with system processes. */
64 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
65 rp = &rproc[slot_nr]; /* get pointer to slot */
66 if (! rp->r_flags & RS_IN_USE) /* check if available */
67 break;
70 /* Obtain command name and parameters. This is a space-separated string
71 * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
73 if (m_ptr->RS_CMD_LEN > MAX_COMMAND_LEN) return(E2BIG);
74 if (OK!=(s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
75 SELF, (vir_bytes) rp->r_cmd, m_ptr->RS_CMD_LEN))) return(s);
76 rp->r_cmd[m_ptr->RS_CMD_LEN] = '\0'; /* ensure it is terminated */
77 if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */
79 rp->r_script[0]= '\0';
81 /* Build argument vector to be passed to execute call. The format of the
82 * arguments vector is: path, arguments, NULL.
84 arg_count = 0; /* initialize arg count */
85 rp->r_argv[arg_count++] = rp->r_cmd; /* start with path */
86 cmd_ptr = rp->r_cmd; /* do some parsing */
87 while(*cmd_ptr != '\0') { /* stop at end of string */
88 if (*cmd_ptr == ' ') { /* next argument */
89 *cmd_ptr = '\0'; /* terminate previous */
90 while (*++cmd_ptr == ' ') ; /* skip spaces */
91 if (*cmd_ptr == '\0') break; /* no arg following */
92 if (arg_count>MAX_NR_ARGS+1) break; /* arg vector full */
93 rp->r_argv[arg_count++] = cmd_ptr; /* add to arg vector */
95 cmd_ptr ++; /* continue parsing */
97 rp->r_argv[arg_count] = NULL; /* end with NULL pointer */
98 rp->r_argc = arg_count;
100 /* Default label for the driver */
101 label= strrchr(rp->r_argv[0], '/');
102 if (label)
103 label++;
104 else
105 label= rp->r_argv[0];
106 len= strlen(label);
107 if (len > MAX_LABEL_LEN-1)
108 len= MAX_LABEL_LEN-1; /* truncate name */
109 memcpy(rp->r_label, label, len);
110 rp->r_label[len]= '\0';
111 if(rs_verbose) printf("RS: do_up: using label '%s'\n", rp->r_label);
113 rp->r_uid= 0;
114 rp->r_nice= 0;
116 rp->r_exec= NULL;
117 if (do_copy)
119 s= read_exec(rp);
120 if (s != OK)
121 return s;
124 /* Initialize some fields. */
125 rp->r_period = m_ptr->RS_PERIOD;
126 rp->r_dev_nr = m_ptr->RS_DEV_MAJOR;
127 rp->r_dev_style = STYLE_DEV;
128 rp->r_restarts = -1; /* will be incremented */
129 rp->r_set_resources= 0; /* old style */
131 /* All information was gathered. Now try to start the system service. */
133 r = start_service(rp, flags, &ep);
134 m_ptr->RS_ENDPOINT = ep;
135 return r;
139 /*===========================================================================*
140 * do_start *
141 *===========================================================================*/
142 PUBLIC int do_start(m_ptr)
143 message *m_ptr; /* request message pointer */
145 /* A request was made to start a new system service.
147 register struct rproc *rp; /* system process table */
148 int slot_nr; /* local table entry */
149 int arg_count; /* number of arguments */
150 char *cmd_ptr; /* parse command string */
151 char *label; /* unique name of command */
152 enum dev_style dev_style; /* device style */
153 int s; /* status variable */
154 int len; /* length of string */
155 int i;
156 int r;
157 endpoint_t ep;
158 struct rproc *tmp_rp;
159 struct rs_start rs_start;
161 /* Get the request structure */
162 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
163 SELF, (vir_bytes) &rs_start, sizeof(rs_start));
164 if (s != OK) return(s);
166 /* See if there is a free entry in the table with system processes. */
167 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
168 rp = &rproc[slot_nr]; /* get pointer to slot */
169 if (! rp->r_flags & RS_IN_USE) /* check if available */
170 break;
173 /* Obtain command name and parameters. This is a space-separated string
174 * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
176 if (rs_start.rss_cmdlen > MAX_COMMAND_LEN-1) return(E2BIG);
177 s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_cmd,
178 SELF, (vir_bytes) rp->r_cmd, rs_start.rss_cmdlen);
179 if (s != OK) return(s);
180 rp->r_cmd[rs_start.rss_cmdlen] = '\0'; /* ensure it is terminated */
181 if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */
183 /* Build argument vector to be passed to execute call. The format of the
184 * arguments vector is: path, arguments, NULL.
186 arg_count = 0; /* initialize arg count */
187 rp->r_argv[arg_count++] = rp->r_cmd; /* start with path */
188 cmd_ptr = rp->r_cmd; /* do some parsing */
189 while(*cmd_ptr != '\0') { /* stop at end of string */
190 if (*cmd_ptr == ' ') { /* next argument */
191 *cmd_ptr = '\0'; /* terminate previous */
192 while (*++cmd_ptr == ' ') ; /* skip spaces */
193 if (*cmd_ptr == '\0') break; /* no arg following */
194 if (arg_count>MAX_NR_ARGS+1) break; /* arg vector full */
195 rp->r_argv[arg_count++] = cmd_ptr; /* add to arg vector */
197 cmd_ptr ++; /* continue parsing */
199 rp->r_argv[arg_count] = NULL; /* end with NULL pointer */
200 rp->r_argc = arg_count;
202 if(rs_start.rss_label) {
203 int len;
204 /* RS_START caller has supplied a custom label for this driver. */
205 len = MIN(sizeof(rp->r_label)-1, rs_start.rss_labellen);
206 s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_label,
207 SELF, (vir_bytes) rp->r_label, len);
208 if(s != OK)
209 return s;
210 rp->r_label[len] = '\0';
211 if(rs_verbose)
212 printf("RS: do_start: using label (custom) '%s'\n", rp->r_label);
213 } else {
214 /* Default label for the driver. */
215 label= strrchr(rp->r_argv[0], '/');
216 if (label)
217 label++;
218 else
219 label= rp->r_argv[0];
220 len= strlen(label);
221 if (len > MAX_LABEL_LEN-1)
222 len= MAX_LABEL_LEN-1; /* truncate name */
223 memcpy(rp->r_label, label, len);
224 rp->r_label[len]= '\0';
225 if(rs_verbose)
226 printf("RS: do_start: using label (from binary %s) '%s'\n",
227 rp->r_argv[0], rp->r_label);
230 /* Check for duplicates */
231 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
232 tmp_rp = &rproc[slot_nr]; /* get pointer to slot */
233 if (!(tmp_rp->r_flags & RS_IN_USE)) /* check if available */
234 continue;
235 if (tmp_rp == rp)
236 continue; /* Our slot */
237 if (strcmp(tmp_rp->r_label, rp->r_label) == 0)
239 printf("RS: found duplicate label '%s': slot %d\n",
240 rp->r_label, slot_nr);
241 return EBUSY;
245 rp->r_script[0]= '\0';
246 if (rs_start.rss_scriptlen > MAX_SCRIPT_LEN-1) return(E2BIG);
247 if (rs_start.rss_script != NULL)
249 s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_script,
250 SELF, (vir_bytes) rp->r_script, rs_start.rss_scriptlen);
251 if (s != OK) return(s);
252 rp->r_script[rs_start.rss_scriptlen] = '\0';
254 rp->r_uid= rs_start.rss_uid;
255 rp->r_nice= rs_start.rss_nice;
257 rp->r_exec= NULL;
258 if (rs_start.rss_flags & RF_COPY)
260 s= read_exec(rp);
261 if (s != OK)
262 return s;
265 /* Copy granted resources */
266 if (rs_start.rss_nr_irq > NR_IRQ)
268 printf("RS: do_start: too many IRQs requested\n");
269 return EINVAL;
271 rp->r_priv.s_nr_irq= rs_start.rss_nr_irq;
272 for (i= 0; i<rp->r_priv.s_nr_irq; i++)
274 rp->r_priv.s_irq_tab[i]= rs_start.rss_irq[i];
275 if(rs_verbose)
276 printf("RS: do_start: IRQ %d\n", rp->r_priv.s_irq_tab[i]);
279 if (rs_start.rss_nr_io > NR_IO_RANGE)
281 printf("RS: do_start: too many I/O ranges requested\n");
282 return EINVAL;
284 rp->r_priv.s_nr_io_range= rs_start.rss_nr_io;
285 for (i= 0; i<rp->r_priv.s_nr_io_range; i++)
287 rp->r_priv.s_io_tab[i].ior_base= rs_start.rss_io[i].base;
288 rp->r_priv.s_io_tab[i].ior_limit=
289 rs_start.rss_io[i].base+rs_start.rss_io[i].len-1;
290 if(rs_verbose)
291 printf("RS: do_start: I/O [%x..%x]\n",
292 rp->r_priv.s_io_tab[i].ior_base,
293 rp->r_priv.s_io_tab[i].ior_limit);
296 if (rs_start.rss_nr_pci_id > MAX_NR_PCI_ID)
298 printf("RS: do_start: too many PCI device IDs\n");
299 return EINVAL;
301 rp->r_nr_pci_id= rs_start.rss_nr_pci_id;
302 for (i= 0; i<rp->r_nr_pci_id; i++)
304 rp->r_pci_id[i].vid= rs_start.rss_pci_id[i].vid;
305 rp->r_pci_id[i].did= rs_start.rss_pci_id[i].did;
306 if(rs_verbose)
307 printf("RS: do_start: PCI %04x/%04x\n",
308 rp->r_pci_id[i].vid, rp->r_pci_id[i].did);
310 if (rs_start.rss_nr_pci_class > MAX_NR_PCI_CLASS)
312 printf("RS: do_start: too many PCI class IDs\n");
313 return EINVAL;
315 rp->r_nr_pci_class= rs_start.rss_nr_pci_class;
316 for (i= 0; i<rp->r_nr_pci_class; i++)
318 rp->r_pci_class[i].class= rs_start.rss_pci_class[i].class;
319 rp->r_pci_class[i].mask= rs_start.rss_pci_class[i].mask;
320 if(rs_verbose)
321 printf("RS: do_start: PCI class %06x mask %06x\n",
322 rp->r_pci_class[i].class, rp->r_pci_class[i].mask);
325 /* Copy 'system' call number bits */
326 if (sizeof(rs_start.rss_system[0]) == sizeof(rp->r_call_mask[0]) &&
327 sizeof(rs_start.rss_system) == sizeof(rp->r_call_mask))
329 for (i= 0; i<RSS_NR_SYSTEM; i++)
330 rp->r_call_mask[i]= rs_start.rss_system[i];
332 else
334 printf(
335 "RS: do_start: internal inconsistency: bad size of r_call_mask\n");
336 memset(rp->r_call_mask, '\0', sizeof(rp->r_call_mask));
339 /* Initialize some fields. */
340 rp->r_period = rs_start.rss_period;
341 rp->r_dev_nr = rs_start.rss_major;
342 rp->r_dev_style = STYLE_DEV;
343 rp->r_restarts = -1; /* will be incremented */
344 rp->r_set_resources= 1; /* new style, enforece
345 * I/O resources
348 /* All information was gathered. Now try to start the system service. */
349 r = start_service(rp, 0, &ep);
350 m_ptr->RS_ENDPOINT = ep;
351 return r;
355 /*===========================================================================*
356 * do_down *
357 *===========================================================================*/
358 PUBLIC int do_down(message *m_ptr)
360 register struct rproc *rp;
361 size_t len;
362 int s, proc;
363 char label[MAX_LABEL_LEN];
365 len= m_ptr->RS_CMD_LEN;
366 if (len >= sizeof(label))
367 return EINVAL; /* Too long */
369 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
370 SELF, (vir_bytes) label, len);
371 if (s != OK) return(s);
372 label[len]= '\0';
374 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
375 if (rp->r_flags & RS_IN_USE && strcmp(rp->r_label, label) == 0) {
376 if(rs_verbose)
377 printf("RS: stopping '%s' (%d)\n", label, rp->r_pid);
378 stop_service(rp,RS_EXITING);
379 if (rp->r_pid == -1)
381 /* Process is already gone */
382 rp->r_flags = 0; /* release slot */
383 if (rp->r_exec)
385 free(rp->r_exec);
386 rp->r_exec= NULL;
388 proc = _ENDPOINT_P(rp->r_proc_nr_e);
389 rproc_ptr[proc] = NULL;
390 return(OK);
393 /* Late reply - send a reply when process dies. */
394 rp->r_flags |= RS_LATEREPLY;
395 rp->r_caller = m_ptr->m_source;
396 return EDONTREPLY;
399 if(rs_verbose) printf("RS: do_down: '%s' not found\n", label);
400 return(ESRCH);
404 /*===========================================================================*
405 * do_restart *
406 *===========================================================================*/
407 PUBLIC int do_restart(message *m_ptr)
409 register struct rproc *rp;
410 size_t len;
411 int s, proc, r;
412 char label[MAX_LABEL_LEN];
413 endpoint_t ep;
415 len= m_ptr->RS_CMD_LEN;
416 if (len >= sizeof(label))
417 return EINVAL; /* Too long */
419 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
420 SELF, (vir_bytes) label, len);
421 if (s != OK) return(s);
422 label[len]= '\0';
424 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
425 if (rp->r_flags & RS_IN_USE && strcmp(rp->r_label, label) == 0) {
426 if(rs_verbose) printf("RS: restarting '%s' (%d)\n", label, rp->r_pid);
427 if (rp->r_pid >= 0)
429 if(rs_verbose)
430 printf("RS: do_restart: '%s' is (still) running, pid = %d\n",
431 rp->r_pid);
432 return EBUSY;
434 rp->r_flags &= ~(RS_EXITING|RS_REFRESHING|RS_NOPINGREPLY);
435 r = start_service(rp, 0, &ep);
436 m_ptr->RS_ENDPOINT = ep;
437 return(r);
440 #if VERBOSE
441 printf("RS: do_restart: '%s' not found\n", label);
442 #endif
443 return(ESRCH);
447 /*===========================================================================*
448 * do_refresh *
449 *===========================================================================*/
450 PUBLIC int do_refresh(message *m_ptr)
452 register struct rproc *rp;
453 size_t len;
454 int s;
455 char label[MAX_LABEL_LEN];
457 len= m_ptr->RS_CMD_LEN;
458 if (len >= sizeof(label))
459 return EINVAL; /* Too long */
461 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
462 SELF, (vir_bytes) label, len);
463 if (s != OK) return(s);
464 label[len]= '\0';
466 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
467 if (rp->r_flags & RS_IN_USE && strcmp(rp->r_label, label) == 0) {
468 #if VERBOSE
469 printf("RS: refreshing %s (%d)\n", rp->r_label, rp->r_pid);
470 #endif
471 stop_service(rp,RS_REFRESHING);
472 return(OK);
475 #if VERBOSE
476 printf("RS: do_refresh: '%s' not found\n", label);
477 #endif
478 return(ESRCH);
481 /*===========================================================================*
482 * do_shutdown *
483 *===========================================================================*/
484 PUBLIC int do_shutdown(message *m_ptr)
486 /* Set flag so that RS server knows services shouldn't be restarted. */
487 shutting_down = TRUE;
488 return(OK);
491 /*===========================================================================*
492 * do_exit *
493 *===========================================================================*/
494 PUBLIC void do_exit(message *m_ptr)
496 register struct rproc *rp;
497 pid_t exit_pid;
498 int exit_status, r;
499 endpoint_t ep;
501 if(rs_verbose)
502 printf("RS: got SIGCHLD signal, doing wait to get exited child.\n");
504 /* See which child exited and what the exit status is. This is done in a
505 * loop because multiple childs may have exited, all reported by one
506 * SIGCHLD signal. The WNOHANG options is used to prevent blocking if,
507 * somehow, no exited child can be found.
509 while ( (exit_pid = waitpid(-1, &exit_status, WNOHANG)) != 0 ) {
511 if(rs_verbose) {
512 printf("RS: pid %d, ", exit_pid);
513 if (WIFSIGNALED(exit_status)) {
514 printf("killed, signal number %d\n", WTERMSIG(exit_status));
516 else if (WIFEXITED(exit_status)) {
517 printf("normal exit, status %d\n", WEXITSTATUS(exit_status));
521 /* Search the system process table to see who exited.
522 * This should always succeed.
524 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
525 if ((rp->r_flags & RS_IN_USE) && rp->r_pid == exit_pid) {
526 int proc;
527 proc = _ENDPOINT_P(rp->r_proc_nr_e);
529 rproc_ptr[proc] = NULL; /* invalidate */
530 rp->r_pid= -1;
532 if ((rp->r_flags & RS_EXITING) || shutting_down) {
533 /* No reply sent to RS_DOWN yet. */
534 if(rp->r_flags & RS_LATEREPLY) {
535 message rsm;
536 rsm.m_type = OK;
537 send(rp->r_caller, &rsm);
540 /* Release slot. */
541 rp->r_flags = 0;
542 if (rp->r_exec)
544 free(rp->r_exec);
545 rp->r_exec= NULL;
547 rproc_ptr[proc] = NULL;
550 else if(rp->r_flags & RS_REFRESHING) {
551 rp->r_restarts = -1; /* reset counter */
552 if (rp->r_script[0] != '\0')
553 run_script(rp);
554 else {
555 start_service(rp, 0, &ep); /* direct restart */
556 m_ptr->RS_ENDPOINT = ep;
559 else if (WIFEXITED(exit_status) &&
560 WEXITSTATUS(exit_status) == EXEC_FAILED) {
561 rp->r_flags = 0; /* release slot */
563 else {
564 if(rs_verbose)
565 printf("RS: unexpected exit. Restarting %s\n", rp->r_cmd);
566 /* Determine what to do. If this is the first unexpected
567 * exit, immediately restart this service. Otherwise use
568 * a binary exponetial backoff.
570 #if 0
571 rp->r_restarts= 0;
572 #endif
573 if (WIFSIGNALED(exit_status)) {
574 switch(WTERMSIG(exit_status))
576 case SIGKILL: rp->r_flags |= RS_KILLED; break;
577 default: rp->r_flags |= RS_CRASHED; break;
580 else
581 rp->r_flags |= RS_CRASHED;
583 if (rp->r_script[0] != '\0')
584 run_script(rp);
585 else if (rp->r_restarts > 0) {
586 rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
587 rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF);
588 if (rp->r_exec != NULL && rp->r_backoff > 1)
589 rp->r_backoff= 1;
591 else {
592 start_service(rp, 0, &ep); /* direct restart */
593 m_ptr->RS_ENDPOINT = ep;
594 /* Do this even if no I/O happens with the ioctl, in
595 * order to disambiguate requests with DEV_IOCTL_S.
599 break;
605 /*===========================================================================*
606 * do_period *
607 *===========================================================================*/
608 PUBLIC void do_period(m_ptr)
609 message *m_ptr;
611 register struct rproc *rp;
612 clock_t now = m_ptr->NOTIFY_TIMESTAMP;
613 int s;
614 endpoint_t ep;
616 /* Search system services table. Only check slots that are in use. */
617 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
618 if (rp->r_flags & RS_IN_USE) {
620 /* If the service is to be revived (because it repeatedly exited,
621 * and was not directly restarted), the binary backoff field is
622 * greater than zero.
624 if (rp->r_backoff > 0) {
625 rp->r_backoff -= 1;
626 if (rp->r_backoff == 0) {
627 start_service(rp, 0, &ep);
628 m_ptr->RS_ENDPOINT = ep;
632 /* If the service was signaled with a SIGTERM and fails to respond,
633 * kill the system service with a SIGKILL signal.
635 else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
636 && rp->r_pid > 0) {
637 kill(rp->r_pid, SIGKILL); /* terminate */
640 /* There seems to be no special conditions. If the service has a
641 * period assigned check its status.
643 else if (rp->r_period > 0) {
645 /* Check if an answer to a status request is still pending. If
646 * the driver didn't respond within time, kill it to simulate
647 * a crash. The failure will be detected and the service will
648 * be restarted automatically.
650 if (rp->r_alive_tm < rp->r_check_tm) {
651 if (now - rp->r_alive_tm > 2*rp->r_period &&
652 rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) {
653 if(rs_verbose)
654 printf("RS: service %d reported late\n",
655 rp->r_proc_nr_e);
656 rp->r_flags |= RS_NOPINGREPLY;
657 kill(rp->r_pid, SIGKILL); /* simulate crash */
661 /* No answer pending. Check if a period expired since the last
662 * check and, if so request the system service's status.
664 else if (now - rp->r_check_tm > rp->r_period) {
665 if(rs_verbose)
666 printf("RS: status request sent to %d\n", rp->r_proc_nr_e);
667 notify(rp->r_proc_nr_e); /* request status */
668 rp->r_check_tm = now; /* mark time */
674 /* Reschedule a synchronous alarm for the next period. */
675 if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
676 panic("RS", "couldn't set alarm", s);
680 /*===========================================================================*
681 * start_service *
682 *===========================================================================*/
683 PRIVATE int start_service(rp, flags, endpoint)
684 struct rproc *rp;
685 int flags;
686 endpoint_t *endpoint;
688 /* Try to execute the given system service. Fork a new process. The child
689 * process will be inhibited from running by the NO_PRIV flag. Only let the
690 * child run once its privileges have been set by the parent.
692 int child_proc_nr_e, child_proc_nr_n; /* child process slot */
693 pid_t child_pid; /* child's process id */
694 char *file_only;
695 int s, use_copy;
696 struct priv *privp;
697 message m;
699 use_copy= (rp->r_exec != NULL);
701 /* Now fork and branch for parent and child process (and check for error). */
702 if (use_copy)
703 child_pid= fork_nb();
704 else
705 child_pid = fork();
707 switch(child_pid) { /* see fork(2) */
708 case -1: /* fork failed */
709 report("RS", "warning, fork() failed", errno); /* shouldn't happen */
710 return(errno); /* return error */
712 case 0: /* child process */
713 /* Try to execute the binary that has an absolute path. If this fails,
714 * e.g., because the root file system cannot be read, try to strip of
715 * the path, and see if the command is in RS' current working dir.
717 nice(rp->r_nice); /* Nice before setuid, to allow negative
718 * nice values.
720 setuid(rp->r_uid);
721 if (!use_copy)
723 execve(rp->r_argv[0], rp->r_argv, NULL); /* POSIX execute */
724 file_only = strrchr(rp->r_argv[0], '/') + 1;
725 execve(file_only, rp->r_argv, NULL); /* POSIX execute */
727 printf("RS: exec failed for %s: %d\n", rp->r_argv[0], errno);
728 exit(EXEC_FAILED); /* terminate child */
730 default: /* parent process */
731 child_proc_nr_e = getnprocnr(child_pid); /* get child slot */
732 break; /* continue below */
735 if (use_copy)
737 extern char **environ;
738 dev_execve(child_proc_nr_e, rp->r_exec, rp->r_exec_len, rp->r_argv,
739 environ);
742 privp= NULL;
743 if (rp->r_set_resources)
745 init_privs(rp, &rp->r_priv);
746 privp= &rp->r_priv;
748 /* Inform the PCI server about the driver */
749 init_pci(rp, child_proc_nr_e);
752 /* Set the privilege structure for the child process to let is run.
753 * This should succeed: we tested number in use above.
755 if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_INIT, 0, privp)) < 0) {
756 report("RS","sys_privctl call failed", s); /* to let child run */
757 rp->r_flags |= RS_EXITING; /* expect exit */
758 if(child_pid > 0) kill(child_pid, SIGKILL); /* kill driver */
759 else report("RS", "didn't kill pid", child_pid);
760 return(s); /* return error */
763 if (rp->r_dev_nr > 0) { /* set driver map */
764 if ((s=mapdriver(child_proc_nr_e, rp->r_dev_nr, rp->r_dev_style,
765 !!use_copy /* force */)) < 0) {
766 report("RS", "couldn't map driver", errno);
767 rp->r_flags |= RS_EXITING; /* expect exit */
768 if(child_pid > 0) kill(child_pid, SIGKILL); /* kill driver */
769 else report("RS", "didn't kill pid", child_pid);
770 return(s); /* return error */
774 if(rs_verbose)
775 printf("RS: started '%s', major %d, pid %d, endpoint %d, proc %d\n",
776 rp->r_cmd, rp->r_dev_nr, child_pid,
777 child_proc_nr_e, child_proc_nr_n);
779 /* The system service now has been successfully started. Update the rest
780 * of the system process table that is maintain by the RS server. The only
781 * thing that can go wrong now, is that execution fails at the child. If
782 * that's the case, the child will exit.
784 child_proc_nr_n = _ENDPOINT_P(child_proc_nr_e);
785 rp->r_flags = RS_IN_USE | flags; /* mark slot in use */
786 rp->r_restarts += 1; /* raise nr of restarts */
787 rp->r_proc_nr_e = child_proc_nr_e; /* set child details */
788 rp->r_pid = child_pid;
789 rp->r_check_tm = 0; /* not check yet */
790 getuptime(&rp->r_alive_tm); /* currently alive */
791 rp->r_stop_tm = 0; /* not exiting yet */
792 rproc_ptr[child_proc_nr_n] = rp; /* mapping for fast access */
794 if(endpoint) *endpoint = child_proc_nr_e; /* send back child endpoint */
795 return(OK);
798 /*===========================================================================*
799 * stop_service *
800 *===========================================================================*/
801 PRIVATE int stop_service(rp,how)
802 struct rproc *rp;
803 int how;
805 /* Try to stop the system service. First send a SIGTERM signal to ask the
806 * system service to terminate. If the service didn't install a signal
807 * handler, it will be killed. If it did and ignores the signal, we'll
808 * find out because we record the time here and send a SIGKILL.
810 if(rs_verbose) printf("RS tries to stop %s (pid %d)\n", rp->r_cmd, rp->r_pid);
812 rp->r_flags |= how; /* what to on exit? */
813 if(rp->r_pid > 0) kill(rp->r_pid, SIGTERM); /* first try friendly */
814 else if(rs_verbose) printf("RS: no process to kill\n");
815 getuptime(&rp->r_stop_tm); /* record current time */
819 /*===========================================================================*
820 * do_getsysinfo *
821 *===========================================================================*/
822 PUBLIC int do_getsysinfo(m_ptr)
823 message *m_ptr;
825 vir_bytes src_addr, dst_addr;
826 int dst_proc;
827 size_t len;
828 int s;
830 switch(m_ptr->m1_i1) {
831 case SI_PROC_TAB:
832 src_addr = (vir_bytes) rproc;
833 len = sizeof(struct rproc) * NR_SYS_PROCS;
834 break;
835 default:
836 return(EINVAL);
839 dst_proc = m_ptr->m_source;
840 dst_addr = (vir_bytes) m_ptr->m1_p1;
841 if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
842 return(s);
843 return(OK);
846 PRIVATE pid_t fork_nb()
848 message m;
850 return(_syscall(PM_PROC_NR, FORK_NB, &m));
853 PRIVATE int read_exec(rp)
854 struct rproc *rp;
856 int e, r, fd;
857 char *e_name;
858 struct stat sb;
860 e_name= rp->r_argv[0];
861 r= stat(e_name, &sb);
862 if (r != 0)
863 return -errno;
865 fd= open(e_name, O_RDONLY);
866 if (fd == -1)
867 return -errno;
869 rp->r_exec_len= sb.st_size;
870 rp->r_exec= malloc(rp->r_exec_len);
871 if (rp->r_exec == NULL)
873 printf("RS: read_exec: unable to allocate %d bytes\n",
874 rp->r_exec_len);
875 close(fd);
876 return ENOMEM;
879 r= read(fd, rp->r_exec, rp->r_exec_len);
880 e= errno;
881 close(fd);
882 if (r == rp->r_exec_len)
883 return OK;
885 printf("RS: read_exec: read failed %d, errno %d\n", r, e);
887 free(rp->r_exec);
888 rp->r_exec= NULL;
890 if (r >= 0)
891 return EIO;
892 else
893 return -e;
896 /*===========================================================================*
897 * run_script *
898 *===========================================================================*/
899 PRIVATE void run_script(rp)
900 struct rproc *rp;
902 int r, proc_nr_e;
903 pid_t pid;
904 char *reason;
905 char incarnation_str[20]; /* Enough for a counter? */
907 if (rp->r_flags & RS_EXITING)
908 reason= "exit";
909 else if (rp->r_flags & RS_REFRESHING)
910 reason= "restart";
911 else if (rp->r_flags & RS_NOPINGREPLY)
912 reason= "no-heartbeat";
913 else if (rp->r_flags & RS_KILLED)
914 reason= "killed";
915 else if (rp->r_flags & RS_CRASHED)
916 reason= "crashed";
917 else
919 printf(
920 "RS: run_script: can't find reason for termination of '%s'\n",
921 rp->r_label);
922 return;
924 sprintf(incarnation_str, "%d", rp->r_restarts);
926 if(rs_verbose) {
927 printf("RS: should call script '%s'\n", rp->r_script);
928 printf("RS: sevice name: '%s'\n", rp->r_label);
929 printf("RS: reason: '%s'\n", reason);
930 printf("RS: incarnation: '%s'\n", incarnation_str);
933 pid= fork();
934 switch(pid)
936 case -1:
937 printf("RS: run_script: fork failed: %s\n", strerror(errno));
938 break;
939 case 0:
940 execle(rp->r_script, rp->r_script, rp->r_label, reason,
941 incarnation_str, NULL, NULL);
943 extern int kputc_use_private_grants;
944 kputc_use_private_grants= 1;
946 printf("RS: run_script: execl '%s' failed: %s\n",
947 rp->r_script, strerror(errno));
948 exit(1);
949 default:
950 /* Set the privilege structure for the child process to let it
951 * run.
953 proc_nr_e = getnprocnr(pid);
954 r= sys_privctl(proc_nr_e, SYS_PRIV_USER, 0, NULL);
955 if (r < 0)
956 printf("RS: run_script: sys_privctl call failed: %d\n", r);
958 /* Do not wait for the child */
959 break;
964 /*===========================================================================*
965 * init_privs *
966 *===========================================================================*/
967 PRIVATE void init_privs(rp, privp)
968 struct rproc *rp;
969 struct priv *privp;
971 int i, src_bits_per_word, dst_bits_per_word, src_word, dst_word,
972 src_bit, call_nr;
973 unsigned long mask;
975 /* Clear s_k_call_mask */
976 memset(privp->s_k_call_mask, '\0', sizeof(privp->s_k_call_mask));
978 src_bits_per_word= 8*sizeof(rp->r_call_mask[0]);
979 dst_bits_per_word= 8*sizeof(privp->s_k_call_mask[0]);
980 for (src_word= 0; src_word < MAX_NR_SYSTEM; src_word++)
982 for (src_bit= 0; src_bit < src_bits_per_word; src_bit++)
984 mask= (1UL << src_bit);
985 if (!(rp->r_call_mask[src_word] & mask))
986 continue;
987 call_nr= src_word*src_bits_per_word+src_bit;
988 if(rs_verbose)
989 printf("RS: init_privs: system call %d\n", call_nr);
990 dst_word= call_nr / dst_bits_per_word;
991 mask= (1UL << (call_nr % dst_bits_per_word));
992 if (dst_word >= CALL_MASK_SIZE)
994 printf(
995 "RS: init_privs: call number %d doesn't fit\n",
996 call_nr);
998 privp->s_k_call_mask[dst_word] |= mask;
1004 /*===========================================================================*
1005 * init_pci *
1006 *===========================================================================*/
1007 PRIVATE void init_pci(rp, endpoint)
1008 struct rproc *rp;
1009 int endpoint;
1011 /* Tell the PCI driver about the new driver */
1012 size_t len;
1013 int i, r;
1014 struct rs_pci rs_pci;
1016 if (strcmp(rp->r_label, "pci") == 0)
1018 if(rs_verbose)
1019 printf("RS: init_pci: not when starting 'pci'\n");
1020 return;
1023 len= strlen(rp->r_label);
1024 if (len+1 > sizeof(rs_pci.rsp_label))
1026 if(rs_verbose)
1027 printf("RS: init_pci: label '%s' too long for rsp_label\n",
1028 rp->r_label);
1029 return;
1031 strcpy(rs_pci.rsp_label, rp->r_label);
1032 rs_pci.rsp_endpoint= endpoint;
1034 rs_pci.rsp_nr_device= rp->r_nr_pci_id;
1035 if (rs_pci.rsp_nr_device > RSP_NR_DEVICE)
1037 printf("RS: init_pci: too many PCI devices (max %d) "
1038 "truncating\n",
1039 RSP_NR_DEVICE);
1040 rs_pci.rsp_nr_device= RSP_NR_DEVICE;
1042 for (i= 0; i<rs_pci.rsp_nr_device; i++)
1044 rs_pci.rsp_device[i].vid= rp->r_pci_id[i].vid;
1045 rs_pci.rsp_device[i].did= rp->r_pci_id[i].did;
1048 rs_pci.rsp_nr_class= rp->r_nr_pci_class;
1049 if (rs_pci.rsp_nr_class > RSP_NR_CLASS)
1051 printf("RS: init_pci: too many PCI classes "
1052 "(max %d) truncating\n",
1053 RSP_NR_CLASS);
1054 rs_pci.rsp_nr_class= RSP_NR_CLASS;
1056 for (i= 0; i<rs_pci.rsp_nr_class; i++)
1058 rs_pci.rsp_class[i].class= rp->r_pci_class[i].class;
1059 rs_pci.rsp_class[i].mask= rp->r_pci_class[i].mask;
1062 if(rs_verbose)
1063 printf("RS: init_pci: calling pci_set_acl\n");
1065 r= pci_set_acl(&rs_pci);
1067 if(rs_verbose)
1068 printf("RS: init_pci: after pci_set_acl\n");
1070 if (r != OK)
1072 printf("RS: init_pci: pci_set_acl failed: %s\n",
1073 strerror(errno));
1074 return;