]> andersk Git - moira.git/blame - server/mr_main.c
Oracle and Solaris/POSIX changes
[moira.git] / server / mr_main.c
CommitLineData
0fa91a0a 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
c801de4c 7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
0fa91a0a 9 *
d548a4e7 10 * MOIRA server process.
0fa91a0a 11 *
12 * Most of this is stolen from ../gdb/tsr.c
13 *
14 * You are in a maze of twisty little finite automata, all different.
15 * Let the reader beware.
16 *
0fa91a0a 17 */
18
d548a4e7 19static char *rcsid_mr_main_c = "$Header$";
0fa91a0a 20
c801de4c 21#include <mit-copyright.h>
70d54e43 22#include <strings.h>
589993be 23#include <sys/types.h>
70d54e43 24#include <sys/errno.h>
70d54e43 25#include <sys/signal.h>
554776b1 26#include <sys/wait.h>
589993be 27#include <sys/stat.h>
d548a4e7 28#include "mr_server.h"
40165bd0 29#include <krb_et.h>
70d54e43 30
0ec57336 31extern CONNECTION newconn, listencon;
0fa91a0a 32
0ec57336 33extern int nclients;
34extern client **clients, *cur_client;
0fa91a0a 35
0ec57336 36extern OPERATION listenop;
37extern LIST_OF_OPERATIONS op_list;
0fa91a0a 38
0ec57336 39extern struct sockaddr_in client_addr;
40extern int client_addrlen;
41extern TUPLE client_tuple;
0fa91a0a 42
0ec57336 43extern char *whoami;
44extern char buf1[BUFSIZ];
45extern char *takedown;
46extern int errno;
2f4ff9cd 47extern FILE *journal;
70d54e43 48
0ec57336 49extern char *inet_ntoa();
d548a4e7 50extern void mr_com_err();
0ec57336 51extern void do_client();
70d54e43 52
0ec57336 53extern int sigshut();
54void clist_append();
55void oplist_append();
589993be 56void reapchild(), godormant(), gowakeup();
0fa91a0a 57
0eb9f52f 58extern time_t now;
59
e448f08d 60#ifdef _DEBUG_MALLOC_INC
61static char *dbg_malloc();
62static int dbg_free();
63#endif
64
0ec57336 65/*
d548a4e7 66 * Main MOIRA server loop.
0ec57336 67 *
68 * Initialize the world, then start accepting connections and
69 * making progress on current connections.
70 */
0fa91a0a 71
0ec57336 72/*ARGSUSED*/
73int
0fa91a0a 74main(argc, argv)
70d54e43 75 int argc;
76 char **argv;
0fa91a0a 77{
cfbc1e92 78 int status, i;
0eb9f52f 79 time_t tardy;
cfbc1e92 80 char *port;
81 extern char *database;
589993be 82 struct stat stbuf;
0ec57336 83
84 whoami = argv[0];
85 /*
86 * Error handler init.
87 */
40165bd0 88 initialize_sms_error_table();
89 initialize_krb_error_table();
adae415b 90 initialize_gdss_error_table();
d548a4e7 91 set_com_err_hook(mr_com_err);
b4182127 92 setlinebuf(stderr);
93
cfbc1e92 94 database = "moira";
95 port = index(MOIRA_SERVER, ':') + 1;
96
97 for (i = 1; i < argc; i++) {
98 if (!strcmp(argv[i], "-db") && i+1 < argc) {
99 database = argv[i+1];
100 i++;
101 } else if (!strcmp(argv[i], "-p") && i+1 < argc) {
102 port = argv[i+1];
103 i++;
104 } else {
105 com_err(whoami, 0, "Usage: moirad [-db database][-p port]");
0ec57336 106 exit(1);
cfbc1e92 107 }
108 }
f5c72293 109
110 /* Profiling implies that getting rid of one level of call
111 * indirection here wins us maybe 1% on the VAX.
112 */
e448f08d 113#ifdef _DEBUG_MALLOC_INC
114 gdb_amv = dbg_malloc;
115 gdb_fmv = dbg_free;
116#else
f5c72293 117 gdb_amv = malloc;
e448f08d 118 gdb_fmv = (int (*)()) free;
119#endif
0ec57336 120
121 /*
122 * GDB initialization.
123 */
5dbd09a0 124 if(gdb_init() != 0) {
125 com_err(whoami, 0, "GDB initialization failed.");
126 exit(1);
127 }
7f024a70 128 gdb_debug(0); /* this can be patched, if necessary, to enable */
129 /* GDB level debugging .. */
4a06eb54 130 krb_realm = malloc(REALM_SZ);
42b1d0ae 131 krb_get_lrealm(krb_realm, 1);
7f024a70 132
f6cc38de 133 /*
083a6e94 134 * Database initialization. Only init if database should be open.
f6cc38de 135 */
136
d548a4e7 137 if (stat(MOIRA_MOTD_FILE, &stbuf) != 0) {
138 if ((status = mr_open_database()) != 0) {
2f4ff9cd 139 com_err(whoami, status, " when trying to open database.");
f6cc38de 140 exit(1);
083a6e94 141 }
142 sanity_check_database();
143 } else {
144 dormant = ASLEEP;
145 com_err(whoami, 0, "sleeping, not opening database");
f6cc38de 146 }
147
2f4ff9cd 148 sanity_check_queries();
2f4ff9cd 149
0ec57336 150 /*
151 * Set up client array handler.
152 */
0fa91a0a 153 nclients = 0;
154 clients = (client **) malloc(0);
70d54e43 155
d548a4e7 156 mr_setup_signals();
0ec57336 157
2f4ff9cd 158 journal = fopen(JOURNAL, "a");
159 if (journal == NULL) {
160 com_err(whoami, errno, " while opening journal file");
161 exit(1);
162 }
163
0ec57336 164 /*
165 * Establish template connection.
166 */
cfbc1e92 167 if ((status = do_listen(port)) != 0) {
0ec57336 168 com_err(whoami, status,
2f4ff9cd 169 " while trying to create listening connection");
0ec57336 170 exit(1);
171 }
0fa91a0a 172
0fa91a0a 173 op_list = create_list_of_operations(1, listenop);
0fa91a0a 174
b4182127 175 com_err(whoami, 0, "started (pid %d)", getpid());
d548a4e7 176 com_err(whoami, 0, rcsid_mr_main_c);
083a6e94 177 if (dormant != ASLEEP)
d548a4e7 178 send_zgram("MOIRA", "server started");
083a6e94 179 else
d548a4e7 180 send_zgram("MOIRA", "server started, but database closed");
0ec57336 181
182 /*
183 * Run until shut down.
184 */
70d54e43 185 while(!takedown) {
0ec57336 186 register int i;
187 /*
188 * Block until something happens.
189 */
5dbd09a0 190#ifdef notdef
191 com_err(whoami, 0, "tick");
192#endif notdef
589993be 193 if (dormant == SLEEPY) {
d548a4e7 194 mr_close_database();
589993be 195 com_err(whoami, 0, "database closed");
d548a4e7 196 mr_setup_signals();
197 send_zgram("MOIRA", "database closed");
589993be 198 dormant = ASLEEP;
199 } else if (dormant == GROGGY) {
d548a4e7 200 mr_open_database();
589993be 201 com_err(whoami, 0, "database open");
d548a4e7 202 mr_setup_signals();
203 send_zgram("MOIRA", "database open again");
589993be 204 dormant = AWAKE;
205 }
206
5dbd09a0 207 errno = 0;
208 status = op_select_any(op_list, 0,
209 (fd_set *)NULL, (fd_set *)NULL,
210 (fd_set *)NULL, (struct timeval *)NULL);
211
212 if (status == -1) {
42b1d0ae 213 if (errno != EINTR)
214 com_err(whoami, errno, " error from op_select");
2e182bc3 215 if (!inc_running || now - inc_started > INC_TIMEOUT)
216 next_incremental();
5dbd09a0 217 continue;
218 } else if (status != -2) {
2f4ff9cd 219 com_err(whoami, 0, " wrong return from op_select_any");
5dbd09a0 220 continue;
221 }
70d54e43 222 if (takedown) break;
0eb9f52f 223 time(&now);
2e182bc3 224 if (!inc_running || now - inc_started > INC_TIMEOUT)
225 next_incremental();
70d54e43 226#ifdef notdef
227 fprintf(stderr, " tick\n");
228#endif notdef
b4182127 229 /*
230 * Handle any new connections; this comes first so
231 * errno isn't tromped on.
232 */
233 if (OP_DONE(listenop)) {
234 if (OP_STATUS(listenop) == OP_CANCELLED) {
235 if (errno == EWOULDBLOCK) {
236 do_reset_listen();
237 } else {
14e2d5ce 238 static int count = 0;
b4182127 239 com_err(whoami, errno,
14e2d5ce 240 " error (%d) on listen", count);
241 if (count++ > 10)
242 exit(1);
b4182127 243 }
244 } else if ((status = new_connection()) != 0) {
245 com_err(whoami, errno,
2f4ff9cd 246 " Error on listening operation.");
b4182127 247 /*
248 * Sleep here to prevent hosing?
249 */
250 }
589993be 251 /* if the new connection is our only connection,
252 * and the server is supposed to be down, then go
253 * down now.
254 */
255 if ((dormant == AWAKE) && (nclients == 1) &&
d548a4e7 256 (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) {
589993be 257 com_err(whoami, 0, "motd file exists, slumbertime");
258 dormant = SLEEPY;
259 }
260 /* on new connection, if we are no longer supposed
261 * to be down, then wake up.
262 */
263 if ((dormant == ASLEEP) &&
d548a4e7 264 (stat(MOIRA_MOTD_FILE, &stbuf) == -1) &&
589993be 265 (errno == ENOENT)) {
266 com_err(whoami, 0, "motd file no longer exists, waking up");
267 dormant = GROGGY;
268 }
269
b4182127 270 }
0ec57336 271 /*
272 * Handle any existing connections.
273 */
0eb9f52f 274 tardy = now - 30*60;
275
0fa91a0a 276 for (i=0; i<nclients; i++) {
0eb9f52f 277 cur_client = clients[i];
0fa91a0a 278 if (OP_DONE(clients[i]->pending_op)) {
0eb9f52f 279 cur_client->last_time_used = now;
70d54e43 280 do_client(cur_client);
0eb9f52f 281 } else if (clients[i]->last_time_used < tardy) {
282 com_err(whoami, 0, "Shutting down connection due to inactivity");
283 shutdown(cur_client->con->in.fd, 0);
0fa91a0a 284 }
0eb9f52f 285 cur_client = NULL;
286 if (takedown) break;
0fa91a0a 287 }
0fa91a0a 288 }
b4182127 289 com_err(whoami, 0, "%s", takedown);
d548a4e7 290 mr_close_database();
291 send_zgram("MOIRA", takedown);
0ec57336 292 return 0;
70d54e43 293}
294
0ec57336 295/*
296 * Set up the template connection and queue the first accept.
297 */
298
299int
cfbc1e92 300do_listen(port)
301char *port;
70d54e43 302{
cfbc1e92 303 listencon = create_listening_connection(port);
0ec57336 304
305 if (listencon == NULL)
306 return errno;
307
308 listenop = create_operation();
309 client_addrlen = sizeof(client_addr);
310
311 start_accepting_client(listencon, listenop, &newconn,
312 (char *)&client_addr,
313 &client_addrlen, &client_tuple);
314 return 0;
0fa91a0a 315}
316
b4182127 317
318do_reset_listen()
319{
320 client_addrlen = sizeof(client_addr);
321 start_accepting_client(listencon, listenop, &newconn,
322 (char *)&client_addr,
323 &client_addrlen, &client_tuple);
324}
325
0ec57336 326/*
327 * This routine is called when a new connection comes in.
328 *
329 * It sets up a new client and adds it to the list of currently active clients.
330 */
331int
5dbd09a0 332new_connection()
0fa91a0a 333{
7f024a70 334 register client *cp;
70d54e43 335 static counter = 0;
0fa91a0a 336
0fa91a0a 337 /*
338 * Make sure there's been no error
339 */
c27b3454 340 if(OP_STATUS(listenop) != OP_COMPLETE) {
0ec57336 341 return errno;
c27b3454 342 }
343
344 if (newconn == NULL) {
d548a4e7 345 return MR_NOT_CONNECTED;
0fa91a0a 346 }
347
0fa91a0a 348 /*
349 * Set up the new connection and reply to the client
350 */
7f024a70 351 cp = (client *)malloc(sizeof *cp);
23e476e8 352 bzero(cp, sizeof(*cp));
0fa91a0a 353 cp->action = CL_ACCEPT;
354 cp->con = newconn;
70d54e43 355 cp->id = counter++;
0ec57336 356 cp->args = NULL;
42b1d0ae 357 cp->clname[0] = NULL;
d548a4e7 358 cp->reply.mr_argv = NULL;
4a06eb54 359 cp->first = NULL;
360 cp->last = NULL;
0eb9f52f 361 cp->last_time_used = now;
0fa91a0a 362 newconn = NULL;
363
364 cp->pending_op = create_operation();
365 reset_operation(cp->pending_op);
366 oplist_append(&op_list, cp->pending_op);
70d54e43 367 cur_client = cp;
368
0ec57336 369 /*
370 * Add a new client to the array..
371 */
372 clist_append(cp);
373
374 /*
375 * Let him know we heard him.
376 */
0fa91a0a 377 start_replying_to_client(cp->pending_op, cp->con, GDB_ACCEPTED,
378 "", "");
0ec57336 379
380 cp->haddr = client_addr;
381
382 /*
383 * Log new connection.
384 */
385
b4182127 386 com_err(whoami, 0, "New connection from %s port %d (now %d client%s)",
387 inet_ntoa(cp->haddr.sin_addr),
388 (int)ntohs(cp->haddr.sin_port),
389 nclients,
390 nclients!=1?"s":"");
0fa91a0a 391
392 /*
0ec57336 393 * Get ready to accept the next connection.
0fa91a0a 394 */
395 reset_operation(listenop);
0ec57336 396 client_addrlen = sizeof(client_addr);
0fa91a0a 397
398 start_accepting_client(listencon, listenop, &newconn,
0ec57336 399 (char *)&client_addr,
400 &client_addrlen, &client_tuple);
401 return 0;
0fa91a0a 402}
403
0fa91a0a 404/*
405 * Add a new client to the known clients.
406 */
0ec57336 407void
0fa91a0a 408clist_append(cp)
409 client *cp;
410{
411 client **clients_n;
412
413 nclients++;
0ec57336 414 clients_n = (client **)malloc
415 ((unsigned)(nclients * sizeof(client *)));
0fa91a0a 416 bcopy((char *)clients, (char *)clients_n, (nclients-1)*sizeof(cp));
417 clients_n[nclients-1] = cp;
418 free((char *)clients);
419 clients = clients_n;
420 clients_n = NULL;
421}
422
70d54e43 423
0ec57336 424void
70d54e43 425clist_delete(cp)
426 client *cp;
427{
70d54e43 428 client **clients_n, **scpp, **dcpp; /* source and dest client */
429 /* ptr ptr */
430
70d54e43 431 int found_it = 0;
432
0ec57336 433 clients_n = (client **)malloc
434 ((unsigned)((nclients - 1)* sizeof(client *)));
70d54e43 435 for (scpp = clients, dcpp = clients_n; scpp < clients+nclients; ) {
436 if (*scpp != cp) {
437 *dcpp++ = *scpp++;
438 } else {
439 scpp++;
440 if (found_it) abort();
441 found_it = 1;
442 }
443 }
444 --nclients;
445 free((char *)clients);
446 clients = clients_n;
447 clients_n = NULL;
c27b3454 448 oplist_delete(op_list, cp->pending_op);
70d54e43 449 reset_operation(cp->pending_op);
450 delete_operation(cp->pending_op);
7f024a70 451 sever_connection(cp->con);
0ec57336 452 free((char *)cp);
70d54e43 453}
0ec57336 454
0fa91a0a 455/*
0ec57336 456 * Add a new operation to a list of operations.
457 *
458 * This should be rewritten to use realloc instead, since in most
459 * cases it won't have to copy the array.
0fa91a0a 460 */
461
0ec57336 462void
0fa91a0a 463oplist_append(oplp, op)
464 LIST_OF_OPERATIONS *oplp;
465 OPERATION op;
466{
467 int count = (*oplp)->count+1;
468 LIST_OF_OPERATIONS newlist = (LIST_OF_OPERATIONS)
469 db_alloc(size_of_list_of_operations(count));
470 bcopy((char *)(*oplp), (char *)newlist,
471 size_of_list_of_operations((*oplp)->count));
0fa91a0a 472 newlist->count++;
473 newlist->op[count-1] = op;
467f5982 474 db_free((char *)(*oplp), size_of_list_of_operations(count-1));
0fa91a0a 475 (*oplp) = newlist;
476}
477
c27b3454 478
479oplist_delete(oplp, op)
480 LIST_OF_OPERATIONS oplp;
481 register OPERATION op;
482{
483 register OPERATION *s;
484 register int c;
485
486 for (s = oplp->op, c=oplp->count; c; --c, ++s) {
487 if (*s == op) {
488 while (c > 0) {
489 *s = *(s+1);
490 ++s;
491 --c;
492 }
493 oplp->count--;
494 return;
495 }
496 }
497 abort();
498}
554776b1 499
500
501void reapchild()
502{
503 union wait status;
504 int pid;
505
506 while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) {
2e182bc3 507 if (pid == inc_pid)
508 inc_running = 0;
42b1d0ae 509 if (!takedown && (status.w_termsig != 0 || status.w_retcode != 0))
589993be 510 com_err(whoami, 0, "%d: child exits with signal %d status %d",
554776b1 511 pid, status.w_termsig, status.w_retcode);
512 }
513}
589993be 514
515
516void godormant()
517{
518 switch (dormant) {
519 case AWAKE:
520 case GROGGY:
521 com_err(whoami, 0, "requested to go dormant");
522 break;
523 case ASLEEP:
524 com_err(whoami, 0, "already asleep");
525 break;
526 case SLEEPY:
527 break;
528 }
529 dormant = SLEEPY;
530}
531
532
533void gowakeup()
534{
535 switch (dormant) {
536 case ASLEEP:
537 case SLEEPY:
538 com_err(whoami, 0, "Good morning");
539 break;
540 case AWAKE:
541 com_err(whoami, 0, "already awake");
542 break;
543 case GROGGY:
544 break;
545 }
546 dormant = GROGGY;
547}
083a6e94 548
549
d548a4e7 550mr_setup_signals()
083a6e94 551{
552 /* There should probably be a few more of these. */
553
554 if ((((int)signal (SIGTERM, sigshut)) < 0) ||
555 (((int)signal (SIGCHLD, reapchild)) < 0) ||
556 (((int)signal (SIGUSR1, godormant)) < 0) ||
557 (((int)signal (SIGUSR2, gowakeup)) < 0) ||
558 (((int)signal (SIGHUP, sigshut)) < 0)) {
559 com_err(whoami, errno, " Unable to establish signal handlers.");
560 exit(1);
561 }
562}
e448f08d 563
564#ifdef _DEBUG_MALLOC_INC
565static char *dbg_malloc(size)
566 SIZETYPE size;
567{
568 return( debug_malloc("somewhere in the gdb code",1,size) );
569}
570
571static int dbg_free(cptr)
572 DATATYPE *cptr;
573{
574 debug_free((char *)NULL, 0, cptr);
575 return 0; /* GDB is being stupid */
576}
577#endif
578
This page took 0.18048 seconds and 5 git commands to generate.