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.4 1987-06-02 20:05:11 wesommer
18 * Bug fixes on memory allocation.
20 * Revision 1.3 87/06/01 04:34:27 wesommer
21 * Changed returned error code.
23 * Revision 1.2 87/06/01 03:34:53 wesommer
24 * Added shutdown, logging.
26 * Revision 1.1 87/05/31 22:06:56 wesommer
31 static char *rcsid_sms_main_c = "$Header$";
34 #include <sys/errno.h>
35 #include <sys/signal.h>
36 #include "sms_private.h"
37 #include "sms_server.h"
39 extern CONNECTION newconn, listencon;
42 extern client **clients, *cur_client;
44 extern OPERATION listenop;
45 extern LIST_OF_OPERATIONS op_list;
47 extern struct sockaddr_in client_addr;
48 extern int client_addrlen;
49 extern TUPLE client_tuple;
52 extern char buf1[BUFSIZ];
53 extern char *takedown;
57 extern char *malloc();
58 extern char *inet_ntoa();
59 extern void sms_com_err();
60 extern void do_client();
65 extern u_short ntohs();
68 * Main SMS server loop.
70 * Initialize the world, then start accepting connections and
71 * making progress on current connections.
88 set_com_err_hook(sms_com_err);
91 com_err(whoami, 0, "Usage: smsd");
101 * Set up client array handler.
104 clients = (client **) malloc(0);
110 if ((((int)signal (SIGTERM, sigshut)) < 0) ||
111 (((int)signal (SIGHUP, sigshut)) < 0)) {
112 com_err(whoami, errno, "Unable to establish signal handler.");
117 * Establish template connection.
119 if ((status = do_listen()) != 0) {
120 com_err(whoami, status,
121 "while trying to create listening connection");
125 op_list = create_list_of_operations(1, listenop);
127 (void) sprintf(buf1, "started (pid %d)", getpid());
128 com_err(whoami, 0, buf1);
129 com_err(whoami, 0, rcsid_sms_main_c);
132 * Run until shut down.
137 * Block until something happens.
139 op_select_any(op_list, 0, NULL, NULL, NULL, NULL);
142 fprintf(stderr, " tick\n");
145 * Handle any existing connections.
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);
156 * Handle any new connections.
158 if (OP_DONE(listenop)) {
159 if ((status = new_connection(listenop)) != 0) {
160 com_err(whoami, errno,
161 "Error on listening operation.");
163 * Sleep here to prevent hosing?
168 com_err(whoami, 0, takedown);
173 * Set up the template connection and queue the first accept.
179 char *service = index(SMS_GDB_SERV, ':') + 1;
181 listencon = create_listening_connection(service);
183 if (listencon == NULL)
186 listenop = create_operation();
187 client_addrlen = sizeof(client_addr);
189 start_accepting_client(listencon, listenop, &newconn,
190 (char *)&client_addr,
191 &client_addrlen, &client_tuple);
196 * This routine is called when a new connection comes in.
198 * It sets up a new client and adds it to the list of currently active clients.
201 new_connection(listenop)
204 register client *cp = (client *)malloc(sizeof *cp);
208 * Make sure there's been no error
210 if(OP_STATUS(listenop) != OP_COMPLETE ||
219 * Set up the new connection and reply to the client
222 cp->state = CL_STARTING;
223 cp->action = CL_ACCEPT;
228 cp->reply.sms_argv = NULL;
232 cp->pending_op = create_operation();
233 reset_operation(cp->pending_op);
234 oplist_append(&op_list, cp->pending_op);
238 * Add a new client to the array..
243 * Let him know we heard him.
245 start_replying_to_client(cp->pending_op, cp->con, GDB_ACCEPTED,
248 cp->haddr = client_addr;
251 * Log new connection.
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),
260 com_err(whoami, 0, buf1);
263 * Get ready to accept the next connection.
265 reset_operation(listenop);
266 client_addrlen = sizeof(client_addr);
268 start_accepting_client(listencon, listenop, &newconn,
269 (char *)&client_addr,
270 &client_addrlen, &client_tuple);
275 * Add a new client to the known clients.
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);
298 client **clients_n, **scpp, **dcpp; /* source and dest client */
303 clients_n = (client **)malloc
304 ((unsigned)((nclients - 1)* sizeof(client *)));
305 for (scpp = clients, dcpp = clients_n; scpp < clients+nclients; ) {
310 if (found_it) abort();
315 free((char *)clients);
319 reset_operation(cp->pending_op);
320 delete_operation(cp->pending_op);
325 * Add a new operation to a list of operations.
327 * This should be rewritten to use realloc instead, since in most
328 * cases it won't have to copy the array.
332 oplist_append(oplp, op)
333 LIST_OF_OPERATIONS *oplp;
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));
342 newlist->op[count-1] = op;
343 db_free((*oplp), size_of_list_of_operations(count-1));