More work on resource monitor.
[egate.git] / kernel / monitor.c
1 /* Gateway Resource Monitor
2  * Europagate, 1995
3  *
4  * $Log: monitor.c,v $
5  * Revision 1.2  1995/05/01 16:26:57  adam
6  * More work on resource monitor.
7  *
8  * Revision 1.1  1995/05/01  12:43:36  adam
9  * First work on resource monitor program.
10  *
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <assert.h>
16 #include <ctype.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <setjmp.h>
21 #include <signal.h>
22
23 #include <sys/file.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <sys/wait.h>
28
29 #include <gw-log.h>
30 #include <gw-log.h>
31 #include <gip.h>
32 #include <strqueue.h>
33 #include <lgets.h>
34
35 #define LINE_MAX 1024
36
37 static char *module = "monitor";
38 static jmp_buf retry_jmp;
39
40 struct ke_info {
41     int pid;
42     int id;
43     GIP gip;
44     struct str_queue *queue;
45     struct ke_info *next;
46 };
47
48 struct ke_info *ke_info_list = NULL;
49
50 struct ke_info *ke_info_add (int id)
51 {
52     struct ke_info **kip;
53
54     for (kip = &ke_info_list; *kip; kip= &(*kip)->next)
55         if ((*kip)->id == id)
56             return *kip;
57     *kip = malloc (sizeof(**kip));
58     assert (*kip);
59     (*kip)->next = NULL;
60     (*kip)->id = id;
61     (*kip)->gip = NULL;
62     if (!((*kip)->queue = str_queue_mk ()))
63     {
64         gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "str_queue_mk");
65         exit (1);
66     }
67     return *kip;
68 }
69
70 void ke_info_del (void)
71 {
72     struct ke_info *ki;
73
74     assert (ke_info_list);
75     ki = ke_info_list;
76     str_queue_rm (&ki->queue);
77     ke_info_list = ki->next;
78     free (ki);
79 }
80
81 static void catchchild (int num)
82 {
83     while (waitpid (-1, 0, WNOHANG) > 0)
84         ;
85     signal (SIGCHLD, catchchild);
86 }
87
88 static void pipe_handle (int dummy)
89 {
90     longjmp (retry_jmp, 1);
91 }
92
93 static pid_t start_kernel (int argc, char **argv, int id)
94 {
95     pid_t pid;
96     int i;
97     char **argv_p;
98     char userid_option[20];
99
100     argv_p = malloc (sizeof(*argv_p)*(argc+2));
101     if (!argv_p)
102     {
103         gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "malloc fail");
104         exit (1);
105     }
106     argv_p[0] = "kernel";
107     for (i = 1; i<argc; i++)
108         argv_p[i] = argv[i];
109     sprintf (userid_option, "-i%d", id);
110     argv_p[i++] = userid_option;
111     argv_p[i++] = NULL;
112
113     gw_log (GW_LOG_DEBUG, module, "Starting kernel");
114     pid = fork ();
115     if (pid == -1)
116     {
117         gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "fork");
118         exit (1);
119     }
120     if (!pid)
121     {
122         execv ("kernel", argv_p);
123         gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "execvp");
124         exit (1);
125     }
126     return pid;
127 }
128
129 static void deliver (int argc, char **argv, int id, struct str_queue *queue,
130                      GIP *gip)
131 {
132     int pass = 0;
133     int r;
134     int index;
135     char fifo_server_name[128];
136     char fifo_client_name[128];
137     void (*oldsig)();
138     const char *msg;
139
140     sprintf (fifo_server_name, "fifo.s.%d", id);
141     sprintf (fifo_client_name, "fifo.c.%d", id);
142
143     assert (gip);
144     if (!*gip)
145         *gip = gipc_initialize (fifo_client_name);
146
147     oldsig = signal (SIGPIPE, pipe_handle);
148     setjmp (retry_jmp);
149     ++pass;
150     if (pass == 1)
151         r = gipc_open (*gip, fifo_server_name, 0);
152     else if (pass == 2)
153     {
154         mknod (fifo_server_name, S_IFIFO|0666, 0);
155         start_kernel (argc, argv, id);
156         r = gipc_open (*gip, fifo_server_name, 1);
157     }
158     else
159     {
160         gw_log (GW_LOG_WARN, module, "Cannot start kernel");
161         return;
162     }
163     if (r < 0)
164     {
165         if (r == -2)
166         {
167             gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "r==-2");
168             longjmp (retry_jmp, 1);
169         }
170         else if (r == -1)
171         {
172             gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "r==-1");
173             longjmp (retry_jmp, 1);
174         }
175         else
176         {
177             gw_log (GW_LOG_WARN|GW_LOG_ERRNO, module, "gipc_open");
178             return;
179         }
180     }
181     index = 0;
182     while ((msg = str_queue_get (queue, index++)))
183         gip_wline (*gip, msg);
184     signal (SIGPIPE, oldsig);
185 }
186
187 static void monitor_events (int argc, char **argv)
188 {
189     GIP gip_m;
190     int r, gip_m_fd;
191     char line_buf[1024];
192     fd_set set_r;
193     char command[128], *cp;
194     int no_process = 0;
195     int max_process = 4;
196
197     gip_m = gips_initialize ("fifo.s");
198     r = gips_open (gip_m, "fifo.c");
199     gip_m_fd = gip_infileno (gip_m);
200     open ("fifo.s", O_WRONLY);
201
202     while (1)
203     {
204         int fd_max;
205         struct ke_info *ki;
206
207         FD_ZERO (&set_r);
208         FD_SET (gip_m_fd, &set_r);
209         gw_log (GW_LOG_DEBUG, module, "set r %d", gip_m_fd);
210         fd_max = gip_m_fd;
211             
212         for (ki = ke_info_list; ki; ki = ki->next)
213         {
214             if (!ki->queue)
215                 continue;
216             gw_log (GW_LOG_DEBUG, module, "Transfer mail to %d", ki->id);
217             deliver (argc, argv, ki->id, ki->queue, &ki->gip);
218             str_queue_rm (&ki->queue);
219         }
220         for (ki = ke_info_list; ki; ki = ki->next)
221         {
222             int fd;
223             if (ki->gip && (fd = gip_infileno (ki->gip)) != -1)
224             {
225                 gw_log (GW_LOG_DEBUG, module, "set r %d", fd);
226                 FD_SET (fd, &set_r);
227                 if (fd > fd_max)
228                     fd_max = fd;
229             }
230         }
231         while (1)
232         {
233             gw_log (GW_LOG_DEBUG, module, "IPC select");
234             r = select (fd_max+1, &set_r, NULL, NULL, NULL);
235             if (r != -1)
236                 break;
237             if (errno != EINTR)
238             {
239                 gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "select");
240                 exit (1);
241             }
242             gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "select");
243         }
244         gw_log (GW_LOG_DEBUG, module, "Testing ke_info_list");
245         for (ki = ke_info_list; ki; ki = ki->next)
246         {
247             int fd;
248             if (ki->gip && (fd = gip_infileno (ki->gip)) != -1)
249             {
250                 gw_log (GW_LOG_DEBUG, module, "Test of %d", fd);
251                 if (FD_ISSET (fd, &set_r))
252                 {
253                     if (lgets (line_buf, sizeof(line_buf)-1, fd))
254                     {
255                         gw_log (GW_LOG_DEBUG, module, "IPC: %s", line_buf);
256                     }
257                     else
258                     {
259                         gw_log (GW_LOG_DEBUG, module, "Close of %d", ki->id);
260                         gipc_close (ki->gip);
261                         gipc_destroy (ki->gip);
262                         ki->gip = NULL;
263                     }
264                 }
265             }
266         }
267
268         gw_log (GW_LOG_DEBUG, module, "Testing gip_m_fd %d", gip_m_fd);
269         if (FD_ISSET (gip_m_fd, &set_r))
270         {
271             gw_log (GW_LOG_DEBUG, module, "Reading from %d", gip_m_fd);
272             if (!(lgets (command, sizeof(command)-1, gip_m_fd)))
273             {
274                 gw_log (GW_LOG_FATAL, module, "Unexpected close");
275                 exit (1);
276             }
277             gw_log (GW_LOG_DEBUG, module, "Done");
278             if ((cp = strchr (command, '\n')))
279                 *cp = '\0';
280             gw_log (GW_LOG_DEBUG, module, "IPC: %s", command);
281             if (!memcmp (command, "eti ", 4))
282             {
283                 int id = atoi (command+4);
284                 struct ke_info *new_k;
285                 
286                 new_k = ke_info_add (id);
287                 gw_log (GW_LOG_DEBUG, module, "Incoming mail %d", id);
288                 str_queue_enq (new_k->queue, "mail\n");
289                 while (lgets (line_buf, sizeof(line_buf)-1, gip_m_fd))
290                     str_queue_enq (new_k->queue, line_buf);
291                 str_queue_enq (new_k->queue, "\001");
292             }
293         }
294     }
295 }
296
297 int main (int argc, char **argv)
298 {
299     gw_log_init (*argv);
300     gw_log_level (GW_LOG_ALL);
301 #if 0
302     signal (SIGCHLD, catchchild);
303     gw_log_file (GW_LOG_ALL, "monitor.log");
304 #endif
305     monitor_events (argc, argv);
306     exit (0);
307 }
308
309
310
311