Added --with-vmps to configure options, so that you can build
[freeradius.git] / src / main / radiusd.c
1 /*
2  * radiusd.c    Main loop of the radius server.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000-2004,2006  The FreeRADIUS server project
21  * Copyright 1999,2000  Miquel van Smoorenburg <miquels@cistron.nl>
22  * Copyright 2000  Alan DeKok <aland@ox.org>
23  * Copyright 2000  Alan Curry <pacman-radius@cqc.com>
24  * Copyright 2000  Jeff Carneal <jeff@apex.net>
25  * Copyright 2000  Chad Miller <cmiller@surfsouth.com>
26  */
27
28 #include <freeradius-devel/ident.h>
29 RCSID("$Id$")
30
31 #include <freeradius-devel/radiusd.h>
32 #include <freeradius-devel/radius_snmp.h>
33 #include <freeradius-devel/rad_assert.h>
34
35 #include <sys/file.h>
36
37 #include <fcntl.h>
38 #include <ctype.h>
39
40 #include <signal.h>
41
42 #ifdef HAVE_GETOPT_H
43 #       include <getopt.h>
44 #endif
45
46 #ifdef HAVE_SYS_WAIT_H
47 #       include <sys/wait.h>
48 #endif
49 #ifndef WEXITSTATUS
50 #       define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
51 #endif
52 #ifndef WIFEXITED
53 #       define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
54 #endif
55
56 /*
57  *  Global variables.
58  */
59 const char *progname = NULL;
60 const char *radius_dir = NULL;
61 const char *radacct_dir = NULL;
62 const char *radlog_dir = NULL;
63 const char *radlib_dir = NULL;
64 int log_stripped_names;
65 int debug_flag = 0;
66 int log_auth_detail = FALSE;
67
68
69 const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
70
71 time_t time_now;
72 static pid_t radius_pid;
73 static int debug_memory = 0;
74 static int has_detail_listener = FALSE;
75
76 static int radius_self_pipe[2];
77
78 /*
79  *  Configuration items.
80  */
81
82 /*
83  *      Static functions.
84  */
85 static void usage(int);
86
87 static void sig_fatal (int);
88 static void sig_hup (int);
89
90 /*
91  *      The main guy.
92  */
93 int main(int argc, char *argv[])
94 {
95         REQUEST *request;
96         unsigned char buffer[4096];
97         fd_set readfds;
98         int argval;
99         int pid;
100         int max_fd;
101         int status;
102         int dont_fork = FALSE;
103         int spawn_flag = TRUE;
104         int sig_hup_block = FALSE;
105         struct timeval tv, *ptv = NULL;
106         int read_from_detail = FALSE;
107         int fd_flags;
108
109 #ifdef HAVE_SIGACTION
110         struct sigaction act;
111 #endif
112         rad_listen_t *listener;
113
114 #ifdef OSFC2
115         set_auth_parameters(argc,argv);
116 #endif
117
118         if ((progname = strrchr(argv[0], '/')) == NULL)
119                 progname = argv[0];
120         else
121                 progname++;
122
123         debug_flag = 0;
124         spawn_flag = TRUE;
125         radius_dir = strdup(RADIUS_DIR);
126
127         /*
128          *      Ensure that the configuration is initialized.
129          */
130         memset(&mainconfig, 0, sizeof(mainconfig));
131         mainconfig.myip.af = AF_UNSPEC;
132         mainconfig.port = -1;
133         mainconfig.radiusd_conf = strdup("radiusd.conf");
134
135 #ifdef HAVE_SIGACTION
136         memset(&act, 0, sizeof(act));
137         act.sa_flags = 0 ;
138         sigemptyset( &act.sa_mask ) ;
139 #endif
140
141         /*
142          *      Don't put output anywhere until we get told a little
143          *      more.
144          */
145         mainconfig.radlog_fd = -1;
146         mainconfig.log_file = NULL;
147
148         /*  Process the options.  */
149         while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:mn:p:sSvxXyz")) != EOF) {
150
151                 switch(argval) {
152
153                         case 'A':
154                                 log_auth_detail = TRUE;
155                                 break;
156
157                         case 'a':
158                                 if (radacct_dir) free(radacct_dir);
159                                 radacct_dir = strdup(optarg);
160                                 break;
161
162                         case 'c':
163                                 /* ignore for backwards compatibility with Cistron */
164                                 break;
165
166                         case 'd':
167                                 if (radius_dir) free(radius_dir);
168                                 radius_dir = strdup(optarg);
169                                 break;
170
171                         case 'f':
172                                 dont_fork = TRUE;
173                                 break;
174
175                         case 'h':
176                                 usage(0);
177                                 break;
178
179                         case 'i':
180                                 if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
181                                         fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
182                                         exit(1);
183                                 }
184                                 break;
185
186                         case 'l':
187                                 if ((strcmp(optarg, "stdout") == 0) ||
188                                     (strcmp(optarg, "stderr") == 0) ||
189                                     (strcmp(optarg, "syslog") == 0)) {
190                                         fprintf(stderr, "radiusd: -l %s is unsupported.  Use log_destination in radiusd.conf\n", optarg);
191                                         exit(1);
192                                 }
193                                 if (radlog_dir) free(radlog_dir);
194                                 radlog_dir = strdup(optarg);
195                                 break;
196
197                         case 'g':
198                                 fprintf(stderr, "radiusd: -g is unsupported.  Use log_destination in radiusd.conf.\n");
199                                 exit(1);
200                                 break;
201
202                         case 'm':
203                                 debug_memory = 1;
204                                 break;
205
206                         case 'n':
207                                 if ((strchr(optarg, '/') != NULL) ||
208                                     (strchr(optarg, '.') != NULL) ||
209                                     (strlen(optarg) > 45)) usage(1);
210
211                                 snprintf(buffer, sizeof(buffer), "%s.conf",
212                                          optarg);
213                                 if (mainconfig.radiusd_conf)
214                                         free(mainconfig.radiusd_conf);
215                                 mainconfig.radiusd_conf = strdup(buffer);
216                                 break;
217
218                         case 'S':
219                                 log_stripped_names++;
220                                 break;
221
222                         case 'p':
223                                 mainconfig.port = atoi(optarg);
224                                 if ((mainconfig.port <= 0) ||
225                                     (mainconfig.port >= 65536)) {
226                                         fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
227                                         exit(1);
228                                 }
229                                 break;
230
231                         case 's':       /* Single process mode */
232                                 spawn_flag = FALSE;
233                                 dont_fork = TRUE;
234                                 break;
235
236                         case 'v':
237                                 version();
238                                 break;
239
240                                 /*
241                                  *  BIG debugging mode for users who are
242                                  *  TOO LAZY to type '-sfxxyz -l stdout' themselves.
243                                  */
244                         case 'X':
245                                 spawn_flag = FALSE;
246                                 dont_fork = TRUE;
247                                 debug_flag += 2;
248                                 mainconfig.log_auth = TRUE;
249                                 mainconfig.log_auth_badpass = TRUE;
250                                 mainconfig.log_auth_goodpass = TRUE;
251                                 mainconfig.radlog_dest = RADLOG_STDOUT;
252                                 mainconfig.radlog_fd = STDOUT_FILENO;
253                                 break;
254
255                         case 'x':
256                                 debug_flag++;
257                                 break;
258
259                         case 'y':
260                                 mainconfig.log_auth = TRUE;
261                                 mainconfig.log_auth_badpass = TRUE;
262                                 break;
263
264                         case 'z':
265                                 mainconfig.log_auth_badpass = TRUE;
266                                 mainconfig.log_auth_goodpass = TRUE;
267                                 break;
268
269                         default:
270                                 usage(1);
271                                 break;
272                 }
273         }
274
275         if (debug_flag) {
276                 radlog(L_INFO, "%s", radiusd_version);
277                 radlog(L_INFO, "Copyright (C) 2000-2007 The FreeRADIUS server project.\n");
278                 radlog(L_INFO, "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
279                 radlog(L_INFO, "PARTICULAR PURPOSE.\n");
280                 radlog(L_INFO, "You may redistribute copies of FreeRADIUS under the terms of the\n");
281                 radlog(L_INFO, "GNU General Public License.\n");
282                 fflush(NULL);
283         }
284
285         /*  Read the configuration files, BEFORE doing anything else.  */
286         if (read_mainconfig(0) < 0) {
287                 exit(1);
288         }
289
290         /*
291          *  Disconnect from session
292          */
293         if (debug_flag == 0 && dont_fork == FALSE) {
294                 pid = fork();
295                 if(pid < 0) {
296                         radlog(L_ERR|L_CONS, "Couldn't fork");
297                         exit(1);
298                 }
299
300                 /*
301                  *  The parent exits, so the child can run in the background.
302                  */
303                 if (pid > 0) {
304                         exit(0);
305                 }
306 #ifdef HAVE_SETSID
307                 setsid();
308 #endif
309         }
310
311         /*
312          *      If we're NOT debugging, trap fatal signals, so we can
313          *      easily clean up after ourselves.
314          *
315          *      If we ARE debugging, don't trap them, so we can
316          *      dump core.
317          */
318         if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {
319 #ifdef SIGSEGV
320 #ifdef HAVE_SIGACTION
321                 act.sa_handler = sig_fatal;
322                 sigaction(SIGSEGV, &act, NULL);
323 #else
324                 signal(SIGSEGV, sig_fatal);
325 #endif
326 #endif
327         }
328
329         /*
330          *  Ensure that we're using the CORRECT pid after forking,
331          *  NOT the one we started with.
332          */
333         radius_pid = getpid();
334
335         /*
336          *  Only write the PID file if we're running as a daemon.
337          *
338          *  And write it AFTER we've forked, so that we write the
339          *  correct PID.
340          */
341         if (dont_fork == FALSE) {
342                 FILE *fp;
343
344                 fp = fopen(mainconfig.pid_file, "w");
345                 if (fp != NULL) {
346                         /*
347                          *      FIXME: What about following symlinks,
348                          *      and having it over-write a normal file?
349                          */
350                         fprintf(fp, "%d\n", (int) radius_pid);
351                         fclose(fp);
352                 } else {
353                         radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n",
354                                mainconfig.pid_file, strerror(errno));
355                         exit(1);
356                 }
357         }
358
359         /*
360          *      Child threads need a pipe to signal us, as do the
361          *      signal handlers.
362          */
363         if (pipe(radius_self_pipe) < 0) {
364                 radlog(L_ERR, "radiusd: Error opening internal pipe: %s",
365                        strerror(errno));
366                 exit(1);
367         }
368         if (fcntl(radius_self_pipe[0], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
369                 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
370                        strerror(errno));
371                 exit(1);
372         }
373         if (fcntl(radius_self_pipe[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
374                 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
375                        strerror(errno));
376                 exit(1);
377         }
378
379         /*
380          *      If we're running as a daemon, close the default file
381          *      descriptors, AFTER forking.
382          */
383         if (!debug_flag) {
384                 int devnull;
385
386                 devnull = open("/dev/null", O_RDWR);
387                 if (devnull < 0) {
388                         radlog(L_ERR|L_CONS, "Failed opening /dev/null: %s\n",
389                                strerror(errno));
390                         exit(1);
391                 }
392                 dup2(devnull, STDIN_FILENO);
393                 if (mainconfig.radlog_dest == RADLOG_STDOUT) {
394                         mainconfig.radlog_fd = dup(STDOUT_FILENO);
395                 }
396                 dup2(devnull, STDOUT_FILENO);
397                 if (mainconfig.radlog_dest == RADLOG_STDERR) {
398                         mainconfig.radlog_fd = dup(STDERR_FILENO);
399                 }
400                 dup2(devnull, STDERR_FILENO);
401                 close(devnull);
402         }
403
404         /*
405          *      It's called the thread pool, but it does a little
406          *      more than that.
407          */
408         radius_event_init(spawn_flag);
409
410         /*
411          *  Use linebuffered or unbuffered stdout if
412          *  the debug flag is on.
413          */
414         if (debug_flag == TRUE)
415                 setlinebuf(stdout);
416
417         /*
418          *      Print out which ports we're listening on.
419          */
420         for (listener = mainconfig.listen;
421              listener != NULL;
422              listener = listener->next) {
423                 listener->print(listener, buffer, sizeof(buffer));
424                 switch (listener->type) {
425                 case RAD_LISTEN_AUTH:
426                         DEBUG("Listening on authentication address %s", buffer);
427                         break;
428
429                 case RAD_LISTEN_ACCT:
430                         DEBUG("Listening on accounting address %s", buffer);
431                         break;
432
433                 case RAD_LISTEN_PROXY:
434                         DEBUG("Listening on proxy address %s", buffer);
435                         break;
436
437                 case RAD_LISTEN_DETAIL:
438                         has_detail_listener = TRUE;
439                         read_from_detail = TRUE;
440                         DEBUG("Listening on detail file %s", buffer);
441                         break;
442
443                 case RAD_LISTEN_SNMP:
444                         DEBUG("Listening on SNMP %s", buffer);
445                         break;
446
447 #ifdef WITH_VMPS
448                 case RAD_LISTEN_VQP:
449                         DEBUG("Listening on vmps %s", buffer);
450                         break;
451 #endif
452
453                 default:
454                         break;
455                 }
456         }
457
458         /*
459          *      Now that we've set everything up, we can install the signal
460          *      handlers.  Before this, if we get any signal, we don't know
461          *      what to do, so we might as well do the default, and die.
462          */
463         signal(SIGPIPE, SIG_IGN);
464 #ifdef HAVE_SIGACTION
465         act.sa_handler = sig_hup;
466         sigaction(SIGHUP, &act, NULL);
467         act.sa_handler = sig_fatal;
468         sigaction(SIGTERM, &act, NULL);
469 #else
470         signal(SIGHUP, sig_hup);
471         signal(SIGTERM, sig_fatal);
472 #endif
473         /*
474          *      If we're debugging, then a CTRL-C will cause the
475          *      server to die immediately.  Use SIGTERM to shut down
476          *      the server cleanly in that case.
477          */
478         if ((debug_memory == 1) || (debug_flag == 0)) {
479 #ifdef HAVE_SIGACTION
480                 act.sa_handler = sig_fatal;
481                 sigaction(SIGINT, &act, NULL);
482                 sigaction(SIGQUIT, &act, NULL);
483 #else
484                 signal(SIGINT, sig_fatal);
485                 signal(SIGQUIT, sig_fatal);
486 #endif
487         }
488
489  restart:
490         radlog(L_INFO, "Ready to process requests.");
491
492         /*
493          *  Receive user requests
494          */
495         for (;;) {
496                 ssize_t rcode;
497
498                 FD_ZERO(&readfds);
499                 max_fd = 0;
500
501                 /*
502                  *      Loop over all the listening FD's.
503                  */
504                 for (listener = mainconfig.listen;
505                      listener != NULL;
506                      listener = listener->next) {
507                         if (listener->fd < 0) continue;
508
509                         if (!read_from_detail &&
510                             (listener->type == RAD_LISTEN_DETAIL)) continue;
511
512                         FD_SET(listener->fd, &readfds);
513                         if (listener->fd > max_fd) max_fd = listener->fd;
514                 }
515
516                 /*
517                  *      Add in the self pipe FD, for signals or
518                  *      notices from the child threads.
519                  */
520                 FD_SET(radius_self_pipe[0], &readfds);
521                 if (radius_self_pipe[0] > max_fd) {
522                         max_fd = radius_self_pipe[0];
523                 }
524
525                 if (!ptv) {
526                         DEBUG2("Nothing to do.  Sleeping until we see a request.");
527                 } else if (tv.tv_sec) {
528                                 DEBUG2("Waking up in %d seconds...",
529                                        (int) tv.tv_sec);
530                 }
531
532                 status = select(max_fd + 1, &readfds, NULL, NULL, ptv);
533                 if ((status < 0) && (errno != EINTR)) {
534                         radlog(L_ERR, "Unexpected error in select(): %s",
535                                strerror(errno));
536                                 exit(1);
537                 }
538                 time_now = time(NULL);
539
540 #ifndef HAVE_PTHREAD_H
541                 /*
542                  *      If there are no child threads, then there may
543                  *      be child processes.  In that case, wait for
544                  *      their exit status, and throw that exit status
545                  *      away.  This helps get rid of zxombie children.
546                  */
547                 while (waitpid(-1, &argval, WNOHANG) > 0) {
548                         /* do nothing */
549                 }
550 #endif
551
552                 /*
553                  *      Before doing anything else, check the self pipe.
554                  */
555                 if (FD_ISSET(radius_self_pipe[0], &readfds) &&
556                     (rcode = read(radius_self_pipe[0], buffer, sizeof(buffer))) > 0) {
557                         ssize_t i;
558
559                         for (i = 1; i < rcode; i++) {
560                                 buffer[0] |= buffer[i];
561                         }
562
563                         if ((buffer[0] & (RADIUS_SIGNAL_SELF_EXIT | RADIUS_SIGNAL_SELF_TERM)) != 0) {
564                                 DEBUG("Exiting...");
565
566                                 /*
567                                  *      Ignore the TERM signal: we're
568                                  *      about to die.
569                                  */
570                                 signal(SIGTERM, SIG_IGN);
571
572                                 /*
573                                  *      Send a TERM signal to all
574                                  *      associated processes
575                                  *      (including us, which gets
576                                  *      ignored.)
577                                  */
578                                 kill(-radius_pid, SIGTERM);
579
580                                 /*
581                                  *      FIXME: Kill child threads, and
582                                  *      clean up?
583                                  */
584
585                                 /*
586                                  *      FIXME: clean up any active REQUEST
587                                  *      handles.
588                                  */
589
590                                 /*
591                                  *      We're exiting, so we can delete the PID
592                                  *      file.  (If it doesn't exist, we can ignore
593                                  *      the error returned by unlink)
594                                  */
595                                 if (dont_fork == FALSE) {
596                                         unlink(mainconfig.pid_file);
597                                 }
598
599                                 radius_event_free();
600
601                                 /*
602                                  *      Free the configuration items.
603                                  */
604                                 free_mainconfig();
605
606                                 /*
607                                  *      Detach any modules.
608                                  */
609                                 detach_modules();
610
611                                 free(radius_dir);
612
613                                 /*
614                                  *      SIGTERM gets do_exit=0,
615                                  *      and we want to exit cleanly.
616                                  *
617                                  *      Other signals make us exit
618                                  *      with an error status.
619                                  */
620                                 if ((buffer[0] & RADIUS_SIGNAL_SELF_EXIT) != 0) {
621                                         exit(1);
622                                 }
623                                 exit(0);
624                         } /* else exit/term flags weren't set */
625
626                         if ((buffer[0] & RADIUS_SIGNAL_SELF_HUP) != 0) {
627                                 DEBUG("Received HUP signal");
628 #ifdef HAVE_PTHREAD_H
629                                 /*
630                                  *      Threads: wait for all threads to stop
631                                  *      processing before re-loading the
632                                  *      config, so we don't pull the rug out
633                                  *      from under them.
634                                  */
635                                 int max_wait = 0;
636                                 if (spawn_flag) for(;;) {
637                                         /*
638                                          *      Block until there are
639                                          *      zero threads with a
640                                          *      REQUEST handle.
641                                          *
642                                          *      FIXME: Wait for
643                                          *      threads to send us a
644                                          *      signal in the pipe?
645                                          */
646                                         sig_hup_block = TRUE;
647
648                                         if( (total_active_threads() == 0) ||
649                                             (max_wait >= 5) ) {
650                                                 sig_hup_block = FALSE;
651                                                 break;
652                                         }
653                                         sleep(1);
654                                         max_wait++;
655                                 }
656 #endif
657
658 #ifdef WITH_SNMP
659                                 if (mainconfig.do_snmp) {
660                                         rad_snmp.smux_failures = 0;
661                                         rad_snmp.smux_event = SMUX_CONNECT;
662                                 }
663 #endif
664                                 if (read_mainconfig(TRUE) < 0) {
665                                         exit(1);
666                                 }
667
668                                 goto restart;
669                         }
670
671                         /*
672                          *      Check if we can read from the detail file
673                          */
674                         if (has_detail_listener &&
675                             (buffer[0] & RADIUS_SIGNAL_SELF_DETAIL) != 0) {
676                                 DEBUG3("Can now read from detail file(s)");
677                                 read_from_detail = TRUE;
678                         }
679                 } /* else the self pipe didn't have data ready */
680
681                 /*
682                  *      Loop over the open socket FD's, reading any data.
683                  */
684                 for (listener = mainconfig.listen;
685                      listener != NULL;
686                      listener = listener->next) {
687                         RAD_REQUEST_FUNP fun;
688
689                         if ((listener->fd >= 0) &&
690                             !FD_ISSET(listener->fd, &readfds))
691                                 continue;
692
693                         /*
694                          *  Receive the packet.
695                          */
696                         if (sig_hup_block != FALSE) {
697                                 continue;
698                         }
699
700                         /*
701                          *      Do per-socket receive processing of
702                          *      the packet.  This also takes care of
703                          *      inserting the request into the event
704                          *      tree, and adding it to the queue for
705                          *      threads.
706                          */
707                         if (!listener->recv(listener, &fun, &request)) {
708                                 continue;
709                         }
710
711                         /*
712                          *      Drop the request into the thread pool,
713                          *      and let the thread pool take care of
714                          *      doing something with it.
715                          */
716                         if (!thread_pool_addrequest(request, fun)) {
717                                 request->child_state = REQUEST_DONE;
718                         }
719
720                         /*
721                          *      If we've read a packet from a socket
722                          *      OTHER than the detail file, we start
723                          *      ignoring the detail file.
724                          *
725                          *      When the child thread pulls the
726                          *      request off of the queues, it will
727                          *      check if the queues are empty.  Once
728                          *      all queues are empty, it will signal
729                          *      us to read the detail file again.
730                          */
731                         if (spawn_flag &&
732                             (listener->type != RAD_LISTEN_DETAIL)) {
733                                 read_from_detail = FALSE;
734                         }
735                 } /* loop over listening sockets*/
736
737                 ptv = &tv;
738                 radius_event_process(&ptv);
739
740 #ifdef HAVE_PTHREAD_H
741
742                 /*
743                  *      Only clean the thread pool if we're spawning
744                  *      child threads.
745                  *
746                  *      FIXME: Move this to the event handler!
747                  */
748                 if (spawn_flag) {
749                         thread_pool_clean(time_now);
750                 }
751 #endif
752         } /* loop forever */
753 }
754
755
756 /*
757  *  Display the syntax for starting this program.
758  */
759 static void NEVER_RETURNS usage(int status)
760 {
761         FILE *output = status?stderr:stdout;
762
763         fprintf(output,
764                         "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-AcfnsSvXxyz]\n", progname);
765         fprintf(output, "Options:\n\n");
766         fprintf(output, "  -a acct_dir     use accounting directory 'acct_dir'.\n");
767         fprintf(output, "  -A              Log auth detail.\n");
768         fprintf(output, "  -d raddb_dir    Configuration files are in \"raddbdir/*\".\n");
769         fprintf(output, "  -f              Run as a foreground process, not a daemon.\n");
770         fprintf(output, "  -h              Print this help message.\n");
771         fprintf(output, "  -i ipaddr       Listen on ipaddr ONLY\n");
772         fprintf(output, "  -l log_dir      Log file is \"log_dir/radius.log\" (not used in debug mode)\n");
773         fprintf(output, "  -p port         Listen on port ONLY\n");
774         fprintf(output, "  -s              Do not spawn child processes to handle requests.\n");
775         fprintf(output, "  -S              Log stripped names.\n");
776         fprintf(output, "  -v              Print server version information.\n");
777         fprintf(output, "  -X              Turn on full debugging.\n");
778         fprintf(output, "  -x              Turn on additional debugging. (-xx gives more debugging).\n");
779         fprintf(output, "  -y              Log authentication failures, with password.\n");
780         fprintf(output, "  -z              Log authentication successes, with password.\n");
781         exit(status);
782 }
783
784
785 /*
786  *      We got a fatal signal.
787  */
788 static void sig_fatal(int sig)
789 {
790         switch(sig) {
791                 case SIGSEGV:
792                         /*
793                          *      We can't really do anything
794                          *      intelligent here so just die
795                          */
796                         _exit(1);
797
798                 case SIGTERM:
799                         radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
800                         break;
801
802                 case SIGINT:
803                 case SIGQUIT:
804                         if (debug_memory) {
805                                 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
806                                 break;
807                         }
808                         /* FALL-THROUGH */
809
810                 default:
811                         radius_signal_self(RADIUS_SIGNAL_SELF_EXIT);
812                         break;
813         }
814 }
815
816
817 /*
818  *  We got the hangup signal.
819  *  Re-read the configuration files.
820  */
821 static void sig_hup(int sig)
822 {
823         sig = sig; /* -Wunused */
824
825         reset_signal(SIGHUP, sig_hup);
826
827         write(STDOUT_FILENO, "STUFF\n", 6);
828
829         radius_signal_self(RADIUS_SIGNAL_SELF_HUP);
830 }
831
832 void radius_signal_self(int flag)
833 {
834         ssize_t rcode;
835         uint8_t buffer[16];
836
837         /*
838          *      The caller is telling us it's OK to read from the
839          *      detail files.  However, we're not even listening on
840          *      the detail files.  Therefore, suppress the flag to
841          *      avoid bothering the mail worker thread.
842          */
843         if ((flag == RADIUS_SIGNAL_SELF_DETAIL) &&
844             !has_detail_listener) {
845                 return;
846         }
847
848         /*
849          *      The read MUST be non-blocking for this to work.
850          */
851         rcode = read(radius_self_pipe[0], buffer, sizeof(buffer));
852         if (rcode > 0) {
853                 ssize_t i;
854
855                 for (i = 1; i < rcode; i++) {
856                         buffer[0] |= buffer[i];
857                 }
858         }
859
860 #ifndef NDEBUG
861         memset(buffer + 1, 0, sizeof(buffer) - 1);
862 #endif
863
864         buffer[0] |= flag;
865
866
867         write(radius_self_pipe[1], buffer, 1);
868 }