source: trunk/athena/etc/larvnetd/larvnetd.c @ 13769

Revision 13769, 6.8 KB checked in by danw, 25 years ago (diff)
compile with warnings
Line 
1/* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16/* This file is part of larvnetd, a monitoring server.  It implements
17 * the main loop.
18 */
19
20static const char rcsid[] = "$Id: larvnetd.c,v 1.4 1999-10-19 20:23:31 danw Exp $";
21
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <sys/time.h>
25#include <sys/socket.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <signal.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <errno.h>
33#include <netdb.h>
34#include <syslog.h>
35#include <hesiod.h>
36#include "larvnetd.h"
37#include "larvnet.h"
38#include "timer.h"
39
40extern char *optarg;
41extern int optind;
42
43static volatile int reload;
44
45static void usage(const char *progname);
46static void hup_handler(void);
47
48int main(int argc, char **argv)
49{
50  struct timeval tv, *tvp;
51  struct sockaddr_in sin;
52  struct sigaction action;
53  struct servent *servent;
54  struct serverstate state;
55  struct printer *printer;
56  unsigned short port;
57  pid_t pid;
58  fd_set readers, writers;
59  int c, nofork = 0, fd, i, nfds, count, status;
60  const char *progname;
61  char *errmem;
62  FILE *fp;
63
64  progname = strrchr(argv[0], '/');
65  progname = (progname) ? progname + 1 : argv[0];
66
67  state.configfile = LARVNET_PATH_CONFIG;
68  while ((c = getopt(argc, argv, "nf:")) != -1)
69    {
70      switch (c)
71        {
72        case 'n':
73          nofork = 1;
74          break;
75        case 'f':
76          state.configfile = optarg;
77          break;
78        default:
79          usage(progname);
80        }
81    }
82  if (argc != optind)
83    usage(progname);
84
85  /* Bind to the server socket. */
86  servent = getservbyname("larvnet", "udp");
87  port = (servent) ? servent->s_port : htons(LARVNET_FALLBACK_PORT);
88  state.server_socket = socket(AF_INET, SOCK_DGRAM, 0);
89  if (state.server_socket == -1)
90    {
91      fprintf(stderr, "%s: socket: %s\n", progname, strerror(errno));
92      return 1;
93    }
94  memset(&sin, 0, sizeof(sin));
95  sin.sin_family = AF_INET;
96  sin.sin_port = port;
97  if (bind(state.server_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1)
98    {
99      fprintf(stderr, "%s: bind: %s\n", progname, strerror(errno));
100      return 1;
101    }
102
103  /* Initialize a resolver channel. */
104  status = ares_init(&state.channel);
105  if (status != ARES_SUCCESS)
106    {
107      fprintf(stderr, "Can't initialize resolver: %s\n",
108              ares_strerror(status, &errmem));
109      ares_free_errmem(errmem);
110      return 1;
111    }
112
113  /* Initialize a Hesiod context. */
114  if (hesiod_init(&state.hescontext) == -1)
115    {
116      fprintf(stderr, "Can't initialize Hesiod context: %s\n",
117              strerror(errno));
118      return 1;
119    }
120
121  /* Determine the port for busy status polls. */
122  servent = getservbyname("busypoll", "udp");
123  state.poll_port = (servent) ? servent->s_port
124      : htons(BUSYPOLL_FALLBACK_PORT);
125
126  if (!nofork)
127    {
128      /* fork, dissociate from our tty, chdir to /, repoint
129       * stdin/stdout/stderr at /dev/null.  Standard daemon stuff.
130       */
131      pid = fork();
132      if (pid == -1)
133        {
134          fprintf(stderr, "%s: fork: %s", progname, strerror(errno));
135          return 1;
136        }
137      if (pid != 0)
138        _exit(0);
139      if (setsid() == -1)
140        {
141          fprintf(stderr, "%s: setsid: %s", progname, strerror(errno));
142          return 1;
143        }
144      chdir("/");
145      fd = open("/dev/null", O_RDWR, 0);
146      if (fd != -1)
147        {
148          dup2(fd, STDIN_FILENO);
149          dup2(fd, STDOUT_FILENO);
150          dup2(fd, STDERR_FILENO);
151          if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
152            close(fd);
153        }
154
155      /* Write a pid file. */
156      fp = fopen(LARVNET_PATH_PIDFILE, "w");
157      if (fp)
158        {
159          fprintf(fp, "%lu\n", (unsigned long) getpid());
160          fclose(fp);
161        }
162    }
163
164  /* Set signal handlers: reread the configuration file on HUP, and
165   * ignore SIGPIPE because every robust network program's gotta.
166   */
167  sigemptyset(&action.sa_mask);
168  action.sa_flags = 0;
169  action.sa_handler = hup_handler;
170  sigaction(SIGHUP, &action, NULL);
171  action.sa_handler = SIG_IGN;
172  sigaction(SIGPIPE, &action, NULL);
173
174  /* Start syslogging. */
175  openlog(progname, LOG_PID, LOG_LOCAL5);
176
177  read_initial_config(&state);
178
179  /* Start initial polls of workstations and printers, and start the
180   * report generation timer. */
181  state.startmachine = 0;
182  ws_poll(&state);
183  printer_start_polls(&state);
184  timer_set_rel(60, report, &state.config);
185
186  while (1)
187    {
188      /* See if we got a SIGHUP and need to reread the config file. */
189      if (reload)
190        {
191          reload = 0;
192          reread_config(&state);
193          printer_start_polls(&state);
194        }
195
196      /* Set up fd sets for select. */
197      FD_ZERO(&readers);
198      FD_ZERO(&writers);
199      nfds = ares_fds(state.channel, &readers, &writers);
200      FD_SET(state.server_socket, &readers);
201      if (state.server_socket >= nfds)
202        nfds = state.server_socket + 1;
203      for (i = 0; i < state.config.nprinters; i++)
204        {
205          printer = &state.config.printers[i];
206          if (printer->s == -1)
207            continue;
208          if (printer->to_send)
209            FD_SET(printer->s, &writers);
210          else
211            FD_SET(printer->s, &readers);
212          if (printer->s >= nfds)
213            nfds = printer->s + 1;
214        }
215
216      /* Find the minimum of the ares and timer timeouts. */
217      tvp = timer_timeout(&tv);
218      tvp = ares_timeout(state.channel, tvp, &tv);
219
220      if (tvp)
221        {
222          syslog(LOG_DEBUG, "main: select timeout %lu %lu",
223                 (unsigned long) tvp->tv_sec, (unsigned long) tvp->tv_usec);
224        }
225      else
226        syslog(LOG_DEBUG, "main: no select timeout");
227
228      /* Wait for network input or a timer event. */
229      count = select(nfds, &readers, &writers, NULL, tvp);
230      if (count < 0 && errno != EINTR)
231        {
232          syslog(LOG_ALERT, "main: aborting on select error: %m");
233          return 1;
234        }
235
236      syslog(LOG_DEBUG, "main: select count %d", count);
237
238      ares_process(state.channel, &readers, &writers);
239      timer_process();
240
241      /* Don't bother scanning fd sets if nothing happened. */
242      if (count <= 0)
243        continue;
244
245      if (FD_ISSET(state.server_socket, &readers))
246        ws_handle_status(state.server_socket, &state.config);
247      for (i = 0; i < state.config.nprinters; i++)
248        {
249          printer = &state.config.printers[i];
250          if (printer->s == -1)
251            continue;
252          if (FD_ISSET(printer->s, &readers))
253            printer_handle_input(&state, printer);
254          else if (FD_ISSET(printer->s, &writers))
255            printer_handle_output(&state, printer);
256        }
257    }
258}
259
260static void usage(const char *progname)
261{
262  fprintf(stderr, "Usage: %s [-n] [-f configfile]\n", progname);
263  exit(1);
264}
265
266static void hup_handler(void)
267{
268  reload = 1;
269}
Note: See TracBrowser for help on using the repository browser.