]> andersk Git - moira.git/blob - server/mr_main.c
Don't print error on successful change of FS
[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 (SIGCHLD, reapchild)) < 0) ||
131             (((int)signal (SIGHUP, sigshut)) < 0)) {
132                 com_err(whoami, errno, " Unable to establish signal handler.");
133                 exit(1);
134         }
135         
136         journal = fopen(JOURNAL, "a");
137         if (journal == NULL) {
138             com_err(whoami, errno, " while opening journal file");
139             exit(1);
140         }
141
142         /*
143          * Establish template connection.
144          */
145         if ((status = do_listen()) != 0) {
146                 com_err(whoami, status,
147                         " while trying to create listening connection");
148                 exit(1);
149         }
150         
151         op_list = create_list_of_operations(1, listenop);
152         
153         com_err(whoami, 0, "started (pid %d)", getpid());
154         com_err(whoami, 0, rcsid_sms_main_c);
155         send_zgram("SMS", "server started");
156
157         /*
158          * Run until shut down.
159          */
160         while(!takedown) {              
161                 register int i;
162                 /*
163                  * Block until something happens.
164                  */
165 #ifdef notdef
166                 com_err(whoami, 0, "tick");
167 #endif notdef
168                 errno = 0;
169                 status = op_select_any(op_list, 0,
170                                        (fd_set *)NULL, (fd_set *)NULL,
171                                        (fd_set *)NULL, (struct timeval *)NULL);
172
173                 if (status == -1) {
174                         com_err(whoami, errno, " error from op_select");
175                         continue;
176                 } else if (status != -2) {
177                         com_err(whoami, 0, " wrong return from op_select_any");
178                         continue;
179                 }
180                 if (takedown) break;
181                 time(&now);
182 #ifdef notdef
183                 fprintf(stderr, "    tick\n");
184 #endif notdef
185                 /*
186                  * Handle any new connections; this comes first so
187                  * errno isn't tromped on.
188                  */
189                 if (OP_DONE(listenop)) {
190                         if (OP_STATUS(listenop) == OP_CANCELLED) {
191                                 if (errno == EWOULDBLOCK) {
192                                         do_reset_listen();
193                                 } else {
194                                         com_err(whoami, errno,
195                                                 " error on listen");
196                                         exit(1);
197                                 }
198                         } else if ((status = new_connection()) != 0) {
199                                 com_err(whoami, errno,
200                                         " Error on listening operation.");
201                                 /*
202                                  * Sleep here to prevent hosing?
203                                  */
204                         }
205                 }
206                 /*
207                  * Handle any existing connections.
208                  */
209                 tardy = now - 30*60;
210                 
211                 for (i=0; i<nclients; i++) {
212                         cur_client = clients[i];
213                         if (OP_DONE(clients[i]->pending_op)) {
214                                 cur_client->last_time_used = now;
215                                 do_client(cur_client);
216                         } else if (clients[i]->last_time_used < tardy) {
217                                 com_err(whoami, 0, "Shutting down connection due to inactivity");
218                                 shutdown(cur_client->con->in.fd, 0);
219                         }
220                         cur_client = NULL;
221                         if (takedown) break;
222                 }
223         }
224         com_err(whoami, 0, "%s", takedown);
225         sms_close_database();
226         send_zgram("SMS", takedown);
227         return 0;
228 }
229
230 /*
231  * Set up the template connection and queue the first accept.
232  */
233
234 int
235 do_listen()
236 {
237         char *service = index(SMS_GDB_SERV, ':') + 1;
238
239         listencon = create_listening_connection(service);
240
241         if (listencon == NULL)
242                 return errno;
243
244         listenop = create_operation();
245         client_addrlen = sizeof(client_addr);
246
247         start_accepting_client(listencon, listenop, &newconn,
248                                (char *)&client_addr,
249                                &client_addrlen, &client_tuple);
250         return 0;
251 }
252
253
254 do_reset_listen()
255 {
256         client_addrlen = sizeof(client_addr);
257         start_accepting_client(listencon, listenop, &newconn,
258                                (char *)&client_addr,
259                                &client_addrlen, &client_tuple);
260 }
261
262 /*
263  * This routine is called when a new connection comes in.
264  *
265  * It sets up a new client and adds it to the list of currently active clients.
266  */
267 int
268 new_connection()
269 {
270         register client *cp;
271         static counter = 0;
272         
273         /*
274          * Make sure there's been no error
275          */
276         if(OP_STATUS(listenop) != OP_COMPLETE) {
277                 return errno;
278         }
279         
280         if (newconn == NULL) {
281                 return SMS_NOT_CONNECTED;
282         }
283
284         /*
285          * Set up the new connection and reply to the client
286          */
287         cp = (client *)malloc(sizeof *cp);
288         bzero(cp, sizeof(*cp));
289         cp->state = CL_STARTING;
290         cp->action = CL_ACCEPT;
291         cp->con = newconn;
292         cp->id = counter++;
293         cp->args = NULL;
294         cp->clname = NULL;
295         cp->reply.sms_argv = NULL;
296         cp->first = NULL;
297         cp->last = NULL;
298         cp->last_time_used = now;
299         newconn = NULL;
300         
301         cp->pending_op = create_operation();
302         reset_operation(cp->pending_op);
303         oplist_append(&op_list, cp->pending_op);
304         cur_client = cp;
305         
306         /*
307          * Add a new client to the array..
308          */
309         clist_append(cp);
310         
311         /*
312          * Let him know we heard him.
313          */
314         start_replying_to_client(cp->pending_op, cp->con, GDB_ACCEPTED,
315                                  "", "");
316
317         cp->haddr = client_addr;
318         
319         /*
320          * Log new connection.
321          */
322         
323         com_err(whoami, 0, "New connection from %s port %d (now %d client%s)",
324                 inet_ntoa(cp->haddr.sin_addr),
325                 (int)ntohs(cp->haddr.sin_port),
326                 nclients,
327                 nclients!=1?"s":"");
328         
329         /*
330          * Get ready to accept the next connection.
331          */
332         reset_operation(listenop);
333         client_addrlen = sizeof(client_addr);
334
335         start_accepting_client(listencon, listenop, &newconn,
336                                (char *)&client_addr,
337                                &client_addrlen, &client_tuple);
338         return 0;
339 }
340
341 /*
342  * Add a new client to the known clients.
343  */
344 void
345 clist_append(cp)
346         client *cp;
347 {               
348         client **clients_n;
349         
350         nclients++;
351         clients_n = (client **)malloc
352                 ((unsigned)(nclients * sizeof(client *)));
353         bcopy((char *)clients, (char *)clients_n, (nclients-1)*sizeof(cp));
354         clients_n[nclients-1] = cp;
355         free((char *)clients);
356         clients = clients_n;
357         clients_n = NULL;
358 }
359
360                 
361 void
362 clist_delete(cp)
363         client *cp;
364 {
365         client **clients_n, **scpp, **dcpp; /* source and dest client */
366                                             /* ptr ptr */
367         
368         int found_it = 0;
369         
370         clients_n = (client **)malloc
371                 ((unsigned)((nclients - 1)* sizeof(client *)));
372         for (scpp = clients, dcpp = clients_n; scpp < clients+nclients; ) {
373                 if (*scpp != cp) {
374                         *dcpp++ = *scpp++;
375                 } else {
376                         scpp++;
377                         if (found_it) abort();
378                         found_it = 1;
379                 }                       
380         }
381         --nclients;     
382         free((char *)clients);
383         clients = clients_n;
384         clients_n = NULL;
385         oplist_delete(op_list, cp->pending_op);
386         reset_operation(cp->pending_op);
387         delete_operation(cp->pending_op);
388         sever_connection(cp->con);
389         free((char *)cp);
390 }
391
392 /*
393  * Add a new operation to a list of operations.
394  *
395  * This should be rewritten to use realloc instead, since in most
396  * cases it won't have to copy the array.
397  */
398
399 void
400 oplist_append(oplp, op)
401         LIST_OF_OPERATIONS *oplp;
402         OPERATION op;
403 {
404         int count = (*oplp)->count+1;
405         LIST_OF_OPERATIONS newlist = (LIST_OF_OPERATIONS)
406                 db_alloc(size_of_list_of_operations(count));
407         bcopy((char *)(*oplp), (char *)newlist,
408               size_of_list_of_operations((*oplp)->count));
409         newlist->count++;
410         newlist->op[count-1] = op;
411         db_free((char *)(*oplp), size_of_list_of_operations(count-1));
412         (*oplp) = newlist;
413 }
414
415
416 oplist_delete(oplp, op)
417         LIST_OF_OPERATIONS oplp;
418         register OPERATION op;
419 {
420         register OPERATION *s;
421         register int c;
422         
423         for (s = oplp->op, c=oplp->count; c; --c, ++s) {
424                 if (*s == op) {
425                         while (c > 0) {
426                                 *s = *(s+1);
427                                 ++s;
428                                 --c;
429                         }
430                         oplp->count--;
431                         return;
432                 }
433         }
434         abort();
435 }
436
437
438 void reapchild()
439 {
440     union wait status;
441     int pid;
442
443     while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) {
444         if  (status.w_termsig == 0 && status.w_retcode == 0)
445           com_err(whoami, 0, "dcm started successfully");
446         else
447           com_err(whoami, 0, "%d: startdcm exits with signal %d status %d",
448                   pid, status.w_termsig, status.w_retcode);
449     }
450 }
This page took 0.078461 seconds and 5 git commands to generate.