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