3 * Jul 22, 2005: Created (Jorrit N. Herder)
10 #include <sys/types.h>
14 #include <minix/dmap.h>
16 #include <minix/endpoint.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
,
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 /*===========================================================================*
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 */
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 */
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], '/');
115 label
= rp
->r_argv
[0];
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
);
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
;
150 /*===========================================================================*
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 */
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 */
183 if (slot_nr
>= NR_SYS_PROCS
)
185 printf("rs`do_start: driver table full\n");
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
) {
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
);
226 rp
->r_label
[len
] = '\0';
228 printf("RS: do_start: using label (custom) '%s'\n", rp
->r_label
);
230 /* Default label for the driver. */
231 label
= strrchr(rp
->r_argv
[0], '/');
235 label
= rp
->r_argv
[0];
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';
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 */
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
);
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
);
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';
286 rp
->r_ipc_list
[0]= '\0';
289 if (rs_start
.rss_flags
& RF_COPY
) {
294 if(rs_start
.rss_flags
& RF_REUSE
) {
295 char *cmd
= rp
->r_cmd
;
298 for(i
= 0; i
< NR_SYS_PROCS
; 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 */
313 s
= copy_exec(rp
, rp2
);
319 /* Copy granted resources */
320 if (rs_start
.rss_nr_irq
> NR_IRQ
)
322 printf("RS: do_start: too many IRQs requested\n");
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
];
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");
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;
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
);
352 if (rs_start
.rss_nr_pci_id
> MAX_NR_PCI_ID
)
354 printf("RS: do_start: too many PCI device IDs\n");
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
;
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");
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
;
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
];
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
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
));
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
;
421 /*===========================================================================*
423 *===========================================================================*/
424 PUBLIC
int do_down(message
*m_ptr
)
426 register struct rproc
*rp
;
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
);
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) {
443 printf("RS: stopping '%s' (%d)\n", label
, rp
->r_pid
);
444 stop_service(rp
,RS_EXITING
);
447 /* Process is already gone */
448 rp
->r_flags
= 0; /* release slot */
454 proc
= _ENDPOINT_P(rp
->r_proc_nr_e
);
455 rproc_ptr
[proc
] = NULL
;
459 /* Late reply - send a reply when process dies. */
460 rp
->r_flags
|= RS_LATEREPLY
;
461 rp
->r_caller
= m_ptr
->m_source
;
465 if(rs_verbose
) printf("RS: do_down: '%s' not found\n", label
);
470 /*===========================================================================*
472 *===========================================================================*/
473 PUBLIC
int do_restart(message
*m_ptr
)
475 register struct rproc
*rp
;
478 char label
[MAX_LABEL_LEN
];
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
);
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
);
496 printf("RS: do_restart: '%s' is (still) running, pid = %d\n",
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
;
508 printf("RS: do_restart: '%s' not found\n", label
);
514 /*===========================================================================*
516 *===========================================================================*/
517 PUBLIC
int do_refresh(message
*m_ptr
)
519 register struct rproc
*rp
;
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
);
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) {
536 printf("RS: refreshing %s (%d)\n", rp
->r_label
, rp
->r_pid
);
538 stop_service(rp
,RS_REFRESHING
);
543 printf("RS: do_refresh: '%s' not found\n", label
);
548 /*===========================================================================*
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
;
558 /*===========================================================================*
560 *===========================================================================*/
561 PUBLIC
void do_exit(message
*m_ptr
)
563 register struct rproc
*rp
;
565 int exit_status
, r
, slot_nr
;
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 ) {
580 printf("RS: pid %d, ", exit_pid
);
582 if (WIFSIGNALED(exit_status
)) {
584 printf("killed, signal number %d\n", WTERMSIG(exit_status
));
587 else if (WIFEXITED(exit_status
)) {
589 printf("normal exit, status %d\n", WEXITSTATUS(exit_status
));
594 /* Read from the exec pipe */
597 r
= read(exec_pipe
[0], &slot_nr
, sizeof(slot_nr
));
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",
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
) {
623 proc
= _ENDPOINT_P(rp
->r_proc_nr_e
);
625 rproc_ptr
[proc
] = NULL
; /* invalidate */
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
) {
635 send(rp
->r_caller
, &rsm
);
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')
653 start_service(rp
, 0, &ep
); /* direct restart */
655 m_ptr
->RS_ENDPOINT
= ep
;
658 else if (rp
->r_flags
& RS_EXECFAILED
) {
659 rp
->r_flags
= 0; /* release slot */
662 /* Determine what to do. If this is the first unexpected
663 * exit, immediately restart this service. Otherwise use
664 * a binary exponetial backoff.
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;
677 rp
->r_flags
|= RS_CRASHED
;
679 if (rp
->r_script
[0] != '\0') {
681 printf("RS: running restart script for %s\n",
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)
693 printf("RS: restarting %s\n", rp
->r_cmd
);
694 start_service(rp
, 0, &ep
); /* direct restart */
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.
708 /*===========================================================================*
710 *===========================================================================*/
711 PUBLIC
void do_period(m_ptr
)
714 register struct rproc
*rp
;
715 clock_t now
= m_ptr
->NOTIFY_TIMESTAMP
;
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
727 if (rp
->r_backoff
> 0) {
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
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
)) {
757 printf("RS: service %d reported late\n",
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
) {
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 /*===========================================================================*
785 *===========================================================================*/
786 PRIVATE
int start_service(rp
, flags
, endpoint
)
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 */
798 int s
, use_copy
, slot_nr
;
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). */
808 if(rs_verbose
) printf("RS: fork_nb..\n");
809 child_pid
= fork_nb();
811 if(rs_verbose
) printf("RS: fork regular..\n");
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
829 cpf_reload(); /* Tell kernel about grant table */
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
);
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 */
845 if(rs_verbose
) printf("RS: parent forked, pid %d..\n", child_pid
);
847 child_proc_nr_e
= getnprocnr(child_pid
); /* get child slot */
849 if(rs_verbose
) printf("RS: forked into %d..\n", child_proc_nr_e
);
851 break; /* continue below */
856 extern char **environ
;
857 dev_execve(child_proc_nr_e
, rp
->r_exec
, rp
->r_exec_len
, rp
->r_argv
,
863 if (rp
->r_set_resources
)
865 init_privs(rp
, &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
);
893 s
= ds_publish_u32(rp
->r_label
, child_proc_nr_e
);
895 printf("RS: start_service: ds_publish_u32 failed: %d\n", s
);
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
);
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 */
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 */
938 /*===========================================================================*
940 *===========================================================================*/
941 PRIVATE
int stop_service(rp
,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 /*===========================================================================*
961 *===========================================================================*/
962 PUBLIC
int do_getsysinfo(m_ptr
)
965 vir_bytes src_addr
, dst_addr
;
970 switch(m_ptr
->m1_i1
) {
972 src_addr
= (vir_bytes
) rproc
;
973 len
= sizeof(struct rproc
) * NR_SYS_PROCS
;
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
)))
986 PRIVATE pid_t
fork_nb()
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
)
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
)
1006 rp_dst
->r_exec
= NULL
;
1010 PRIVATE
int read_exec(rp
)
1018 e_name
= rp
->r_argv
[0];
1019 r
= stat(e_name
, &sb
);
1023 fd
= open(e_name
, O_RDONLY
);
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",
1037 r
= read(fd
, rp
->r_exec
, rp
->r_exec_len
);
1040 if (r
== rp
->r_exec_len
)
1043 printf("RS: read_exec: read failed %d, errno %d\n", r
, e
);
1054 /*===========================================================================*
1056 *===========================================================================*/
1057 PRIVATE
void run_script(rp
)
1063 char incarnation_str
[20]; /* Enough for a counter? */
1064 char *envp
[1] = { NULL
};
1066 if (rp
->r_flags
& RS_EXITING
)
1068 else if (rp
->r_flags
& RS_REFRESHING
)
1070 else if (rp
->r_flags
& RS_NOPINGREPLY
)
1071 reason
= "no-heartbeat";
1072 else if (rp
->r_flags
& RS_KILLED
)
1074 else if (rp
->r_flags
& RS_CRASHED
)
1076 else if (rp
->r_flags
& RS_SIGNALED
)
1081 "RS: run_script: can't find reason for termination of '%s'\n",
1085 sprintf(incarnation_str
, "%d", rp
->r_restarts
);
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
);
1098 printf("RS: run_script: fork failed: %s\n", strerror(errno
));
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
));
1107 /* Set the privilege structure for the child process to let it
1110 proc_nr_e
= getnprocnr(pid
);
1111 r
= sys_privctl(proc_nr_e
, SYS_PRIV_USER
, NULL
);
1113 printf("RS: run_script: sys_privctl call failed: %d\n", r
);
1115 /* Do not wait for the child */
1121 /*===========================================================================*
1123 *===========================================================================*/
1124 PRIVATE
char *get_next_label(ptr
, label
, caller_label
)
1129 /* Get the next label from the list of (IPC) labels.
1134 for (p
= ptr
; p
[0] != '\0'; p
= q
)
1136 /* Skip leading space */
1137 while (p
[0] != '\0' && isspace((unsigned char)p
[0]))
1140 /* Find start of next word */
1142 while (q
[0] != '\0' && !isspace((unsigned char)q
[0]))
1147 if (len
> MAX_LABEL_LEN
)
1150 "rs:get_next_label: bad ipc list entry '.*s' for %s: too long\n",
1151 len
, p
, caller_label
);
1154 memcpy(label
, p
, len
);
1157 return q
; /* found another */
1160 return NULL
; /* done */
1163 /*===========================================================================*
1165 *===========================================================================*/
1166 PRIVATE
void add_forward_ipc(rp
, privp
)
1170 /* Add IPC send permissions to a process based on that process's IPC
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
;
1180 while ((p
= get_next_label(p
, label
, rp
->r_label
)) != NULL
) {
1182 if (strcmp(label
, "SYSTEM") == 0)
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
;
1202 /* Try to find process */
1203 for (slot_nr
= 0; slot_nr
< NR_SYS_PROCS
;
1206 tmp_rp
= &rproc
[slot_nr
];
1207 if (!(tmp_rp
->r_flags
& RS_IN_USE
))
1209 if (strcmp(tmp_rp
->r_label
, label
) == 0)
1212 if (slot_nr
>= NR_SYS_PROCS
)
1215 "add_forward_ipc: unable to find '%s'\n",
1219 proc_nr_e
= tmp_rp
->r_proc_nr_e
;
1222 priv_id
= sys_getprivid(proc_nr_e
);
1226 "add_forward_ipc: unable to get priv_id for '%s': %d\n",
1230 set_sys_bit(privp
->s_ipc_to
, priv_id
);
1235 /*===========================================================================*
1236 * add_backward_ipc *
1237 *===========================================================================*/
1238 PRIVATE
void add_backward_ipc(rp
, 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
;
1252 for (rrp
=BEG_RPROC_ADDR
; rrp
<END_RPROC_ADDR
; rrp
++) {
1253 if (!(rrp
->r_flags
& RS_IN_USE
))
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]) {
1263 p
= rrp
->r_ipc_list
;
1265 while ((p
= get_next_label(p
, label
, rp
->r_label
)) !=
1267 if (!strcmp(rp
->r_label
, label
)) {
1277 priv_id
= sys_getprivid(rrp
->r_proc_nr_e
);
1281 "add_backward_ipc: unable to get priv_id for '%s': %d\n",
1286 set_sys_bit(privp
->s_ipc_to
, priv_id
);
1291 /*===========================================================================*
1293 *===========================================================================*/
1294 PRIVATE
void init_privs(rp
, privp
)
1298 int i
, src_bits_per_word
, dst_bits_per_word
, src_word
, dst_word
,
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
))
1314 call_nr
= src_word
*src_bits_per_word
+src_bit
;
1317 printf("RS: init_privs: system call %d\n", call_nr
);
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
)
1324 "RS: init_privs: call number %d doesn't fit\n",
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
);
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 /*===========================================================================*
1353 *===========================================================================*/
1354 PRIVATE
void init_pci(rp
, endpoint
)
1358 /* Tell the PCI driver about the new driver */
1361 struct rs_pci rs_pci
;
1363 if (strcmp(rp
->r_label
, "pci") == 0)
1366 printf("RS: init_pci: not when starting 'pci'\n");
1370 len
= strlen(rp
->r_label
);
1371 if (len
+1 > sizeof(rs_pci
.rsp_label
))
1374 printf("RS: init_pci: label '%s' too long for rsp_label\n",
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) "
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",
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
;
1410 printf("RS: init_pci: calling pci_set_acl\n");
1412 r
= pci_set_acl(&rs_pci
);
1415 printf("RS: init_pci: after pci_set_acl\n");
1419 printf("RS: init_pci: pci_set_acl failed: %s\n",
1425 /*===========================================================================*
1427 *===========================================================================*/
1428 PUBLIC
int do_lookup(m_ptr
)
1431 static char namebuf
[100];
1435 len
= m_ptr
->RS_NAME_LEN
;
1437 if(len
< 2 || len
>= sizeof(namebuf
)) {
1438 printf("RS: len too weird (%d)\n", len
);
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");
1449 namebuf
[len
] = '\0';
1451 for (rrp
=BEG_RPROC_ADDR
; rrp
<END_RPROC_ADDR
; rrp
++) {
1452 if (!(rrp
->r_flags
& RS_IN_USE
))
1454 if (!strcmp(rrp
->r_label
, namebuf
)) {
1455 m_ptr
->RS_ENDPOINT
= rrp
->r_proc_nr_e
;