Allow building WITHOUT_STATS
[freeradius.git] / src / main / radiusd.c
index 5f19e98..20ad58e 100644 (file)
@@ -29,7 +29,7 @@
 RCSID("$Id$")
 
 #include <freeradius-devel/radiusd.h>
-#include <freeradius-devel/radius_snmp.h>
+#include <freeradius-devel/modules.h>
 #include <freeradius-devel/rad_assert.h>
 
 #include <sys/file.h>
@@ -63,17 +63,13 @@ const char *radlog_dir = NULL;
 const char *radlib_dir = NULL;
 int log_stripped_names;
 int debug_flag = 0;
-int log_auth_detail = FALSE;
-
+int check_config = FALSE;
 
 const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
 
-time_t time_now;
-static pid_t radius_pid;
-static int debug_memory = 0;
-static int has_detail_listener = FALSE;
+pid_t radius_pid;
 
-static int radius_self_pipe[2];
+static int debug_memory = 0;
 
 /*
  *  Configuration items.
@@ -85,41 +81,44 @@ static int radius_self_pipe[2];
 static void usage(int);
 
 static void sig_fatal (int);
+#ifdef SIGHUP
 static void sig_hup (int);
+#endif
 
 /*
  *     The main guy.
  */
 int main(int argc, char *argv[])
 {
-       REQUEST *request;
-       unsigned char buffer[4096];
-       fd_set readfds;
+       int rcode;
        int argval;
-       int pid;
-       int max_fd;
-       int status;
-       int dont_fork = FALSE;
        int spawn_flag = TRUE;
-       int sig_hup_block = FALSE;
-       struct timeval tv, *ptv = NULL;
-       int read_from_detail = FALSE;
-       int fd_flags;
+       int dont_fork = FALSE;
+       int flag = 0;
 
 #ifdef HAVE_SIGACTION
        struct sigaction act;
 #endif
-       rad_listen_t *listener;
 
 #ifdef OSFC2
        set_auth_parameters(argc,argv);
 #endif
 
-       if ((progname = strrchr(argv[0], '/')) == NULL)
+       if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL)
                progname = argv[0];
        else
                progname++;
 
+#ifdef WIN32
+       {
+               WSADATA wsaData;
+               if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
+                       fprintf(stderr, "%s: Unable to initialize socket library.\n");
+                       return 1;
+               }
+       }
+#endif
+
        debug_flag = 0;
        spawn_flag = TRUE;
        radius_dir = strdup(RADIUS_DIR);
@@ -130,7 +129,7 @@ int main(int argc, char *argv[])
        memset(&mainconfig, 0, sizeof(mainconfig));
        mainconfig.myip.af = AF_UNSPEC;
        mainconfig.port = -1;
-       mainconfig.radiusd_conf = strdup("radiusd.conf");
+       mainconfig.name = "radiusd";
 
 #ifdef HAVE_SIGACTION
        memset(&act, 0, sizeof(act));
@@ -142,25 +141,18 @@ int main(int argc, char *argv[])
         *      Don't put output anywhere until we get told a little
         *      more.
         */
+       mainconfig.radlog_dest = RADLOG_NULL;
        mainconfig.radlog_fd = -1;
        mainconfig.log_file = NULL;
 
        /*  Process the options.  */
