Release version 997 generated by do-release.sh
[citadel.git] / citadel / server / control.c
index 4efe823fcbb8c4c22c25a92e69ddd9d656a2f991..b3df0ae3fbf97dd78beddf0302c493a67926413a 100644 (file)
@@ -1,11 +1,10 @@
 //
 // This module handles states which are global to the entire server.
 //
-// Copyright (c) 1987-2022 by the citadel.org team
+// Copyright (c) 1987-2024 by the citadel.org team
 //
 // This program is open source software.  Use, duplication, or disclosure
 // is subject to the terms of the GNU General Public License, version 3.
-// The program is distributed without any warranty, expressed or implied.
 
 #include <stdio.h>
 #include <sys/file.h>
 #include "config.h"
 #include "citserver.h"
 #include "user_ops.h"
+#include "room_ops.h"
 
 long control_highest_user = 0;
 
-/*
- * This is the legacy "control record" format for the message base.  If found
- * on disk, its contents will be migrated into the system configuration.  Never
- * change this.
- */
+// This is the legacy "control record" format for the message base.  If found
+// on disk, its contents will be migrated into the system configuration.  Never
+// change this.
 struct legacy_ctrl_format {
-       long MMhighest;                 /* highest message number in file   */
-       unsigned MMflags;               /* Global system flags              */
-       long MMnextuser;                /* highest user number on system    */
-       long MMnextroom;                /* highest room number on system    */
-       int MM_hosted_upgrade_level;    /* Server-hosted upgrade level      */
-       int MM_fulltext_wordbreaker;    /* ID of wordbreaker in use         */
-       long MMfulltext;                /* highest message number indexed   */
-       int MMdbversion;                /* Version of Berkeley DB used on previous server run */
+       long MMhighest;                 // highest message number in file
+       unsigned MMflags;               // Global system flags
+       long MMnextuser;                // highest user number on system
+       long MMnextroom;                // highest room number on system
+       int MM_hosted_upgrade_level;    // Server-hosted upgrade level
+       int MM_fulltext_wordbreaker;    // ID of wordbreaker in use
+       long MMfulltext;                // highest message number indexed
+       int MMdbversion;                // Version of Berkeley DB used on previous server run
 };
 
 
-/*
- * data that gets passed back and forth between control_find_highest() and its caller
- */
+// data that gets passed back and forth between control_find_highest() and its caller
 struct cfh {
        long highest_roomnum_found;
        long highest_msgnum_found;
 };
 
 
