fixed path of mysql/errmsg.h (OSX compilation fix)
[NeonServV5.git] / src / main.c
index 0ca3d31ea190c1be70efb3f6eded83e96dfa43d9..5ab1efd0bd5f93ccce05657783bcdda7f8722484 100644 (file)
@@ -1,4 +1,4 @@
-/* main.c - NeonServ v5.3
+/* main.c - NeonServ v5.6
  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
  * 
  * This program is free software: you can redistribute it and/or modify
 #include "ModeNode.h"
 #include "IRCQueue.h"
 #include "DBHelper.h"
-#include "commands.h"
 #include "ConfigParser.h"
-#include "ssl.h"
 #include "QServer.h"
 #include "version.h"
+#include "modules.h"
+#include "module_commands.h"
+#include "ModuleFunctions.h"
+#include "IOHandler.h"
 
 time_t start_time;
 static int running, hard_restart;
@@ -106,28 +108,23 @@ static int load_mysql_config() {
     return 1;
 }
 
-#ifdef HAVE_THREADS
-pthread_t *current_threads = NULL;
+static TIMEQ_CALLBACK(clear_cache) {
+    timeq_add(CLEAR_CACHE_INTERVAL, 0, clear_cache, NULL);
+    clearTempUsers();
+    destroyEvents();
+    mysql_free();
+}
 
-void * thread_main(void *arg) {
-    time_t socket_wait;
+void *thread_main(void *arg) {
     while(running) {
-        socket_wait = time(0) + SOCKET_SELECT_TIME;
-        do {
-            if(!socket_loop(SOCKET_SELECT_TIME)) {
-                putlog(LOGLEVEL_ERROR, "No more active Bots... shutting down.");
-                cleanup();
-                exit(0);
-            }
-        } while(time(0) < socket_wait);
-        clearTempUsers();
-        destroyEvents();
-        mysql_free();
+        iohandler_poll();
     }
-    running_threads--;
     return NULL;
 }
 
+#ifdef HAVE_THREADS
+pthread_t *current_threads = NULL;
+
 int getCurrentThreadID() {
     if(!current_threads) return 0;
     int i;
@@ -146,6 +143,7 @@ int getCurrentThreadID() {
 #endif
 
 void exit_daemon() {
+    running = 0;
     if(daemonized) {
         remove(PID_FILE);
     }
@@ -191,14 +189,21 @@ int main(int argc, char *argv[]) {
             break;
         }
     }
+    #ifndef WIN32
     if(geteuid() == 0 || getuid() == 0) {
         fprintf(stderr, "NeonServ may not be run with super user privileges.\n");
         exit(0);
     }
+    #endif
+    #ifdef ENABLE_MEMORY_DEBUG
+    initMemoryDebug();
+    #endif
     if(!loadConfig(CONF_FILE)) {
         fprintf(stderr, "Unable to load " CONF_FILE "\n");
         exit(0);
     }
+    init_bind();
+    event_reload(1);
     #if HAVE_THREADS
     THREAD_MUTEX_INIT(log_sync);
     #endif
@@ -207,6 +212,12 @@ int main(int argc, char *argv[]) {
         exit(0);
     }
     check_firstrun();
+    char **modulelist = get_all_fieldnames("modules");
+    if(!modulelist || !modulelist[0]) {
+        fprintf(stderr, "no modules loaded... Please update your configuration!\n");
+        exit(0);
+    }
+    free(modulelist);
     if (run_as_daemon) {
         #ifndef WIN32
         /* Attempt to fork into the background if daemon mode is on. */
