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