#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
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) {
- 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);
- }
}
*/
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);
}
* 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;
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"));
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);
}
++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")
* 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);
}
}
+ // 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);
}
}
+ // 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();
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);
}
}