@@ -223,15 +234,16 @@ int main(int argc, char *argv[]) {
         atexit(exit_daemon);
         FILE *pidfile = fopen(PID_FILE, "w");
         if (pidfile == NULL) {
-            fprintf(stderr, "Unable to create PID file: %s", strerror(errno));
-            putlog(LOGLEVEL_ERROR, "Unable to create PID file: %s", strerror(errno));
+            fprintf(stderr, "Unable to create PID file: %s\n", strerror(errno));
+            putlog(LOGLEVEL_ERROR, "Unable to create PID file: %s\n", strerror(errno));
         } else {
             fprintf(pidfile, "%i\n", (int)getpid());
             fclose(pidfile);
         }
-        fclose(stdin); fopen("/dev/null", "r");
-        fclose(stdout); fopen("/dev/null", "w");
-        fclose(stderr); fopen("/dev/null", "w");
+               FILE *retn;
+        fclose(stdin); retn = fopen("/dev/null", "r");
+        fclose(stdout); retn = fopen("/dev/null", "w");
+        fclose(stderr); retn = fopen("/dev/null", "w");
         #endif
     }
     
@@ -243,24 +255,8 @@ main:
     signal(SIGSEGV, sighandler);
     signal(SIGTERM, sighandler);
     
-    #ifdef ENABLE_MEMORY_DEBUG
-    initMemoryDebug();
-    #endif
-    
     start_time = time(0);
     
-    #ifdef WIN32
-    int res;
-    WSADATA wsadata;
-    // Start Windows Sockets.
-    res = WSAStartup(MAKEWORD(2, 0), &wsadata);
-    if (res)
-    {
-        perror("Unable to start Windows Sockets");
-        return 0;
-    }
-    #endif
-    
     statistics_enabled = get_int_field("statistics.enable");
     
     #ifdef HAVE_THREADS
@@ -269,20 +265,18 @@ main:
     THREAD_MUTEX_INIT(whohandler_mass_sync);
     #endif
     
-    queue_init();
-    init_sockets();
-    init_timeq();
     init_lang();
-    ssl_init();
     init_parser();
     init_UserNode();
     init_ChanNode();
     init_ModeNode();
     init_bind();
        init_modcmd();
+    register_module_commands();
     init_handleinfohandler();
     init_tools();
-    
+    init_modulefunctions();
+    loadModules();
     init_bots();
     init_DBHelper();
     qserver_init();
@@ -294,6 +288,8 @@ main:
     
     timeq_add(90, 0, main_checkauths, NULL);
     
+    timeq_add(CLEAR_CACHE_INTERVAL, 0, clear_cache, NULL);
+    
     int worker_threads = get_int_field("General.worker_threads");
     if(!worker_threads) worker_threads = 1;
     running = 1;
@@ -304,38 +300,13 @@ main:
         running_threads++;
         pthread_create(&current_threads[tid_id], NULL, thread_main, NULL);
     }
-    int usleep_delay = 1000000 / TICKS_PER_SECOND;
-    while(running) {
-        timeq_tick();
-        loop_modules();
-        qserver_loop();
-        queue_loop();
-        mysql_free();
-        usleep(usleep_delay);
-    }
+    #endif
+    thread_main(NULL);
+    #ifdef HAVE_THREADS
     for(tid_id = 0; tid_id < worker_threads; tid_id++) {
         pthread_join(current_threads[tid_id], NULL);
     }
     running_threads = 0;
