* $Header$
*
* Copyright (C) 1987 by the Massachusetts Institute of Technology
- *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
*
* SMS server process.
*
* You are in a maze of twisty little finite automata, all different.
* Let the reader beware.
*
- * $Log$
- * Revision 1.10 1987-06-30 20:02:26 wesommer
- * Added returned tuple chain to client structure.
- * Added local realm global variable.
- *
- * Revision 1.9 87/06/21 16:39:54 wesommer
- * Performance work, rearrangement of include files.
- *
- * Revision 1.8 87/06/09 18:44:45 wesommer
- * modified error handling.
- *
- * Revision 1.7 87/06/08 02:44:44 wesommer
- * Minor lint fix.
- *
- * Revision 1.6 87/06/03 17:41:00 wesommer
- * Added startup support.
- *
- * Revision 1.5 87/06/03 16:07:17 wesommer
- * Fixes for lint.
- *
- * Revision 1.4 87/06/02 20:05:11 wesommer
- * Bug fixes on memory allocation.
- *
- * Revision 1.3 87/06/01 04:34:27 wesommer
- * Changed returned error code.
- *
- * Revision 1.2 87/06/01 03:34:53 wesommer
- * Added shutdown, logging.
- *
- * Revision 1.1 87/05/31 22:06:56 wesommer
- * Initial revision
- *
*/
static char *rcsid_sms_main_c = "$Header$";
+#include <mit-copyright.h>
#include <strings.h>
#include <sys/errno.h>
#include <sys/signal.h>
+#include <sys/wait.h>
#include "sms_server.h"
extern CONNECTION newconn, listencon;
extern char buf1[BUFSIZ];
extern char *takedown;
extern int errno;
-
+extern FILE *journal;
+#define JOURNAL "/u1/sms/journal"
extern char *malloc();
+extern int free();
extern char *inet_ntoa();
extern void sms_com_err();
extern void do_client();
extern int sigshut();
void clist_append();
void oplist_append();
-extern u_short ntohs();
+void reapchild();
+
+extern time_t now;
/*
* Main SMS server loop.
char **argv;
{
int status;
+ time_t tardy;
whoami = argv[0];
/*
init_sms_err_tbl();
init_krb_err_tbl();
set_com_err_hook(sms_com_err);
-
+ setlinebuf(stderr);
+
if (argc != 1) {
com_err(whoami, 0, "Usage: smsd");
exit(1);
}
+
+ /* Profiling implies that getting rid of one level of call
+ * indirection here wins us maybe 1% on the VAX.
+ */
+ gdb_amv = malloc;
+ gdb_fmv = free;
/*
* GDB initialization.
*/
if ((status = sms_open_database()) != 0) {
- com_err(whoami, status, "when trying to open database.");
+ com_err(whoami, status, " when trying to open database.");
exit(1);
}
+ sanity_check_queries();
+ sanity_check_database();
+
/*
* Set up client array handler.
*/
*/
if ((((int)signal (SIGTERM, sigshut)) < 0) ||
+ (((int)signal (SIGCHLD, reapchild)) < 0) ||
(((int)signal (SIGHUP, sigshut)) < 0)) {
- com_err(whoami, errno, "Unable to establish signal handler.");
+ com_err(whoami, errno, " Unable to establish signal handler.");
exit(1);
}
+ journal = fopen(JOURNAL, "a");
+ if (journal == NULL) {
+ com_err(whoami, errno, " while opening journal file");
+ exit(1);
+ }
+
/*
* Establish template connection.
*/
if ((status = do_listen()) != 0) {
com_err(whoami, status,
- "while trying to create listening connection");
+ " while trying to create listening connection");
exit(1);
}
op_list = create_list_of_operations(1, listenop);
- (void) sprintf(buf1, "started (pid %d)", getpid());
- com_err(whoami, 0, buf1);
+ com_err(whoami, 0, "started (pid %d)", getpid());
com_err(whoami, 0, rcsid_sms_main_c);
+ send_zgram("SMS", "server started");
/*
* Run until shut down.
(fd_set *)NULL, (struct timeval *)NULL);
if (status == -1) {
- com_err(whoami, errno, "error from op_select");
+ com_err(whoami, errno, " error from op_select");
continue;
} else if (status != -2) {
- com_err(whoami, 0, "wrong return from op_select_any");
+ com_err(whoami, 0, " wrong return from op_select_any");
continue;
}
if (takedown) break;
+ time(&now);
#ifdef notdef
fprintf(stderr, " tick\n");
#endif notdef
/*
- * Handle any existing connections.
- */
- for (i=0; i<nclients; i++) {
- if (OP_DONE(clients[i]->pending_op)) {
- cur_client = clients[i];
- do_client(cur_client);
- cur_client = NULL;
- if (takedown) break;
- }
- }
- /*
- * Handle any new connections.
+ * Handle any new connections; this comes first so
+ * errno isn't tromped on.
*/
if (OP_DONE(listenop)) {
if (OP_STATUS(listenop) == OP_CANCELLED) {
- com_err(whoami, errno, "Error on listen");
- exit(1);
-
+ if (errno == EWOULDBLOCK) {
+ do_reset_listen();
+ } else {
+ com_err(whoami, errno,
+ " error on listen");
+ exit(1);
+ }
} else if ((status = new_connection()) != 0) {
com_err(whoami, errno,
- "Error on listening operation.");
+ " Error on listening operation.");
/*
* Sleep here to prevent hosing?
*/
}
}
+ /*
+ * Handle any existing connections.
+ */
+ tardy = now - 30*60;
+
+ for (i=0; i<nclients; i++) {
+ cur_client = clients[i];
+ if (OP_DONE(clients[i]->pending_op)) {
+ cur_client->last_time_used = now;
+ do_client(cur_client);
+ } else if (clients[i]->last_time_used < tardy) {
+ com_err(whoami, 0, "Shutting down connection due to inactivity");
+ shutdown(cur_client->con->in.fd, 0);
+ }
+ cur_client = NULL;
+ if (takedown) break;
+ }
}
- com_err(whoami, 0, takedown);
+ com_err(whoami, 0, "%s", takedown);
sms_close_database();
+ send_zgram("SMS", takedown);
return 0;
}
return 0;
}
+
+do_reset_listen()
+{
+ client_addrlen = sizeof(client_addr);
+ start_accepting_client(listencon, listenop, &newconn,
+ (char *)&client_addr,
+ &client_addrlen, &client_tuple);
+}
+
/*
* This routine is called when a new connection comes in.
*
* Set up the new connection and reply to the client
*/
cp = (client *)malloc(sizeof *cp);
- cp->state = CL_STARTING;
+ bzero(cp, sizeof(*cp));
cp->action = CL_ACCEPT;
cp->con = newconn;
cp->id = counter++;
cp->reply.sms_argv = NULL;
cp->first = NULL;
cp->last = NULL;
-
+ cp->last_time_used = now;
newconn = NULL;
cp->pending_op = create_operation();
* Log new connection.
*/
- (void) sprintf(buf1,
- "New connection from %s port %d (now %d client%s)",
- inet_ntoa(cp->haddr.sin_addr),
- (int)ntohs(cp->haddr.sin_port),
- nclients,
- nclients!=1?"s":"");
- com_err(whoami, 0, buf1);
+ com_err(whoami, 0, "New connection from %s port %d (now %d client%s)",
+ inet_ntoa(cp->haddr.sin_addr),
+ (int)ntohs(cp->haddr.sin_port),
+ nclients,
+ nclients!=1?"s":"");
/*
* Get ready to accept the next connection.
}
abort();
}
+
+
+void reapchild()
+{
+ union wait status;
+ int pid;
+
+ if (takedown)
+ return;
+ while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) {
+ if (status.w_termsig == 0 && status.w_retcode == 0)
+ com_err(whoami, 0, "dcm started successfully");
+ else
+ com_err(whoami, 0, "%d: startdcm exits with signal %d status %d",
+ pid, status.w_termsig, status.w_retcode);
+ }
+}