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