-       while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:mn:p:sSvxXyz")) != EOF) {
+       while ((argval = getopt(argc, argv, "Cd:fhi:l:mn:p:stvxX")) != EOF) {
 
                switch(argval) {
-
-                       case 'A':
-                               log_auth_detail = TRUE;
-                               break;
-
-                       case 'a':
-                               if (radacct_dir) free(radacct_dir);
-                               radacct_dir = strdup(optarg);
-                               break;
-
-                       case 'c':
-                               /* ignore for backwards compatibility with Cistron */
+                       case 'C':
+                               check_config = TRUE;
+                               spawn_flag = FALSE;
+                               dont_fork = TRUE;
                                break;
 
                        case 'd':
@@ -176,49 +168,36 @@ int main(int argc, char *argv[])
                                usage(0);
                                break;
 
-                       case 'i':
-                               if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
-                                       fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
+                       case 'l':
+                               if (strcmp(optarg, "stdout") == 0) {
+                                       goto do_stdout;
+                               }
+                               mainconfig.log_file = strdup(optarg);
+                               mainconfig.radlog_dest = RADLOG_FILES;
+                               mainconfig.radlog_fd = open(mainconfig.log_file,
+                                                           O_WRONLY | O_APPEND | O_CREAT, 0640);
+                               if (mainconfig.radlog_fd < 0) {
+                                       fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, strerror(errno));
                                        exit(1);
                                }
-                               break;
+                               break;            
 
-                       case 'l':
-                               if ((strcmp(optarg, "stdout") == 0) ||
-                                   (strcmp(optarg, "stderr") == 0) ||
-                                   (strcmp(optarg, "syslog") == 0)) {
-                                       fprintf(stderr, "radiusd: -l %s is unsupported.  Use log_destination in radiusd.conf\n", optarg);
+                       case 'i':
+                               if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
+                                       fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
                                        exit(1);
                                }
-                               if (radlog_dir) free(radlog_dir);
-                               radlog_dir = strdup(optarg);
+                               flag |= 1;
                                break;
 
-                       case 'g':
-                               fprintf(stderr, "radiusd: -g is unsupported.  Use log_destination in radiusd.conf.\n");
-                               exit(1);
+                       case 'n':
+                               mainconfig.name = optarg;
                                break;
 
                        case 'm':
                                debug_memory = 1;
                                break;
 
-                       case 'n':
-                               if ((strchr(optarg, '/') != NULL) ||
-                                   (strchr(optarg, '.') != NULL) ||
-                                   (strlen(optarg) > 45)) usage(1);
-
-                               snprintf(buffer, sizeof(buffer), "%s.conf",
-                                        optarg);
-                               if (mainconfig.radiusd_conf)
-                                       free(mainconfig.radiusd_conf);
-                               mainconfig.radiusd_conf = strdup(buffer);
-                               break;
-
-                       case 'S':
-                               log_stripped_names++;
-                               break;
-
                        case 'p':
                                mainconfig.port = atoi(optarg);
                                if ((mainconfig.port <= 0) ||
@@ -226,6 +205,7 @@ int main(int argc, char *argv[])
                                        fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
                                        exit(1);
                                }
+                               flag |= 2;
                                break;
 
                        case 's':       /* Single process mode */
@@ -233,14 +213,14 @@ int main(int argc, char *argv[])
                                dont_fork = TRUE;
                                break;
 
+                       case 't':       /* no child threads */
+                               spawn_flag = FALSE;
+                               break;
+
                        case 'v':
                                version();
                                break;
 
-                               /*
-                                *  BIG debugging mode for users who are
-                                *  TOO LAZY to type '-sfxxyz -l stdout' themselves.
-                                */
                        case 'X':
                                spawn_flag = FALSE;
                                dont_fork = TRUE;
@@ -248,37 +228,34 @@ int main(int argc, char *argv[])
                                mainconfig.log_auth = TRUE;
                                mainconfig.log_auth_badpass = TRUE;
                                mainconfig.log_auth_goodpass = TRUE;
+               do_stdout:
                                mainconfig.radlog_dest = RADLOG_STDOUT;
                                mainconfig.radlog_fd = STDOUT_FILENO;
+                               fr_log_fp = stdout;
                                break;
 
                        case 'x':
                                debug_flag++;
                                break;
 
-                       case 'y':
-                               mainconfig.log_auth = TRUE;
-                               mainconfig.log_auth_badpass = TRUE;
-                               break;
-
-                       case 'z':
-                               mainconfig.log_auth_badpass = TRUE;
-                               mainconfig.log_auth_goodpass = TRUE;
-                               break;
-
                        default:
                                usage(1);
                                break;
                }
        }
 
