Added lance entry to drivers.conf.
[minix3-old.git] / servers / rs / main.c
blobc201d0eb6334762ff6a811e9b5b37e5563fc1d47
1 /* Reincarnation Server. This servers starts new system services and detects
2 * they are exiting. In case of errors, system services can be restarted.
3 * The RS server periodically checks the status of all registered services
4 * services to see whether they are still alive. The system services are
5 * expected to periodically send a heartbeat message.
6 *
7 * Created:
8 * Jul 22, 2005 by Jorrit N. Herder
9 */
10 #include "inc.h"
11 #include <fcntl.h>
12 #include <minix/endpoint.h>
13 #include "../../kernel/const.h"
14 #include "../../kernel/type.h"
16 /* Declare some local functions. */
17 FORWARD _PROTOTYPE(void init_server, (void) );
18 FORWARD _PROTOTYPE(void sig_handler, (void) );
19 FORWARD _PROTOTYPE(void get_work, (message *m) );
20 FORWARD _PROTOTYPE(void reply, (int whom, message *m_out) );
22 /* Data buffers to retrieve info during initialization. */
23 PRIVATE struct boot_image image[NR_BOOT_PROCS];
25 long rs_verbose = 0;
27 /*===========================================================================*
28 * main *
29 *===========================================================================*/
30 PUBLIC int main(void)
32 /* This is the main routine of this service. The main loop consists of
33 * three major activities: getting new work, processing the work, and
34 * sending the reply. The loop never terminates, unless a panic occurs.
36 message m; /* request message */
37 int call_nr, who_e,who_p; /* call number and caller */
38 int result; /* result to return */
39 sigset_t sigset; /* system signal set */
40 int s;
41 uid_t euid;
43 /* Initialize the server, then go to work. */
44 init_server();
46 /* Main loop - get work and do it, forever. */
47 while (TRUE) {
49 /* Wait for request message. */
50 get_work(&m);
51 who_e = m.m_source;
52 who_p = _ENDPOINT_P(who_e);
53 if(who_p < -NR_TASKS || who_p >= NR_PROCS)
54 panic("RS","message from bogus source", who_e);
56 call_nr = m.m_type;
58 /* Now determine what to do. Three types of requests are expected:
59 * - Heartbeat messages (notifications from registered system services)
60 * - System notifications (POSIX signals or synchronous alarm)
61 * - User requests (control messages to manage system services)
64 /* Notification messages are control messages and do not need a reply.
65 * These include heartbeat messages and system notifications.
67 if (m.m_type & NOTIFY_MESSAGE) {
68 switch (call_nr) {
69 case SYN_ALARM:
70 do_period(&m); /* check drivers status */
71 continue;
72 case PROC_EVENT:
73 sig_handler();
74 continue;
75 default: /* heartbeat notification */
76 if (rproc_ptr[who_p] != NULL) /* mark heartbeat time */
77 rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP;
81 /* If this is not a notification message, it is a normal request.
82 * Handle the request and send a reply to the caller.
84 else {
85 if (call_nr < RS_RQ_BASE || call_nr >= RS_RQ_BASE+0x100)
87 /* Ignore invalid requests. Do not try to reply. */
88 printf("RS: got invalid request %d from endpoint %d\n",
89 call_nr, m.m_source);
90 continue;
93 /* Only root can make calls to rs */
94 euid= getpeuid(m.m_source);
95 if (euid != 0)
97 printf("RS: got unauthorized request %d from endpoint %d\n",
98 call_nr, m.m_source);
99 m.m_type = EPERM;
100 reply(who_e, &m);
101 continue;
104 switch(call_nr) {
105 case RS_UP: result = do_up(&m, FALSE, 0); break;
106 case RS_UP_COPY: result = do_up(&m, TRUE, 0); break;
107 case RS_START: result = do_start(&m); break;
108 case RS_DOWN: result = do_down(&m); break;
109 case RS_REFRESH: result = do_refresh(&m); break;
110 case RS_RESTART: result = do_restart(&m); break;
111 case RS_SHUTDOWN: result = do_shutdown(&m); break;
112 case GETSYSINFO: result = do_getsysinfo(&m); break;
113 default:
114 printf("Warning, RS got unexpected request %d from %d\n",
115 m.m_type, m.m_source);
116 result = EINVAL;
119 /* Finally send reply message, unless disabled. */
120 if (result != EDONTREPLY) {
121 m.m_type = result;
122 reply(who_e, &m);
129 /*===========================================================================*
130 * init_server *
131 *===========================================================================*/
132 PRIVATE void init_server(void)
134 /* Initialize the reincarnation server. */
135 struct sigaction sa;
136 struct boot_image *ip;
137 int s,t;
139 /* Install signal handlers. Ask PM to transform signal into message. */
140 sa.sa_handler = SIG_MESS;
141 sigemptyset(&sa.sa_mask);
142 sa.sa_flags = 0;
143 if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno);
144 if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno);
146 /* Initialize the system process table. Use the boot image from the kernel
147 * and the device map from the FS to gather all needed information.
149 if ((s = sys_getimage(image)) != OK)
150 panic("RS","warning: couldn't get copy of image table", s);
152 /* Set alarm to periodically check driver status. */
153 if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
154 panic("RS", "couldn't set alarm", s);
156 /* See if we run in verbose mode. */
157 env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);
159 /* Initialize the exec pipe. */
160 if (pipe(exec_pipe) == -1)
161 panic("RS", "pipe failed", errno);
162 if (fcntl(exec_pipe[0], F_SETFD,
163 fcntl(exec_pipe[0], F_GETFD) | FD_CLOEXEC) == -1)
165 panic("RS", "fcntl set FD_CLOEXEC on pipe input failed", errno);
167 if (fcntl(exec_pipe[1], F_SETFD,
168 fcntl(exec_pipe[1], F_GETFD) | FD_CLOEXEC) == -1)
170 panic("RS", "fcntl set FD_CLOEXEC on pipe output failed", errno);
172 if (fcntl(exec_pipe[0], F_SETFL,
173 fcntl(exec_pipe[0], F_GETFL) | O_NONBLOCK) == -1)
175 panic("RS", "fcntl set O_NONBLOCK on pipe input failed", errno);
179 /*===========================================================================*
180 * sig_handler *
181 *===========================================================================*/
182 PRIVATE void sig_handler()
184 sigset_t sigset;
185 int sig;
187 /* Try to obtain signal set from PM. */
188 if (getsigset(&sigset) != 0) return;
190 /* Check for known signals. */
191 if (sigismember(&sigset, SIGCHLD)) do_exit(NULL);
192 if (sigismember(&sigset, SIGTERM)) do_shutdown(NULL);
195 /*===========================================================================*
196 * get_work *
197 *===========================================================================*/
198 PRIVATE void get_work(m_in)
199 message *m_in; /* pointer to message */
201 int s; /* receive status */
202 if (OK != (s=receive(ANY, m_in))) /* wait for message */
203 panic("RS","receive failed", s);
207 /*===========================================================================*
208 * reply *
209 *===========================================================================*/
210 PRIVATE void reply(who, m_out)
211 int who; /* replyee */
212 message *m_out; /* reply message */
214 int s; /* send status */
216 s = sendnb(who, m_out); /* send the message */
217 if (s != OK)
218 printf("RS: unable to send reply to %d: %d\n", who, s);