FIFO existence is used to test for a running kernel.
[egate.git] / kernel / eti.c
1 /* Gateway kernel
2  * Europagate, 1995
3  *
4  * $Log: eti.c,v $
5  * Revision 1.3  1995/03/28 08:01:23  adam
6  * FIFO existence is used to test for a running kernel.
7  *
8  * Revision 1.2  1995/03/27  12:51:05  adam
9  * New log level in use: GW_LOG_ERRNO.
10  *
11  * Revision 1.1  1995/03/27  08:24:00  adam
12  * First use of gip interface and gw-db.
13  * First work on eti program.
14  *
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <assert.h>
20 #include <ctype.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <setjmp.h>
25 #include <signal.h>
26
27 #include <gw-log.h>
28 #include <gw-db.h>
29 #include <gip.h>
30
31 #define LINE_MAX 1024
32 static char line_buf[LINE_MAX+1];
33
34 static char *module = "eti";
35 static jmp_buf retry_jmp;
36
37 static void pipe_handle (int dummy)
38 {
39     longjmp (retry_jmp, 1);
40 }
41
42 static int email_header (FILE *inf, char *from_str, char *subject_str)
43 {
44     *from_str = '\0';
45     *subject_str = '\0';
46     while (fgets (line_buf, LINE_MAX, inf))
47     {
48         if (line_buf[0] == '\n')
49             return 0;
50         if (strncmp (line_buf, "From ", 5) == 0)
51             sscanf (line_buf+4, "%s", from_str);
52         if (strncmp (line_buf, "Subject: ", 9) == 0 &&
53             sscanf (line_buf+9, "%s", subject_str+1) == 1)
54             strcpy (subject_str, line_buf+9);
55     }
56     return 1;
57 }
58
59 static void start_kernel (int argc, char **argv, int id)
60 {
61     pid_t pid;
62     int i;
63     char **argv_p;
64     char userid_option[20];
65
66     argv_p = malloc (sizeof(*argv_p)*(argc+2));
67     if (!argv_p)
68     {
69         gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "malloc fail");
70         exit (1);
71     }
72     argv_p[0] = "kernel";
73     for (i = 1; i<argc; i++)
74         argv_p[i] = argv[i];
75     sprintf (userid_option, "-i%d", id);
76     argv_p[i++] = userid_option;
77     argv_p[i++] = NULL;
78
79     gw_log (GW_LOG_DEBUG, module, "Starting kernel");
80     pid = fork ();
81     if (pid == -1)
82     {
83         gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "fork");
84         exit (1);
85     }
86     if (!pid)
87     {
88         execvp ("kernel", argv_p);
89         gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "execvp");
90         exit (1);
91     }
92 }
93
94 int main (int argc, char **argv)
95 {
96     char from_str[LINE_MAX+1];
97     char subject_str[LINE_MAX+1];
98     char line_str[LINE_MAX+1];
99     GW_DB user_db;
100     GIP  gip;
101     void *user_info;
102     size_t info_length;
103     int  id;
104     int  r;
105     static int pass = 0;
106     char fifo_client_name[1024];
107     char fifo_server_name[1024];
108
109     gw_log_init (*argv);
110     gw_log_level (GW_LOG_ALL);
111     gw_log_file (GW_LOG_ALL, "eti.log");
112     r = email_header (stdin, from_str, subject_str);
113     if (! *from_str)
114     {
115         gw_log (GW_LOG_WARN, module, "No \"From\" in mail");
116         exit (1);
117     }
118     gw_log (GW_LOG_STAT, module, "Mail from %s", from_str);
119     user_db = gw_db_open ("user.db", 1);
120
121     r = gw_db_lookup (user_db, from_str, strlen(from_str),
122                       &user_info, &info_length);
123     if (r == 0)
124     {
125         gw_log (GW_LOG_STAT, module, "New user");
126         id = gw_db_seq_no (user_db);
127         r = gw_db_insert (user_db, from_str, strlen(from_str),
128                           &id, sizeof(id));
129         gw_log (GW_LOG_STAT, module, "Added user with id %d", id);
130     }
131     else if (r == 1)
132     {
133         if (sizeof(id) != info_length)
134         {
135             gw_log (GW_LOG_FATAL, module, "Bad id-size");
136             exit (1);
137         }
138         memcpy (&id, user_info, sizeof(id));
139         gw_log (GW_LOG_STAT, module, "Found with id %d", id);
140     }
141     else
142     {
143         gw_log (GW_LOG_FATAL, module, "gw_db_lookup fail");
144     }
145     sprintf (fifo_server_name, "fifo.s.%d", id);
146     sprintf (fifo_client_name, "fifo.c.%d", id);
147
148     gip = gipc_initialize (fifo_client_name);
149
150     signal (SIGPIPE, pipe_handle);
151     setjmp (retry_jmp);
152     ++pass;
153     gw_log (GW_LOG_DEBUG, module, "Pass %d", pass);
154     if (pass == 1)
155         r = gipc_open (gip, fifo_server_name, 0);
156     else if (pass == 2)
157     {
158         gipc_close (gip);
159         start_kernel (argc, argv, id);
160         r = gipc_open (gip, fifo_server_name, 1);
161     }
162     else if (pass == 3)
163     {
164         gw_log (GW_LOG_FATAL, module, "Cannot start kernel");
165         exit (1);
166     }
167     if (r < 0)
168         if (r == -2)
169         {
170             gw_log (GW_LOG_WARN|GW_LOG_ERRNO, module, "r==-2");
171             longjmp (retry_jmp, 1);
172         }
173         else if (r == -1)
174         {
175             gw_log (GW_LOG_WARN|GW_LOG_ERRNO, module, "r==-1");
176             longjmp (retry_jmp, 1);
177         }
178         else
179         {
180             gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "gipc_open");
181             exit (1);
182         }
183     /* deliver message ... */
184     gw_log (GW_LOG_DEBUG, module, "Delivering mail header");
185     gip_wline (gip, "mail\n");
186     gip_wline (gip, "From ");
187     gip_wline (gip, from_str);
188     gip_wline (gip, "\n");
189     if (*subject_str)
190     {
191         gip_wline (gip, "Subject: ");
192         gip_wline (gip, subject_str);
193         gip_wline (gip, "\n");
194     }
195     gip_wline (gip, "\n");
196     gw_log (GW_LOG_DEBUG, module, "Delivering mail body");
197     while (fgets (line_str, LINE_MAX, stdin))
198         gip_wline (gip, line_str);
199     gip_wline (gip, "\001");
200     gw_log (GW_LOG_DEBUG, module, "Closing");
201     gipc_close (gip);
202     gipc_destroy (gip);
203     gw_db_close (user_db);
204     exit (0);
205 }
206