+       if (flag && (flag != 0x03)) {
+               fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n");
+               exit(1);
+       }
+
        if (debug_flag) {
                radlog(L_INFO, "%s", radiusd_version);
-               radlog(L_INFO, "Copyright (C) 2000-2007 The FreeRADIUS server project.\n");
+               radlog(L_INFO, "Copyright (C) 1999-2009 The FreeRADIUS server project and contributors.\n");
                radlog(L_INFO, "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
                radlog(L_INFO, "PARTICULAR PURPOSE.\n");
                radlog(L_INFO, "You may redistribute copies of FreeRADIUS under the terms of the\n");
-               radlog(L_INFO, "GNU General Public License.\n");
+               radlog(L_INFO, "GNU General Public License v2.\n");
                fflush(NULL);
        }
 
@@ -287,13 +264,15 @@ int main(int argc, char *argv[])
                exit(1);
        }
 
+#ifndef __MINGW32__
        /*
         *  Disconnect from session
         */
-       if (debug_flag == 0 && dont_fork == FALSE) {
-               pid = fork();
-               if(pid < 0) {
-                       radlog(L_ERR|L_CONS, "Couldn't fork");
+       if (dont_fork == FALSE) {
+               pid_t pid = fork();
+
+               if (pid < 0) {
+                       radlog(L_ERR, "Couldn't fork: %s", strerror(errno));
                        exit(1);
                }
 
@@ -307,24 +286,7 @@ int main(int argc, char *argv[])
                setsid();
 #endif
        }
-
-       /*
-        *      If we're NOT debugging, trap fatal signals, so we can
-        *      easily clean up after ourselves.
-        *
-        *      If we ARE debugging, don't trap them, so we can
-        *      dump core.
-        */
-       if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {
-#ifdef SIGSEGV
-#ifdef HAVE_SIGACTION
-               act.sa_handler = sig_fatal;
-               sigaction(SIGSEGV, &act, NULL);
-#else
-               signal(SIGSEGV, sig_fatal);
 #endif
-#endif
-       }
 
        /*
         *  Ensure that we're using the CORRECT pid after forking,
@@ -333,50 +295,6 @@ int main(int argc, char *argv[])
        radius_pid = getpid();
 
        /*
-        *  Only write the PID file if we're running as a daemon.
-        *
-        *  And write it AFTER we've forked, so that we write the
-        *  correct PID.
-        */
-       if (dont_fork == FALSE) {
-               FILE *fp;
-
-               fp = fopen(mainconfig.pid_file, "w");
-               if (fp != NULL) {
-                       /*
-                        *      FIXME: What about following symlinks,
-                        *      and having it over-write a normal file?
-                        */
-                       fprintf(fp, "%d\n", (int) radius_pid);
-                       fclose(fp);
-               } else {
-                       radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n",
-                              mainconfig.pid_file, strerror(errno));
-                       exit(1);
-               }
-       }
-
-       /*
-        *      Child threads need a pipe to signal us, as do the
-        *      signal handlers.
-        */
-       if (pipe(radius_self_pipe) < 0) {
-               radlog(L_ERR, "radiusd: Error opening internal pipe: %s",
-                      strerror(errno));
-               exit(1);
-       }
-       if (fcntl(radius_self_pipe[0], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
-               radlog(L_ERR, "radiusd: Error setting internal flags: %s",
-                      strerror(errno));
-               exit(1);
-       }
-       if (fcntl(radius_self_pipe[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
-               radlog(L_ERR, "radiusd: Error setting internal flags: %s",
-                      strerror(errno));
-               exit(1);
-       }
-
-       /*
         *      If we're running as a daemon, close the default file
         *      descriptors, AFTER forking.
         */
@@ -392,80 +310,42 @@ int main(int argc, char *argv[])
                dup2(devnull, STDIN_FILENO);
                if (mainconfig.radlog_dest == RADLOG_STDOUT) {
                        mainconfig.radlog_fd = dup(STDOUT_FILENO);
+                       setlinebuf(stdout);
                }
                dup2(devnull, STDOUT_FILENO);
                if (mainconfig.radlog_dest == RADLOG_STDERR) {
                        mainconfig.radlog_fd = dup(STDERR_FILENO);
+                       setlinebuf(stdout);
                }
                dup2(devnull, STDERR_FILENO);
                close(devnull);
-       }
 
-       /*
-        *      It's called the thread pool, but it does a little
-        *      more than that.
-        */
-       radius_event_init(spawn_flag);
-
-       /*
-        *  Use linebuffered or unbuffered stdout if
-        *  the debug flag is on.
-        */
-       if (debug_flag == TRUE)
-               setlinebuf(stdout);
+       } else {
+               setlinebuf(stdout); /* unbuffered output */
+       }
 
        /*
-        *      Print out which ports we're listening on.
+        *      Initialize the event pool, including threads.
         */
-       for (listener = mainconfig.listen;
-            listener != NULL;
-            listener = listener->next) {
-               listener->print(listener, buffer, sizeof(buffer));
-               switch (listener->type) {
-               case RAD_LISTEN_AUTH:
-                       DEBUG("Listening on authentication address %s", buffer);
-                       break;
-
-               case RAD_LISTEN_ACCT:
-                       DEBUG("Listening on accounting address %s", buffer);
-                       break;
-
-               case RAD_LISTEN_PROXY:
-                       DEBUG("Listening on proxy address %s", buffer);
-                       break;
-
-               case RAD_LISTEN_DETAIL:
-                       has_detail_listener = TRUE;
-                       read_from_detail = TRUE;
-                       DEBUG("Listening on detail file %s", buffer);
-                       break;
-
-               case RAD_LISTEN_SNMP:
-                       DEBUG("Listening on SNMP %s", buffer);
-                       break;
-
-               case RAD_LISTEN_VQP:
-                       DEBUG("Listening on vmps %s", buffer);
-                       break;
-
-               default:
-                       break;
-               }
-       }
+       radius_event_init(mainconfig.config, spawn_flag);
 
        /*
         *      Now that we've set everything up, we can install the signal
         *      handlers.  Before this, if we get any signal, we don't know
         *      what to do, so we might as well do the default, and die.
         */
+#ifdef SIGPIPE
        signal(SIGPIPE, SIG_IGN);
+#endif
 #ifdef HAVE_SIGACTION
        act.sa_handler = sig_hup;
        sigaction(SIGHUP, &act, NULL);
        act.sa_handler = sig_fatal;
        sigaction(SIGTERM, &act, NULL);
 #else
+#ifdef SIGHUP
        signal(SIGHUP, sig_hup);
+#endif
        signal(SIGTERM, sig_fatal);
 #endif
        /*
@@ -480,274 +360,104 @@ int main(int argc, char *argv[])
                sigaction(SIGQUIT, &act, NULL);
 #else
                signal(SIGINT, sig_fatal);
+#ifdef SIGQUIT
                signal(SIGQUIT, sig_fatal);
 #endif
+#endif
        }
 
- restart:
-       radlog(L_INFO, "Ready to process requests.");
-
        /*
-        *  Receive user requests
+        *      Everything seems to have loaded OK, exit gracefully.
         */
-       for (;;) {
-               ssize_t rcode;
-
-               FD_ZERO(&readfds);
-               max_fd = 0;
-
-               /*
-                *      Loop over all the listening FD's.
-                */
-               for (listener = mainconfig.listen;
-                    listener != NULL;
-                    listener = listener->next) {
-                       if (listener->fd < 0) continue;
-
-                       if (!read_from_detail &&
-                           (listener->type == RAD_LISTEN_DETAIL)) continue;
-
-                       FD_SET(listener->fd, &readfds);
-                       if (listener->fd > max_fd) max_fd = listener->fd;
-               }
-
-               /*
-                *      Add in the self pipe FD, for signals or
-                *      notices from the child threads.
-                */
-               FD_SET(radius_self_pipe[0], &readfds);
-               if (radius_self_pipe[0] > max_fd) {
-                       max_fd = radius_self_pipe[0];
-               }
-
-               if (!ptv) {
-                       DEBUG2("Nothing to do.  Sleeping until we see a request.");
-               } else if (tv.tv_sec) {
-                               DEBUG2("Waking up in %d seconds...",
-                                      (int) tv.tv_sec);
-               }
-
-               status = select(max_fd + 1, &readfds, NULL, NULL, ptv);
-               if ((status < 0) && (errno != EINTR)) {
-                       radlog(L_ERR, "Unexpected error in select(): %s",
-                              strerror(errno));
-                               exit(1);
-               }
-               time_now = time(NULL);
-
-#ifndef HAVE_PTHREAD_H
-               /*
-                *      If there are no child threads, then there may
-                *      be child processes.  In that case, wait for
-                *      their exit status, and throw that exit status
-                *      away.  This helps get rid of zxombie children.
-                */
-               while (waitpid(-1, &argval, WNOHANG) > 0) {
-                       /* do nothing */
-               }
-#endif
-
-               /*
-                *      Before doing anything else, check the self pipe.
-                */
-               if (FD_ISSET(radius_self_pipe[0], &readfds) &&
-                   (rcode = read(radius_self_pipe[0], buffer, sizeof(buffer))) > 0) {
-                       ssize_t i;
-
-                       for (i = 1; i < rcode; i++) {
-                               buffer[0] |= buffer[i];
-                       }
-
-                       if ((buffer[0] & (RADIUS_SIGNAL_SELF_EXIT | RADIUS_SIGNAL_SELF_TERM)) != 0) {
-                               DEBUG("Exiting...");
-
-                               /*
-                                *      Ignore the TERM signal: we're
-                                *      about to die.
-                                */
-                               signal(SIGTERM, SIG_IGN);
-
-                               /*
-                                *      Send a TERM signal to all
-                                *      associated processes
-                                *      (including us, which gets
-                                *      ignored.)
-                                */
-                               kill(-radius_pid, SIGTERM);
-
-                               /*
-                                *      FIXME: Kill child threads, and
-                                *      clean up?
-                                */
-
-                               /*
-                                *      FIXME: clean up any active REQUEST
-                                *      handles.
-                                */
-
-                               /*
-                                *      We're exiting, so we can delete the PID
-                                *      file.  (If it doesn't exist, we can ignore
-                                *      the error returned by unlink)
-                                */
-                               if (dont_fork == FALSE) {
-                                       unlink(mainconfig.pid_file);
-                               }
-
-                               radius_event_free();
-
-                               /*
-                                *      Free the configuration items.
-                                */
-                               free_mainconfig();
-
-                               /*
-                                *      Detach any modules.
-                                */
-                               detach_modules();
-
-                               free(radius_dir);
-
-                               /*
-                                *      SIGTERM gets do_exit=0,
-                                *      and we want to exit cleanly.
-                                *
-                                *      Other signals make us exit
-                                *      with an error status.
-                                */
-                               if ((buffer[0] & RADIUS_SIGNAL_SELF_EXIT) != 0) {
-                                       exit(1);
-                               }
-                               exit(0);
-                       } /* else exit/term flags weren't set */
-
-                       if ((buffer[0] & RADIUS_SIGNAL_SELF_HUP) != 0) {
-                               DEBUG("Received HUP signal");
-#ifdef HAVE_PTHREAD_H
-                               /*
-                                *      Threads: wait for all threads to stop
-                                *      processing before re-loading the
-                                *      config, so we don't pull the rug out
-                                *      from under them.
-                                */
-                               int max_wait = 0;
-                               if (spawn_flag) for(;;) {
-                                       /*
-                                        *      Block until there are
-                                        *      zero threads with a
-                                        *      REQUEST handle.
-                                        *
-                                        *      FIXME: Wait for
-                                        *      threads to send us a
-                                        *      signal in the pipe?
-                                        */
-                                       sig_hup_block = TRUE;
-
-                                       if( (total_active_threads() == 0) ||
-                                           (max_wait >= 5) ) {
-                                               sig_hup_block = FALSE;
-                                               break;
-                                       }
-                                       sleep(1);
-                                       max_wait++;
-                               }
-#endif
+       if (check_config) {
+               DEBUG("Configuration appears to be OK.");
+               exit(0);
+       }
 
-#ifdef WITH_SNMP
-                               if (mainconfig.do_snmp) {
-                                       rad_snmp.smux_failures = 0;
-                                       rad_snmp.smux_event = SMUX_CONNECT;
-                               }
+#ifdef WITH_STATS
+       radius_stats_init(0);
 #endif
-                               if (read_mainconfig(TRUE) < 0) {
-                                       exit(1);
-                               }
-
-                               goto restart;
-                       }
-
-                       /*
-                        *      Check if we can read from the detail file
-                        */
-                       if (has_detail_listener &&
-                           (buffer[0] & RADIUS_SIGNAL_SELF_DETAIL) != 0) {
-                               DEBUG3("Can now read from detail file(s)");
-                               read_from_detail = TRUE;
-                       }
-               } /* else the self pipe didn't have data ready */
-
-               /*
-                *      Loop over the open socket FD's, reading any data.
-                */
-               for (listener = mainconfig.listen;
-                    listener != NULL;
-                    listener = listener->next) {
-                       RAD_REQUEST_FUNP fun;
-
-                       if ((listener->fd >= 0) &&
-                           !FD_ISSET(listener->fd, &readfds))
-                               continue;
 
-                       /*
-                        *  Receive the packet.
-                        */
-                       if (sig_hup_block != FALSE) {
-                               continue;
-                       }
-
-                       /*
-                        *      Do per-socket receive processing of
-                        *      the packet.  This also takes care of
-                        *      inserting the request into the event
-                        *      tree, and adding it to the queue for
-                        *      threads.
-                        */
-                       if (!listener->recv(listener, &fun, &request)) {
-                               continue;
-                       }
-
-                       /*
-                        *      Drop the request into the thread pool,
-                        *      and let the thread pool take care of
-                        *      doing something with it.
-                        */
-                       if (!thread_pool_addrequest(request, fun)) {
-                               request->child_state = REQUEST_DONE;
-                       }
+       /*
+        *  Only write the PID file if we're running as a daemon.
+        *
+        *  And write it AFTER we've forked, so that we write the
+        *  correct PID.
+        */
+       if (dont_fork == FALSE) {
+               FILE *fp;
 
+               fp = fopen(mainconfig.pid_file, "w");
+               if (fp != NULL) {
                        /*
-                        *      If we've read a packet from a socket
-                        *      OTHER than the detail file, we start
-                        *      ignoring the detail file.
-                        *
-                        *      When the child thread pulls the
-                        *      request off of the queues, it will
-                        *      check if the queues are empty.  Once
-                        *      all queues are empty, it will signal
-                        *      us to read the detail file again.
+                        *      FIXME: What about following symlinks,
+                        *      and having it over-write a normal file?
                         */
-                       if (spawn_flag &&
-                           (listener->type != RAD_LISTEN_DETAIL)) {
-                               read_from_detail = FALSE;
-                       }
-               } /* loop over listening sockets*/
-
-               ptv = &tv;
-               radius_event_process(&ptv);
-
-#ifdef HAVE_PTHREAD_H
-
-               /*
-                *      Only clean the thread pool if we're spawning
-                *      child threads.
-                *
-                *      FIXME: Move this to the event handler!
-                */
-               if (spawn_flag) {
-                       thread_pool_clean(time_now);
+                       fprintf(fp, "%d\n", (int) radius_pid);
+                       fclose(fp);
+               } else {
+                       radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n",
+                              mainconfig.pid_file, strerror(errno));
+                       exit(1);
                }
+       }
+
+       /*
+        *      Process requests until HUP or exit.
+        */
+       while ((rcode = radius_event_process()) == 0x80) {
+               radius_stats_init(1);
+               hup_mainconfig();
+       }
+       
+       radlog(L_INFO, "Exiting normally.");
+       
+       /*
+        *      Ignore the TERM signal: we're
+        *      about to die.
+        */
+       signal(SIGTERM, SIG_IGN);
+       
+       /*
+        *      Send a TERM signal to all
+        *      associated processes
+        *      (including us, which gets
+        *      ignored.)
+        */
+#ifndef __MINGW32__
+       if (spawn_flag) kill(-radius_pid, SIGTERM);
 #endif
-       } /* loop forever */
+       
+       /*
+        *      We're exiting, so we can delete the PID
+        *      file.  (If it doesn't exist, we can ignore
+        *      the error returned by unlink)
+        */
+       if (dont_fork == FALSE) {
+               unlink(mainconfig.pid_file);
+       }
+               
+       radius_event_free();
+       
+       /*
+        *      Free the configuration items.
+        */
+       free_mainconfig();
+       
+       /*
+        *      Detach any modules.
+        */
+       detach_modules();
+       
+       xlat_free();            /* modules may have xlat's */
+
+       free(radius_dir);
+               
+#ifdef WIN32
+       WSACleanup();
+#endif
+
+       return (rcode - 1);
 }
 
 
@@ -759,23 +469,19 @@ static void NEVER_RETURNS usage(int status)
        FILE *output = status?stderr:stdout;
 
        fprintf(output,
-                       "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-AcfnsSvXxyz]\n", progname);
+                       "Usage: %s [-d db_dir] [-l log_dir] [-i address] [-n name] [-fsvXx]\n", progname);
        fprintf(output, "Options:\n\n");
