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