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