]> andersk Git - moira.git/blame - server/mr_main.c
Include KERBEROS members of lists that are in the ATHENA realm.
[moira.git] / server / mr_main.c
CommitLineData
7ac48069 1/* $Id$
0fa91a0a 2 *
7ac48069 3 * Moira server process.
0fa91a0a 4 *
7ac48069 5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
5eaef520 8 *
0fa91a0a 9 */
10
c801de4c 11#include <mit-copyright.h>
7ac48069 12#include "mr_server.h"
13
14#include <sys/socket.h>
15#include <sys/stat.h>
589993be 16#include <sys/types.h>
7ac48069 17#include <sys/utsname.h>
554776b1 18#include <sys/wait.h>
7ac48069 19
20#include <netinet/in.h>
03c05291 21#include <arpa/inet.h>
70d54e43 22
7ac48069 23#include <ctype.h>
24#include <errno.h>
25#include <signal.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30
85330553 31#include <krb.h>
32
7ac48069 33RCSID("$Header$");
34
85330553 35client *cur_client;
0fa91a0a 36
85330553 37char *whoami;
38char *takedown;
39FILE *journal;
0fa91a0a 40
85330553 41time_t now;
0fa91a0a 42
85330553 43char *host;
44char krb_realm[REALM_SZ];
70d54e43 45
85330553 46/* Client array and associated data. This needs to be global for _list_users */
47client **clients;
48int nclients, clientssize;
0eb9f52f 49
85330553 50int dormant;
9af63f7e 51int child_exited_abnormally = 0;
52int child_pid, child_signal, child_status;
3d0d0f07 53
7ac48069 54void reapchild(int x);
55void godormant(int x);
56void gowakeup(int x);
03c05291 57void clist_append(client *cp);
03c05291 58void mr_setup_signals(void);
e448f08d 59
0ec57336 60/*
59ec8dae 61 * Main Moira server loop.
0ec57336 62 *
63 * Initialize the world, then start accepting connections and
64 * making progress on current connections.
65 */
0fa91a0a 66
5eaef520 67int main(int argc, char **argv)
0fa91a0a 68{
85330553 69 int status, i, listener;
5eaef520 70 time_t tardy;
71 char *port, *p;
72 extern char *database;
73 struct stat stbuf;
7ac48069 74 struct utsname uts;
85330553 75 fd_set readfds, writefds, xreadfds, xwritefds;
76 int nfds, counter = 0;
5eaef520 77
78 whoami = argv[0];
79 /*
80 * Error handler init.
81 */
85330553 82 mr_init();
5eaef520 83 set_com_err_hook(mr_com_err);
84 setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
85
86 port = strchr(MOIRA_SERVER, ':') + 1;
87
88 for (i = 1; i < argc; i++)
89 {
90 if (!strcmp(argv[i], "-db") && i + 1 < argc)
91 {
92 database = argv[i + 1];
93 i++;
5dbd09a0 94 }
5eaef520 95 else if (!strcmp(argv[i], "-p") && i + 1 < argc)
96 {
97 port = argv[i + 1];
98 i++;
f6cc38de 99 }
5eaef520 100 else
101 {
102 com_err(whoami, 0, "Usage: moirad [-db database][-p port]");
3d0d0f07 103 exit(1);
104 }
5eaef520 105 }
106
5eaef520 107 krb_get_lrealm(krb_realm, 1);
108
109 /*
110 * Database initialization. Only init if database should be open.
111 */
112
113 if (stat(MOIRA_MOTD_FILE, &stbuf) != 0)
114 {
115 if ((status = mr_open_database()))
116 {
85330553 117 com_err(whoami, status, "trying to open database.");
5eaef520 118 exit(1);
2f4ff9cd 119 }
5eaef520 120 sanity_check_database();
121 }
122 else
123 {
124 dormant = ASLEEP;
125 com_err(whoami, 0, "sleeping, not opening database");
126 }
2f4ff9cd 127
5eaef520 128 sanity_check_queries();
129
130 /*
131 * Get moira server hostname for authentication
132 */
7ac48069 133 if (uname(&uts) < 0)
5eaef520 134 {
135 com_err(whoami, errno, "Unable to get local hostname");
136 exit(1);
137 }
e688520a 138 host = canonicalize_hostname(xstrdup(uts.nodename));
5eaef520 139 for (p = host; *p && *p != '.'; p++)
140 {
141 if (isupper(*p))
142 *p = tolower(*p);
143 }
144 *p = '\0';
145
146 /*
147 * Set up client array handler.
148 */
149 nclients = 0;
85330553 150 clientssize = 10;
e688520a 151 clients = xmalloc(clientssize * sizeof(client *));
5eaef520 152
153 mr_setup_signals();
154
155 journal = fopen(JOURNAL, "a");
156 if (!journal)
157 {
85330553 158 com_err(whoami, errno, "opening journal file");
5eaef520 159 exit(1);
160 }
161
162 /*
163 * Establish template connection.
164 */
da6a4096 165 listener = mr_listen(port);
166 if (listener == -1)
5eaef520 167 {
93ba0dea 168 com_err(whoami, MR_ABORTED, "trying to create listening connection");
5eaef520 169 exit(1);
170 }
85330553 171 FD_ZERO(&xreadfds);
172 FD_ZERO(&xwritefds);
173 FD_SET(listener, &xreadfds);
174 nfds = listener + 1;
5eaef520 175
176 com_err(whoami, 0, "started (pid %d)", getpid());
7ac48069 177 com_err(whoami, 0, rcsid);
5eaef520 178 if (dormant != ASLEEP)
179 send_zgram("MOIRA", "server started");
180 else
181 send_zgram("MOIRA", "server started, but database closed");
182
183 /*
184 * Run until shut down.
185 */
186 while (!takedown)
187 {
44d12d58 188 int i;
9294e804 189 struct timeval timeout = {60, 0}; /* 1 minute */
85330553 190
191 /* If we're supposed to go down and we can, do it */
59ad5a76 192 if (((dormant == AWAKE) && (nclients == 0) &&
193 (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) ||
194 (dormant == SLEEPY))
5eaef520 195 {
196 mr_close_database();
197 com_err(whoami, 0, "database closed");
198 mr_setup_signals();
199 send_zgram("MOIRA", "database closed");
200 dormant = ASLEEP;
201 }
589993be 202
85330553 203 /* Block until something happens. */
204 memcpy(&readfds, &xreadfds, sizeof(readfds));
205 memcpy(&writefds, &xwritefds, sizeof(writefds));
9294e804 206 if (select(nfds, &readfds, &writefds, NULL, &timeout) == -1)
5eaef520 207 {
208 if (errno != EINTR)
85330553 209 com_err(whoami, errno, "in select");
5eaef520 210 if (!inc_running || now - inc_started > INC_TIMEOUT)
211 next_incremental();
212 continue;
213 }
85330553 214
5eaef520 215 if (takedown)
216 break;
9af63f7e 217
218 if (child_exited_abnormally)
219 {
220 critical_alert("moirad", "%d: child exits with signal %d status %d",
221 child_pid, child_signal, child_status);
222 child_exited_abnormally = 0;
223 }
224
5eaef520 225 time(&now);
226 if (!inc_running || now - inc_started > INC_TIMEOUT)
227 next_incremental();
85330553 228 tardy = now - 30 * 60;
229
230 /* If we're asleep and we should wake up, do it */
231 if ((dormant == ASLEEP) && (stat(MOIRA_MOTD_FILE, &stbuf) == -1) &&
232 (errno == ENOENT))
233 {
234 mr_open_database();
235 com_err(whoami, 0, "database open");
236 mr_setup_signals();
237 send_zgram("MOIRA", "database open again");
238 dormant = AWAKE;
239 }
5eaef520 240
85330553 241 /* Handle any new connections */
242 if (FD_ISSET(listener, &readfds))
5eaef520 243 {
8691463b 244 int newconn, addrlen = sizeof(struct sockaddr_in);
85330553 245 struct sockaddr_in addr;
246 client *cp;
247
8691463b 248 newconn = accept(listener, (struct sockaddr *)&addr, &addrlen);
85330553 249 if (newconn == -1)
250 com_err(whoami, errno, "accepting new connection");
251 else if (newconn > 0)
5eaef520 252 {
85330553 253 if (newconn + 1 > nfds)
254 nfds = newconn + 1;
255 FD_SET(newconn, &xreadfds);
256
257 /* Add a new client to the array */
258 nclients++;
259 if (nclients > clientssize)
5eaef520 260 {
85330553 261 clientssize = 2 * clientssize;
262 clients = xrealloc(clients, clientssize * sizeof(client *));
0fa91a0a 263 }
85330553 264
265 clients[nclients - 1] = cp = xmalloc(sizeof(client));
266 memset(cp, 0, sizeof(client));
267 cp->con = newconn;
268 cp->id = counter++;
269 cp->last_time_used = now;
270 cp->haddr = addr;
271 cp->tuplessize = 1;
272 cp->tuples = xmalloc(sizeof(mr_params));
273 memset(cp->tuples, 0, sizeof(mr_params));
8691463b 274 cp->state = CL_ACCEPTING;
c44ddfa7 275 cp->version = 2;
85330553 276
277 cur_client = cp;
278 com_err(whoami, 0,
279 "New connection from %s port %d (now %d client%s)",
280 inet_ntoa(cp->haddr.sin_addr),
281 (int)ntohs(cp->haddr.sin_port),
282 nclients, nclients != 1 ? "s" : "");
5eaef520 283 }
0fa91a0a 284 }
5eaef520 285
85330553 286 /* Handle any existing connections. */
5eaef520 287 for (i = 0; i < nclients; i++)
288 {
289 cur_client = clients[i];
85330553 290
291 if (FD_ISSET(clients[i]->con, &writefds))
292 {
293 client_write(clients[i]);
294 if (!clients[i]->ntuples)
295 {
296 FD_CLR(clients[i]->con, &xwritefds);
85330553 297 FD_SET(clients[i]->con, &xreadfds);
298 }
299 clients[i]->last_time_used = now;
300 }
301
302 if (FD_ISSET(clients[i]->con, &readfds))
5eaef520 303 {
8691463b 304 if (clients[i]->state == CL_ACCEPTING)
305 {
306 switch(mr_cont_accept(clients[i]->con,
307 &clients[i]->hsbuf,
308 &clients[i]->hslen))
309 {
310 case -1:
311 break;
312
313 case 0:
314 clients[i]->state = CL_CLOSING;
315 break;
316
317 default:
318 clients[i]->state = CL_ACTIVE;
319 clients[i]->hsbuf = NULL;
320 break;
321 }
322 }
323 else
324 {
325 client_read(clients[i]);
326 if (clients[i]->ntuples)
327 {
328 FD_CLR(clients[i]->con, &xreadfds);
329 FD_SET(clients[i]->con, &xwritefds);
330 }
331 clients[i]->last_time_used = now;
332 }
5eaef520 333 }
85330553 334
335 if (clients[i]->last_time_used < tardy)
5eaef520 336 {
337 com_err(whoami, 0, "Shutting down connection due to inactivity");
8691463b 338 clients[i]->state = CL_CLOSING;
85330553 339 }
340
8691463b 341 if (clients[i]->state == CL_CLOSING)
85330553 342 {
343 client *old;
344
345 com_err(whoami, 0, "Closed connection (now %d client%s, "
346 "%d queries)", nclients - 1, nclients != 2 ? "s" : "",
347 newqueries);
348
349 shutdown(clients[i]->con, 2);
350 close(clients[i]->con);
351 FD_CLR(clients[i]->con, &xreadfds);
352 FD_CLR(clients[i]->con, &xwritefds);
92ced3ed 353 free_rtn_tuples(clients[i]);
85330553 354 free(clients[i]->tuples);
8691463b 355 free(clients[i]->hsbuf);
85330553 356 old = clients[i];
357 clients[i] = clients[--nclients];
358 free(old);
5eaef520 359 }
85330553 360
5eaef520 361 cur_client = NULL;
362 if (takedown)
363 break;
364 }
365 }
85330553 366
5eaef520 367 com_err(whoami, 0, "%s", takedown);
368 if (dormant != ASLEEP)
369 mr_close_database();
370 send_zgram("MOIRA", takedown);
371 return 0;
70d54e43 372}
373
5eaef520 374void reapchild(int x)
554776b1 375{
5eaef520 376 int status, pid;
377
378 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
379 {
380 if (pid == inc_pid)
381 inc_running = 0;
382 if (!takedown && (WTERMSIG(status) != 0 || WEXITSTATUS(status) != 0))
71c89283 383 {
9af63f7e 384 child_exited_abnormally = 1;
385 child_pid = pid;
386 child_signal = WTERMSIG(status);
387 child_status = WEXITSTATUS(status);
71c89283 388 }
554776b1 389 }
390}
589993be 391
392
5eaef520 393void godormant(int x)
589993be 394{
5eaef520 395 switch (dormant)
396 {
589993be 397 case AWAKE:
398 case GROGGY:
5eaef520 399 com_err(whoami, 0, "requested to go dormant");
400 break;
589993be 401 case ASLEEP:
5eaef520 402 com_err(whoami, 0, "already asleep");
403 break;
589993be 404 case SLEEPY:
5eaef520 405 break;
589993be 406 }
5eaef520 407 dormant = SLEEPY;
589993be 408}
409
410
5eaef520 411void gowakeup(int x)
589993be 412{
5eaef520 413 switch (dormant)
414 {
589993be 415 case ASLEEP:
416 case SLEEPY:
5eaef520 417 com_err(whoami, 0, "Good morning");
418 break;
589993be 419 case AWAKE:
5eaef520 420 com_err(whoami, 0, "already awake");
421 break;
589993be 422 case GROGGY:
5eaef520 423 break;
589993be 424 }
5eaef520 425 dormant = GROGGY;
589993be 426}
083a6e94 427
5eaef520 428
03c05291 429void mr_setup_signals(void)
083a6e94 430{
5eaef520 431 struct sigaction action;
432
433 action.sa_flags = 0;
434 sigemptyset(&action.sa_mask);
03c05291 435
5eaef520 436 /* There should probably be a few more of these. */
03c05291 437
5eaef520 438 action.sa_handler = sigshut;
439 if ((sigaction(SIGTERM, &action, NULL) < 0) ||
440 (sigaction(SIGINT, &action, NULL) < 0) ||
441 (sigaction(SIGHUP, &action, NULL) < 0))
442 {
03c05291 443 com_err(whoami, errno, "Unable to establish signal handlers.");
444 exit(1);
083a6e94 445 }
e448f08d 446
5eaef520 447 action.sa_handler = godormant;
448 if (sigaction(SIGUSR1, &action, NULL) < 0)
449 {
03c05291 450 com_err(whoami, errno, "Unable to establish signal handlers.");
451 exit(1);
452 }
e448f08d 453
5eaef520 454 action.sa_handler = gowakeup;
455 if (sigaction(SIGUSR2, &action, NULL) < 0)
456 {
03c05291 457 com_err(whoami, errno, "Unable to establish signal handlers.");
458 exit(1);
459 }
e448f08d 460
44762a3f 461 action.sa_handler = SIG_IGN;
462 if (sigaction(SIGPIPE, &action, NULL) < 0)
463 {
464 com_err(whoami, errno, "Unable to establish signal handlers.");
465 exit(1);
466 }
467
5eaef520 468 action.sa_handler = reapchild;
469 sigaddset(&action.sa_mask, SIGCHLD);
470 if (sigaction(SIGCHLD, &action, NULL) < 0)
471 {
03c05291 472 com_err(whoami, errno, "Unable to establish signal handlers.");
473 exit(1);
474 }
475}
This page took 0.347812 seconds and 5 git commands to generate.