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