fix possible crash on user deletion
[srvx.git] / src / main-common.c
index 7ac6dcef5f9d425faa3df30874452f44f4b92a9a..85b9dd34a2dd3395658562eaee9fad9280b4af68 100644 (file)
@@ -1,6 +1,8 @@
 extern FILE *replay_file;
 
-time_t boot_time, burst_begin, now;
+unsigned long boot_time;
+unsigned long burst_begin;
+unsigned long now;
 unsigned long burst_length;
 struct log_type *MAIN_LOG;
 
@@ -51,6 +53,7 @@ static const struct message_entry msgtab[] = {
     { "MSG_STUPID_ACCESS_CHANGE", "Please ask someone $belse$b to demote you." },
     { "MSG_NO_SEARCH_ACCESS", "You do not have enough access to search based on $b%s$b." },
     { "MSG_INVALID_CRITERIA", "$b%s$b is an invalid search criteria." },
+    { "MSG_INVALID_FIELD", "$b%s$b is an invalid search field." },
     { "MSG_MATCH_COUNT", "Found $b%u$b matches." },
     { "MSG_NO_MATCHES", "Nothing matched the criteria of your search." },
     { "MSG_TOPIC_UNKNOWN", "No help on that topic." },
@@ -59,8 +62,8 @@ static const struct message_entry msgtab[] = {
     { "MSG_DB_UNKNOWN", "I do not know of a database named %s." },
     { "MSG_DB_IS_MONDO", "Database %s is in the \"mondo\" database and cannot be written separately." },
     { "MSG_DB_WRITE_ERROR", "Error while writing database %s." },
-    { "MSG_DB_WROTE_DB", "Wrote database %s (in "FMT_TIME_T".%06lu seconds)." },
-    { "MSG_DB_WROTE_ALL", "Wrote all databases (in "FMT_TIME_T".%06lu seconds)." },
+    { "MSG_DB_WROTE_DB", "Wrote database %s (in %lu.%06lu seconds)." },
+    { "MSG_DB_WROTE_ALL", "Wrote all databases (in %lu.%06lu seconds)." },
     { "MSG_AND", "and" },
     { "MSG_0_SECONDS", "0 seconds" },
     { "MSG_YEAR", "year" },
@@ -91,7 +94,7 @@ uplink_insert(const char *key, void *data, UNUSED_ARG(void *extra))
 
     if(!uplink)
     {
-       return 0;
+        return 0;
     }
 
     uplink->name = (char *)key;
@@ -105,7 +108,7 @@ uplink_insert(const char *key, void *data, UNUSED_ARG(void *extra))
     str = database_get_data(rd->d.object, "enabled", RECDB_QSTRING);
     if(str)
     {
-       enabled = atoi(str) ? 1 : 0;
+        enabled = atoi(str) ? 1 : 0;
     }
 
     cManager.enabled += enabled;
@@ -123,14 +126,14 @@ uplink_insert(const char *key, void *data, UNUSED_ARG(void *extra))
     if (!getaddrinfo(str, NULL, &hints, &ai))
     {
         uplink->bind_addr_len = ai->ai_addrlen;
-       uplink->bind_addr = calloc(1, ai->ai_addrlen);
+        uplink->bind_addr = calloc(1, ai->ai_addrlen);
         memcpy(uplink->bind_addr, ai->ai_addr, ai->ai_addrlen);
         freeaddrinfo(ai);
     }
     else
     {
-       uplink->bind_addr = NULL;
-       uplink->bind_addr_len = 0;
+        uplink->bind_addr = NULL;
+        uplink->bind_addr_len = 0;
     }
 
     uplink->next = cManager.uplinks;
@@ -138,7 +141,7 @@ uplink_insert(const char *key, void *data, UNUSED_ARG(void *extra))
 
     if(cManager.uplinks)
     {
-       cManager.uplinks->prev = uplink;
+        cManager.uplinks->prev = uplink;
     }
 
     cManager.uplinks = uplink;
@@ -150,9 +153,9 @@ uplink_insert(const char *key, void *data, UNUSED_ARG(void *extra))
        && !irccasecmp(uplink->host, cManager.uplink->host)
        && uplink->port == cManager.uplink->port)
     {
-       uplink->state = cManager.uplink->state;
-       uplink->tries = cManager.uplink->tries;
-       cManager.uplink = uplink;
+        uplink->state = cManager.uplink->state;
+        uplink->tries = cManager.uplink->tries;
+        cManager.uplink = uplink;
     }
 
     return 0;
@@ -174,7 +177,7 @@ uplink_compile(void)
     if(!(conf_node = conf_get_data("uplinks", RECDB_OBJECT)))
     {
         log_module(MAIN_LOG, LOG_FATAL, "No uplinks configured; giving up.");
-       exit(1);
+        exit(1);
     }
 
     cManager.enabled = 0;
@@ -184,29 +187,29 @@ uplink_compile(void)
        is a reference to one of these, because it won't get dereferenced. */
     if(oldUplinks)
     {
-       struct uplinkNode *uplink, *next;
+        struct uplinkNode *uplink, *next;
 
-       oldUplinks->prev->next = NULL;
+        oldUplinks->prev->next = NULL;
 
-       for(uplink = oldUplinks; uplink; uplink = next)
-       {
-           next = uplink->next;
+        for(uplink = oldUplinks; uplink; uplink = next)
+        {
+            next = uplink->next;
             free(uplink->bind_addr);
-           free(uplink);
-       }
+            free(uplink);
+        }
     }
 
     /* If the uplink hasn't changed, it's either NULL or pointing at
        an uplink that was just deleted, select a new one. */
     if(cManager.uplink == oldUplink)
     {
-       if(oldUplink)
-       {
-           irc_squit(self, "Uplinks updated; selecting new uplink.", NULL);
-       }
+        if(oldUplink)
+        {
+            irc_squit(self, "Uplinks updated; selecting new uplink.", NULL);
+        }
 
-       cManager.uplink = NULL;
-       uplink_select(NULL);
+        cManager.uplink = NULL;
+        uplink_select(NULL);
     }
 }
 
