First work on resource monitor program.
[egate.git] / kernel / monitor.c
diff --git a/kernel/monitor.c b/kernel/monitor.c
new file mode 100644 (file)
index 0000000..d985fce
--- /dev/null
@@ -0,0 +1,280 @@
+/* Gateway Resource Monitor
+ * Europagate, 1995
+ *
+ * $Log: monitor.c,v $
+ * Revision 1.1  1995/05/01 12:43:36  adam
+ * First work on resource monitor program.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <signal.h>
+
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <gw-log.h>
+#include <gw-log.h>
+#include <gip.h>
+#include <strqueue.h>
+#include <lgets.h>
+
+#define LINE_MAX 1024
+
+static char *module = "monitor";
+static jmp_buf retry_jmp;
+
+struct ke_info {
+    int pid;
+    int id;
+    GIP gip;
+    struct str_queue *queue;
+    struct ke_info *next;
+};
+
+struct ke_info *ke_info_list = NULL;
+
+struct ke_info *ke_info_add (int id)
+{
+    struct ke_info **kip;
+
+    for (kip = &ke_info_list; *kip; kip= &(*kip)->next)
+        if ((*kip)->id == id)
+           return *kip;
+    *kip = malloc (sizeof(**kip));
+    assert (*kip);
+    (*kip)->next = NULL;
+    (*kip)->id = id;
+    (*kip)->gip = NULL;
+    if (!((*kip)->queue = str_queue_mk ()))
+    {
+        gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "str_queue_mk");
+        exit (1);
+    }
+    return *kip;
+}
+
+void ke_info_del (void)
+{
+    struct ke_info *ki;
+
+    assert (ke_info_list);
+    ki = ke_info_list;
+    str_queue_rm (&ki->queue);
+    ke_info_list = ki->next;
+    free (ki);
+}
+
+static void pipe_handle (int dummy)
+{
+    longjmp (retry_jmp, 1);
+}
+
+static pid_t start_kernel (int argc, char **argv, int id)
+{
+    pid_t pid;
+    int i;
+    char **argv_p;
+    char userid_option[20];
+
+    argv_p = malloc (sizeof(*argv_p)*(argc+2));
+    if (!argv_p)
+    {
+       gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "malloc fail");
+       exit (1);
+    }
+    argv_p[0] = "kernel";
+    for (i = 1; i<argc; i++)
+        argv_p[i] = argv[i];
+    sprintf (userid_option, "-i%d", id);
+    argv_p[i++] = userid_option;
+    argv_p[i++] = NULL;
+
+    gw_log (GW_LOG_DEBUG, module, "Starting kernel");
+    pid = fork ();
+    if (pid == -1)
+    {
+       gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "fork");
+       exit (1);
+    }
+    if (!pid)
+    {
+        execv ("kernel", argv_p);
+       gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "execvp");
+       exit (1);
+    }
+    return pid;
+}
+
+static void deliver (int argc, char **argv, int id, struct str_queue *queue,
+                     GIP *gip)
+{
+    int pass = 0;
+    int r;
+    int index;
+    char fifo_server_name[128];
+    char fifo_client_name[128];
+    void (*oldsig)();
+    const char *msg;
+
+    sprintf (fifo_server_name, "fifo.s.%d", id);
+    sprintf (fifo_client_name, "fifo.c.%d", id);
+
+    assert (gip);
+    if (!*gip)
+        *gip = gipc_initialize (fifo_client_name);
+
+    oldsig = signal (SIGPIPE, pipe_handle);
+    setjmp (retry_jmp);
+    ++pass;
+    if (pass == 1)
+        r = gipc_open (*gip, fifo_server_name, 0);
+    else if (pass == 2)
+    {
+        mknod (fifo_server_name, S_IFIFO|0666, 0);
+       start_kernel (argc, argv, id);
+       r = gipc_open (*gip, fifo_server_name, 1);
+    }
+    else
+    {
+        gw_log (GW_LOG_WARN, module, "Cannot start kernel");
+       return;
+    }
+    if (r < 0)
+    {
+        if (r == -2)
+       {
+            gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "r==-2");
+           longjmp (retry_jmp, 1);
+       }
+       else if (r == -1)
+       {
+            gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "r==-1");
+           longjmp (retry_jmp, 1);
+       }
+       else
+       {
+            gw_log (GW_LOG_WARN|GW_LOG_ERRNO, module, "gipc_open");
+           return;
+       }
+    }
+    index = 0;
+    while ((msg = str_queue_get (queue, index++)))
+        gip_wline (*gip, msg);
+    signal (SIGPIPE, oldsig);
+}
+
+static void monitor_events (int argc, char **argv)
+{
+    GIP gip_m;
+    int r, gip_m_fd;
+    char line_buf[1024];
+    fd_set set_r;
+    char command[128], *cp;
+    int no_process = 0;
+    int max_process = 4;
+
+    gip_m = gips_initialize ("fifo.s");
+    r = gips_open (gip_m, "fifo.c");
+    gip_m_fd = gip_infileno (gip_m);
+    open ("fifo.s", O_WRONLY);
+
+    while (1)
+    {
+        int fd_max;
+       struct ke_info *ki;
+
+        FD_ZERO (&set_r);
+       FD_SET (gip_m_fd, &set_r);
+       fd_max = gip_m_fd;
+
+       for (ki = ke_info_list; ki; ki = ki->next)
+       {
+           if (!ki->queue)
+                continue;
+           gw_log (GW_LOG_DEBUG, module, "Transfer mail to %d", ki->id);
+            deliver (argc, argv, ki->id, ki->queue, &ki->gip);
+           str_queue_rm (&ki->queue);
+        }
+       for (ki = ke_info_list; ki; ki = ki->next)
+       {
+           int fd;
+            if (ki->gip && (fd = gip_infileno (ki->gip)) != -1)
+           {
+               gw_log (GW_LOG_DEBUG, module, "set r %d", fd);
+                FD_SET (fd, &set_r);
+                if (fd > fd_max)
+                    fd_max = fd;
+           }
+       }
+       gw_log (GW_LOG_DEBUG, module, "Monitor select");
+       r = select (fd_max+1, &set_r, NULL, NULL, NULL);
+       if (r == -1)
+       {
+            gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "select");
+           exit (1);
+       }
+       if (FD_ISSET (gip_m_fd, &set_r))
+       {
+            if (!(lgets (command, sizeof(command)-1, gip_m_fd)))
+           {
+                gw_log (GW_LOG_FATAL, module, "Unexpected close");
+               exit (1);
+           }
+           if ((cp = strchr (command, '\n')))
+               *cp = '\0';
+           gw_log (GW_LOG_DEBUG, module, "IPC: %s", command);
+           if (!memcmp (command, "eti ", 4))
+           {
+               int id = atoi (command+4);
+               struct ke_info *new_k;
+
+                new_k = ke_info_add (id);
+                gw_log (GW_LOG_DEBUG, "module", "Incoming mail %d", id);
+               str_queue_enq (new_k->queue, "mail\n");
+               while (lgets (line_buf, sizeof(line_buf)-1, gip_m_fd))
+                   str_queue_enq (new_k->queue, line_buf);
+               str_queue_enq (new_k->queue, "\001");
+           }
+       }
+       for (ki = ke_info_list; ki; ki = ki->next)
+       {
+           int fd;
+            if (ki->gip && (fd = gip_infileno (ki->gip)) != -1 &&
+               FD_ISSET (fd, &set_r))
+           {
+               if (lgets (line_buf, sizeof(line_buf)-1, fd))
+               {
+                    gw_log (GW_LOG_DEBUG, module, "IPC: %s", line_buf);
+               }
+               else
+               {
+                    gw_log (GW_LOG_DEBUG, module, "Close of %d", ki->id);
+                    gipc_close (ki->gip);
+                    gipc_destroy (ki->gip);
+                   ki->gip = NULL;
+               }
+           }
+       }
+    }
+}
+
+int main (int argc, char **argv)
+{
+    gw_log_init (*argv);
+    gw_log_level (GW_LOG_ALL);
+    gw_log_file (GW_LOG_ALL, "monitor.log");
+
+    monitor_events (argc, argv);
+    exit (0);
+}
+