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