6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
11 * Most of this is stolen from ../gdb/tsr.c
13 * You are in a maze of twisty little finite automata, all different.
14 * Let the reader beware.
17 * Revision 1.6 1987-06-03 17:41:00 wesommer
18 * Added startup support.
20 * Revision 1.5 87/06/03 16:07:17 wesommer
23 * Revision 1.4 87/06/02 20:05:11 wesommer
24 * Bug fixes on memory allocation.
26 * Revision 1.3 87/06/01 04:34:27 wesommer
27 * Changed returned error code.
29 * Revision 1.2 87/06/01 03:34:53 wesommer
30 * Added shutdown, logging.
32 * Revision 1.1 87/05/31 22:06:56 wesommer
37 static char *rcsid_sms_main_c = "$Header$";
40 #include <sys/errno.h>
41 #include <sys/signal.h>
42 #include "sms_private.h"
43 #include "sms_server.h"
45 extern CONNECTION newconn, listencon;
48 extern client **clients, *cur_client;
50 extern OPERATION listenop;
51 extern LIST_OF_OPERATIONS op_list;
53 extern struct sockaddr_in client_addr;
54 extern int client_addrlen;
55 extern TUPLE client_tuple;
58 extern char buf1[BUFSIZ];
59 extern char *takedown;
63 extern char *malloc();
64 extern char *inet_ntoa();
65 extern void sms_com_err();
66 extern void do_client();
71 extern u_short ntohs();
74 * Main SMS server loop.
76 * Initialize the world, then start accepting connections and
77 * making progress on current connections.
94 set_com_err_hook(sms_com_err);
97 com_err(whoami, 0, "Usage: smsd");
102 * GDB initialization.
104 if(gdb_init() != 0) {
105 com_err(whoami, 0, "GDB initialization failed.");
110 * Database initialization.
113 if ((status = sms_open_database()) != 0) {
114 com_err(whoami, status, "when trying to open database.");
119 * Set up client array handler.
122 clients = (client **) malloc(0);
126 * There should probably be a few more of these.
129 if ((((int)signal (SIGTERM, sigshut)) < 0) ||
130 (((int)signal (SIGHUP, sigshut)) < 0)) {
131 com_err(whoami, errno, "Unable to establish signal handler.");
136 * Establish template connection.
138 if ((status = do_listen()) != 0) {
139 com_err(whoami, status,
140 "while trying to create listening connection");
144 op_list = create_list_of_operations(1, listenop);
146 (void) sprintf(buf1, "started (pid %d)", getpid());
147 com_err(whoami, 0, buf1);
148 com_err(whoami, 0, rcsid_sms_main_c);
151 * Run until shut down.
156 * Block until something happens.
159 com_err(whoami, 0, "tick");
162 status = op_select_any(op_list, 0,
163 (fd_set *)NULL, (fd_set *)NULL,
164 (fd_set *)NULL, (struct timeval *)NULL);
167 com_err(whoami, errno, "error from op_select");
169 } else if (status != -2) {
170 com_err(whoami, 0, "wrong return from op_select_any");
175 fprintf(stderr, " tick\n");
178 * Handle any existing connections.
180 for (i=0; i<nclients; i++) {
181 if (OP_DONE(clients[i]->pending_op)) {
182 cur_client = clients[i];
183 do_client(cur_client);
189 * Handle any new connections.
191 if (OP_DONE(listenop)) {
192 if ((status = new_connection()) != 0) {
193 com_err(whoami, errno,
194 "Error on listening operation.");
196 * Sleep here to prevent hosing?
201 com_err(whoami, 0, takedown);
202 sms_close_database();
207 * Set up the template connection and queue the first accept.
213 char *service = index(SMS_GDB_SERV, ':') + 1;
215 listencon = create_listening_connection(service);
217 if (listencon == NULL)
220 listenop = create_operation();
221 client_addrlen = sizeof(client_addr);
223 start_accepting_client(listencon, listenop, &newconn,
224 (char *)&client_addr,
225 &client_addrlen, &client_tuple);
230 * This routine is called when a new connection comes in.
232 * It sets up a new client and adds it to the list of currently active clients.
237 register client *cp = (client *)malloc(sizeof *cp);
241 * Make sure there's been no error
243 if(OP_STATUS(listenop) != OP_COMPLETE ||
252 * Set up the new connection and reply to the client
255 cp->state = CL_STARTING;
256 cp->action = CL_ACCEPT;
261 cp->reply.sms_argv = NULL;
265 cp->pending_op = create_operation();
266 reset_operation(cp->pending_op);
267 oplist_append(&op_list, cp->pending_op);
271 * Add a new client to the array..
276 * Let him know we heard him.
278 start_replying_to_client(cp->pending_op, cp->con, GDB_ACCEPTED,
281 cp->haddr = client_addr;
284 * Log new connection.
288 "New connection from %s port %d (now %d client%s)",
289 inet_ntoa(cp->haddr.sin_addr),
290 (int)ntohs(cp->haddr.sin_port),
293 com_err(whoami, 0, buf1);
296 * Get ready to accept the next connection.
298 reset_operation(listenop);
299 client_addrlen = sizeof(client_addr);
301 start_accepting_client(listencon, listenop, &newconn,
302 (char *)&client_addr,
303 &client_addrlen, &client_tuple);
308 * Add a new client to the known clients.
317 clients_n = (client **)malloc
318 ((unsigned)(nclients * sizeof(client *)));
319 bcopy((char *)clients, (char *)clients_n, (nclients-1)*sizeof(cp));
320 clients_n[nclients-1] = cp;
321 free((char *)clients);
331 client **clients_n, **scpp, **dcpp; /* source and dest client */
336 clients_n = (client **)malloc
337 ((unsigned)((nclients - 1)* sizeof(client *)));
338 for (scpp = clients, dcpp = clients_n; scpp < clients+nclients; ) {
343 if (found_it) abort();
348 free((char *)clients);
352 reset_operation(cp->pending_op);
353 delete_operation(cp->pending_op);
358 * Add a new operation to a list of operations.
360 * This should be rewritten to use realloc instead, since in most
361 * cases it won't have to copy the array.
365 oplist_append(oplp, op)
366 LIST_OF_OPERATIONS *oplp;
369 int count = (*oplp)->count+1;
370 LIST_OF_OPERATIONS newlist = (LIST_OF_OPERATIONS)
371 db_alloc(size_of_list_of_operations(count));
372 bcopy((char *)(*oplp), (char *)newlist,
373 size_of_list_of_operations((*oplp)->count));
375 newlist->op[count-1] = op;
376 db_free((*oplp), size_of_list_of_operations(count-1));