RS_LOOKUP feature for libc functions that want to access servers.
[minix.git] / servers / rs / manager.c
blobcd1ae0e37406caaf429dc4380cc02df90ba6319e
1 /*
2 * Changes:
3 * Jul 22, 2005: Created (Jorrit N. Herder)
4 */
6 #include "inc.h"
7 #include <ctype.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <sys/wait.h>
13 #include <sys/vm.h>
14 #include <minix/dmap.h>
15 #include <minix/ds.h>
16 #include <minix/endpoint.h>
17 #include <minix/vm.h>
18 #include <minix/rs.h>
19 #include <lib.h>
21 #include <timers.h> /* For priv.h */
22 #include "../../kernel/priv.h"
24 /* Allocate variables. */
25 struct rproc rproc[NR_SYS_PROCS]; /* system process table */
26 struct rproc *rproc_ptr[NR_PROCS]; /* mapping for fast access */
28 /* Prototypes for internal functions that do the hard work. */
29 FORWARD _PROTOTYPE( int start_service, (struct rproc *rp, int flags,
30 endpoint_t *ep) );
31 FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp,int how) );
32 FORWARD _PROTOTYPE( int fork_nb, (void) );
33 FORWARD _PROTOTYPE( int read_exec, (struct rproc *rp) );
34 FORWARD _PROTOTYPE( int copy_exec, (struct rproc *rp_src,
35 struct rproc *rp_dst) );
36 FORWARD _PROTOTYPE( void run_script, (struct rproc *rp) );
37 FORWARD _PROTOTYPE( char *get_next_label, (char *ptr, char *label,
38 char *caller_label) );
39 FORWARD _PROTOTYPE( void add_forward_ipc, (struct rproc *rp,
40 struct priv *privp) );
41 FORWARD _PROTOTYPE( void add_backward_ipc, (struct rproc *rp,
42 struct priv *privp) );
43 FORWARD _PROTOTYPE( void init_privs, (struct rproc *rp, struct priv *privp) );
44 FORWARD _PROTOTYPE( void init_pci, (struct rproc *rp, int endpoint) );
46 PRIVATE int shutting_down = FALSE;
48 extern int rs_verbose;
50 /*===========================================================================*
51 * do_up *
52 *===========================================================================*/
53 PUBLIC int do_up(m_ptr, do_copy, flags)
54 message *m_ptr; /* request message pointer */
55 int do_copy; /* keep copy in memory */
56 int flags; /* extra flags, if any */
58 /* A request was made to start a new system service. Dismember the request
59 * message and gather all information needed to start the service. Starting
60 * is done by a helper routine.
62 register struct rproc *rp; /* system process table */
63 int slot_nr; /* local table entry */
64 int arg_count; /* number of arguments */
65 char *cmd_ptr; /* parse command string */
66 char *label; /* unique name of command */
67 enum dev_style dev_style; /* device style */
68 int s; /* status variable */
69 int len; /* length of string */
70 int r;
71 endpoint_t ep; /* new endpoint no. */
73 /* See if there is a free entry in the table with system processes. */
74 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
75 rp = &rproc[slot_nr]; /* get pointer to slot */
76 if (! rp->r_flags & RS_IN_USE) /* check if available */
77 break;
80 /* Obtain command name and parameters. This is a space-separated string
81 * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
83 if (m_ptr->RS_CMD_LEN > MAX_COMMAND_LEN) return(E2BIG);
84 if (OK!=(s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
85 SELF, (vir_bytes) rp->r_cmd, m_ptr->RS_CMD_LEN))) return(s);
86 rp->r_cmd[m_ptr->RS_CMD_LEN] = '\0'; /* ensure it is terminated */
87 if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */
89 rp->r_script[0]= '\0';
91 /* Build argument vector to be passed to execute call. The format of the
92 * arguments vector is: path, arguments, NULL.
94 arg_count = 0; /* initialize arg count */
95 rp->r_argv[arg_count++] = rp->r_cmd; /* start with path */
96 cmd_ptr = rp->r_cmd; /* do some parsing */
97 while(*cmd_ptr != '\0') { /* stop at end of string */
98 if (*cmd_ptr == ' ') { /* next argument */
99 *cmd_ptr = '\0'; /* terminate previous */
100 while (*++cmd_ptr == ' ') ; /* skip spaces */
101 if (*cmd_ptr == '\0') break; /* no arg following */
102 if (arg_count>MAX_NR_ARGS+1) break; /* arg vector full */
103 rp->r_argv[arg_count++] = cmd_ptr; /* add to arg vector */
105 cmd_ptr ++; /* continue parsing */
107 rp->r_argv[arg_count] = NULL; /* end with NULL pointer */
108 rp->r_argc = arg_count;
110 /* Default label for the driver */
111 label= strrchr(rp->r_argv[0], '/');
112 if (label)
113 label++;
114 else
115 label= rp->r_argv[0];
116 len= strlen(label);
117 if (len > MAX_LABEL_LEN-1)
118 len= MAX_LABEL_LEN-1; /* truncate name */
119 memcpy(rp->r_label, label, len);
120 rp->r_label[len]= '\0';
121 if(rs_verbose) printf("RS: do_up: using label '%s'\n", rp->r_label);
123 rp->r_uid= 0;
124 rp->r_nice= 0;
126 rp->r_exec= NULL;
128 if (do_copy)
130 s= read_exec(rp);
131 if (s != OK)
132 return s;
135 /* Initialize some fields. */
136 rp->r_period = m_ptr->RS_PERIOD;
137 rp->r_dev_nr = m_ptr->RS_DEV_MAJOR;
138 rp->r_dev_style = STYLE_DEV;
139 rp->r_restarts = -1; /* will be incremented */
140 rp->r_set_resources= 0; /* old style */
142 /* All information was gathered. Now try to start the system service. */
144 r = start_service(rp, flags, &ep);
145 m_ptr->RS_ENDPOINT = ep;
146 return r;
150 /*===========================================================================*
151 * do_start *
152 *===========================================================================*/
153 PUBLIC int do_start(m_ptr)
154 message *m_ptr; /* request message pointer */
156 /* A request was made to start a new system service.
158 register struct rproc *rp; /* system process table */
159 int slot_nr; /* local table entry */
160 int arg_count; /* number of arguments */
161 char *cmd_ptr; /* parse command string */
162 char *label; /* unique name of command */
163 enum dev_style dev_style; /* device style */
164 int s; /* status variable */
165 int len; /* length of string */
166 int i;
167 int r;
168 endpoint_t ep;
169 struct rproc *tmp_rp;
170 struct rs_start rs_start;
172 /* Get the request structure */
173 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
174 SELF, (vir_bytes) &rs_start, sizeof(rs_start));
175 if (s != OK) return(s);
177 /* See if there is a free entry in the table with system processes. */
178 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
179 rp = &rproc[slot_nr]; /* get pointer to slot */
180 if (!(rp->r_flags & RS_IN_USE)) /* check if available */
181 break;
183 if (slot_nr >= NR_SYS_PROCS)
185 printf("rs`do_start: driver table full\n");
186 return ENOMEM;
189 /* Obtain command name and parameters. This is a space-separated string
190 * that looks like "/sbin/service arg1 arg2 ...". Arguments are optional.
192 if (rs_start.rss_cmdlen > MAX_COMMAND_LEN-1) return(E2BIG);
193 s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_cmd,
194 SELF, (vir_bytes) rp->r_cmd, rs_start.rss_cmdlen);
195 if (s != OK) return(s);
196 rp->r_cmd[rs_start.rss_cmdlen] = '\0'; /* ensure it is terminated */
197 if (rp->r_cmd[0] != '/') return(EINVAL); /* insist on absolute path */
199 /* Build argument vector to be passed to execute call. The format of the
200 * arguments vector is: path, arguments, NULL.
202 arg_count = 0; /* initialize arg count */
203 rp->r_argv[arg_count++] = rp->r_cmd; /* start with path */
204 cmd_ptr = rp->r_cmd; /* do some parsing */
205 while(*cmd_ptr != '\0') { /* stop at end of string */
206 if (*cmd_ptr == ' ') { /* next argument */
207 *cmd_ptr = '\0'; /* terminate previous */
208 while (*++cmd_ptr == ' ') ; /* skip spaces */
209 if (*cmd_ptr == '\0') break; /* no arg following */
210 if (arg_count>MAX_NR_ARGS+1) break; /* arg vector full */
211 rp->r_argv[arg_count++] = cmd_ptr; /* add to arg vector */
213 cmd_ptr ++; /* continue parsing */
215 rp->r_argv[arg_count] = NULL; /* end with NULL pointer */
216 rp->r_argc = arg_count;
218 if(rs_start.rss_label) {
219 int len;
220 /* RS_START caller has supplied a custom label for this driver. */
221 len = MIN(sizeof(rp->r_label)-1, rs_start.rss_labellen);
222 s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_label,
223 SELF, (vir_bytes) rp->r_label, len);
224 if(s != OK)
225 return s;
226 rp->r_label[len] = '\0';
227 if(rs_verbose)
228 printf("RS: do_start: using label (custom) '%s'\n", rp->r_label);
229 } else {
230 /* Default label for the driver. */
231 label= strrchr(rp->r_argv[0], '/');
232 if (label)
233 label++;
234 else
235 label= rp->r_argv[0];
236 len= strlen(label);
237 if (len > MAX_LABEL_LEN-1)
238 len= MAX_LABEL_LEN-1; /* truncate name */
239 memcpy(rp->r_label, label, len);
240 rp->r_label[len]= '\0';
241 if(rs_verbose)
242 printf("RS: do_start: using label (from binary %s) '%s'\n",
243 rp->r_argv[0], rp->r_label);
246 /* Check for duplicates */
247 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
248 tmp_rp = &rproc[slot_nr]; /* get pointer to slot */
249 if (!(tmp_rp->r_flags & RS_IN_USE)) /* check if available */
250 continue;
251 if (tmp_rp == rp)
252 continue; /* Our slot */
253 if (strcmp(tmp_rp->r_label, rp->r_label) == 0)
255 printf("RS: found duplicate label '%s': slot %d\n",
256 rp->r_label, slot_nr);
257 return EBUSY;
261 rp->r_script[0]= '\0';
262 if (rs_start.rss_scriptlen > MAX_SCRIPT_LEN-1) return(E2BIG);
263 if (rs_start.rss_script != NULL)
265 s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_script,
266 SELF, (vir_bytes) rp->r_script, rs_start.rss_scriptlen);
267 if (s != OK) return(s);
268 rp->r_script[rs_start.rss_scriptlen] = '\0';
270 rp->r_uid= rs_start.rss_uid;
271 rp->r_nice= rs_start.rss_nice;
273 if (rs_start.rss_flags & RF_IPC_VALID)
275 if (rs_start.rss_ipclen+1 > sizeof(rp->r_ipc_list))
277 printf("rs: ipc list too long for '%s'\n", rp->r_label);
278 return EINVAL;
280 s=sys_datacopy(m_ptr->m_source, (vir_bytes) rs_start.rss_ipc,
281 SELF, (vir_bytes) rp->r_ipc_list, rs_start.rss_ipclen);
282 if (s != OK) return(s);
283 rp->r_ipc_list[rs_start.rss_ipclen]= '\0';
285 else
286 rp->r_ipc_list[0]= '\0';
288 rp->r_exec= NULL;
289 if (rs_start.rss_flags & RF_COPY) {
290 int exst_cpy;
291 struct rproc *rp2;
292 exst_cpy = 0;
294 if(rs_start.rss_flags & RF_REUSE) {
295 char *cmd = rp->r_cmd;
296 int i;
298 for(i = 0; i < NR_SYS_PROCS; i++) {
299 rp2 = &rproc[i];
300 if(strcmp(rp->r_cmd, rp2->r_cmd) == 0 &&
301 rp2->r_exec != NULL) {
302 /* We have found the same binary that's
303 * already been copied */
304 exst_cpy = 1;
305 break;
310 if(!exst_cpy)
311 s = read_exec(rp);
312 else
313 s = copy_exec(rp, rp2);
315 if (s != OK)
316 return s;
319 /* Copy granted resources */
320 if (rs_start.rss_nr_irq > NR_IRQ)
322 printf("RS: do_start: too many IRQs requested\n");
323 return EINVAL;
325 rp->r_priv.s_nr_irq= rs_start.rss_nr_irq;
326 for (i= 0; i<rp->r_priv.s_nr_irq; i++)
328 rp->r_priv.s_irq_tab[i]= rs_start.rss_irq[i];
329 if(rs_verbose)
330 printf("RS: do_start: IRQ %d\n", rp->r_priv.s_irq_tab[i]);
333 if (rs_start.rss_nr_io > NR_IO_RANGE)
335 printf("RS: do_start: too many I/O ranges requested\n");
336 return EINVAL;
338 rp->r_priv.s_nr_io_range= rs_start.rss_nr_io;
339 for (i= 0; i<rp->r_priv.s_nr_io_range; i++)
341 rp->r_priv.s_io_tab[i].ior_base= rs_start.rss_io[i].base;
342 rp->r_priv.s_io_tab[i].ior_limit=
343 rs_start.rss_io[i].base+rs_start.rss_io[i].len-1;
344 #if 0
345 if(rs_verbose)
346 printf("RS: do_start: I/O [%x..%x]\n",
347 rp->r_priv.s_io_tab[i].ior_base,
348 rp->r_priv.s_io_tab[i].ior_limit);
349 #endif
352 if (rs_start.rss_nr_pci_id > MAX_NR_PCI_ID)
354 printf("RS: do_start: too many PCI device IDs\n");
355 return EINVAL;
357 rp->r_nr_pci_id= rs_start.rss_nr_pci_id;
358 for (i= 0; i<rp->r_nr_pci_id; i++)
360 rp->r_pci_id[i].vid= rs_start.rss_pci_id[i].vid;
361 rp->r_pci_id[i].did= rs_start.rss_pci_id[i].did;
362 if(rs_verbose)
363 printf("RS: do_start: PCI %04x/%04x\n",
364 rp->r_pci_id[i].vid, rp->r_pci_id[i].did);
366 if (rs_start.rss_nr_pci_class > MAX_NR_PCI_CLASS)
368 printf("RS: do_start: too many PCI class IDs\n");
369 return EINVAL;
371 rp->r_nr_pci_class= rs_start.rss_nr_pci_class;
372 for (i= 0; i<rp->r_nr_pci_class; i++)
374 rp->r_pci_class[i].class= rs_start.rss_pci_class[i].class;
375 rp->r_pci_class[i].mask= rs_start.rss_pci_class[i].mask;
376 if(rs_verbose)
377 printf("RS: do_start: PCI class %06x mask %06x\n",
378 rp->r_pci_class[i].class, rp->r_pci_class[i].mask);
381 /* Copy 'system' call number bits */
382 if (sizeof(rs_start.rss_system[0]) == sizeof(rp->r_call_mask[0]) &&
383 sizeof(rs_start.rss_system) == sizeof(rp->r_call_mask))
385 for (i= 0; i<RSS_NR_SYSTEM; i++)
386 rp->r_call_mask[i]= rs_start.rss_system[i];
388 else
390 printf(
391 "RS: do_start: internal inconsistency: bad size of r_call_mask\n");
392 memset(rp->r_call_mask, '\0', sizeof(rp->r_call_mask));
395 /* Initialize some fields. */
396 rp->r_period = rs_start.rss_period;
397 rp->r_dev_nr = rs_start.rss_major;
398 rp->r_dev_style = STYLE_DEV;
399 rp->r_restarts = -1; /* will be incremented */
400 rp->r_set_resources= 1; /* new style, enforece
401 * I/O resources
403 if (sizeof(rp->r_vm) == sizeof(rs_start.rss_vm) &&
404 sizeof(rp->r_vm[0]) == sizeof(rs_start.rss_vm[0]))
406 memcpy(rp->r_vm, rs_start.rss_vm, sizeof(rp->r_vm));
408 else
410 printf("RS: do_start: internal inconsistency: bad size of r_vm\n");
411 memset(rp->r_vm, '\0', sizeof(rp->r_vm));
414 /* All information was gathered. Now try to start the system service. */
415 r = start_service(rp, 0, &ep);
416 m_ptr->RS_ENDPOINT = ep;
417 return r;
421 /*===========================================================================*
422 * do_down *
423 *===========================================================================*/
424 PUBLIC int do_down(message *m_ptr)
426 register struct rproc *rp;
427 size_t len;
428 int s, proc;
429 char label[MAX_LABEL_LEN];
431 len= m_ptr->RS_CMD_LEN;
432 if (len >= sizeof(label))
433 return EINVAL; /* Too long */
435 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
436 SELF, (vir_bytes) label, len);
437 if (s != OK) return(s);
438 label[len]= '\0';
440 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
441 if (rp->r_flags & RS_IN_USE && strcmp(rp->r_label, label) == 0) {
442 if(rs_verbose)
443 printf("RS: stopping '%s' (%d)\n", label, rp->r_pid);
444 stop_service(rp,RS_EXITING);
445 if (rp->r_pid == -1)
447 /* Process is already gone */
448 rp->r_flags = 0; /* release slot */
449 if (rp->r_exec)
451 free(rp->r_exec);
452 rp->r_exec= NULL;
454 proc = _ENDPOINT_P(rp->r_proc_nr_e);
455 rproc_ptr[proc] = NULL;
456 return(OK);
459 /* Late reply - send a reply when process dies. */
460 rp->r_flags |= RS_LATEREPLY;
461 rp->r_caller = m_ptr->m_source;
462 return EDONTREPLY;
465 if(rs_verbose) printf("RS: do_down: '%s' not found\n", label);
466 return(ESRCH);
470 /*===========================================================================*
471 * do_restart *
472 *===========================================================================*/
473 PUBLIC int do_restart(message *m_ptr)
475 register struct rproc *rp;
476 size_t len;
477 int s, proc, r;
478 char label[MAX_LABEL_LEN];
479 endpoint_t ep;
481 len= m_ptr->RS_CMD_LEN;
482 if (len >= sizeof(label))
483 return EINVAL; /* Too long */
485 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
486 SELF, (vir_bytes) label, len);
487 if (s != OK) return(s);
488 label[len]= '\0';
490 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
491 if ((rp->r_flags & RS_IN_USE) && strcmp(rp->r_label, label) == 0) {
492 if(rs_verbose) printf("RS: restarting '%s' (%d)\n", label, rp->r_pid);
493 if (rp->r_pid >= 0)
495 if(rs_verbose)
496 printf("RS: do_restart: '%s' is (still) running, pid = %d\n",
497 rp->r_pid);
498 return EBUSY;
500 rp->r_flags &= ~(RS_EXITING|RS_REFRESHING|RS_NOPINGREPLY);
501 r = start_service(rp, 0, &ep);
502 if (r != OK) printf("do_restart: start_service failed: %d\n", r);
503 m_ptr->RS_ENDPOINT = ep;
504 return(r);
507 #if VERBOSE
508 printf("RS: do_restart: '%s' not found\n", label);
509 #endif
510 return(ESRCH);
514 /*===========================================================================*
515 * do_refresh *
516 *===========================================================================*/
517 PUBLIC int do_refresh(message *m_ptr)
519 register struct rproc *rp;
520 size_t len;
521 int s;
522 char label[MAX_LABEL_LEN];
524 len= m_ptr->RS_CMD_LEN;
525 if (len >= sizeof(label))
526 return EINVAL; /* Too long */
528 s= sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_CMD_ADDR,
529 SELF, (vir_bytes) label, len);
530 if (s != OK) return(s);
531 label[len]= '\0';
533 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
534 if (rp->r_flags & RS_IN_USE && strcmp(rp->r_label, label) == 0) {
535 #if VERBOSE
536 printf("RS: refreshing %s (%d)\n", rp->r_label, rp->r_pid);
537 #endif
538 stop_service(rp,RS_REFRESHING);
539 return(OK);
542 #if VERBOSE
543 printf("RS: do_refresh: '%s' not found\n", label);
544 #endif
545 return(ESRCH);
548 /*===========================================================================*
549 * do_shutdown *
550 *===========================================================================*/
551 PUBLIC int do_shutdown(message *m_ptr)
553 /* Set flag so that RS server knows services shouldn't be restarted. */
554 shutting_down = TRUE;
555 return(OK);
558 /*===========================================================================*
559 * do_exit *
560 *===========================================================================*/
561 PUBLIC void do_exit(message *m_ptr)
563 register struct rproc *rp;
564 pid_t exit_pid;
565 int exit_status, r, slot_nr;
566 endpoint_t ep;
568 if(rs_verbose)
569 printf("RS: got SIGCHLD signal, doing wait to get exited child.\n");
571 /* See which child exited and what the exit status is. This is done in a
572 * loop because multiple children may have exited, all reported by one
573 * SIGCHLD signal. The WNOHANG options is used to prevent blocking if,
574 * somehow, no exited child can be found.
576 while ( (exit_pid = waitpid(-1, &exit_status, WNOHANG)) != 0 ) {
578 if(rs_verbose) {
579 #if 0
580 printf("RS: pid %d, ", exit_pid);
581 #endif
582 if (WIFSIGNALED(exit_status)) {
583 #if 0
584 printf("killed, signal number %d\n", WTERMSIG(exit_status));
585 #endif
587 else if (WIFEXITED(exit_status)) {
588 #if 0
589 printf("normal exit, status %d\n", WEXITSTATUS(exit_status));
590 #endif
594 /* Read from the exec pipe */
595 for (;;)
597 r= read(exec_pipe[0], &slot_nr, sizeof(slot_nr));
598 if (r == -1)
600 break; /* No data */
602 if (r != sizeof(slot_nr))
604 panic("RS", "do_exit: unaligned read from exec pipe",
607 printf("do_exit: got slot %d\n", slot_nr);
608 if (slot_nr < 0 || slot_nr >= NR_SYS_PROCS)
610 panic("RS", "do_exit: bad slot number from exec pipe",
611 slot_nr);
613 rp= &rproc[slot_nr];
614 rp->r_flags |= RS_EXECFAILED;
617 /* Search the system process table to see who exited.
618 * This should always succeed.
620 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
621 if ((rp->r_flags & RS_IN_USE) && rp->r_pid == exit_pid) {
622 int proc;
623 proc = _ENDPOINT_P(rp->r_proc_nr_e);
625 rproc_ptr[proc] = NULL; /* invalidate */
626 rp->r_pid= -1;
628 pci_del_acl(rp->r_proc_nr_e); /* Ignore errors */
630 if ((rp->r_flags & RS_EXITING) || shutting_down) {
631 /* No reply sent to RS_DOWN yet. */
632 if(rp->r_flags & RS_LATEREPLY) {
633 message rsm;
634 rsm.m_type = OK;
635 send(rp->r_caller, &rsm);
638 /* Release slot. */
639 rp->r_flags = 0;
640 if (rp->r_exec)
642 free(rp->r_exec);
643 rp->r_exec= NULL;
645 rproc_ptr[proc] = NULL;
648 else if(rp->r_flags & RS_REFRESHING) {
649 rp->r_restarts = -1; /* reset counter */
650 if (rp->r_script[0] != '\0')
651 run_script(rp);
652 else {
653 start_service(rp, 0, &ep); /* direct restart */
654 if(m_ptr)
655 m_ptr->RS_ENDPOINT = ep;
658 else if (rp->r_flags & RS_EXECFAILED) {
659 rp->r_flags = 0; /* release slot */
661 else {
662 /* Determine what to do. If this is the first unexpected
663 * exit, immediately restart this service. Otherwise use
664 * a binary exponetial backoff.
666 #if 0
667 rp->r_restarts= 0;
668 #endif
669 if (WIFSIGNALED(exit_status)) {
670 switch(WTERMSIG(exit_status))
672 case SIGKILL: rp->r_flags |= RS_KILLED; break;
673 default: rp->r_flags |= RS_SIGNALED; break;
676 else
677 rp->r_flags |= RS_CRASHED;
679 if (rp->r_script[0] != '\0') {
680 if(rs_verbose)
681 printf("RS: running restart script for %s\n",
682 rp->r_cmd);
683 run_script(rp);
684 } else if (rp->r_restarts > 0) {
685 printf("RS: restarting %s, restarts %d\n",
686 rp->r_cmd, rp->r_backoff);
687 rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
688 rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF);
689 if (rp->r_exec != NULL && rp->r_backoff > 1)
690 rp->r_backoff= 1;
692 else {
693 printf("RS: restarting %s\n", rp->r_cmd);
694 start_service(rp, 0, &ep); /* direct restart */
695 if(m_ptr)
696 m_ptr->RS_ENDPOINT = ep;
697 /* Do this even if no I/O happens with the ioctl, in
698 * order to disambiguate requests with DEV_IOCTL_S.
702 break;
708 /*===========================================================================*
709 * do_period *
710 *===========================================================================*/
711 PUBLIC void do_period(m_ptr)
712 message *m_ptr;
714 register struct rproc *rp;
715 clock_t now = m_ptr->NOTIFY_TIMESTAMP;
716 int s;
717 endpoint_t ep;
719 /* Search system services table. Only check slots that are in use. */
720 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
721 if (rp->r_flags & RS_IN_USE) {
723 /* If the service is to be revived (because it repeatedly exited,
724 * and was not directly restarted), the binary backoff field is
725 * greater than zero.
727 if (rp->r_backoff > 0) {
728 rp->r_backoff -= 1;
729 if (rp->r_backoff == 0) {
730 start_service(rp, 0, &ep);
731 m_ptr->RS_ENDPOINT = ep;
735 /* If the service was signaled with a SIGTERM and fails to respond,
736 * kill the system service with a SIGKILL signal.
738 else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
739 && rp->r_pid > 0) {
740 kill(rp->r_pid, SIGKILL); /* terminate */
743 /* There seems to be no special conditions. If the service has a
744 * period assigned check its status.
746 else if (rp->r_period > 0) {
748 /* Check if an answer to a status request is still pending. If
749 * the driver didn't respond within time, kill it to simulate
750 * a crash. The failure will be detected and the service will
751 * be restarted automatically.
753 if (rp->r_alive_tm < rp->r_check_tm) {
754 if (now - rp->r_alive_tm > 2*rp->r_period &&
755 rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) {
756 if(rs_verbose)
757 printf("RS: service %d reported late\n",
758 rp->r_proc_nr_e);
759 rp->r_flags |= RS_NOPINGREPLY;
760 kill(rp->r_pid, SIGKILL); /* simulate crash */
764 /* No answer pending. Check if a period expired since the last
765 * check and, if so request the system service's status.
767 else if (now - rp->r_check_tm > rp->r_period) {
768 if(rs_verbose)
769 printf("RS: status request sent to %d\n", rp->r_proc_nr_e);
770 notify(rp->r_proc_nr_e); /* request status */
771 rp->r_check_tm = now; /* mark time */
777 /* Reschedule a synchronous alarm for the next period. */
778 if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
779 panic("RS", "couldn't set alarm", s);
783 /*===========================================================================*
784 * start_service *
785 *===========================================================================*/
786 PRIVATE int start_service(rp, flags, endpoint)
787 struct rproc *rp;
788 int flags;
789 endpoint_t *endpoint;
791 /* Try to execute the given system service. Fork a new process. The child
792 * process will be inhibited from running by the NO_PRIV flag. Only let the
793 * child run once its privileges have been set by the parent.
795 int child_proc_nr_e, child_proc_nr_n; /* child process slot */
796 pid_t child_pid; /* child's process id */
797 char *file_only;
798 int s, use_copy, slot_nr;
799 struct priv *privp;
800 bitchunk_t *vm_mask;
801 message m;
802 char * null_env = NULL;
804 use_copy= (rp->r_exec != NULL);
806 /* Now fork and branch for parent and child process (and check for error). */
807 if (use_copy) {
808 if(rs_verbose) printf("RS: fork_nb..\n");
809 child_pid= fork_nb();
810 } else {
811 if(rs_verbose) printf("RS: fork regular..\n");
812 child_pid = fork();
815 switch(child_pid) { /* see fork(2) */
816 case -1: /* fork failed */
817 report("RS", "warning, fork() failed", errno); /* shouldn't happen */
818 return(errno); /* return error */
820 case 0: /* child process */
821 /* Try to execute the binary that has an absolute path. If this fails,
822 * e.g., because the root file system cannot be read, try to strip of
823 * the path, and see if the command is in RS' current working dir.
825 nice(rp->r_nice); /* Nice before setuid, to allow negative
826 * nice values.
828 setuid(rp->r_uid);
829 cpf_reload(); /* Tell kernel about grant table */
830 if (!use_copy)
832 execve(rp->r_argv[0], rp->r_argv, &null_env); /* POSIX execute */
833 file_only = strrchr(rp->r_argv[0], '/') + 1;
834 execve(file_only, rp->r_argv, &null_env); /* POSIX execute */
836 printf("RS: exec failed for %s: %d\n", rp->r_argv[0], errno);
837 slot_nr= rp-rproc;
838 s= write(exec_pipe[1], &slot_nr, sizeof(slot_nr));
839 if (s != sizeof(slot_nr))
840 printf("RS: write to exec pipe failed: %d/%d\n", s, errno);
841 exit(1); /* terminate child */
843 default: /* parent process */
844 #if 0
845 if(rs_verbose) printf("RS: parent forked, pid %d..\n", child_pid);
846 #endif
847 child_proc_nr_e = getnprocnr(child_pid); /* get child slot */
848 #if 0
849 if(rs_verbose) printf("RS: forked into %d..\n", child_proc_nr_e);
850 #endif
851 break; /* continue below */
854 if (use_copy)
856 extern char **environ;
857 dev_execve(child_proc_nr_e, rp->r_exec, rp->r_exec_len, rp->r_argv,
858 environ);
861 privp= NULL;
862 vm_mask = NULL;
863 if (rp->r_set_resources)
865 init_privs(rp, &rp->r_priv);
866 privp= &rp->r_priv;
868 /* Inform the PCI server about the driver */
869 init_pci(rp, child_proc_nr_e);
871 vm_mask = &rp->r_vm[0];
874 /* Set the privilege structure for the child process to let is run.
875 * This should succeed: we tested number in use above.
877 if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_INIT, privp)) < 0) {
878 report("RS","sys_privctl call failed", s); /* to let child run */
879 rp->r_flags |= RS_EXITING; /* expect exit */
880 if(child_pid > 0) kill(child_pid, SIGKILL); /* kill driver */
881 else report("RS", "didn't kill pid", child_pid);
882 return(s); /* return error */
885 if ((s = vm_set_priv(child_proc_nr_e, vm_mask)) < 0) {
886 report("RS", "vm_set_priv call failed", s);
887 rp->r_flags |= RS_EXITING;
888 if (child_pid > 0) kill(child_pid, SIGKILL);
889 else report("RS", "didn't kill pid", child_pid);
890 return (s);
893 s= ds_publish_u32(rp->r_label, child_proc_nr_e);
894 if (s != OK)
895 printf("RS: start_service: ds_publish_u32 failed: %d\n", s);
896 else if(rs_verbose)
897 printf("RS: start_service: ds_publish_u32 done: %s -> %d\n",
898 rp->r_label, child_proc_nr_e);
900 if (rp->r_dev_nr > 0) { /* set driver map */
901 if ((s=mapdriver5(rp->r_label, strlen(rp->r_label),
902 rp->r_dev_nr, rp->r_dev_style, !!use_copy /* force */)) < 0) {
903 report("RS", "couldn't map driver (continuing)", errno);
904 #if 0
905 rp->r_flags |= RS_EXITING; /* expect exit */
906 if(child_pid > 0) kill(child_pid, SIGKILL); /* kill driver */
907 else report("RS", "didn't kill pid", child_pid);
908 return(s); /* return error */
909 #endif
913 if(rs_verbose)
914 printf("RS: started '%s', major %d, pid %d, endpoint %d, proc %d\n",
915 rp->r_cmd, rp->r_dev_nr, child_pid,
916 child_proc_nr_e, child_proc_nr_n);
918 /* The system service now has been successfully started. Update the rest
919 * of the system process table that is maintain by the RS server. The only
920 * thing that can go wrong now, is that execution fails at the child. If
921 * that's the case, the child will exit.
923 child_proc_nr_n = _ENDPOINT_P(child_proc_nr_e);
924 rp->r_flags = RS_IN_USE | flags; /* mark slot in use */
925 rp->r_restarts += 1; /* raise nr of restarts */
926 rp->r_proc_nr_e = child_proc_nr_e; /* set child details */
927 rp->r_pid = child_pid;
928 rp->r_check_tm = 0; /* not check yet */
929 getuptime(&rp->r_alive_tm); /* currently alive */
930 rp->r_stop_tm = 0; /* not exiting yet */
931 rproc_ptr[child_proc_nr_n] = rp; /* mapping for fast access */
933 if(endpoint) *endpoint = child_proc_nr_e; /* send back child endpoint */
935 return(OK);
938 /*===========================================================================*
939 * stop_service *
940 *===========================================================================*/
941 PRIVATE int stop_service(rp,how)
942 struct rproc *rp;
943 int how;
945 /* Try to stop the system service. First send a SIGTERM signal to ask the
946 * system service to terminate. If the service didn't install a signal
947 * handler, it will be killed. If it did and ignores the signal, we'll
948 * find out because we record the time here and send a SIGKILL.
950 if(rs_verbose) printf("RS tries to stop %s (pid %d)\n", rp->r_cmd, rp->r_pid);
952 rp->r_flags |= how; /* what to on exit? */
953 if(rp->r_pid > 0) kill(rp->r_pid, SIGTERM); /* first try friendly */
954 else if(rs_verbose) printf("RS: no process to kill\n");
955 getuptime(&rp->r_stop_tm); /* record current time */
959 /*===========================================================================*
960 * do_getsysinfo *
961 *===========================================================================*/
962 PUBLIC int do_getsysinfo(m_ptr)
963 message *m_ptr;
965 vir_bytes src_addr, dst_addr;
966 int dst_proc;
967 size_t len;
968 int s;
970 switch(m_ptr->m1_i1) {
971 case SI_PROC_TAB:
972 src_addr = (vir_bytes) rproc;
973 len = sizeof(struct rproc) * NR_SYS_PROCS;
974 break;
975 default:
976 return(EINVAL);
979 dst_proc = m_ptr->m_source;
980 dst_addr = (vir_bytes) m_ptr->m1_p1;
981 if (OK != (s=sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len)))
982 return(s);
983 return(OK);
986 PRIVATE pid_t fork_nb()
988 message m;
990 return(_syscall(PM_PROC_NR, FORK_NB, &m));
993 PRIVATE int copy_exec(rp_dst, rp_src)
994 struct rproc *rp_dst, *rp_src;
996 /* Copy binary from rp_src to rp_dst. */
997 rp_dst->r_exec_len = rp_src->r_exec_len;
998 rp_dst->r_exec = malloc(rp_dst->r_exec_len);
999 if(rp_dst->r_exec == NULL)
1000 return ENOMEM;
1002 memcpy(rp_dst->r_exec, rp_src->r_exec, rp_dst->r_exec_len);
1003 if(rp_dst->r_exec_len != 0 && rp_dst->r_exec != NULL)
1004 return OK;
1006 rp_dst->r_exec = NULL;
1007 return EIO;
1010 PRIVATE int read_exec(rp)
1011 struct rproc *rp;
1013 int e, r, fd;
1014 char *e_name;
1015 struct stat sb;
1018 e_name= rp->r_argv[0];
1019 r= stat(e_name, &sb);
1020 if (r != 0)
1021 return -errno;
1023 fd= open(e_name, O_RDONLY);
1024 if (fd == -1)
1025 return -errno;
1027 rp->r_exec_len= sb.st_size;
1028 rp->r_exec= malloc(rp->r_exec_len);
1029 if (rp->r_exec == NULL)
1031 printf("RS: read_exec: unable to allocate %d bytes\n",
1032 rp->r_exec_len);
1033 close(fd);
1034 return ENOMEM;
1037 r= read(fd, rp->r_exec, rp->r_exec_len);
1038 e= errno;
1039 close(fd);
1040 if (r == rp->r_exec_len)
1041 return OK;
1043 printf("RS: read_exec: read failed %d, errno %d\n", r, e);
1045 free(rp->r_exec);
1046 rp->r_exec= NULL;
1048 if (r >= 0)
1049 return EIO;
1050 else
1051 return -e;
1054 /*===========================================================================*
1055 * run_script *
1056 *===========================================================================*/
1057 PRIVATE void run_script(rp)
1058 struct rproc *rp;
1060 int r, proc_nr_e;
1061 pid_t pid;
1062 char *reason;
1063 char incarnation_str[20]; /* Enough for a counter? */
1064 char *envp[1] = { NULL };
1066 if (rp->r_flags & RS_EXITING)
1067 reason= "exit";
1068 else if (rp->r_flags & RS_REFRESHING)
1069 reason= "restart";
1070 else if (rp->r_flags & RS_NOPINGREPLY)
1071 reason= "no-heartbeat";
1072 else if (rp->r_flags & RS_KILLED)
1073 reason= "killed";
1074 else if (rp->r_flags & RS_CRASHED)
1075 reason= "crashed";
1076 else if (rp->r_flags & RS_SIGNALED)
1077 reason= "signaled";
1078 else
1080 printf(
1081 "RS: run_script: can't find reason for termination of '%s'\n",
1082 rp->r_label);
1083 return;
1085 sprintf(incarnation_str, "%d", rp->r_restarts);
1087 if(rs_verbose) {
1088 printf("RS: calling script '%s'\n", rp->r_script);
1089 printf("RS: sevice name: '%s'\n", rp->r_label);
1090 printf("RS: reason: '%s'\n", reason);
1091 printf("RS: incarnation: '%s'\n", incarnation_str);
1094 pid= fork();
1095 switch(pid)
1097 case -1:
1098 printf("RS: run_script: fork failed: %s\n", strerror(errno));
1099 break;
1100 case 0:
1101 execle(rp->r_script, rp->r_script, rp->r_label, reason,
1102 incarnation_str, NULL, envp);
1103 printf("RS: run_script: execl '%s' failed: %s\n",
1104 rp->r_script, strerror(errno));
1105 exit(1);
1106 default:
1107 /* Set the privilege structure for the child process to let it
1108 * run.
1110 proc_nr_e = getnprocnr(pid);
1111 r= sys_privctl(proc_nr_e, SYS_PRIV_USER, NULL);
1112 if (r < 0)
1113 printf("RS: run_script: sys_privctl call failed: %d\n", r);
1115 /* Do not wait for the child */
1116 break;
1121 /*===========================================================================*
1122 * get_next_label *
1123 *===========================================================================*/
1124 PRIVATE char *get_next_label(ptr, label, caller_label)
1125 char *ptr;
1126 char *label;
1127 char *caller_label;
1129 /* Get the next label from the list of (IPC) labels.
1131 char *p, *q;
1132 size_t len;
1134 for (p= ptr; p[0] != '\0'; p= q)
1136 /* Skip leading space */
1137 while (p[0] != '\0' && isspace((unsigned char)p[0]))
1138 p++;
1140 /* Find start of next word */
1141 q= p;
1142 while (q[0] != '\0' && !isspace((unsigned char)q[0]))
1143 q++;
1144 if (q == p)
1145 continue;
1146 len= q-p;
1147 if (len > MAX_LABEL_LEN)
1149 printf(
1150 "rs:get_next_label: bad ipc list entry '.*s' for %s: too long\n",
1151 len, p, caller_label);
1152 continue;
1154 memcpy(label, p, len);
1155 label[len]= '\0';
1157 return q; /* found another */
1160 return NULL; /* done */
1163 /*===========================================================================*
1164 * add_forward_ipc *
1165 *===========================================================================*/
1166 PRIVATE void add_forward_ipc(rp, privp)
1167 struct rproc *rp;
1168 struct priv *privp;
1170 /* Add IPC send permissions to a process based on that process's IPC
1171 * list.
1173 char label[MAX_LABEL_LEN+1], *p;
1174 struct rproc *tmp_rp;
1175 endpoint_t proc_nr_e;
1176 int slot_nr, priv_id;
1178 p = rp->r_ipc_list;
1180 while ((p = get_next_label(p, label, rp->r_label)) != NULL) {
1182 if (strcmp(label, "SYSTEM") == 0)
1183 proc_nr_e= SYSTEM;
1184 else if (strcmp(label, "USER") == 0)
1185 proc_nr_e= INIT_PROC_NR; /* all user procs */
1186 else if (strcmp(label, "PM") == 0)
1187 proc_nr_e= PM_PROC_NR;
1188 else if (strcmp(label, "VFS") == 0)
1189 proc_nr_e= FS_PROC_NR;
1190 else if (strcmp(label, "RS") == 0)
1191 proc_nr_e= RS_PROC_NR;
1192 else if (strcmp(label, "LOG") == 0)
1193 proc_nr_e= LOG_PROC_NR;
1194 else if (strcmp(label, "TTY") == 0)
1195 proc_nr_e= TTY_PROC_NR;
1196 else if (strcmp(label, "DS") == 0)
1197 proc_nr_e= DS_PROC_NR;
1198 else if (strcmp(label, "VM") == 0)
1199 proc_nr_e= VM_PROC_NR;
1200 else
1202 /* Try to find process */
1203 for (slot_nr = 0; slot_nr < NR_SYS_PROCS;
1204 slot_nr++)
1206 tmp_rp = &rproc[slot_nr];
1207 if (!(tmp_rp->r_flags & RS_IN_USE))
1208 continue;
1209 if (strcmp(tmp_rp->r_label, label) == 0)
1210 break;
1212 if (slot_nr >= NR_SYS_PROCS)
1214 printf(
1215 "add_forward_ipc: unable to find '%s'\n",
1216 label);
1217 continue;
1219 proc_nr_e= tmp_rp->r_proc_nr_e;
1222 priv_id= sys_getprivid(proc_nr_e);
1223 if (priv_id < 0)
1225 printf(
1226 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
1227 label, priv_id);
1228 continue;
1230 set_sys_bit(privp->s_ipc_to, priv_id);
1235 /*===========================================================================*
1236 * add_backward_ipc *
1237 *===========================================================================*/
1238 PRIVATE void add_backward_ipc(rp, privp)
1239 struct rproc *rp;
1240 struct priv *privp;
1242 /* Add IPC send permissions to a process based on other processes' IPC
1243 * lists. This is enough to allow each such two processes to talk to
1244 * each other, as the kernel guarantees send mask symmetry. We need to
1245 * add these permissions now because the current process may not yet
1246 * have existed at the time that the other process was initialized.
1248 char label[MAX_LABEL_LEN+1], *p;
1249 struct rproc *rrp;
1250 int priv_id, found;
1252 for (rrp=BEG_RPROC_ADDR; rrp<END_RPROC_ADDR; rrp++) {
1253 if (!(rrp->r_flags & RS_IN_USE))
1254 continue;
1256 /* If an IPC target list was provided for the process being
1257 * checked here, make sure that the label of the new process
1258 * is in that process's list.
1260 if (rrp->r_ipc_list[0]) {
1261 found = 0;
1263 p = rrp->r_ipc_list;
1265 while ((p = get_next_label(p, label, rp->r_label)) !=
1266 NULL) {
1267 if (!strcmp(rp->r_label, label)) {
1268 found = 1;
1269 break;
1273 if (!found)
1274 continue;
1277 priv_id= sys_getprivid(rrp->r_proc_nr_e);
1278 if (priv_id < 0)
1280 printf(
1281 "add_backward_ipc: unable to get priv_id for '%s': %d\n",
1282 label, priv_id);
1283 continue;
1286 set_sys_bit(privp->s_ipc_to, priv_id);
1291 /*===========================================================================*
1292 * init_privs *
1293 *===========================================================================*/
1294 PRIVATE void init_privs(rp, privp)
1295 struct rproc *rp;
1296 struct priv *privp;
1298 int i, src_bits_per_word, dst_bits_per_word, src_word, dst_word,
1299 src_bit, call_nr;
1300 unsigned long mask;
1302 /* Clear s_k_call_mask */
1303 memset(privp->s_k_call_mask, '\0', sizeof(privp->s_k_call_mask));
1305 src_bits_per_word= 8*sizeof(rp->r_call_mask[0]);
1306 dst_bits_per_word= 8*sizeof(privp->s_k_call_mask[0]);
1307 for (src_word= 0; src_word < MAX_NR_SYSTEM; src_word++)
1309 for (src_bit= 0; src_bit < src_bits_per_word; src_bit++)
1311 mask= (1UL << src_bit);
1312 if (!(rp->r_call_mask[src_word] & mask))
1313 continue;
1314 call_nr= src_word*src_bits_per_word+src_bit;
1315 #if 0
1316 if(rs_verbose)
1317 printf("RS: init_privs: system call %d\n", call_nr);
1318 #endif
1319 dst_word= call_nr / dst_bits_per_word;
1320 mask= (1UL << (call_nr % dst_bits_per_word));
1321 if (dst_word >= CALL_MASK_SIZE)
1323 printf(
1324 "RS: init_privs: call number %d doesn't fit\n",
1325 call_nr);
1327 privp->s_k_call_mask[dst_word] |= mask;
1331 /* Clear s_ipc_to */
1332 memset(&privp->s_ipc_to, '\0', sizeof(privp->s_ipc_to));
1334 if (strlen(rp->r_ipc_list) != 0)
1336 add_forward_ipc(rp, privp);
1337 add_backward_ipc(rp, privp);
1340 else
1342 for (i= 0; i<NR_SYS_PROCS; i++)
1344 if (i != USER_PRIV_ID)
1345 set_sys_bit(privp->s_ipc_to, i);
1351 /*===========================================================================*
1352 * init_pci *
1353 *===========================================================================*/
1354 PRIVATE void init_pci(rp, endpoint)
1355 struct rproc *rp;
1356 int endpoint;
1358 /* Tell the PCI driver about the new driver */
1359 size_t len;
1360 int i, r;
1361 struct rs_pci rs_pci;
1363 if (strcmp(rp->r_label, "pci") == 0)
1365 if(rs_verbose)
1366 printf("RS: init_pci: not when starting 'pci'\n");
1367 return;
1370 len= strlen(rp->r_label);
1371 if (len+1 > sizeof(rs_pci.rsp_label))
1373 if(rs_verbose)
1374 printf("RS: init_pci: label '%s' too long for rsp_label\n",
1375 rp->r_label);
1376 return;
1378 strcpy(rs_pci.rsp_label, rp->r_label);
1379 rs_pci.rsp_endpoint= endpoint;
1381 rs_pci.rsp_nr_device= rp->r_nr_pci_id;
1382 if (rs_pci.rsp_nr_device > RSP_NR_DEVICE)
1384 printf("RS: init_pci: too many PCI devices (max %d) "
1385 "truncating\n",
1386 RSP_NR_DEVICE);
1387 rs_pci.rsp_nr_device= RSP_NR_DEVICE;
1389 for (i= 0; i<rs_pci.rsp_nr_device; i++)
1391 rs_pci.rsp_device[i].vid= rp->r_pci_id[i].vid;
1392 rs_pci.rsp_device[i].did= rp->r_pci_id[i].did;
1395 rs_pci.rsp_nr_class= rp->r_nr_pci_class;
1396 if (rs_pci.rsp_nr_class > RSP_NR_CLASS)
1398 printf("RS: init_pci: too many PCI classes "
1399 "(max %d) truncating\n",
1400 RSP_NR_CLASS);
1401 rs_pci.rsp_nr_class= RSP_NR_CLASS;
1403 for (i= 0; i<rs_pci.rsp_nr_class; i++)
1405 rs_pci.rsp_class[i].class= rp->r_pci_class[i].class;
1406 rs_pci.rsp_class[i].mask= rp->r_pci_class[i].mask;
1409 if(rs_verbose)
1410 printf("RS: init_pci: calling pci_set_acl\n");
1412 r= pci_set_acl(&rs_pci);
1414 if(rs_verbose)
1415 printf("RS: init_pci: after pci_set_acl\n");
1417 if (r != OK)
1419 printf("RS: init_pci: pci_set_acl failed: %s\n",
1420 strerror(errno));
1421 return;
1425 /*===========================================================================*
1426 * do_lookup *
1427 *===========================================================================*/
1428 PUBLIC int do_lookup(m_ptr)
1429 message *m_ptr;
1431 static char namebuf[100];
1432 int len, r;
1433 struct rproc *rrp;
1435 len = m_ptr->RS_NAME_LEN;
1437 if(len < 2 || len >= sizeof(namebuf)) {
1438 printf("RS: len too weird (%d)\n", len);
1439 return EINVAL;
1442 if((r=sys_vircopy(m_ptr->m_source, D, (vir_bytes) m_ptr->RS_NAME,
1443 SELF, D, (vir_bytes) namebuf, len)) != OK) {
1444 printf("RS: name copy failed\n");
1445 return r;
1449 namebuf[len] = '\0';
1451 for (rrp=BEG_RPROC_ADDR; rrp<END_RPROC_ADDR; rrp++) {
1452 if (!(rrp->r_flags & RS_IN_USE))
1453 continue;
1454 if (!strcmp(rrp->r_label, namebuf)) {
1455 m_ptr->RS_ENDPOINT = rrp->r_proc_nr_e;
1456 return OK;
1460 return ESRCH;