X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/f6cc38de12ba163c8368d8f44882f026796ae062..refs/heads/qvalidate:/server/mr_main.c diff --git a/server/mr_main.c b/server/mr_main.c index a5a12fac..d5b13763 100644 --- a/server/mr_main.c +++ b/server/mr_main.c @@ -4,43 +4,34 @@ * $Header$ * * Copyright (C) 1987 by the Massachusetts Institute of Technology + * For copying and distribution information, please see the file + * . * - * - * SMS server process. + * MOIRA server process. * * Most of this is stolen from ../gdb/tsr.c * * You are in a maze of twisty little finite automata, all different. * Let the reader beware. * - * $Log$ - * Revision 1.6 1987-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$"; +static char *rcsid_mr_main_c = "$Header$"; -#include +#include +#include +#include +#include #include #include -#include "sms_private.h" -#include "sms_server.h" +#include +#include +#include +#include +#include "mr_server.h" +#include +#include +#include extern CONNECTION newconn, listencon; @@ -58,46 +49,63 @@ extern char *whoami; extern char buf1[BUFSIZ]; extern char *takedown; extern int errno; +extern FILE *journal; +extern time_t now; -extern char *malloc(); -extern char *inet_ntoa(); -extern void sms_com_err(); -extern void do_client(); +char hostbuf[BUFSIZ], *host; -extern int sigshut(); -void clist_append(); -void oplist_append(); -extern u_short ntohs(); +int do_listen(char *port); +void do_reset_listen(void); +void clist_append(client *cp); +void oplist_append(LIST_OF_OPERATIONS *oplp, OPERATION op); +void oplist_delete(LIST_OF_OPERATIONS oplp, OPERATION op); +void mr_setup_signals(void); +int new_connection(void); /* - * Main SMS server loop. + * Main MOIRA server loop. * * Initialize the world, then start accepting connections and * making progress on current connections. */ /*ARGSUSED*/ -int -main(argc, argv) - int argc; - char **argv; +int main(argc, argv) + int argc; + char **argv; { - int status; + int status, i; + time_t tardy; + char *port, *p; + extern char *database; + struct stat stbuf; whoami = argv[0]; /* * Error handler init. */ - init_sms_err_tbl(); - init_krb_err_tbl(); - set_com_err_hook(sms_com_err); - - if (argc != 1) { - com_err(whoami, 0, "Usage: smsd"); + initialize_sms_error_table(); + initialize_krb_error_table(); + initialize_gdss_error_table(); + set_com_err_hook(mr_com_err); + setvbuf(stderr, NULL, _IOLBF, BUFSIZ); + + port = strchr(MOIRA_SERVER, ':') + 1; + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-db") && i+1 < argc) { + database = argv[i+1]; + i++; + } else if (!strcmp(argv[i], "-p") && i+1 < argc) { + port = argv[i+1]; + i++; + } else { + com_err(whoami, 0, "Usage: moirad [-db database][-p port]"); exit(1); - } - + } + } + /* * GDB initialization. */ @@ -105,47 +113,72 @@ main(argc, argv) com_err(whoami, 0, "GDB initialization failed."); exit(1); } - + gdb_debug(0); /* this can be patched, if necessary, to enable */ + /* GDB level debugging .. */ + krb_realm = malloc(REALM_SZ); + krb_get_lrealm(krb_realm, 1); + /* - * Database initialization. + * Database initialization. Only init if database should be open. */ - if ((status = sms_open_database()) != 0) { - com_err(whoami, status, "when trying to open database."); + if (stat(MOIRA_MOTD_FILE, &stbuf) != 0) { + if ((status = mr_open_database()) != 0) { + com_err(whoami, status, " when trying to open database."); exit(1); + } + sanity_check_database(); + } else { + dormant = ASLEEP; + com_err(whoami, 0, "sleeping, not opening database"); } + sanity_check_queries(); + + /* + * Get moira server hostname for authentication + */ + if (gethostname(hostbuf, sizeof(hostbuf)) < 0) { + com_err(whoami, errno, "Unable to get local hostname"); + exit(1); + } + host = canonicalize_hostname(strsave(hostbuf)); + for (p = host; *p && *p != '.'; p++) + if (isupper(*p)) + *p = tolower(*p); + *p = 0; + /* * Set up client array handler. */ nclients = 0; clients = (client **) malloc(0); - /* - * Signal handlers - * There should probably be a few more of these. - */ + mr_setup_signals(); - if ((((int)signal (SIGTERM, sigshut)) < 0) || - (((int)signal (SIGHUP, sigshut)) < 0)) { - 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) { + if ((status = do_listen(port)) != 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, rcsid_sms_main_c); + com_err(whoami, 0, "started (pid %d)", getpid()); + com_err(whoami, 0, rcsid_mr_main_c); + if (dormant != ASLEEP) + send_zgram("MOIRA", "server started"); + else + send_zgram("MOIRA", "server started, but database closed"); /* * Run until shut down. @@ -158,48 +191,105 @@ main(argc, argv) #ifdef notdef com_err(whoami, 0, "tick"); #endif notdef + if (dormant == SLEEPY) { + mr_close_database(); + com_err(whoami, 0, "database closed"); + mr_setup_signals(); + send_zgram("MOIRA", "database closed"); + dormant = ASLEEP; + } else if (dormant == GROGGY) { + mr_open_database(); + com_err(whoami, 0, "database open"); + mr_setup_signals(); + send_zgram("MOIRA", "database open again"); + dormant = AWAKE; + } + errno = 0; status = op_select_any(op_list, 0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)NULL); if (status == -1) { - com_err(whoami, errno, "error from op_select"); + if (errno != EINTR) + com_err(whoami, errno, " error from op_select"); + if (!inc_running || now - inc_started > INC_TIMEOUT) + next_incremental(); 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); + if (!inc_running || now - inc_started > INC_TIMEOUT) + next_incremental(); #ifdef notdef fprintf(stderr, " tick\n"); #endif notdef /* - * Handle any existing connections. - */ - for (i=0; ipending_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 ((status = new_connection()) != 0) { + if (OP_STATUS(listenop) == OP_CANCELLED) { + if (errno == EWOULDBLOCK) { + do_reset_listen(); + } else { + static int count = 0; + com_err(whoami, errno, + " error (%d) on listen", count); + if (count++ > 10) + 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? */ } + /* if the new connection is our only connection, + * and the server is supposed to be down, then go + * down now. + */ + if ((dormant == AWAKE) && (nclients == 1) && + (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) { + com_err(whoami, 0, "motd file exists, slumbertime"); + dormant = SLEEPY; + } + /* on new connection, if we are no longer supposed + * to be down, then wake up. + */ + if ((dormant == ASLEEP) && + (stat(MOIRA_MOTD_FILE, &stbuf) == -1) && + (errno == ENOENT)) { + com_err(whoami, 0, "motd file no longer exists, waking up"); + dormant = GROGGY; + } + + } + /* + * Handle any existing connections. + */ + tardy = now - 30*60; + + for (i=0; ipending_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, 2); + } + cur_client = NULL; + if (takedown) break; } } - com_err(whoami, 0, takedown); - sms_close_database(); + com_err(whoami, 0, "%s", takedown); + if (dormant != ASLEEP) mr_close_database(); + send_zgram("MOIRA", takedown); return 0; } @@ -207,12 +297,10 @@ main(argc, argv) * Set up the template connection and queue the first accept. */ -int -do_listen() +int do_listen(port) + char *port; { - char *service = index(SMS_GDB_SERV, ':') + 1; - - listencon = create_listening_connection(service); + listencon = create_listening_connection(port); if (listencon == NULL) return errno; @@ -226,40 +314,50 @@ do_listen() return 0; } + +void do_reset_listen(void) +{ + 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. * * It sets up a new client and adds it to the list of currently active clients. */ -int -new_connection() +int new_connection(void) { - register client *cp = (client *)malloc(sizeof *cp); + register client *cp; static counter = 0; /* * Make sure there's been no error */ - if(OP_STATUS(listenop) != OP_COMPLETE || - newconn == NULL) { + if(OP_STATUS(listenop) != OP_COMPLETE) { return errno; -#ifdef notdef - exit(8); /* XXX */ -#endif notdef + } + + if (newconn == NULL) { + return MR_NOT_CONNECTED; } /* * Set up the new connection and reply to the client */ - - cp->state = CL_STARTING; + cp = (client *)malloc(sizeof *cp); + memset(cp, 0, sizeof(*cp)); cp->action = CL_ACCEPT; cp->con = newconn; cp->id = counter++; cp->args = NULL; - cp->clname = NULL; - cp->reply.sms_argv = NULL; - + cp->clname[0] = NULL; + cp->reply.mr_argv = NULL; + cp->first = NULL; + cp->last = NULL; + cp->last_time_used = now; newconn = NULL; cp->pending_op = create_operation(); @@ -284,13 +382,11 @@ new_connection() * 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. @@ -307,16 +403,15 @@ new_connection() /* * Add a new client to the known clients. */ -void -clist_append(cp) - client *cp; +void clist_append(cp) + client *cp; { client **clients_n; nclients++; clients_n = (client **)malloc ((unsigned)(nclients * sizeof(client *))); - bcopy((char *)clients, (char *)clients_n, (nclients-1)*sizeof(cp)); + memcpy((char *)clients_n, (char *)clients, (nclients-1)*sizeof(cp)); clients_n[nclients-1] = cp; free((char *)clients); clients = clients_n; @@ -324,9 +419,8 @@ clist_append(cp) } -void -clist_delete(cp) - client *cp; +void clist_delete(cp) + client *cp; { client **clients_n, **scpp, **dcpp; /* source and dest client */ /* ptr ptr */ @@ -348,9 +442,10 @@ clist_delete(cp) free((char *)clients); clients = clients_n; clients_n = NULL; - + oplist_delete(op_list, cp->pending_op); reset_operation(cp->pending_op); delete_operation(cp->pending_op); + sever_connection(cp->con); free((char *)cp); } @@ -361,19 +456,132 @@ clist_delete(cp) * cases it won't have to copy the array. */ -void -oplist_append(oplp, op) - LIST_OF_OPERATIONS *oplp; - OPERATION op; +void oplist_append(oplp, op) + LIST_OF_OPERATIONS *oplp; + OPERATION op; { int count = (*oplp)->count+1; LIST_OF_OPERATIONS newlist = (LIST_OF_OPERATIONS) db_alloc(size_of_list_of_operations(count)); - bcopy((char *)(*oplp), (char *)newlist, + memcpy((char *)newlist, (char *)(*oplp), size_of_list_of_operations((*oplp)->count)); newlist->count++; newlist->op[count-1] = op; - db_free((*oplp), size_of_list_of_operations(count-1)); + db_free((char *)(*oplp), size_of_list_of_operations(count-1)); (*oplp) = newlist; } + +void oplist_delete(oplp, op) + LIST_OF_OPERATIONS oplp; + OPERATION op; +{ + register OPERATION *s; + register int c; + + for (s = oplp->op, c=oplp->count; c; --c, ++s) { + if (*s == op) { + while (c > 0) { + *s = *(s+1); + ++s; + --c; + } + oplp->count--; + return; + } + } + abort(); +} + + +void reapchild(x) + int x; +{ + int status, pid; + + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { +#ifdef INCR_DEBUG + com_err(whoami, 0, "Reaping %d (inc_pid=%d, inc_running=%d)", + pid, inc_pid, inc_running); +#endif + if (pid == inc_pid) + inc_running = 0; + if (!takedown && (WTERMSIG(status)!= 0 || WEXITSTATUS(status)!= 0)) + com_err(whoami, 0, "%d: child exits with signal %d status %d", + pid, WTERMSIG(status), WEXITSTATUS(status)); + } +} + + +void godormant(x) + int x; +{ + switch (dormant) { + case AWAKE: + case GROGGY: + com_err(whoami, 0, "requested to go dormant"); + break; + case ASLEEP: + com_err(whoami, 0, "already asleep"); + break; + case SLEEPY: + break; + } + dormant = SLEEPY; +} + + +void gowakeup(x) + int x; +{ + switch (dormant) { + case ASLEEP: + case SLEEPY: + com_err(whoami, 0, "Good morning"); + break; + case AWAKE: + com_err(whoami, 0, "already awake"); + break; + case GROGGY: + break; + } + dormant = GROGGY; +} + + +void mr_setup_signals(void) +{ + struct sigaction action; + + action.sa_flags = 0; + sigemptyset(&action.sa_mask); + + /* There should probably be a few more of these. */ + + action.sa_handler = sigshut; + if ((sigaction(SIGTERM, &action, NULL) < 0) || + (sigaction(SIGINT, &action, NULL) < 0) || + (sigaction(SIGHUP, &action, NULL) < 0)) { + com_err(whoami, errno, "Unable to establish signal handlers."); + exit(1); + } + + action.sa_handler = godormant; + if (sigaction(SIGUSR1, &action, NULL) < 0) { + com_err(whoami, errno, "Unable to establish signal handlers."); + exit(1); + } + + action.sa_handler = gowakeup; + if (sigaction(SIGUSR2, &action, NULL) < 0) { + com_err(whoami, errno, "Unable to establish signal handlers."); + exit(1); + } + + action.sa_handler = reapchild; + sigaddset(&action.sa_mask, SIGCHLD); + if (sigaction(SIGCHLD, &action, NULL) < 0) { + com_err(whoami, errno, "Unable to establish signal handlers."); + exit(1); + } +}