};
-/* Bits which may appear in CitControl.MMflags. Note that these don't
- * necessarily pertain to the message base -- it's just a good place to
- * store any global flags.
+/* Bits which may appear in MMflags.
*/
#define MM_VALID 4 /* New users need validating */
open_databases();
/* Load site-specific configuration */
- syslog(LOG_INFO, "Loading citadel.config");
+ syslog(LOG_INFO, "Initializing configuration system");
initialize_config_system();
validate_config();
+ migrate_legacy_control_record();
/* Check floor reference counts */
check_ref_counts();
#include "citserver.h"
#include "user_ops.h"
-struct CitControl CitControl;
-FILE *control_fp = NULL;
long control_highest_user = 0;
+/*
+ * This is the control record for the message base...
+ */
+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 */
+};
+
/*
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;
}
{
for (c=0; c<num_msgs; c++)
{
- if (msglist[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;
}
{
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)
/*
- * 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) {
- 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) {
- 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);
- }
-}
+
+
/*
*/
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.
{
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);
}
* 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");
}
{
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);
}
{
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);
}
* index so it doesn't try to use it later.
*/
if (CtdlGetConfigInt("c_enable_fulltext") == 0) {
- CitControl.MM_fulltext_wordbreaker = 0;
- put_control();
+ CtdlSetConfigInt("MM_fulltext_wordbreaker", 0);
}
}
long int get_new_message_number (void);
long int get_new_user_number (void);
long int get_new_room_number (void);
+void migrate_legacy_control_record(void);
}
-
/*
* get user parameters
*/
void cmd_getu(char *cmdbuf)
{
-
if (CtdlAccessCheck(ac_logged_in))
return;
CtdlGetUser(&CC->user, CC->curr_user);
- cprintf("%d 80|24|%d|\n",
- CIT_OK,
- (CC->user.flags & US_USER_SET)
- );
+ cprintf("%d 80|24|%d|\n", CIT_OK, (CC->user.flags & US_USER_SET));
}
+
/*
* set user parameters
*/
return;
}
- if ((CitControl.MMflags & MM_VALID) == 0) {
+ if ((CtdlGetConfigInt("MMflags") & MM_VALID) == 0) {
cprintf("%d There are no unvalidated users.\n", CIT_OK);
return;
}
*/
begin_critical_section(S_CONTROL);
- get_control();
- CitControl.MMflags = CitControl.MMflags & (~MM_VALID);
- put_control();
+ int flags;
+ flags = CtdlGetConfigInt("MMflags");
+ flags = flags & (~MM_VALID);
+ CtdlSetConfigInt("MMflags", flags);
end_critical_section(S_CONTROL);
cprintf("%d *** End of registration.\n", CIT_OK);
-
-
}
regis = 1;
if (CC->user.axlevel >= AxAideU) {
- get_control();
- if (CitControl.MMflags & MM_VALID)
+ if (CtdlGetConfigInt("MMflags") & MM_VALID) {
vali = 1;
+ }
}
/* check for mail */
*/
void ft_index_msg(long msgnum, void *userdata) {
- if ((msgnum > CitControl.MMfulltext) && (msgnum <= ft_newhighest)) {
+ if ((msgnum > CtdlGetConfigLong("MMfulltext")) && (msgnum <= ft_newhighest)) {
++ft_num_msgs;
if (ft_num_msgs > ft_num_alloc) {
ft_num_alloc += 1024;
* Check to see whether the fulltext index is up to date; if there
* are no messages to index, don't waste any more time trying.
*/
- if ((CitControl.MMfulltext >= CitControl.MMhighest) && (CitControl.MM_fulltext_wordbreaker == FT_WORDBREAKER_ID)) {
+ if (
+ (CtdlGetConfigLong("MMfulltext") >= CtdlGetConfigLong("MMhighest"))
+ && (CtdlGetConfigInt("MM_fulltext_wordbreaker") == FT_WORDBREAKER_ID)
+ ) {
return; /* nothing to do! */
}
* over.
*/
begin_critical_section(S_CONTROL);
- if (CitControl.MM_fulltext_wordbreaker != FT_WORDBREAKER_ID) {
+ if (CtdlGetConfigInt("MM_fulltext_wordbreaker") != FT_WORDBREAKER_ID) {
syslog(LOG_DEBUG, "wb ver on disk = %d, code ver = %d",
- CitControl.MM_fulltext_wordbreaker, FT_WORDBREAKER_ID
+ CtdlGetConfigInt("MM_fulltext_wordbreaker"), FT_WORDBREAKER_ID
);
syslog(LOG_INFO, "(re)initializing full text index");
cdb_trunc(CDB_FULLTEXT);
- CitControl.MMfulltext = 0L;
- put_control();
+ CtdlSetConfigLong("MMfulltext", 0);
}
end_critical_section(S_CONTROL);
/*
* Now go through each room and find messages to index.
*/
- ft_newhighest = CitControl.MMhighest;
+ ft_newhighest = CtdlGetConfigLong("MMhighest");
CtdlForEachRoom(ft_index_room, NULL); /* load all msg pointers */
if (ft_num_msgs > 0) {
/* Save our place so we don't have to do this again */
ft_flush_cache();
begin_critical_section(S_CONTROL);
- CitControl.MMfulltext = ft_newhighest;
- CitControl.MM_fulltext_wordbreaker = FT_WORDBREAKER_ID;
- put_control();
+ CtdlSetConfigLong("MMfulltext", ft_newhighest);
+ CtdlSetConfigInt("MM_fulltext_wordbreaker", FT_WORDBREAKER_ID);
end_critical_section(S_CONTROL);
last_index = time(NULL);
IAPrintf("* %d RECENT\r\n", new);
IAPrintf("* OK [UIDVALIDITY %ld] UID validity status\r\n", GLOBAL_UIDVALIDITY_VALUE);
- IAPrintf("* OK [UIDNEXT %ld] Predicted next UID\r\n", CitControl.MMhighest + 1);
+ IAPrintf("* OK [UIDNEXT %ld] Predicted next UID\r\n", CtdlGetConfigLong("MMhighest") + 1);
/* Technically, \Deleted is a valid flag, but not a permanent flag,
* because we don't maintain its state across sessions. Citadel
IPutStr(imaproomname, len);
IAPrintf(" (MESSAGES %d ", msgs);
IAPrintf("RECENT %d ", new); /* Initially, new==recent */
- IAPrintf("UIDNEXT %ld ", CitControl.MMhighest + 1);
+ IAPrintf("UIDNEXT %ld ", CtdlGetConfigLong("MMhighest") + 1);
IAPrintf("UNSEEN %d)\r\n", new);
/*
* Explanation of <progress> tags:
*
* 0% nothing
- * 1% finished exporting config
- * 2% finished exporting control
+ * 2% finished exporting configuration
* 7% finished exporting users
* 12% finished exporting openids
* 17% finished exporting rooms
#include "database.h"
#include "msgbase.h"
#include "user_ops.h"
-#include "control.h"
#include "euidindex.h"
#include "ctdl_module.h"
cprintf("<version>%d</version>\n", REV_LEVEL);
cprintf("<progress>%d</progress>\n", 0);
- /* export the config file (this is done using x-macros) */
+ /* export the configuration database */
migr_export_configs();
- cprintf("<progress>%d</progress>\n", 1);
-
- /* Export the control file */
- get_control();
- client_write("<control>\n", 10);
- cprintf("<control_highest>%ld</control_highest>\n", CitControl.MMhighest);
- cprintf("<control_flags>%u</control_flags>\n", CitControl.MMflags);
- cprintf("<control_nextuser>%ld</control_nextuser>\n", CitControl.MMnextuser);
- cprintf("<control_nextroom>%ld</control_nextroom>\n", CitControl.MMnextroom);
- cprintf("<control_version>%d</control_version>\n", CitControl.MM_hosted_upgrade_level);
- client_write("</control>\n", 11);
cprintf("<progress>%d</progress>\n", 2);
-
+
if (Ctx->kill_me == 0) migr_export_users();
cprintf("<progress>%d</progress>\n", 7);
if (Ctx->kill_me == 0) migr_export_openids();
}
-
-int migr_controlrecord(void *data, const char *el)
-{
- if (!strcasecmp(el, "control_highest")) CitControl.MMhighest = atol(ChrPtr(migr_chardata));
- else if (!strcasecmp(el, "control_flags")) CitControl.MMflags = atoi(ChrPtr(migr_chardata));
- else if (!strcasecmp(el, "control_nextuser")) CitControl.MMnextuser = atol(ChrPtr(migr_chardata));
- else if (!strcasecmp(el, "control_nextroom")) CitControl.MMnextroom = atol(ChrPtr(migr_chardata));
- else if (!strcasecmp(el, "control_version")) CitControl.MM_hosted_upgrade_level = atoi(ChrPtr(migr_chardata));
-
- else if (!strcasecmp(el, "control")) {
- CitControl.MMfulltext = (-1L); /* always flush */
- put_control();
- syslog(LOG_INFO, "Completed import of control record\n");
- }
- else return 0;
- return 1;
-
-}
-
-
int migr_userrecord(void *data, const char *el)
{
if (!strcasecmp(el, "u_version")) usbuf.version = atoi(ChrPtr(migr_chardata));
CtdlSetConfigInt("c_enable_fulltext", 0); /* always disable FIXME put this somewhere more appropriate */
}
- /*** CONTROL ***/
- else if ((!strncasecmp(el, HKEY("control"))) &&
- migr_controlrecord(data, el))
- ; /* Nothing to do anymore */
/*** USER ***/
else if ((!strncasecmp(el, HKEY("u_"))) &&
migr_userrecord(data, el))
* Volume of messages submitted
*/
void mrtg_messages(void) {
- mrtg_output(CitControl.MMhighest, 0L);
+ mrtg_output(CtdlGetConfigLong("MMhighest"), 0);
}
*/
void update_config(void) {
- int oldver = CitControl.MM_hosted_upgrade_level;
+ int oldver = CtdlGetConfigInt("MM_hosted_upgrade_level");
if (oldver < 606) {
CtdlSetConfigInt("c_rfc822_strict_from", 0);
*/
void check_server_upgrades(void) {
- get_control();
syslog(LOG_INFO, "Existing database version on disk is %d.%02d",
- (CitControl.MM_hosted_upgrade_level / 100),
- (CitControl.MM_hosted_upgrade_level % 100)
+ (CtdlGetConfigInt("MM_hosted_upgrade_level") / 100),
+ (CtdlGetConfigInt("MM_hosted_upgrade_level") % 100)
);
- if (CitControl.MM_hosted_upgrade_level < REV_LEVEL) {
+ if (CtdlGetConfigInt("MM_hosted_upgrade_level") < REV_LEVEL) {
syslog(LOG_WARNING,
"Server hosted updates need to be processed at this time. Please wait..."
);
update_config();
- if ((CitControl.MM_hosted_upgrade_level > 000) && (CitControl.MM_hosted_upgrade_level < 555)) {
+ if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 555)) {
syslog(LOG_EMERG, "This database is too old to be upgraded. Citadel server will exit.");
exit(EXIT_FAILURE);
}
- if ((CitControl.MM_hosted_upgrade_level > 000) && (CitControl.MM_hosted_upgrade_level < 591)) {
+ if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 591)) {
bump_mailbox_generation_numbers();
}
- if ((CitControl.MM_hosted_upgrade_level > 000) && (CitControl.MM_hosted_upgrade_level < 608)) {
+ if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 608)) {
convert_ctdluid_to_minusone();
}
- if ((CitControl.MM_hosted_upgrade_level > 000) && (CitControl.MM_hosted_upgrade_level < 659)) {
+ if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 659)) {
rebuild_euid_index();
}
- if (CitControl.MM_hosted_upgrade_level < 735) {
+ if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 735) {
fix_sys_user_name();
}
- if (CitControl.MM_hosted_upgrade_level < 736) {
+ if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 736) {
rebuild_usersbynumber();
}
- if (CitControl.MM_hosted_upgrade_level < 790) {
+ if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 790) {
remove_thread_users();
}
- if (CitControl.MM_hosted_upgrade_level < 810) {
+ if (CtdlGetConfigInt("MM_hosted_upgrade_level") < 810) {
struct ctdlroom QRoom;
if (!CtdlGetRoom(&QRoom, SMTP_SPOOLOUT_ROOM)) {
QRoom.QRdefaultview = VIEW_QUEUE;
}
}
- CitControl.MM_hosted_upgrade_level = REV_LEVEL;
+ CtdlSetConfigInt("MM_hosted_upgrade_level", REV_LEVEL);
/*
* Negative values for maxsessions are not allowed.
CtdlSetConfigInt("c_ep_mode", EXPIRE_MANUAL);
CtdlSetConfigInt("c_ep_value", 0);
}
-
- put_control();
}
* set global flag calling for an aide to validate new users
*/
void set_mm_valid(void) {
+ int flags = 0;
+
begin_critical_section(S_CONTROL);
- get_control();
- CitControl.MMflags = CitControl.MMflags | MM_VALID ;
- put_control();
+ flags = CtdlGetConfigInt("MMflags");
+ flags = flags | MM_VALID ;
+ CtdlSetConfigInt("MMflags", flags);
end_critical_section(S_CONTROL);
}
#define CS_POSTING 4 /* Posting */
-/*
- * This is the control record for the message base...
- */
-struct CitControl {
- 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 */
-};
-
extern int ScheduledShutdown;
-extern struct CitControl CitControl;
extern uid_t ctdluid;
struct ExpressMessage {