source: branches/minix3-book/servers/rs/manager.c@ 25

Last change on this file since 25 was 4, checked in by Mattia Monga, 14 years ago

Importazione sorgenti libro

File size: 4.6 KB
Line 
1/* This file contains procedures to manage the system processes.
2 *
3 * The entry points into this file are
4 * do_start:
5 * do_stop:
6 * do_exit: a child of this server exited
7 *
8 * Changes:
9 * Jul 22, 2005: Created (Jorrit N. Herder)
10 */
11
12#include "rs.h"
13#include <unistd.h>
14#include <sys/types.h>
15#include <sys/wait.h>
16#include <minix/dmap.h>
17
18extern int errno;
19
20#define EXEC_FAILED 49 /* arbitrary, recognizable status */
21#define MAX_PATH_LEN 256 /* maximum path string length */
22#define MAX_ARGS_LEN 4096 /* maximum argument string length */
23#define MAX_ARG_COUNT 1 /* parsed arguments count */
24
25PRIVATE char command[MAX_PATH_LEN+1];
26PRIVATE char arg_buf[MAX_ARGS_LEN+1];
27
28/*===========================================================================*
29 * do_start *
30 *===========================================================================*/
31PUBLIC int do_start(message *m_ptr)
32{
33 message m;
34 int child_proc_nr;
35 int major_nr;
36 enum dev_style dev_style;
37 pid_t child_pid;
38 char *args[MAX_ARG_COUNT+1];
39 int s;
40
41 /* Obtain command name and parameters. */
42 if (m_ptr->SRV_PATH_LEN > MAX_PATH_LEN) return(E2BIG);
43 if (OK != (s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->SRV_PATH_ADDR,
44 SELF, (vir_bytes) command, m_ptr->SRV_PATH_LEN))) return(s);
45 command[m_ptr->SRV_PATH_LEN] = '\0';
46 if (command[0] != '/') return(EINVAL);
47
48 args[0] = command;
49 if (m_ptr->SRV_ARGS_LEN > 0) {
50 if (m_ptr->SRV_ARGS_LEN > MAX_ARGS_LEN) return(E2BIG);
51 if (OK != (s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->SRV_ARGS_ADDR,
52 SELF, (vir_bytes) arg_buf, m_ptr->SRV_ARGS_LEN))) return(s);
53 arg_buf[m_ptr->SRV_ARGS_LEN] = '\0';
54 args[1] = &arg_buf[0];
55 args[2] = NULL;
56 } else {
57 args[1] = NULL;
58 }
59
60 /* Now try to execute the new system service. Fork a new process. The child
61 * process will be inhibited from running by the NO_PRIV flag. Only let the
62 * child run once its privileges have been set by the parent.
63 */
64 if ((s = _taskcall(PM_PROC_NR, FORK, &m)) < 0) /* use raw interface */
65 report("SM", "_taskcall to PM failed", s); /* to get both */
66 child_pid = m.m_type; /* - child's pid */
67 child_proc_nr = m.PR_PROC_NR; /* - process nr */
68
69 /* Now branch for parent and child process, and check for error. */
70 switch(child_pid) { /* see fork(2) */
71 case 0: /* child process */
72 execve(command, args, NULL); /* POSIX exec */
73 report("SM", "warning, exec() failed", errno); /* shouldn't happen */
74 exit(EXEC_FAILED); /* terminate child */
75 break;
76 case -1: /* fork failed */
77 report("SM", "warning, fork() failed", errno); /* shouldn't happen */
78 return(errno);
79 default: /* parent process */
80 if ((major_nr = m_ptr->SRV_DEV_MAJOR) > 0) { /* set driver map */
81 dev_style = STYLE_DEV;
82 if ((s=mapdriver(child_proc_nr, major_nr, dev_style)) < 0) {
83
84#if VERBOSE
85 printf("SM: '%s %s', major %d, pid %d, proc_nr %d",
86 command, arg_buf, major_nr, child_pid, child_proc_nr);
87#endif
88 report("SM", "couldn't map driver", errno);
89 }
90 }
91 if ((s = _taskcall(SYSTEM, SYS_PRIVCTL, &m)) < 0) /* set privileges */
92 report("SM", "_taskcall to SYSTEM failed", s); /* to let child run */
93#if VERBOSE
94 printf("SM: started '%s %s', major %d, pid %d, proc_nr %d",
95 command, arg_buf, major_nr, child_pid, child_proc_nr);
96#endif
97 /* update tables */
98 }
99 return(OK);
100}
101
102
103/*===========================================================================*
104 * do_stop *
105 *===========================================================================*/
106PUBLIC int do_stop(message *m_ptr)
107{
108 return(ENOSYS);
109}
110
111/*===========================================================================*
112 * do_exit *
113 *===========================================================================*/
114PUBLIC int do_exit(message *m_ptr)
115{
116 pid_t exit_pid;
117 int exit_status;
118
119#if VERBOSE
120 printf("SM: got SIGCHLD signal, doing wait to get exited child.\n");
121#endif
122
123 /* See which child exited and what the exit status is. This is done in a
124 * loop because multiple childs may have exited, all reported by one
125 * SIGCHLD signal. The WNOHANG options is used to prevent blocking if,
126 * somehow, no exited child can be found.
127 */
128 while ( (exit_pid = waitpid(-1, &exit_status, WNOHANG)) != 0 ) {
129
130#if VERBOSE
131 printf("SM: pid %d,", exit_pid);
132 if (WIFSIGNALED(exit_status)) {
133 printf("killed, signal number %d\n", WTERMSIG(exit_status));
134 } else if (WIFEXITED(exit_status)) {
135 printf("normal exit, status %d\n", WEXITSTATUS(exit_status));
136 }
137#endif
138
139 }
140 return(OK);
141}
142
143
Note: See TracBrowser for help on using the repository browser.