]> andersk Git - moira.git/blob - server/mr_main.c
Catch children (i.e. spawned DCM's) and print their status if non-zero
[moira.git] / server / mr_main.c
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
6  *      Copyright (C) 1987 by the Massachusetts Institute of Technology
7  *
8  *
9  *      SMS server process.
10  *
11  *      Most of this is stolen from ../gdb/tsr.c
12  *
13  *      You are in a maze of twisty little finite automata, all different.
14  *      Let the reader beware.
15  * 
16  */
17
18 static char *rcsid_sms_main_c = "$Header$";
19
20 #include <strings.h>
21 #include <sys/errno.h>
22 #include <sys/signal.h>
23 #include <sys/wait.h>
24 #include "sms_server.h"
25
26 extern CONNECTION newconn, listencon;
27
28 extern int nclients;
29 extern client **clients, *cur_client;
30
31 extern OPERATION listenop;
32 extern LIST_OF_OPERATIONS op_list;
33
34 extern struct sockaddr_in client_addr;
35 extern int client_addrlen;
36 extern TUPLE client_tuple;
37
38 extern char *whoami;
39 extern char buf1[BUFSIZ];
40 extern char *takedown;
41 extern int errno;
42 extern FILE *journal;
43 #define JOURNAL "/u1/sms/journal"
44
45 extern char *malloc();
46 extern int free();
47 extern char *inet_ntoa();
48 extern void sms_com_err();
49 extern void do_client();
50
51 extern int sigshut();
52 void clist_append();
53 void oplist_append();
54 void reapchild();
55
56 extern time_t now;
57
58 /*
59  * Main SMS server loop.
60  *
61  * Initialize the world, then start accepting connections and
62  * making progress on current connections.
63  */
64
65 /*ARGSUSED*/
66 int
67 main(argc, argv)
68         int argc;
69         char **argv;
70 {
71         int status;
72         time_t tardy;
73         
74         whoami = argv[0];
75         /*
76          * Error handler init.
77          */
78         init_sms_err_tbl();
79         init_krb_err_tbl();
80         set_com_err_hook(sms_com_err);
81         setlinebuf(stderr);
82         
83         if (argc != 1) {
84                 com_err(whoami, 0, "Usage: smsd");
85                 exit(1);
86         }               
87
88         /* Profiling implies that getting rid of one level of call
89          * indirection here wins us maybe 1% on the VAX.
90          */
91         gdb_amv = malloc;
92         gdb_fmv = free;
93         
94         /*
95          * GDB initialization.
96          */
97         if(gdb_init() != 0) {
98                 com_err(whoami, 0, "GDB initialization failed.");
99                 exit(1);
100         }
101         gdb_debug(0); /* this can be patched, if necessary, to enable */
102                       /* GDB level debugging .. */
103         krb_realm = malloc(REALM_SZ);
104         get_krbrlm(krb_realm, 1);
105         
106         /*
107          * Database initialization.
108          */
109
110         if ((status = sms_open_database()) != 0) {
111                 com_err(whoami, status, " when trying to open database.");
112                 exit(1);
113         }
114         
115         sanity_check_queries();
116         sanity_check_database();
117
118         /*
119          * Set up client array handler.
120          */
121         nclients = 0;
122         clients = (client **) malloc(0);
123         
124         /*
125          * Signal handlers
126          *      There should probably be a few more of these.
127          */
128         
129         if ((((int)signal (SIGTERM, sigshut)) < 0) ||
130             (((int)signal (SIGHUP, sigshut)) < 0)) {
131                 com_err(whoami, errno, " Unable to establish signal handler.");
132                 exit(1);
133         }
134         
135         journal = fopen(JOURNAL, "a");
136         if (journal == NULL) {
137             com_err(whoami, errno, " while opening journal file");
138             exit(1);
139         }
140
141         /*
142          * Establish template connection.
143          */
144         if ((status = do_listen()) != 0) {
145                 com_err(whoami, status,
146                         " while trying to create listening connection");
147                 exit(1);
148         }
149         
150         op_list = create_list_of_operations(1, listenop);
151         
152         com_err(whoami, 0, "started (pid %d)", getpid());
153         com_err(whoami, 0, rcsid_sms_main_c);
154         send_zgram("SMS", "server started");
155
156         /*
157          * Run until shut down.
158          */
159         while(!takedown) {              
160                 register int i;
161                 /*
162                  * Block until something happens.
163                  */
164 #ifdef notdef
165                 com_err(whoami, 0, "tick");
166 #endif notdef
167                 errno = 0;
168                 status = op_select_any(op_list, 0,
169                                        (fd_set *)NULL, (fd_set *)NULL,
170                                        (fd_set *)NULL, (struct timeval *)NULL);
171
172                 if (status == -1) {
173                         com_err(whoami, errno, " error from op_select");
174                         continue;
175                 } else if (status != -2) {
176                         com_err(whoami, 0, " wrong return from op_select_any");
177                         continue;
178                 }
179                 if (takedown) break;
180                 time(&now);
181 #ifdef notdef
182                 fprintf(stderr, "    tick\n");
183 #endif notdef
184                 /*
185                  * Handle any new connections; this comes first so
186                  * errno isn't tromped on.
187                  */
188                 if (OP_DONE(listenop)) {
189                         if (OP_STATUS(listenop) == OP_CANCELLED) {
190                                 if (errno == EWOULDBLOCK) {
191                                         do_reset_listen();
192                                 } else {
193                                         com_err(whoami, errno,
194                                                 " error on listen");
195                                         exit(1);
196                                 }
197                         } else if ((status = new_connection()) != 0) {
198                                 com_err(whoami, errno,
199                                         " Error on listening operation.");
200                                 /*
201                                  * Sleep here to prevent hosing?
202                                  */
203                         }
204                 }
205                 /*
206                  * Handle any existing connections.
207                  */
208                 tardy = now - 30*60;
209                 
210                 for (i=0; i<nclients; i++) {
211                         cur_client = clients[i];
212                         if (OP_DONE(clients[i]->pending_op)) {
213                                 cur_client->last_time_used = now;
214                                 do_client(cur_client);
215                         } else if (clients[i]->last_time_used < tardy) {
216                                 com_err(whoami, 0, "Shutting down connection due to inactivity");
217                                 shutdown(cur_client->con->in.fd, 0);
218                         }
219                         cur_client = NULL;
220                         if (takedown) break;
221                 }
222         }
223         com_err(whoami, 0, "%s", takedown);
224         sms_close_database();
225         send_zgram("SMS", takedown);
226         return 0;
227 }
228
229 /*
230  * Set up the template connection and queue the first accept.
231  */
232
233 int
234 do_listen()
235 {
236         char *service = index(SMS_GDB_SERV, ':') + 1;
237
238         listencon = create_listening_connection(service);
239
240         if (listencon == NULL)
241                 return errno;
242
243         listenop = create_operation();
244         client_addrlen = sizeof(client_addr);
245
246         start_accepting_client(listencon, listenop, &newconn,
247                                (char *)&client_addr,
248                                &client_addrlen, &client_tuple);
249         return 0;
250 }
251
252
253 do_reset_listen()
254 {
255         client_addrlen = sizeof(client_addr);
256         start_accepting_client(listencon, listenop, &newconn,
257                                (char *)&client_addr,
258                                &client_addrlen, &client_tuple);
259 }
260
261 /*
262  * This routine is called when a new connection comes in.
263  *
264  * It sets up a new client and adds it to the list of currently active clients.
265  */
266 int
267 new_connection()
268 {
269         register client *cp;
270         static counter = 0;
271         
272         /*
273          * Make sure there's been no error
274          */
275         if(OP_STATUS(listenop) != OP_COMPLETE) {
276                 return errno;
277         }
278         
279         if (newconn == NULL) {
280                 return SMS_NOT_CONNECTED;
281         }
282
283         /*
284          * Set up the new connection and reply to the client
285          */
286         cp = (client *)malloc(sizeof *cp);
287         bzero(cp, sizeof(*cp));
288         cp->state = CL_STARTING;
289         cp->action = CL_ACCEPT;
290         cp->con = newconn;
291         cp->id = counter++;
292         cp->args = NULL;
293         cp->clname = NULL;
294         cp->reply.sms_argv = NULL;
295         cp->first = NULL;
296         cp->last = NULL;
297         cp->last_time_used = now;
298         newconn = NULL;
299         
300         cp->pending_op = create_operation();
301         reset_operation(cp->pending_op);
302         oplist_append(&op_list, cp->pending_op);
303         cur_client = cp;
304         
305         /*
306          * Add a new client to the array..
307          */
308         clist_append(cp);
309         
310         /*
311          * Let him know we heard him.
312          */
313         start_replying_to_client(cp->pending_op, cp->con, GDB_ACCEPTED,
314                                  "", "");
315
316         cp->haddr = client_addr;
317         
318         /*
319          * Log new connection.
320          */
321         
322         com_err(whoami, 0, "New connection from %s port %d (now %d client%s)",
323                 inet_ntoa(cp->haddr.sin_addr),
324                 (int)ntohs(cp->haddr.sin_port),
325                 nclients,
326                 nclients!=1?"s":"");
327         
328         /*
329          * Get ready to accept the next connection.
330          */
331         reset_operation(listenop);
332         client_addrlen = sizeof(client_addr);
333
334         start_accepting_client(listencon, listenop, &newconn,
335                                (char *)&client_addr,
336                                &client_addrlen, &client_tuple);
337         return 0;
338 }
339
340 /*
341  * Add a new client to the known clients.
342  */
343 void
344 clist_append(cp)
345         client *cp;
346 {               
347         client **clients_n;
348         
349         nclients++;
350         clients_n = (client **)malloc
351                 ((unsigned)(nclients * sizeof(client *)));
352         bcopy((char *)clients, (char *)clients_n, (nclients-1)*sizeof(cp));
353         clients_n[nclients-1] = cp;
354         free((char *)clients);
355         clients = clients_n;
356         clients_n = NULL;
357 }
358
359                 
360 void
361 clist_delete(cp)
362         client *cp;
363 {
364         client **clients_n, **scpp, **dcpp; /* source and dest client */
365                                             /* ptr ptr */
366         
367         int found_it = 0;
368         
369         clients_n = (client **)malloc
370                 ((unsigned)((nclients - 1)* sizeof(client *)));
371         for (scpp = clients, dcpp = clients_n; scpp < clients+nclients; ) {
372                 if (*scpp != cp) {
373                         *dcpp++ = *scpp++;
374                 } else {
375                         scpp++;
376                         if (found_it) abort();
377                         found_it = 1;
378                 }                       
379         }
380         --nclients;     
381         free((char *)clients);
382         clients = clients_n;
383         clients_n = NULL;
384         oplist_delete(op_list, cp->pending_op);
385         reset_operation(cp->pending_op);
386         delete_operation(cp->pending_op);
387         sever_connection(cp->con);
388         free((char *)cp);
389 }
390
391 /*
392  * Add a new operation to a list of operations.
393  *
394  * This should be rewritten to use realloc instead, since in most
395  * cases it won't have to copy the array.
396  */
397
398 void
399 oplist_append(oplp, op)
400         LIST_OF_OPERATIONS *oplp;
401         OPERATION op;
402 {
403         int count = (*oplp)->count+1;
404         LIST_OF_OPERATIONS newlist = (LIST_OF_OPERATIONS)
405                 db_alloc(size_of_list_of_operations(count));
406         bcopy((char *)(*oplp), (char *)newlist,
407               size_of_list_of_operations((*oplp)->count));
408         newlist->count++;
409         newlist->op[count-1] = op;
410         db_free((char *)(*oplp), size_of_list_of_operations(count-1));
411         (*oplp) = newlist;
412 }
413
414
415 oplist_delete(oplp, op)
416         LIST_OF_OPERATIONS oplp;
417         register OPERATION op;
418 {
419         register OPERATION *s;
420         register int c;
421         
422         for (s = oplp->op, c=oplp->count; c; --c, ++s) {
423                 if (*s == op) {
424                         while (c > 0) {
425                                 *s = *(s+1);
426                                 ++s;
427                                 --c;
428                         }
429                         oplp->count--;
430                         return;
431                 }
432         }
433         abort();
434 }
435
436
437 void reapchild()
438 {
439     union wait status;
440     int pid;
441
442     while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) {
443         if  (status.w_termsig == 0 && status.w_retcode == 0)
444           com_err(whoami, 0, "dcm started successfully");
445         else
446           com_err(whoami, 0, "%d: startdcm exits with signal %d status %d",
447                   pid, status.w_termsig, status.w_retcode);
448     }
449 }
This page took 0.390236 seconds and 5 git commands to generate.