-       fprintf(output, "  -a acct_dir     use accounting directory 'acct_dir'.\n");
-       fprintf(output, "  -A              Log auth detail.\n");
+       fprintf(output, "  -C              Check configuration and exit.\n");
        fprintf(output, "  -d raddb_dir    Configuration files are in \"raddbdir/*\".\n");
        fprintf(output, "  -f              Run as a foreground process, not a daemon.\n");
        fprintf(output, "  -h              Print this help message.\n");
        fprintf(output, "  -i ipaddr       Listen on ipaddr ONLY\n");
-       fprintf(output, "  -l log_dir      Log file is \"log_dir/radius.log\" (not used in debug mode)\n");
+       fprintf(output, "  -n name         Read raddb/name.conf instead of raddb/radiusd.conf\n");
        fprintf(output, "  -p port         Listen on port ONLY\n");
        fprintf(output, "  -s              Do not spawn child processes to handle requests.\n");
-       fprintf(output, "  -S              Log stripped names.\n");
        fprintf(output, "  -v              Print server version information.\n");
        fprintf(output, "  -X              Turn on full debugging.\n");
        fprintf(output, "  -x              Turn on additional debugging. (-xx gives more debugging).\n");
-       fprintf(output, "  -y              Log authentication failures, with password.\n");
-       fprintf(output, "  -z              Log authentication successes, with password.\n");
        exit(status);
 }
 
