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