libical, expat, and libsieve are now *required*.
[citadel.git] / citadel / citserver.c
index 966bbbe8dedc10bbdd865067689295e618ef3911..6dba619936c800ab85004676a4f547c02d10d46d 100644 (file)
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <libcitadel.h>
 #include "citadel.h"
 #include "server.h"
 #include "sysdep_decls.h"
+#include "threads.h"
 #include "citserver.h"
 #include "config.h"
 #include "database.h"
 #include "file_ops.h"
 #include "policy.h"
 #include "control.h"
-#include "tools.h"
 #include "euidindex.h"
 
 #ifndef HAVE_SNPRINTF
 #include "snprintf.h"
 #endif
 
+#include "ctdl_module.h"
+
+
 struct CitContext *ContextList = NULL;
 struct CitContext* next_session = NULL;
 char *unique_session_numbers;
 int ScheduledShutdown = 0;
-int do_defrag = 0;
 time_t server_startup_time;
 int panic_fd;
 
@@ -132,10 +135,10 @@ void master_startup(void) {
        lprintf(CTDL_INFO, "Opening databases\n");
        open_databases();
 
-       if (do_defrag) {
-               defrag_databases();
-       }
-
+       ctdl_thread_internal_init_tsd();
+       
+       CtdlThreadAllocTSD();
+       
        check_ref_counts();
 
        lprintf(CTDL_INFO, "Creating base rooms (if necessary)\n");
@@ -150,6 +153,12 @@ void master_startup(void) {
                 lputroom(&qrbuf);
         }
 
+       /* Aide needs to be public postable, else we're not RFC conformant. */
+        if (lgetroom(&qrbuf, AIDEROOM) == 0) {
+                qrbuf.QRflags2 |= QR2_SMTP_PUBLIC;
+                lputroom(&qrbuf);
+        }
+
        lprintf(CTDL_INFO, "Seeding the pseudo-random number generator...\n");
        urandom = fopen("/dev/urandom", "r");
        if (urandom != NULL) {
@@ -176,7 +185,6 @@ void master_startup(void) {
  */
 void master_cleanup(int exitcode) {
        struct CleanupFunctionHook *fcn;
-       struct MaintenanceThreadHook *m_fcn;
        static int already_cleaning_up = 0;
 
        if (already_cleaning_up) while(1) sleep(1);
@@ -190,19 +198,13 @@ void master_cleanup(int exitcode) {
        /* Close the AdjRefCount queue file */
        AdjRefCount(-1, 0);
 
-       for (m_fcn = MaintenanceThreadHookTable; m_fcn != NULL; m_fcn = m_fcn->next) {
-               lprintf(CTDL_INFO, "Waiting for maintenance thread \"%s\" to shut down\n", m_fcn->name);
-               pthread_join(m_fcn->MaintenanceThread_tid, NULL);
-       }
+       /* Do system-dependent stuff */
+       sysdep_master_cleanup();
        
-
        /* Close databases */
        lprintf(CTDL_INFO, "Closing databases\n");
        close_databases();
 
-       /* Do system-dependent stuff */
-       sysdep_master_cleanup();
-       
 #ifdef DEBUG_MEMORY_LEAKS
        dump_heap();
 #endif
@@ -292,15 +294,23 @@ void cmd_info(void) {
        cprintf("0\n"); /* 1 = no, this server is not LDAP-enabled */
 #endif
 
-       if (config.c_auth_mode == 1) {
-               cprintf("1\n"); /* "create new user" never works with host auth */
+       if (config.c_auth_mode == AUTHMODE_NATIVE) {
+               cprintf("%d\n", config.c_disable_newu);
        }
        else {
-               cprintf("%d\n", config.c_disable_newu); /* otherwise, site defined */
+               cprintf("1\n"); /* "create new user" does not work with non-native auth modes */
        }
 
        cprintf("%s\n", config.c_default_cal_zone);
 
+       /* Output load averages */
+       cprintf("%f\n", CtdlThreadLoadAvg);
+       cprintf("%f\n", CtdlThreadWorkerAvg);
+       cprintf("%d\n", CtdlThreadGetCount());
+
+       cprintf("1\n");         /* yes, Sieve mail filtering is supported */
+       cprintf("%d\n", config.c_enable_fulltext);
+       
        cprintf("000\n");
 }
 
@@ -347,11 +357,16 @@ int is_public_client(void)
        char addrbuf[1024];
        FILE *fp;
        int i;
+       char *public_clientspos;
+       char *public_clientsend;
+       char *paddr = NULL;
        struct stat statbuf;
        static time_t pc_timestamp = 0;
        static char public_clients[SIZ];
        static char public_clients_file[SIZ];
 
+#define LOCALHOSTSTR "127.0.0.1"
+
        snprintf(public_clients_file, 
                         sizeof public_clients_file,
                         "%s/public_clients",
@@ -374,36 +389,45 @@ int is_public_client(void)
                begin_critical_section(S_PUBLIC_CLIENTS);
                lprintf(CTDL_INFO, "Loading %s\n", public_clients_file);
 
-               safestrncpy(public_clients, "127.0.0.1", sizeof public_clients);
+               public_clientspos = &public_clients[0];
+               public_clientsend = public_clientspos + SIZ;
+               safestrncpy(public_clientspos, LOCALHOSTSTR, sizeof public_clients);
+               public_clientspos += sizeof(LOCALHOSTSTR) - 1;
+               
                if (hostname_to_dotted_quad(addrbuf, config.c_fqdn) == 0) {
-                       strcat(public_clients, "|");
-                       strcat(public_clients, addrbuf);
+                       *(public_clientspos++) = '|';
+                       paddr = &addrbuf[0];
+                       while (!IsEmptyStr (paddr) && 
+                              (public_clientspos < public_clientsend))
+                               *(public_clientspos++) = *(paddr++);
                }
 
                fp = fopen(public_clients_file, "r");
-               if (fp != NULL) while (fgets(buf, sizeof buf, fp)!=NULL) {
-                       char *ptr;
-                       ptr = buf;
-                       while (!IsEmptyStr(ptr)) {
-                               if (*ptr == '#') {
-                                       *ptr = 0;
-                                       break;
-                               }
+               if (fp != NULL) 
+                       while ((fgets(buf, sizeof buf, fp)!=NULL) &&
+                              (public_clientspos < public_clientsend)){
+                               char *ptr;
+                               ptr = buf;
+                               while (!IsEmptyStr(ptr)) {
+                                       if (*ptr == '#') {
+                                               *ptr = 0;
+                                               break;
+                                       }
                                else ptr++;
-                       }
-                       ptr--;
-                       while (ptr>buf && isspace(*ptr)) {
-                               *(ptr--) = 0;
-                       }
-                       if (hostname_to_dotted_quad(addrbuf, buf) == 0) {
-                               if ((strlen(public_clients) +
-                                  strlen(addrbuf) + 2)
-                                  < sizeof(public_clients)) {
-                                       strcat(public_clients, "|");
-                                       strcat(public_clients, addrbuf);
+                               }
+                               ptr--;
+                               while (ptr>buf && isspace(*ptr)) {
+                                       *(ptr--) = 0;
+                               }
+                               if (hostname_to_dotted_quad(addrbuf, buf) == 0) {
+                                       *(public_clientspos++) = '|';
+                                       paddr = addrbuf;
+                                       while (!IsEmptyStr(paddr) && 
+                                              (public_clientspos < public_clientsend)){
+                                               *(public_clientspos++) = *(paddr++);
+                                       }
                                }
                        }
-               }
                fclose(fp);
                pc_timestamp = time(NULL);
                end_critical_section(S_PUBLIC_CLIENTS);
@@ -643,9 +667,9 @@ void GenerateRoomDisplay(char *real_room,
        }
 
        if (viewed->cs_flags & CS_CHAT) {
-               while (strlen(real_room) < 14)
+               while (strlen(real_room) < 14) {
                        strcat(real_room, " ");
-
+               }
                strcpy(&real_room[14], "<chat>");
        }
 
@@ -826,7 +850,7 @@ void cmd_down(char *argbuf) {
        {
                cprintf(Reply, CIT_OK + SERVER_SHUTTING_DOWN);
        }
-       time_to_die = 1;
+       CtdlThreadStopAll();
 }
 
 /*
@@ -837,7 +861,7 @@ void cmd_halt(void) {
        if (CtdlAccessCheck(ac_aide)) return;
 
        cprintf("%d Halting server.  Goodbye.\n", CIT_OK);
-       time_to_die = 1;
+       CtdlThreadStopAll();
        shutdown_and_halt = 1;
 }
 
@@ -957,7 +981,12 @@ void begin_session(struct CitContext *con)
                con->nologin = 1;
        }
 
-       lprintf(CTDL_NOTICE, "Session started.\n");
+       if (!CC->is_local_socket) {
+               lprintf(CTDL_NOTICE, "Session started from %s [%s].\n", con->cs_host, con->cs_addr);
+       }
+       else {
+               lprintf(CTDL_NOTICE, "Session started via local socket.\n");
+       }
 
        /* Run any session startup routines registered by loadable modules */
        PerformSessionHooks(EVT_START);
@@ -986,12 +1015,16 @@ void citproto_begin_session() {
  */
 void do_command_loop(void) {
        char cmdbuf[SIZ];
-
+       const char *old_name = NULL;
+       
+       old_name = CtdlThreadName("do_command_loop");
+       
        time(&CC->lastcmd);
        memset(cmdbuf, 0, sizeof cmdbuf); /* Clear it, just in case */
        if (client_getln(cmdbuf, sizeof cmdbuf) < 1) {
                lprintf(CTDL_ERR, "Client disconnected: ending session.\n");
                CC->kill_me = 1;
+               CtdlThreadName(old_name);
                return;
        }
 
@@ -1020,6 +1053,8 @@ void do_command_loop(void) {
                safestrncpy(CC->lastcmdname, cmdbuf, sizeof(CC->lastcmdname));
                time(&CC->lastidle);
        }
+       
+       CtdlThreadName(cmdbuf);
                
        if ((strncasecmp(cmdbuf, "ENT0", 4))
           && (strncasecmp(cmdbuf, "MESG", 4))
@@ -1032,6 +1067,10 @@ void do_command_loop(void) {
                cprintf("%d%cok\n", CIT_OK, CtdlCheckExpress() );
        }
        
+       else if (!strncasecmp(cmdbuf, "XYZZY", 5)) {
+               cprintf("%d Nothing happens.\n", CIT_OK);
+       }
+       
        else if (!strncasecmp(cmdbuf, "QNOP", 4)) {
                /* do nothing, this command returns no response */
        }
@@ -1382,15 +1421,19 @@ void do_command_loop(void) {
                cmd_isme(&cmdbuf[5]);
        }
 
+       else if (!strncasecmp(cmdbuf, "RENU", 4)) {
+               cmd_renu(&cmdbuf[5]);
+       }
+
        else if (!DLoader_Exec_Cmd(cmdbuf)) {
-               cprintf("%d Unrecognized or unsupported command.\n",
-                       ERROR + CMD_NOT_SUPPORTED);
-              }
+               cprintf("%d Unrecognized or unsupported command.\n", ERROR + CMD_NOT_SUPPORTED);
+       }
 
        unbuffer_output();
 
        /* Run any after-each-command routines registered by modules */
        PerformSessionHooks(EVT_CMD);
+       CtdlThreadName(old_name);
 }