@@ -786,19 +492,14 @@ static void NEVER_RETURNS usage(int status)
 static void sig_fatal(int sig)
 {
        switch(sig) {
-               case SIGSEGV:
-                       /*
-                        *      We can't really do anything
-                        *      intelligent here so just die
-                        */
-                       _exit(1);
-
                case SIGTERM:
                        radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
                        break;
 
                case SIGINT:
+#ifdef SIGQUIT
                case SIGQUIT:
+#endif
                        if (debug_memory) {
                                radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
                                break;
@@ -806,12 +507,11 @@ static void sig_fatal(int sig)
                        /* FALL-THROUGH */
 
                default:
-                       radius_signal_self(RADIUS_SIGNAL_SELF_EXIT);
-                       break;
+                       _exit(sig);
        }
 }
 
-
+#ifdef SIGHUP
 /*
  *  We got the hangup signal.
  *  Re-read the configuration files.
@@ -822,45 +522,6 @@ static void sig_hup(int sig)
 
        reset_signal(SIGHUP, sig_hup);
 
-       write(STDOUT_FILENO, "STUFF\n", 6);
-
        radius_signal_self(RADIUS_SIGNAL_SELF_HUP);
 }
-
-void radius_signal_self(int flag)
-{
-       ssize_t rcode;
-       uint8_t buffer[16];
-
-       /*
-        *      The caller is telling us it's OK to read from the
-        *      detail files.  However, we're not even listening on
-        *      the detail files.  Therefore, suppress the flag to
-        *      avoid bothering the mail worker thread.
-        */
-       if ((flag == RADIUS_SIGNAL_SELF_DETAIL) &&
-           !has_detail_listener) {
-               return;
-       }
-
-       /*
-        *      The read MUST be non-blocking for this to work.
-        */
-       rcode = read(radius_self_pipe[0], buffer, sizeof(buffer));
-       if (rcode > 0) {
-               ssize_t i;
-
-               for (i = 1; i < rcode; i++) {
-                       buffer[0] |= buffer[i];
-               }
-       }
-
-#ifndef NDEBUG
-       memset(buffer + 1, 0, sizeof(buffer) - 1);
 #endif
-
-       buffer[0] |= flag;
-
-
-       write(radius_self_pipe[1], buffer, 1);
-}