1 /* Gateway Resource Monitor
5 * Revision 1.5 1995/05/03 07:37:42 adam
6 * CCL commands stop/continue implemented. New functions gw_res_{int,bool}
7 * are used when possible.
9 * Revision 1.4 1995/05/02 15:26:00 adam
10 * Monitor observes death of child (email kernel). The number
11 * of simultanous processes is controlled now. Email requests are
12 * queued if necessary. This scheme should only be forced if no kernels
15 * Revision 1.3 1995/05/02 07:20:10 adam
16 * Use pid of exited child to close fifos.
18 * Revision 1.2 1995/05/01 16:26:57 adam
19 * More work on resource monitor.
21 * Revision 1.1 1995/05/01 12:43:36 adam
22 * First work on resource monitor program.
38 #include <sys/types.h>
50 #define MONITOR_FIFO_S "fifo.s.m"
51 #define MONITOR_FIFO_C "fifo.c.m"
53 static char *module = "monitor";
54 static jmp_buf retry_jmp;
56 static GwRes monitor_res = NULL;
57 static int no_process = 0;
58 static int max_process = 1;
59 static int got_sighup = 0;
60 static int got_term = 0;
61 const char *default_res = "default.res";
63 static void reread_resources (void)
66 gw_res_close (monitor_res);
67 monitor_res = gw_res_init ();
68 if (gw_res_merge (monitor_res, default_res))
70 gw_log (GW_LOG_WARN, module, "Couldn't read resource file %s",
74 max_process = gw_res_int (monitor_res, "gw.max.process", 10);
81 struct str_queue *queue;
85 struct ke_info *ke_info_list = NULL;
87 struct ke_info *ke_info_add (int id)
91 for (kip = &ke_info_list; *kip; kip= &(*kip)->next)
94 *kip = malloc (sizeof(**kip));
103 static void ke_info_del (void)
107 assert (ke_info_list);
109 str_queue_rm (&ki->queue);
110 ke_info_list = ki->next;
114 static void catch_child (int num)
119 while ((pid=waitpid (-1, 0, WNOHANG)) > 0)
121 for (ki = ke_info_list; ki; ki = ki->next)
126 signal (SIGCHLD, catch_child);
129 static void catch_hup (int num)
132 signal (SIGHUP, catch_hup);
135 static void catch_term (int num)
138 signal (SIGTERM, catch_term);
141 static void pipe_handle (int dummy)
143 longjmp (retry_jmp, 1);
146 static pid_t start_kernel (int argc, char **argv, int id)
151 char userid_option[20];
153 argv_p = malloc (sizeof(*argv_p)*(argc+2));
156 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "malloc fail");
159 argv_p[0] = "kernel";
160 for (i = 1; i<argc; i++)
162 sprintf (userid_option, "-i%d", id);
163 argv_p[i++] = userid_option;
166 gw_log (GW_LOG_DEBUG, module, "Starting kernel");
170 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "fork");
175 execv ("kernel", argv_p);
176 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "execvp");
182 static int deliver (int argc, char **argv, int id, struct str_queue *queue,
183 GIP *gip, pid_t *pidp, int dont_exec)
188 char fifo_server_name[128];
189 char fifo_client_name[128];
193 sprintf (fifo_server_name, "fifo.s.%d", id);
194 sprintf (fifo_client_name, "fifo.c.%d", id);
198 *gip = gipc_initialize (fifo_client_name);
200 oldsig = signal (SIGPIPE, pipe_handle);
206 r = gipc_open (*gip, fifo_server_name, 0);
214 signal (SIGPIPE, oldsig);
217 mknod (fifo_server_name, S_IFIFO|0666, 0);
218 pid = start_kernel (argc, argv, id);
221 r = gipc_open (*gip, fifo_server_name, 1);
225 signal (SIGPIPE, oldsig);
226 gw_log (GW_LOG_WARN, module, "Cannot start kernel");
233 gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "r==-2");
234 longjmp (retry_jmp, 1);
238 gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "r==-1");
239 longjmp (retry_jmp, 1);
243 gw_log (GW_LOG_WARN|GW_LOG_ERRNO, module, "gipc_open");
247 while ((msg = str_queue_get (queue, index++)))
248 gip_wline (*gip, msg);
249 signal (SIGPIPE, oldsig);
253 static void monitor_events (int argc, char **argv)
259 char command[128], *cp;
261 gip_m = gips_initialize (MONITOR_FIFO_S);
262 r = gips_open (gip_m, MONITOR_FIFO_C);
263 gip_m_fd = gip_infileno (gip_m);
264 open (MONITOR_FIFO_S, O_WRONLY);
275 gw_log (GW_LOG_STAT, module, "Got SIGHUP. Reading resources");
281 gw_log (GW_LOG_STAT, module, "Got SIGTERM. Exiting...");
282 unlink (MONITOR_FIFO_S);
283 unlink (MONITOR_FIFO_C);
286 for (ki = ke_info_list; ki; ki = ki->next)
290 gw_log (GW_LOG_DEBUG, module, "Transfer mail to %d", ki->id);
291 r = deliver (argc, argv, ki->id, ki->queue, &ki->gip, &ki->pid,
292 no_process >= max_process);
295 if (r == 1 || r == 2)
296 str_queue_rm (&ki->queue);
299 FD_SET (gip_m_fd, &set_r);
300 gw_log (GW_LOG_DEBUG, module, "set gip_m_fd %d", gip_m_fd);
303 for (ki = ke_info_list; ki; ki = ki->next)
310 gw_log (GW_LOG_DEBUG, module, "Close of %d", ki->id);
311 gipc_close (ki->gip);
312 gipc_destroy (ki->gip);
315 else if ((fd = gip_infileno (ki->gip)) != -1)
317 gw_log (GW_LOG_DEBUG, module, "set fd %d", fd);
324 gw_log (GW_LOG_DEBUG, module, "Cur/Max processes %d/%d",
325 no_process, max_process);
326 gw_log (GW_LOG_DEBUG, module, "IPC select");
327 r = select (fd_max+1, &set_r, NULL, NULL, NULL);
332 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "select");
335 gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "select");
337 gw_log (GW_LOG_DEBUG, module, "Testing ke_info_list");
338 for (ki = ke_info_list; ki; ki = ki->next)
341 if (ki->gip && (fd = gip_infileno (ki->gip)) != -1)
343 gw_log (GW_LOG_DEBUG, module, "Test of %d", fd);
344 if (FD_ISSET (fd, &set_r))
346 if (lgets (line_buf, sizeof(line_buf)-1, fd))
348 gw_log (GW_LOG_DEBUG, module, "IPC: %s", line_buf);
352 gw_log (GW_LOG_DEBUG, module, "Close of %d", ki->id);
353 gipc_close (ki->gip);
354 gipc_destroy (ki->gip);
360 gw_log (GW_LOG_DEBUG, module, "Testing gip_m_fd %d", gip_m_fd);
361 if (FD_ISSET (gip_m_fd, &set_r))
363 gw_log (GW_LOG_DEBUG, module, "Reading from %d", gip_m_fd);
364 if (!(lgets (command, sizeof(command)-1, gip_m_fd)))
366 gw_log (GW_LOG_FATAL, module, "Unexpected close");
369 gw_log (GW_LOG_DEBUG, module, "Done");
370 if ((cp = strchr (command, '\n')))
372 gw_log (GW_LOG_DEBUG, module, "IPC: %s", command);
373 if (!memcmp (command, "eti ", 4))
375 int id = atoi (command+4);
376 struct ke_info *new_k;
378 new_k = ke_info_add (id);
379 gw_log (GW_LOG_DEBUG, module, "Incoming mail %d", id);
383 if (!(new_k->queue = str_queue_mk ()))
385 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module,
390 str_queue_enq (new_k->queue, "mail\n");
391 while (lgets (line_buf, sizeof(line_buf)-1, gip_m_fd))
392 str_queue_enq (new_k->queue, line_buf);
393 str_queue_enq (new_k->queue, "\001");
399 int main (int argc, char **argv)
404 while (++argno < argc)
406 if (argv[argno][0] == '-')
408 switch (argv[argno][1])
411 fprintf (stderr, "monitor [option..] [resource]\n");
412 fprintf (stderr, "If no resource file is given");
413 fprintf (stderr, " default.res is used\n");
414 fprintf (stderr, "Options are transferred to kernel\n");
417 gw_log_level (GW_LOG_ALL & ~RES_DEBUG);
420 gw_log_level (GW_LOG_ALL);
425 default_res = argv[argno];
428 signal (SIGCHLD, catch_child);
429 signal (SIGHUP, catch_hup);
430 signal (SIGTERM, catch_term);
432 gw_log_file (GW_LOG_ALL, "monitor.log");
434 monitor_events (argc, argv);