-/*
- * Callback to get highest room number when rebuilding message base metadata
- *
- * sanity_diag_mode (can be set by -s flag at startup) may be:
- * 0 = attempt to fix inconsistencies
- * 1 = show inconsistencies but don't repair them, exit after complete
- * 2 = show inconsistencies but don't repair them, continue execution
- */
+// Callback to get highest room number when rebuilding message base metadata
+//
+// sanity_diag_mode (can be set by -s flag at startup) may be:
+// 0 = attempt to fix inconsistencies
+// 1 = show inconsistencies but don't repair them, exit after complete
+// 2 = show inconsistencies but don't repair them, continue execution
 void control_find_highest(struct ctdlroom *qrbuf, void *data) {
        struct cfh *cfh = (struct cfh *)data;
-       struct cdbdata *cdbfr;
        long *msglist;
        int num_msgs=0;
        int c;
@@ -63,16 +56,8 @@ void control_find_highest(struct ctdlroom *qrbuf, void *data) {
                cfh->highest_roomnum_found = qrbuf->QRnumber;
        }
 
-       /* Load the message list */
-       cdbfr = cdb_fetch(CDB_MSGLISTS, &qrbuf->QRnumber, sizeof(long));
-       if (cdbfr != NULL) {
-               msglist = (long *) cdbfr->ptr;
-               num_msgs = cdbfr->len / sizeof(long);
-       }
-       else {
-               return; /* No messages at all?  No further action. */
-       }
-
+       // Load the message list
+       num_msgs = CtdlFetchMsgList(qrbuf->QRnumber, &msglist);
        if (num_msgs > 0) {
                for (c=0; c<num_msgs; c++) {
                        if (msglist[c] > cfh->highest_msgnum_found) {
@@ -80,14 +65,11 @@ void control_find_highest(struct ctdlroom *qrbuf, void *data) {
                        }
                }
        }
-
-       cdb_free(cdbfr);
+       free(msglist);
 }
 
 
-/*
- * Callback to get highest user number.
- */
+// Callback to get highest user number.
 void control_find_user(char *username, void *out_data) {
        struct ctdluser EachUser;
 
@@ -106,9 +88,7 @@ void control_find_user(char *username, void *out_data) {
 }
 
 
-/*
- * If we have a legacy format control record on disk, import it.
- */
+// If we have a legacy format control record on disk, import it.
 void migrate_legacy_control_record(void) {
        FILE *fp = NULL;
        struct legacy_ctrl_format c;
@@ -137,9 +117,7 @@ void migrate_legacy_control_record(void) {
 }
 
 
-/*
- * check_control   -  check the control record has sensible values for message, user and room numbers
- */
+// check_control   -  check the control record has sensible values for message, user and room numbers
 void check_control(void) {
 
        syslog(LOG_INFO, "control: sanity checking the recorded highest message and room numbers");
@@ -168,16 +146,13 @@ void check_control(void) {
 
        if (sanity_diag_mode == 1) {
                syslog(LOG_INFO, "control: sanity check diagnostic mode is active - exiting now");
-               abort();
+               exit(CTDLEXIT_SANITY);
        }
 }
 
 
-/*
- * get_new_message_number()  -  Obtain a new, unique ID to be used for a message.
- */
-long get_new_message_number(void)
-{
+// get_new_message_number()  -  Obtain a new, unique ID to be used for a message.
+long get_new_message_number(void) {
        long retval = 0L;
        begin_critical_section(S_CONTROL);
        retval = CtdlGetConfigLong("MMhighest");
@@ -188,25 +163,19 @@ long get_new_message_number(void)
 }
 
 
-/*
- * CtdlGetCurrentMessageNumber()  -  Obtain the current highest message number in the system
- * This provides a quick way to initialize a variable that might be used to indicate
- * messages that should not be processed.   For example, an inbox rules script will use this
- * to record determine that messages older than this should not be processed.
- *
- * (Why is this function here?  Can't we just go straight to the config variable it fetches?)
- */
-long CtdlGetCurrentMessageNumber(void)
-{
+// CtdlGetCurrentMessageNumber()  -  Obtain the current highest message number in the system
+// This provides a quick way to initialize a variable that might be used to indicate
+// messages that should not be processed.   For example, an inbox rules script will use this
+// to record determine that messages older than this should not be processed.
+//
+// (Why is this function here?  Can't we just go straight to the config variable it fetches?)
+long CtdlGetCurrentMessageNumber(void) {
        return CtdlGetConfigLong("MMhighest");
 }
 
 
-/*
- * get_new_user_number()  -  Obtain a new, unique ID to be used for a user.
- */
-long get_new_user_number(void)
-{
+// get_new_user_number()  -  Obtain a new, unique ID to be used for a user.
+long get_new_user_number(void) {
        long retval = 0L;
        begin_critical_section(S_CONTROL);
        retval = CtdlGetConfigLong("MMnextuser");
@@ -217,11 +186,8 @@ long get_new_user_number(void)
 }
 
 
-/*
- * get_new_room_number()  -  Obtain a new, unique ID to be used for a room.
- */
-long get_new_room_number(void)
-{
+// get_new_room_number()  -  Obtain a new, unique ID to be used for a room.
+long get_new_room_number(void) {
        long retval = 0L;
        begin_critical_section(S_CONTROL);
        retval = CtdlGetConfigLong("MMnextroom");
@@ -232,22 +198,16 @@ long get_new_room_number(void)
 }
 
 
-/*
- * Helper function for cmd_conf() to handle boolean values
- */
-int confbool(char *v)
-{
+// Helper function for cmd_conf() to handle boolean values
+int confbool(char *v) {
        if (IsEmptyStr(v)) return(0);
        if (atoi(v) != 0) return(1);
        return(0);
 }
 
 
-/* 
- * Get or set global configuration options
- */
-void cmd_conf(char *argbuf)
-{
+// Get or set global configuration options
+void cmd_conf(char *argbuf) {
        char cmd[16];
        char buf[1024];
        int a, i;
@@ -266,7 +226,7 @@ void cmd_conf(char *argbuf)
                cprintf("%s\n",         CtdlGetConfigStr("c_nodename"));
                cprintf("%s\n",         CtdlGetConfigStr("c_fqdn"));
                cprintf("%s\n",         CtdlGetConfigStr("c_humannode"));
-               cprintf("xxx\n"); /* placeholder -- field no longer in use */
+               cprintf("xxx\n");
                cprintf("%d\n",         CtdlGetConfigInt("c_creataide"));
                cprintf("%d\n",         CtdlGetConfigInt("c_sleeping"));
                cprintf("%d\n",         CtdlGetConfigInt("c_initax"));
@@ -278,7 +238,7 @@ void cmd_conf(char *argbuf)
                cprintf("%s\n",         CtdlGetConfigStr("c_site_location"));
                cprintf("%s\n",         CtdlGetConfigStr("c_sysadm"));
                cprintf("%d\n",         CtdlGetConfigInt("c_maxsessions"));
-               cprintf("xxx\n"); /* placeholder -- field no longer in use */
+               cprintf("xxx\n");
                cprintf("%d\n",         CtdlGetConfigInt("c_userpurge"));
                cprintf("%d\n",         CtdlGetConfigInt("c_roompurge"));
                cprintf("%s\n",         CtdlGetConfigStr("c_logpages"));
@@ -293,7 +253,7 @@ void cmd_conf(char *argbuf)
                cprintf("%d\n",         CtdlGetConfigInt("c_imap_port"));
                cprintf("%ld\n",        CtdlGetConfigLong("c_net_freq"));
                cprintf("%d\n",         CtdlGetConfigInt("c_disable_newu"));
-               cprintf("1\n"); /* niu */
+               cprintf("1\n");
                cprintf("%d\n",         CtdlGetConfigInt("c_purge_hour"));
                cprintf("%s\n",         CtdlGetConfigStr("c_ldap_host"));
                cprintf("%d\n",         CtdlGetConfigInt("c_ldap_port"));
@@ -306,7 +266,7 @@ void cmd_conf(char *argbuf)
                cprintf("%d\n",         CtdlGetConfigInt("c_pop3s_port"));
                cprintf("%d\n",         CtdlGetConfigInt("c_smtps_port"));
                cprintf("%d\n",         CtdlGetConfigInt("c_enable_fulltext"));
-               cprintf("%d\n",         CtdlGetConfigInt("c_auto_cull"));
+               cprintf("1\n");
                cprintf("1\n");
                cprintf("%d\n",         CtdlGetConfigInt("c_allow_spoofing"));
                cprintf("%d\n",         CtdlGetConfigInt("c_journal_email"));
@@ -335,6 +295,7 @@ void cmd_conf(char *argbuf)
                cprintf("%d\n",         ctdluid);
                cprintf("%d\n",         CtdlGetConfigInt("c_nntp_port"));
                cprintf("%d\n",         CtdlGetConfigInt("c_nntps_port"));
+               cprintf("%d\n",         CtdlGetConfigInt("smtp_advertise_starttls"));
                cprintf("000\n");
        }
 
@@ -356,7 +317,7 @@ void cmd_conf(char *argbuf)
                                CtdlSetConfigStr("c_humannode", buf);
                                break;
                        case 3:
-                               /* placeholder -- field no longer in use */
+                               // placeholder -- field no longer in use
                                break;
                        case 4:
                                CtdlSetConfigInt("c_creataide", confbool(buf));
@@ -397,7 +358,7 @@ void cmd_conf(char *argbuf)
                                CtdlSetConfigInt("c_maxsessions", i);
                                break;
                        case 15:
-                               /* placeholder -- field no longer in use */
+                               // placeholder -- field no longer in use
                                break;
                        case 16:
                                CtdlSetConfigInt("c_userpurge", atoi(buf));
@@ -454,7 +415,7 @@ void cmd_conf(char *argbuf)
                                CtdlSetConfigInt("c_disable_newu", confbool(buf));
                                break;
                        case 30:
-                               /* niu */
+                               // niu
                                break;
                        case 31:
                                i = atoi(buf);
@@ -496,10 +457,10 @@ void cmd_conf(char *argbuf)
                                CtdlSetConfigInt("c_enable_fulltext", confbool(buf));
                                break;
                        case 43:
-                               CtdlSetConfigInt("c_auto_cull", confbool(buf));
+                               // niu
                                break;
                        case 44:
-                               /* niu */
+                               // niu
                                break;
                        case 45:
                                CtdlSetConfigInt("c_allow_spoofing", confbool(buf));
@@ -520,31 +481,31 @@ void cmd_conf(char *argbuf)
                                CtdlSetConfigInt("c_pftcpdict_port", atoi(buf));
                                break;
                        case 51:
-                               /* niu */
+                               // niu
                                break;
                        case 52:
                                CtdlSetConfigInt("c_auth_mode", atoi(buf));
                                break;
                        case 53:
-                               /* niu */
+                               // niu
                                break;
                        case 54:
-                               /* niu */
+                               // niu
                                break;
                        case 55:
-                               /* niu */
+                               // niu
                                break;
                        case 56:
-                               /* niu */
+                               // niu
                                break;
                        case 57:
                                CtdlSetConfigInt("c_rbl_at_greeting", confbool(buf));
                                break;
                        case 58:
-                               /* niu */
+                               // niu
                                break;
                        case 59:
-                               /* niu */
+                               // niu
                                break;
                        case 60:
                                CtdlSetConfigStr("c_pager_program", buf);
@@ -574,7 +535,7 @@ void cmd_conf(char *argbuf)
                                CtdlSetConfigInt("c_port_number", atoi(buf));
                                break;
                        case 69:
-                               /* niu */
+                               // niu
                                break;
                        case 70:
                                CtdlSetConfigInt("c_nntp_port", atoi(buf));
@@ -582,6 +543,9 @@ void cmd_conf(char *argbuf)
                        case 71:
                                CtdlSetConfigInt("c_nntps_port", atoi(buf));
                                break;
+                       case 72:
+                               CtdlSetConfigInt("smtp_advertise_starttls", atoi(buf));
+                               break;
                        }
                        ++a;
                }
@@ -594,9 +558,7 @@ void cmd_conf(char *argbuf)
                if (!IsEmptyStr(CtdlGetConfigStr("c_logpages")))
                        CtdlCreateRoom(CtdlGetConfigStr("c_logpages"), 3, "", 0, 1, 1, VIEW_BBS);
 
-               /* If full text indexing has been disabled, invalidate the
-                * index so it doesn't try to use it later.
-                */
+               // If full text indexing has been disabled, invalidate the index so it doesn't try to use it later.
                if (CtdlGetConfigInt("c_enable_fulltext") == 0) {
                        CtdlSetConfigInt("MM_fulltext_wordbreaker", 0);
                }
@@ -612,13 +574,14 @@ void cmd_conf(char *argbuf)
                        len = strlen(confptr);
                        cprintf("%d %s\n", LISTING_FOLLOWS, confname);
                        client_write(confptr, len);
-                       if ((len > 0) && (confptr[len - 1] != 10))
+                       if ((len > 0) && (confptr[len - 1] != 10)) {
                                client_write("\n", 1);
+                       }
                        cprintf("000\n");
                        free(confptr);
-               } else {
-                       cprintf("%d No such configuration.\n",
-                               ERROR + ILLEGAL_VALUE);
+               }
+               else {
+                       cprintf("%d No such configuration.\n", ERROR + ILLEGAL_VALUE);
                }
        }
 
@@ -681,21 +644,20 @@ void cmd_conf(char *argbuf)
 
        // CONF LISTVAL - list configuration variables in the database and their values
        else if (!strcasecmp(cmd, "LISTVAL")) {
-               struct cdbdata *cdbcfg;
+               struct cdbkeyval cdbcfg;
                int keylen = 0;
                char *key = NULL;
                char *value = NULL;
        
                cprintf("%d all configuration variables\n", LISTING_FOLLOWS);
                cdb_rewind(CDB_CONFIG);
-               while (cdbcfg = cdb_next_item(CDB_CONFIG), cdbcfg != NULL) {
-                       if (cdbcfg->len < 1020) {
-                               keylen = strlen(cdbcfg->ptr);
-                               key = cdbcfg->ptr;
-                               value = cdbcfg->ptr + keylen + 1;
+               while (cdbcfg = cdb_next_item(CDB_CONFIG), cdbcfg.val.ptr!=NULL) {      // MUST read to the end
+                       if (cdbcfg.val.len < 1020) {
+                               keylen = strlen(cdbcfg.val.ptr);
+                               key = cdbcfg.val.ptr;
+                               value = cdbcfg.val.ptr + keylen + 1;
                                cprintf("%s|%s\n", key, value);
                        }
-                       cdb_free(cdbcfg);
                }
                cprintf("000\n");
        }
@@ -709,7 +671,7 @@ void cmd_conf(char *argbuf)
 typedef struct __ConfType {
        ConstStr Name;
        long Type;
-}ConfType;
+} ConfType;
 
 ConfType CfgNames[] = {
        { {HKEY("localhost") },    0},
@@ -725,8 +687,7 @@ ConfType CfgNames[] = {
 };
 
 HashList *CfgNameHash = NULL;
-void cmd_gvdn(char *argbuf)
-{
+void cmd_gvdn(char *argbuf) {
        const ConfType *pCfg;
        char *confptr;
        long min = atol(argbuf);
@@ -753,19 +714,15 @@ void cmd_gvdn(char *argbuf)
 
        Line = NewStrBufPlain(NULL, StrLength(Config));
        CfgToken = NewStrBufPlain(NULL, StrLength(Config));
-       while (StrBufSipLine(Line, Config, &Pos))
-       {
+       while (StrBufSipLine(Line, Config, &Pos)) {
                if (Cfg == NULL)
                        Cfg = NewStrBufPlain(NULL, StrLength(Line));
                PPos = NULL;
                StrBufExtract_NextToken(Cfg, Line, &PPos, '|');
                StrBufExtract_NextToken(CfgToken, Line, &PPos, '|');
-               if (GetHash(CfgNameHash, SKEY(CfgToken), &vptr) &&
-                   (vptr != NULL))
-               {
+               if (GetHash(CfgNameHash, SKEY(CfgToken), &vptr) && (vptr != NULL)) {
                        pCfg = (ConfType *) vptr;
-                       if (pCfg->Type <= min)
-                       {
+                       if (pCfg->Type <= min) {
                                Put(List, SKEY(Cfg), Cfg, HFreeStrBuf);
                                Cfg = NULL;
                        }
@@ -774,8 +731,7 @@ void cmd_gvdn(char *argbuf)
 
        cprintf("%d Valid Domains\n", LISTING_FOLLOWS);
        It = GetNewHashPos(List, 1);
-       while (GetNextHashPos(List, It, &HKLen, &HKey, &vptr))
-       {
+       while (GetNextHashPos(List, It, &HKLen, &HKey, &vptr)) {
                cputbuf(vptr);
                cprintf("\n");
        }
@@ -789,21 +745,20 @@ void cmd_gvdn(char *argbuf)
        FreeStrBuf(&Config);
 }
 
-/*****************************************************************************/
-/*                      MODULE INITIALIZATION STUFF                          */
-/*****************************************************************************/
 
+// MODULE INITIALIZATION STUFF
 char *ctdl_module_init_control(void) {
        if (!threading) {
                int i;
 
                CfgNameHash = NewHash(1, NULL);
-               for (i = 0; CfgNames[i].Name.Key != NULL; i++)
+               for (i = 0; CfgNames[i].Name.Key != NULL; i++) {
                        Put(CfgNameHash, CKEY(CfgNames[i].Name), &CfgNames[i], reference_free_handler);
+               }
 
                CtdlRegisterProtoHook(cmd_gvdn, "GVDN", "get valid domain names");
                CtdlRegisterProtoHook(cmd_conf, "CONF", "get/set system configuration");
        }
-       /* return our id for the log */
+       // return our id for the log
        return "control";
 }