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