@@ -217,15 +220,15 @@ uplink_find(char *name)
 
     if(!cManager.enabled || !cManager.uplinks)
     {
-       return NULL;
+        return NULL;
     }
 
     for(uplink = cManager.uplinks; uplink; uplink = uplink->next)
     {
-       if(!strcasecmp(uplink->name, name))
-       {
-           return uplink;
-       }
+        if(!strcasecmp(uplink->name, name))
+        {
+            return uplink;
+        }
     }
 
     return NULL;
@@ -239,84 +242,84 @@ uplink_select(char *name)
 
     if(!cManager.enabled || !cManager.uplinks)
     {
-       log_module(MAIN_LOG, LOG_FATAL, "No uplinks enabled; giving up.");
-       exit(1);
+        log_module(MAIN_LOG, LOG_FATAL, "No uplinks enabled; giving up.");
+        exit(1);
     }
 
     if(!cManager.uplink)
     {
-       start = cManager.uplinks;
+        start = cManager.uplinks;
     }
     else
     {
-       start = cManager.uplink->next;
-       if(!start)
-       {
-           start = cManager.uplinks;
-       }
+        start = cManager.uplink->next;
+        if(!start)
+        {
+            start = cManager.uplinks;
+        }
     }
 
     stop = 0;
     for(uplink = start; uplink; uplink = next)
     {
-       next = uplink->next ? uplink->next : cManager.uplinks;
-
-       if(stop)
-       {
-           uplink = NULL;
-           break;
-       }
-
-       /* We've wrapped around the list. */
-       if(next == start)
-       {
-           sleep((cManager.cycles >> 1) * 5);
-           cManager.cycles++;
-
-           if(max_cycles && (cManager.cycles >= max_cycles))
-           {
-               log_module(MAIN_LOG, LOG_FATAL, "Maximum uplink list cycles exceeded; giving up.");
-               exit(1);
-           }
-
-           /* Give the uplink currently in 'uplink' consideration,
-              and if not selected, break on the next iteration. */
-           stop = 1;
-       }
-
-       /* Skip bad uplinks. */
-       if(uplink->flags & UPLINK_UNAVAILABLE)
-       {
-           continue;
-       }
-
-       if(name && irccasecmp(uplink->name, name))
-       {
-           /* If we were told to connect to a specific uplink, don't stop
-              until we find it.
-           */
-           continue;
-       }
-
-       /* It would be possible to track uplink health through a variety
-          of statistics and only break on the best uplink. For now, break
-          on the first available one.
-       */
-
-       break;
+        next = uplink->next ? uplink->next : cManager.uplinks;
+
+        if(stop)
+        {
+            uplink = NULL;
+            break;
+        }
+
+        /* We've wrapped around the list. */
+        if(next == start)
+        {
+            sleep((cManager.cycles >> 1) * 5);
+            cManager.cycles++;
+
+            if(max_cycles && (cManager.cycles >= max_cycles))
+            {
+                log_module(MAIN_LOG, LOG_ERROR, "Maximum uplink list cycles exceeded; giving up.");
+                exit(1);
+            }
+
+            /* Give the uplink currently in 'uplink' consideration,
+               and if not selected, break on the next iteration. */
+            stop = 1;
+        }
+
+        /* Skip bad uplinks. */
+        if(uplink->flags & UPLINK_UNAVAILABLE)
+        {
+            continue;
+        }
+
+        if(name && irccasecmp(uplink->name, name))
+        {
+            /* If we were told to connect to a specific uplink, don't stop
+               until we find it.
+            */
+            continue;
+        }
+
+        /* It would be possible to track uplink health through a variety
+           of statistics and only break on the best uplink. For now, break
+           on the first available one.
+        */
+
+        break;
     }
 
     if(!uplink)
     {
-       /* We are shit outta luck if every single uplink has been passed
-          over. Use the current uplink if possible. */
-       if(!cManager.uplink || cManager.uplink->flags & UPLINK_UNAVAILABLE)
-       {
-           log_module(MAIN_LOG, LOG_FATAL, "All available uplinks exhausted; giving up.");
-           exit(1);
-       }
+        /* We are shit outta luck if every single uplink has been passed
+           over. Use the current uplink if possible. */
+        if(!cManager.uplink || cManager.uplink->flags & UPLINK_UNAVAILABLE)
+        {
+            log_module(MAIN_LOG, LOG_ERROR, "All available uplinks exhausted; giving up.");
+            exit(1);
+        }
 
-       return;
+        return;
     }
 
     cManager.uplink = uplink;