-    #else
-    time_t socket_wait;
-    while(running) {
-        socket_wait = time(0) + SOCKET_SELECT_TIME;
-        do {
-            if(!socket_loop(SOCKET_SELECT_TIME)) {
-                putlog(LOGLEVEL_ERROR, "No more active Bots... shutting down.");
-                cleanup();
-                exit(0);
-            }
-        } while(time(0) < socket_wait);
-        timeq_tick();
-        loop_modules();
-        clearTempUsers();
-        destroyEvents();
-        qserver_loop();
-        queue_loop();
-        mysql_free();
-    }
     #endif
     cleanup();
     if(hard_restart) {
@@ -397,6 +368,7 @@ void stop_bot() {
 
 void reload_config() {
     loadConfig(CONF_FILE);
+    event_reload(0);
 }
 
 static int getCurrentSecondsOfDay() {
@@ -416,15 +388,24 @@ static AUTHLOOKUP_CALLBACK(main_checkauths_callback) {
     printf_mysql_query("SELECT `user_id`, `user_registered` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
     res = mysql_use();
     if ((row = mysql_fetch_row(res)) != NULL) {
-        if(!exists || (strcmp(row[1], "0") && registered != atoi(row[1]))) {
+        int diff = registered - atoi(row[1]);
+        if(diff < 0)
+            diff *= -1;
+        if(!exists || (strcmp(row[1], "0") && diff > 86400)) {
             //User is no longer valid! Delete it...
             deleteUser(atoi(row[0]));
             char *alertchan = get_string_field("General.CheckAuths.alertchan");
             if(alertchan) {
+                char reason[MAXLEN];
+                if(!exists) {
+                    strcpy(reason, "USER_NOT_EXISTS");
+                } else {
+                    sprintf(reason, "USER_REGISTERED_MISSMATCH: %lu, expected %d (diff: %d)", (unsigned long) registered, atoi(row[1]), diff);
+                }
                 struct ChanNode *alertchan_chan = getChanByName(alertchan);
                 struct ClientSocket *alertclient;
                 if(alertchan_chan && (alertclient = getChannelBot(alertchan_chan, 0)) != NULL) {
-                    putsock(alertclient, "PRIVMSG %s :Deleted User %s", alertchan_chan->name, auth);
+                    putsock(alertclient, "PRIVMSG %s :Deleted User %s (%s)", alertchan_chan->name, auth, reason);
                 }
             }
         } else if(exists && !strcmp(row[1], "0")) {
@@ -457,7 +438,7 @@ TIMEQ_CALLBACK(main_checkauths) {
             if ((row = mysql_fetch_row(res)) != NULL) {
                 lastcheck = atoi(row[1]);
                 if(!lastcheck || unixtime - lastcheck >= min_unckecked) {
-                    lookup_authname(row[0], main_checkauths_callback, NULL);
+                    lookup_authname(row[0], 0, main_checkauths_callback, NULL);
                 } else 
                     next_call = 300;
             }
@@ -498,7 +479,7 @@ TIMEQ_CALLBACK(main_statistics) {
         statistics_enabled = 0;
 }
 
-void statistics_update() {
+int statistics_update() {
     if(get_int_field("statistics.enable") && statistics_requested_lusers && get_string_field("statistics.execute")) {
         statistics_requested_lusers = 0;
         char command[MAXLEN];
@@ -514,8 +495,9 @@ void statistics_update() {
         sprintf(command, "%s %d %d %d %d %d %d %d", get_string_field("statistics.execute"), getUserCount(), getChanUserCount(), getChannelCount(), statistics_privmsg, statistics_commands, statistics_network_users, statistics_network_channels);
         statistics_privmsg = 0;
         statistics_commands = 0;
-        system(command);
+        return system(command);
     }
+       return -1;
 }
 
 time_t getStartTime() {
@@ -523,7 +505,11 @@ time_t getStartTime() {
 }
 
 int getRunningThreads() {
+       #ifdef HAVE_THREADS
     return running_threads;
+       #else
+       return 1;
+       #endif
 }
 
 void write_log(int loglevel, const char *line, int len) {
@@ -576,7 +562,7 @@ static void check_firstrun() {
         printf("AuthServ account name of admin user: ");
         char *ptr;
         char adminuser[31];
-        fgets(adminuser, 30, stdin);
+        ptr = fgets(adminuser, 30, stdin);
         for(ptr = adminuser; *ptr; ptr++) { if(*ptr == '\n' || *ptr == '\r') *ptr = '\0'; }
         if(strlen(adminuser) < 2) goto check_firstrun_admin;
         printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(adminuser));
@@ -596,25 +582,25 @@ static void check_firstrun() {
         char bot_nick[31];
         check_firstrun_bot_nick:
         printf("Nick: ");
-        fgets(bot_nick, 30, stdin);
+        ptr = fgets(bot_nick, 30, stdin);
         for(ptr = bot_nick; *ptr; ptr++) { if(*ptr == '\n' || *ptr == '\r') *ptr = '\0'; }
         if(strlen(bot_nick) < 2) goto check_firstrun_bot_nick;
         char bot_ident[16];
         check_firstrun_bot_ident:
         printf("Ident: ");
-        fgets(bot_ident, 15, stdin);
+        ptr = fgets(bot_ident, 15, stdin);
         for(ptr = bot_ident; *ptr; ptr++) { if(*ptr == '\n' || *ptr == '\r') *ptr = '\0'; }
         if(strlen(bot_ident) < 2) goto check_firstrun_bot_ident;
         char bot_realname[101];
         check_firstrun_bot_realname:
         printf("Realname: ");
-        fgets(bot_realname, 100, stdin);
+        ptr = fgets(bot_realname, 100, stdin);
         for(ptr = bot_realname; *ptr; ptr++) { if(*ptr == '\n' || *ptr == '\r') *ptr = '\0'; }
         if(strlen(bot_realname) < 2) goto check_firstrun_bot_realname;
         char bot_server[101];
         check_firstrun_bot_server:
         printf("Server: [irc.onlinegamesnet.net] ");
-        fgets(bot_server, 100, stdin);
+        ptr = fgets(bot_server, 100, stdin);
         for(ptr = bot_server; *ptr; ptr++) { if(*ptr == '\n' || *ptr == '\r') *ptr = '\0'; }
         if(*bot_server && strlen(bot_nick) < 5) goto check_firstrun_bot_server;
         if(!*bot_server)
@@ -622,7 +608,7 @@ static void check_firstrun() {
         int bot_port;
         char bot_port_buf[7];
         printf("Port: [6667] ");
-        fgets(bot_port_buf, 6, stdin);
+        ptr = fgets(bot_port_buf, 6, stdin);
         for(ptr = bot_port_buf; *ptr; ptr++) { if(*ptr == '\n' || *ptr == '\r') *ptr = '\0'; }
         if(!*bot_port_buf)
             bot_port = 6667;
@@ -632,7 +618,7 @@ static void check_firstrun() {
         char bot_ssl_buf[5];
         check_firstrun_bot_ssl:
         printf("SSL: [y/N] ");
-        fgets(bot_ssl_buf, 4, stdin);
+        ptr = fgets(bot_ssl_buf, 4, stdin);
         for(ptr = bot_ssl_buf; *ptr; ptr++) { if(*ptr == '\n' || *ptr == '\r') *ptr = '\0'; }
         if(!*bot_ssl_buf || tolower(*bot_ssl_buf) == 'n')
             bot_ssl = 0;
@@ -642,12 +628,12 @@ static void check_firstrun() {
             goto check_firstrun_bot_ssl;
         char bot_pass[101];
         printf("Server Password: [] ");
-        fgets(bot_pass, 100, stdin);
+        ptr = fgets(bot_pass, 100, stdin);
         for(ptr = bot_pass; *ptr; ptr++) { if(*ptr == '\n' || *ptr == '\r') *ptr = '\0'; }
         int bot_maxchan;
         char bot_maxchan_buf[5];
         printf("MaxChannel: [20] ");
-        fgets(bot_maxchan_buf, 5, stdin);
+        ptr = fgets(bot_maxchan_buf, 5, stdin);
         for(ptr = bot_maxchan_buf; *ptr; ptr++) { if(*ptr == '\n' || *ptr == '\r') *ptr = '\0'; }
         if(*bot_maxchan_buf)
             bot_maxchan = atoi(bot_maxchan_buf);
@@ -657,7 +643,7 @@ static void check_firstrun() {
         char bot_queue_buf[5];
         check_firstrun_bot_queue:
         printf("Queue (prevents excess floods): [Y/n] ");
-        fgets(bot_queue_buf, 4, stdin);
+        ptr = fgets(bot_queue_buf, 4, stdin);
         for(ptr = bot_queue_buf; *ptr; ptr++) { if(*ptr == '\n' || *ptr == '\r') *ptr = '\0'; }
         if(!*bot_queue_buf || tolower(*bot_queue_buf) == 'y')
             bot_queue = 1;