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.5 1987-06-03 16:07:17 wesommer
20 * Revision 1.4 87/06/02 20:05:11 wesommer
21 * Bug fixes on memory allocation.
23 * Revision 1.3 87/06/01 04:34:27 wesommer
24 * Changed returned error code.
26 * Revision 1.2 87/06/01 03:34:53 wesommer
27 * Added shutdown, logging.
29 * Revision 1.1 87/05/31 22:06:56 wesommer
34 static char *rcsid_sms_main_c = "$Header$";
37 #include <sys/errno.h>
38 #include <sys/signal.h>
39 #include "sms_private.h"
40 #include "sms_server.h"
42 extern CONNECTION newconn, listencon;
45 extern client **clients, *cur_client;
47 extern OPERATION listenop;
48 extern LIST_OF_OPERATIONS op_list;
50 extern struct sockaddr_in client_addr;
51 extern int client_addrlen;
52 extern TUPLE client_tuple;
55 extern char buf1[BUFSIZ];
56 extern char *takedown;
60 extern char *malloc();
61 extern char *inet_ntoa();
62 extern void sms_com_err();
63 extern void do_client();
68 extern u_short ntohs();
71 * Main SMS server loop.
73 * Initialize the world, then start accepting connections and
74 * making progress on current connections.
91 set_com_err_hook(sms_com_err);
94 com_err(whoami, 0, "Usage: smsd");
101 if(gdb_init() != 0) {
102 com_err(whoami, 0, "GDB initialization failed.");
107 * Set up client array handler.
110 clients = (client **) malloc(0);
116 if ((((int)signal (SIGTERM, sigshut)) < 0) ||
117 (((int)signal (SIGHUP, sigshut)) < 0)) {
118 com_err(whoami, errno, "Unable to establish signal handler.");
123 * Establish template connection.
125 if ((status = do_listen()) != 0) {
126 com_err(whoami, status,
127 "while trying to create listening connection");
131 op_list = create_list_of_operations(1, listenop);
133 (void) sprintf(buf1, "started (pid %d)", getpid());
134 com_err(whoami, 0, buf1);
135 com_err(whoami, 0, rcsid_sms_main_c);
138 * Run until shut down.
143 * Block until something happens.
146 com_err(whoami, 0, "tick");
149 status = op_select_any(op_list, 0,
150 (fd_set *)NULL, (fd_set *)NULL,
151 (fd_set *)NULL, (struct timeval *)NULL);
154 com_err(whoami, errno, "error from op_select");
156 } else if (status != -2) {
157 com_err(whoami, 0, "wrong return from op_select_any");
162 fprintf(stderr, " tick\n");
165 * Handle any existing connections.
167 for (i=0; i<nclients; i++) {
168 if (OP_DONE(clients[i]->pending_op)) {
169 cur_client = clients[i];
170 do_client(cur_client);
176 * Handle any new connections.
178 if (OP_DONE(listenop)) {
179 if ((status = new_connection()) != 0) {
180 com_err(whoami, errno,
181 "Error on listening operation.");
183 * Sleep here to prevent hosing?
188 com_err(whoami, 0, takedown);
193 * Set up the template connection and queue the first accept.
199 char *service = index(SMS_GDB_SERV, ':') + 1;
201 listencon = create_listening_connection(service);
203 if (listencon == NULL)
206 listenop = create_operation();
207 client_addrlen = sizeof(client_addr);
209 start_accepting_client(listencon, listenop, &newconn,
210 (char *)&client_addr,
211 &client_addrlen, &client_tuple);
216 * This routine is called when a new connection comes in.
218 * It sets up a new client and adds it to the list of currently active clients.
223 register client *cp = (client *)malloc(sizeof *cp);
227 * Make sure there's been no error
229 if(OP_STATUS(listenop) != OP_COMPLETE ||
238 * Set up the new connection and reply to the client
241 cp->state = CL_STARTING;
242 cp->action = CL_ACCEPT;
247 cp->reply.sms_argv = NULL;
251 cp->pending_op = create_operation();
252 reset_operation(cp->pending_op);
253 oplist_append(&op_list, cp->pending_op);
257 * Add a new client to the array..
262 * Let him know we heard him.
264 start_replying_to_client(cp->pending_op, cp->con, GDB_ACCEPTED,
267 cp->haddr = client_addr;
270 * Log new connection.
274 "New connection from %s port %d (now %d client%s)",
275 inet_ntoa(cp->haddr.sin_addr),
276 (int)ntohs(cp->haddr.sin_port),
279 com_err(whoami, 0, buf1);
282 * Get ready to accept the next connection.
284 reset_operation(listenop);
285 client_addrlen = sizeof(client_addr);
287 start_accepting_client(listencon, listenop, &newconn,
288 (char *)&client_addr,
289 &client_addrlen, &client_tuple);
294 * Add a new client to the known clients.
303 clients_n = (client **)malloc
304 ((unsigned)(nclients * sizeof(client *)));
305 bcopy((char *)clients, (char *)clients_n, (nclients-1)*sizeof(cp));
306 clients_n[nclients-1] = cp;
307 free((char *)clients);
317 client **clients_n, **scpp, **dcpp; /* source and dest client */
322 clients_n = (client **)malloc
323 ((unsigned)((nclients - 1)* sizeof(client *)));
324 for (scpp = clients, dcpp = clients_n; scpp < clients+nclients; ) {
329 if (found_it) abort();
334 free((char *)clients);
338 reset_operation(cp->pending_op);
339 delete_operation(cp->pending_op);
344 * Add a new operation to a list of operations.
346 * This should be rewritten to use realloc instead, since in most
347 * cases it won't have to copy the array.
351 oplist_append(oplp, op)
352 LIST_OF_OPERATIONS *oplp;
355 int count = (*oplp)->count+1;
356 LIST_OF_OPERATIONS newlist = (LIST_OF_OPERATIONS)
357 db_alloc(size_of_list_of_operations(count));
358 bcopy((char *)(*oplp), (char *)newlist,
359 size_of_list_of_operations((*oplp)->count));
361 newlist->op[count-1] = op;
362 db_free((*oplp), size_of_list_of_operations(count-1));