@@ -329,36 +332,36 @@ uplink_connect(void)
 
     if(uplink->state != DISCONNECTED)
     {
-       return 0;
+        return 0;
     }
 
     if(uplink->flags & UPLINK_UNAVAILABLE)
     {
-       uplink_select(NULL);
-       uplink = cManager.uplink;
+        uplink_select(NULL);
+        uplink = cManager.uplink;
     }
 
     if(uplink->tries)
     {
-       /* This delay could scale with the number of tries. */
-       sleep(2);
+        /* This delay could scale with the number of tries. */
+        sleep(2);
     }
 
     if(!create_socket_client(uplink))
     {
-       if(uplink->max_tries && (uplink->tries >= uplink->max_tries))
-       {
-           /* This is a bad uplink, move on. */
-           uplink->flags |= UPLINK_UNAVAILABLE;
-           uplink_select(NULL);
-       }
+        if(uplink->max_tries && (uplink->tries >= uplink->max_tries))
+        {
+            /* This is a bad uplink, move on. */
+            uplink->flags |= UPLINK_UNAVAILABLE;
+            uplink_select(NULL);
+        }
 
-       return 0;
+        return 0;
     }
     else
     {
-       uplink->state = AUTHENTICATING;
-       irc_introduce(uplink->password);
+        uplink->state = AUTHENTICATING;
+        irc_introduce(uplink->password);
     }
 
     return 1;
@@ -380,13 +383,13 @@ static unsigned int ef_size = 0, ef_used = 0;
 void reg_exit_func(exit_func_t handler)
 {
     if (ef_used == ef_size) {
-       if (ef_size) {
-           ef_size <<= 1;
-           ef_list = realloc(ef_list, ef_size*sizeof(exit_func_t));
-       } else {
-           ef_size = 8;
-           ef_list = malloc(ef_size*sizeof(exit_func_t));
-       }
+        if (ef_size) {
+            ef_size <<= 1;
+            ef_list = realloc(ef_list, ef_size*sizeof(exit_func_t));
+        } else {
+            ef_size = 8;
+            ef_list = malloc(ef_size*sizeof(exit_func_t));
+        }
     }
     ef_list[ef_used++] = handler;
 }
@@ -402,7 +405,7 @@ void call_exit_funcs(void)
      */
 
     while (n > 0) {
-       ef_list[--n]();
+        ef_list[--n]();
     }
     free(ef_list);
     ef_used = ef_size = 0;
@@ -439,6 +442,11 @@ conf_globals(void)
     if (info && (info[0] == '.'))
         info = NULL;
     init_chanserv(info);
+    
+    info = conf_get_data("services/spamserv/nick", RECDB_QSTRING);
+    if (info && (info[0] == '.'))
+        info = NULL;
+    init_spamserv(info);
 
     god_policer_params = policer_params_new();
     if ((dict = conf_get_data("policers/commands-god", RECDB_OBJECT))) {
@@ -529,6 +537,51 @@ conf_rlimits(void)
 
 #endif
 
+static void
+usage(char *exe_name)
+{
+    /* We can assume we have getopt_long(). */
+    printf("Usage: %s [-c config] [-r log] [-d] [-f] [-v|-h]\n"
+           " -c, --config         selects a different configuration file.\n"
+           " -d, --debug          enables debug mode.\n"
+           " -f, --foreground     run srvx in the foreground.\n"
+           " -h, --help           prints this usage message.\n"
+           " -k, --check          checks the configuration file's syntax.\n"
+           " -r, --replay         replay a log file (for debugging).\n"
+           " -v, --version        prints this program's version.\n"
+           , exe_name);
+}
+
+static void
+version()
+{
+    printf("    --------------------------------------------------\n"
+           "    - "PACKAGE_STRING" ("CODENAME"), Built: " __DATE__ ", " __TIME__".\n"
+           "    - Copyright (C) 2000 - 2007, srvx Development Team\n"
+           "    - Version tag %s\n"
+           "    --------------------------------------------------\n",
+           git_version);
+}
+
+static void
+license()
+{
+    printf("\n"
+           "This program is free software; you can redistribute it and/or modify\n"
+           "it under the terms of the GNU General Public License as published by\n"
+           "the Free Software Foundation; either version 2 of the License, or\n"
+           "(at your option) any later version.\n"
+           "\n"
+           "This program is distributed in the hope that it will be useful,\n"
+           "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+           "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+           "GNU General Public License for more details.\n"
+           "\n"
+           "You should have received a copy of the GNU General Public License\n"
+           "along with this program; if not, write to the Free Software\n"
+           "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
+}
+
 void main_shutdown(void)
 {
     struct uplinkNode *ul, *ul_next;