X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fcontrol.c;h=24b643229edca506347d1dbbebf9c9a0e28b8794;hb=9af50cb0641f0168c770554af3f446e35fc1008c;hp=01f3d5fc85d80397b22d826a26f198a0ac351c89;hpb=1ce87e9f74acae1f6c294bc19189542b859a466b;p=citadel.git diff --git a/citadel/control.c b/citadel/control.c index 01f3d5fc8..24b643229 100644 --- a/citadel/control.c +++ b/citadel/control.c @@ -21,25 +21,23 @@ #include "citserver.h" #include "user_ops.h" -struct CitControl CitControl; -FILE *control_fp = NULL; long control_highest_user = 0; - /* - * lock_control - acquire a lock on the control record file. - * This keeps multiple citservers from running concurrently. + * This is the control record for the message base... */ -void lock_control(void) -{ -#if defined(LOCK_EX) && defined(LOCK_NB) - if (flock(fileno(control_fp), (LOCK_EX | LOCK_NB))) { - syslog(LOG_EMERG, "citserver: unable to lock %s.\n", file_citadel_control); - syslog(LOG_EMERG, "Is another citserver already running?\n"); - exit(CTDLEXIT_CONTROL); - } -#endif -} +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 */ +}; + + /* * callback to get highest room number when rebuilding control file @@ -54,9 +52,9 @@ void control_find_highest(struct ctdlroom *qrbuf, void *data) int room_fixed = 0; int message_fixed = 0; - if (qrbuf->QRnumber > CitControl.MMnextroom) + if (qrbuf->QRnumber > CtdlGetConfigLong("MMnextroom")) { - CitControl.MMnextroom = qrbuf->QRnumber; + CtdlSetConfigLong("MMnextroom", qrbuf->QRnumber); room_fixed = 1; } @@ -75,18 +73,20 @@ void control_find_highest(struct ctdlroom *qrbuf, void *data) { for (c=0; c CitControl.MMhighest) + if (msglist[c] > CtdlGetConfigLong("MMhighest")) { - CitControl.MMhighest = msglist[c]; + CtdlSetConfigLong("MMhighest", msglist[c]); message_fixed = 1; } } } cdb_free(cdbfr); - if (room_fixed) + if (room_fixed) { syslog(LOG_INFO, "Control record checking....Fixed room counter\n"); - if (message_fixed) + } + if (message_fixed) { syslog(LOG_INFO, "Control record checking....Fixed message count\n"); + } return; } @@ -99,9 +99,9 @@ void control_find_user (struct ctdluser *EachUser, void *out_data) { int user_fixed = 0; - if (EachUser->usernum > CitControl.MMnextuser) + if (EachUser->usernum > CtdlGetConfigLong("MMnextuser")) { - CitControl.MMnextuser = EachUser->usernum; + CtdlSetConfigLong("MMnextuser", EachUser->usernum); user_fixed = 1; } if(user_fixed) @@ -110,92 +110,34 @@ void control_find_user (struct ctdluser *EachUser, void *out_data) /* - * get_control - read the control record into memory. + * If we have a legacy format control record on disk, import it. */ -void get_control(void) +void migrate_legacy_control_record(void) { - static int already_have_control = 0; - int rv = 0; - - /* - * If we already have the control record in memory, there's no point - * in reading it from disk again. - */ - if (already_have_control) return; - - /* Zero it out. If the control record on disk is missing or short, - * the system functions with all control record fields initialized - * to zero. - */ - memset(&CitControl, 0, sizeof(struct CitControl)); - if (control_fp == NULL) { - control_fp = fopen(file_citadel_control, "rb+"); - if (control_fp != NULL) { - lock_control(); - rv = fchown(fileno(control_fp), ctdluid, -1); - if (rv == -1) - syslog(LOG_EMERG, "Failed to adjust ownership of: %s [%s]\n", - file_citadel_control, strerror(errno)); - rv = fchmod(fileno(control_fp), S_IRUSR|S_IWUSR); - if (rv == -1) - syslog(LOG_EMERG, "Failed to adjust accessrights of: %s [%s]\n", - file_citadel_control, strerror(errno)); - } - } - if (control_fp == NULL) { - control_fp = fopen(file_citadel_control, "wb+"); - if (control_fp != NULL) { - lock_control(); - memset(&CitControl, 0, sizeof(struct CitControl)); - - rv = fchown(fileno(control_fp), ctdluid, -1); - if (rv == -1) - syslog(LOG_EMERG, "Failed to adjust ownership of: %s [%s]\n", - file_citadel_control, strerror(errno)); - - rv = fchmod(fileno(control_fp), S_IRUSR|S_IWUSR); - if (rv == -1) - syslog(LOG_EMERG, "Failed to adjust accessrights of: %s [%s]\n", - file_citadel_control, strerror(errno)); - rv = fwrite(&CitControl, sizeof(struct CitControl), 1, control_fp); - if (rv == -1) - syslog(LOG_EMERG, "Failed to write: %s [%s]\n", - file_citadel_control, strerror(errno)); - rewind(control_fp); + FILE *fp = NULL; + struct legacy_ctrl_format c; + memset(&c, 0, sizeof(c)); + + fp = fopen(file_citadel_control, "rb+"); + if (fp != NULL) { + syslog(LOG_INFO, "Legacy format control record found -- importing to db"); + fread(&c, sizeof(struct legacy_ctrl_format), 1, fp); + + CtdlSetConfigLong( "MMhighest", c.MMhighest); + CtdlSetConfigInt( "MMflags", c.MMflags); + CtdlSetConfigLong( "MMnextuser", c.MMnextuser); + CtdlSetConfigLong( "MMnextroom", c.MMnextroom); + CtdlSetConfigInt( "MM_hosted_upgrade_level", c.MM_hosted_upgrade_level); + CtdlSetConfigInt( "MM_fulltext_wordbreaker", c.MM_fulltext_wordbreaker); + CtdlSetConfigLong( "MMfulltext", c.MMfulltext); + + fclose(fp); + if (unlink(file_citadel_control) != 0) { + fprintf(stderr, "Unable to remove legacy control record %s after migrating it.\n", file_citadel_control); + fprintf(stderr, "Exiting to prevent data corruption.\n"); + exit(CTDLEXIT_CONFIG); } } - if (control_fp == NULL) { - syslog(LOG_ALERT, "ERROR opening %s: %s\n", file_citadel_control, strerror(errno)); - return; - } - - rewind(control_fp); - rv = fread(&CitControl, sizeof(struct CitControl), 1, control_fp); - if (rv == -1) - syslog(LOG_EMERG, "Failed to read Controlfile: %s [%s]\n", - file_citadel_control, strerror(errno)); - already_have_control = 1; - rv = chown(file_citadel_control, ctdluid, (-1)); - if (rv == -1) - syslog(LOG_EMERG, "Failed to adjust ownership of: %s [%s]\n", - file_citadel_control, strerror(errno)); -} - -/* - * put_control - write the control record to disk. - */ -void put_control(void) -{ - int rv = 0; - - if (control_fp != NULL) { - rewind(control_fp); - rv = fwrite(&CitControl, sizeof(struct CitControl), 1, control_fp); - if (rv == -1) - syslog(LOG_EMERG, "Failed to write: %s [%s]\n", - file_citadel_control, strerror(errno)); - fflush(control_fp); - } } @@ -204,25 +146,12 @@ void put_control(void) */ void check_control(void) { - syslog(LOG_INFO, "Checking/re-building control record\n"); - get_control(); - // Find highest room number and message number. + syslog(LOG_INFO, "Sanity checking the recorded highest message, user, and room numbers\n"); CtdlForEachRoom(control_find_highest, NULL); ForEachUser(control_find_user, NULL); - put_control(); } -/* - * release_control - close our fd on exit - */ -void release_control(void) -{ - if (control_fp != NULL) { - fclose(control_fp); - } - control_fp = NULL; -} /* * get_new_message_number() - Obtain a new, unique ID to be used for a message. @@ -231,9 +160,9 @@ long get_new_message_number(void) { long retval = 0L; begin_critical_section(S_CONTROL); - get_control(); - retval = ++CitControl.MMhighest; - put_control(); + retval = CtdlGetConfigLong("MMhighest"); + ++retval; + CtdlSetConfigLong("MMhighest", retval); end_critical_section(S_CONTROL); return(retval); } @@ -244,15 +173,12 @@ long get_new_message_number(void) * This provides a quick way to initialise a variable that might be used to indicate * messages that should not be processed. EG. a new Sieve 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) { - long retval = 0L; - begin_critical_section(S_CONTROL); - get_control(); - retval = CitControl.MMhighest; - end_critical_section(S_CONTROL); - return(retval); + return CtdlGetConfigLong("MMhighest"); } @@ -263,9 +189,9 @@ long get_new_user_number(void) { long retval = 0L; begin_critical_section(S_CONTROL); - get_control(); - retval = ++CitControl.MMnextuser; - put_control(); + retval = CtdlGetConfigLong("MMnextuser"); + ++retval; + CtdlSetConfigLong("MMnextuser", retval); end_critical_section(S_CONTROL); return(retval); } @@ -279,9 +205,9 @@ long get_new_room_number(void) { long retval = 0L; begin_critical_section(S_CONTROL); - get_control(); - retval = ++CitControl.MMnextroom; - put_control(); + retval = CtdlGetConfigLong("MMnextroom"); + ++retval; + CtdlSetConfigLong("MMnextroom", retval); end_critical_section(S_CONTROL); return(retval); } @@ -303,13 +229,13 @@ int confbool(char *v) * Get or set global configuration options * * IF YOU ADD OR CHANGE FIELDS HERE, YOU *MUST* DOCUMENT YOUR CHANGES AT: - * http://www.citadel.org/doku.php?id=documentation:applicationprotocol + * http://www.citadel.org/doku.php/documentation:appproto:system_config * */ void cmd_conf(char *argbuf) { char cmd[16]; - char buf[256]; + char buf[1024]; int a, i; long ii; char *confptr; @@ -318,6 +244,8 @@ void cmd_conf(char *argbuf) if (CtdlAccessCheck(ac_aide)) return; extract_token(cmd, argbuf, 0, '|', sizeof cmd); + + // CONF GET - retrieve system configuration in legacy format (deprecated) if (!strcasecmp(cmd, "GET")) { cprintf("%d Configuration...\n", LISTING_FOLLOWS); cprintf("%s\n", CtdlGetConfigStr("c_nodename")); @@ -403,6 +331,7 @@ void cmd_conf(char *argbuf) cprintf("000\n"); } + // CONF SET - set system configuration in legacy format (really deprecated) else if (!strcasecmp(cmd, "SET")) { unbuffer_output(); cprintf("%d Send configuration...\n", SEND_LISTING); @@ -520,152 +449,152 @@ void cmd_conf(char *argbuf) /* niu */ break; case 31: - if ((config.c_purge_hour >= 0) - && (config.c_purge_hour <= 23)) { - config.c_purge_hour = atoi(buf); + i = atoi(buf); + if ((i >= 0) && (i <= 23)) { + CtdlSetConfigInt("c_purge_hour", i); } break; -#ifdef HAVE_LDAP case 32: - safestrncpy(config.c_ldap_host, buf, sizeof config.c_ldap_host); + CtdlSetConfigStr("c_ldap_host", buf); break; case 33: - config.c_ldap_port = atoi(buf); + CtdlSetConfigInt("c_ldap_port", atoi(buf)); break; case 34: - safestrncpy(config.c_ldap_base_dn, buf, sizeof config.c_ldap_base_dn); + CtdlSetConfigStr("c_ldap_base_dn", buf); break; case 35: - safestrncpy(config.c_ldap_bind_dn, buf, sizeof config.c_ldap_bind_dn); + CtdlSetConfigStr("c_ldap_bind_dn", buf); break; case 36: - safestrncpy(config.c_ldap_bind_pw, buf, sizeof config.c_ldap_bind_pw); + CtdlSetConfigStr("c_ldap_bind_pw", buf); break; -#endif case 37: - safestrncpy(config.c_ip_addr, buf, sizeof config.c_ip_addr); + CtdlSetConfigStr("c_ip_addr", buf); + break; case 38: - config.c_msa_port = atoi(buf); + CtdlSetConfigInt("c_msa_port", atoi(buf)); break; case 39: - config.c_imaps_port = atoi(buf); + CtdlSetConfigInt("c_imaps_port", atoi(buf)); break; case 40: - config.c_pop3s_port = atoi(buf); + CtdlSetConfigInt("c_pop3s_port", atoi(buf)); break; case 41: - config.c_smtps_port = atoi(buf); + CtdlSetConfigInt("c_smtps_port", atoi(buf)); break; case 42: - config.c_enable_fulltext = atoi(buf); + CtdlSetConfigInt("c_enable_fulltext", confbool(buf)); break; case 43: - config.c_auto_cull = atoi(buf); + CtdlSetConfigInt("c_auto_cull", confbool(buf)); break; case 44: /* niu */ break; case 45: - config.c_allow_spoofing = atoi(buf); + CtdlSetConfigInt("c_allow_spoofing", confbool(buf)); break; case 46: - config.c_journal_email = atoi(buf); + CtdlSetConfigInt("c_journal_email", confbool(buf)); break; case 47: - config.c_journal_pubmsgs = atoi(buf); + CtdlSetConfigInt("c_journal_pubmsgs", confbool(buf)); break; case 48: - safestrncpy(config.c_journal_dest, buf, sizeof config.c_journal_dest); + CtdlSetConfigStr("c_journal_dest", buf); + break; case 49: - safestrncpy(config.c_default_cal_zone, buf, sizeof config.c_default_cal_zone); + CtdlSetConfigStr("c_default_cal_zone", buf); break; case 50: - config.c_pftcpdict_port = atoi(buf); + CtdlSetConfigInt("c_pftcpdict_port", atoi(buf)); break; case 51: - config.c_managesieve_port = atoi(buf); + CtdlSetConfigInt("c_managesieve_port", atoi(buf)); break; case 52: - config.c_auth_mode = atoi(buf); + CtdlSetConfigInt("c_auth_mode", atoi(buf)); + break; case 53: - safestrncpy(config.c_funambol_host, buf, sizeof config.c_funambol_host); + CtdlSetConfigStr("c_funambol_host", buf); break; case 54: - config.c_funambol_port = atoi(buf); + CtdlSetConfigInt("c_funambol_port", atoi(buf)); break; case 55: - safestrncpy(config.c_funambol_source, buf, sizeof config.c_funambol_source); + CtdlSetConfigStr("c_funambol_source", buf); break; case 56: - safestrncpy(config.c_funambol_auth, buf, sizeof config.c_funambol_auth); + CtdlSetConfigStr("c_funambol_auth", buf); break; case 57: - config.c_rbl_at_greeting = atoi(buf); + CtdlSetConfigInt("c_rbl_at_greeting", confbool(buf)); break; case 58: - safestrncpy(config.c_master_user, buf, sizeof config.c_master_user); + CtdlSetConfigStr("c_master_user", buf); break; case 59: - safestrncpy(config.c_master_pass, buf, sizeof config.c_master_pass); + CtdlSetConfigStr("c_master_pass", buf); break; case 60: - safestrncpy(config.c_pager_program, buf, sizeof config.c_pager_program); + CtdlSetConfigStr("c_pager_program", buf); break; case 61: - config.c_imap_keep_from = atoi(buf); + CtdlSetConfigInt("c_imap_keep_from", confbool(buf)); break; case 62: - config.c_xmpp_c2s_port = atoi(buf); + CtdlSetConfigInt("c_xmpp_c2s_port", atoi(buf)); break; case 63: - config.c_xmpp_s2s_port = atoi(buf); + CtdlSetConfigInt("c_xmpp_s2s_port", atoi(buf)); break; case 64: - config.c_pop3_fetch = atol(buf); + CtdlSetConfigLong("c_pop3_fetch", atol(buf)); break; case 65: - config.c_pop3_fastest = atol(buf); + CtdlSetConfigLong("c_pop3_fastest", atol(buf)); break; case 66: - config.c_spam_flag_only = atoi(buf); + CtdlSetConfigInt("c_spam_flag_only", confbool(buf)); break; case 67: - config.c_guest_logins = atoi(buf); + CtdlSetConfigInt("c_guest_logins", confbool(buf)); break; case 68: - config.c_port_number = atoi(buf); + CtdlSetConfigInt("c_port_number", atoi(buf)); break; case 69: /* niu */ break; case 70: - config.c_nntp_port = atoi(buf); + CtdlSetConfigInt("c_nntp_port", atoi(buf)); break; case 71: - config.c_nntps_port = atoi(buf); + CtdlSetConfigInt("c_nntps_port", atoi(buf)); break; } ++a; } - put_config(); snprintf(buf, sizeof buf, "The global system configuration has been edited by %s.\n", (CC->logged_in ? CC->curr_user : "an administrator") ); CtdlAideMessage(buf,"Citadel Configuration Manager Message"); - if (!IsEmptyStr(config.c_logpages)) - CtdlCreateRoom(config.c_logpages, 3, "", 0, 1, 1, VIEW_BBS); + 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 (config.c_enable_fulltext == 0) { - CitControl.MM_fulltext_wordbreaker = 0; - put_control(); + if (CtdlGetConfigInt("c_enable_fulltext") == 0) { + CtdlSetConfigInt("MM_fulltext_wordbreaker", 0); } } + // CONF GETSYS - retrieve arbitrary system configuration stanzas stored in the message base else if (!strcasecmp(cmd, "GETSYS")) { extract_token(confname, argbuf, 1, '|', sizeof confname); confptr = CtdlGetSysConfig(confname); @@ -685,18 +614,41 @@ void cmd_conf(char *argbuf) } } + // CONF PUTSYS - store arbitrary system configuration stanzas in the message base else if (!strcasecmp(cmd, "PUTSYS")) { extract_token(confname, argbuf, 1, '|', sizeof confname); unbuffer_output(); cprintf("%d %s\n", SEND_LISTING, confname); - confptr = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0); + confptr = CtdlReadMessageBody(HKEY("000"), CtdlGetConfigLong("c_maxmsglen"), NULL, 0, 0); CtdlPutSysConfig(confname, confptr); free(confptr); } + else if (!strcasecmp(cmd, "GETVAL")) { + extract_token(confname, argbuf, 1, '|', sizeof confname); + char *v = CtdlGetConfigStr(confname); + if (v) { + cprintf("%d|%s|\n", CIT_OK, v); + } + else { + cprintf("%d||\n", ERROR); + } + } + + else if (!strcasecmp(cmd, "PUTVAL")) { + if (num_tokens(argbuf, '|') < 3) { + cprintf("%d name and value required\n", ERROR); + } + else { + extract_token(confname, argbuf, 1, '|', sizeof confname); + extract_token(buf, argbuf, 2, '|', sizeof buf); + CtdlSetConfigStr(confname, buf); + cprintf("%d setting '%s' to '%s'\n", CIT_OK, confname, buf); + } + } + else { - cprintf("%d Illegal option(s) specified.\n", - ERROR + ILLEGAL_VALUE); + cprintf("%d Illegal option(s) specified.\n", ERROR + ILLEGAL_VALUE); } } @@ -737,7 +689,7 @@ void cmd_gvdn(char *argbuf) void *vptr; List = NewHash(1, NULL); - Cfg = NewStrBufPlain(config.c_fqdn, -1); + Cfg = NewStrBufPlain(CtdlGetConfigStr("c_fqdn"), -1); Put(List, SKEY(Cfg), Cfg, HFreeStrBuf); Cfg = NULL;