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