/*
* Read and write the citadel.config file
*
- * Copyright (c) 1987-2012 by the citadel.org team
+ * Copyright (c) 1987-2015 by the citadel.org team
*
* This program is open source software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3.
*/
#include "sysdep.h"
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <unistd.h>
#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <limits.h>
#include <sys/utsname.h>
#include <libcitadel.h>
-#include "citadel.h"
-#include "server.h"
#include "config.h"
#include "ctdl_module.h"
-struct config config;
+struct config config; // legacy configuration
+HashList *ctdlconfig = NULL; // new configuration
+
+#define STR_NOT_EMPTY(CFG_FIELDNAME) if (IsEmptyStr(config.CFG_FIELDNAME)) \
+ syslog(LOG_EMERG, "configuration setting "#CFG_FIELDNAME" is empty, but must not - check your config!");
+
+#define TEST_PORT(CFG_PORT, DEFAULTPORT) \
+ if ((config.CFG_PORT < -1) || \
+ (config.CFG_PORT == 0) || \
+ (config.CFG_PORT > UINT16_MAX)) \
+ syslog(LOG_EMERG, "configuration setting "#CFG_PORT" is not -1 (disabled) or a valid TCP-Port - check your config! Default setting is: "#DEFAULTPORT);
+
+
+void validate_config(void) {
+/* these shouldn't be empty: */
+ STR_NOT_EMPTY(c_fqdn);
+
+ STR_NOT_EMPTY(c_baseroom);
+ STR_NOT_EMPTY(c_aideroom);
+ STR_NOT_EMPTY(c_twitroom);
+ STR_NOT_EMPTY(c_nodename);
+ STR_NOT_EMPTY(c_default_cal_zone);
+
+/* we bind a lot of ports: */
+ TEST_PORT(c_smtp_port, 25);
+ TEST_PORT(c_pop3_port, 110);
+ TEST_PORT(c_imap_port, 143);
+ TEST_PORT(c_msa_port, 587);
+ TEST_PORT(c_port_number, 504);
+ TEST_PORT(c_smtps_port, 465);
+ TEST_PORT(c_pop3s_port, 995);
+ TEST_PORT(c_imaps_port, 993);
+ TEST_PORT(c_pftcpdict_port, -1);
+ TEST_PORT(c_managesieve_port, 2020);
+ TEST_PORT(c_xmpp_c2s_port, 5222);
+ TEST_PORT(c_xmpp_s2s_port, 5269);
+ TEST_PORT(c_nntp_port, 119);
+ TEST_PORT(c_nntps_port, 563);
+
+ if (getpwuid(ctdluid) == NULL) {
+ syslog(LOG_EMERG, "The UID (%d) citadel is configured to use is not defined in your system (/etc/passwd?)!", ctdluid);
+ }
+
+}
/*
* Put some sane default values into our configuration. Some will be overridden when we run setup.
*/
void brand_new_installation_set_defaults(void) {
- struct passwd *pw;
struct utsname my_utsname;
struct hostent *he;
uname(&my_utsname);
/* set some sample/default values in place of blanks... */
- char c_nodename[256];
- safestrncpy(c_nodename, my_utsname.nodename, sizeof c_nodename);
- strtok(config.c_nodename, ".");
+ extract_token(config.c_nodename, my_utsname.nodename, 0, '.', sizeof config.c_nodename);
if (IsEmptyStr(config.c_fqdn) ) {
if ((he = gethostbyname(my_utsname.nodename)) != NULL) {
safestrncpy(config.c_fqdn, he->h_name, sizeof config.c_fqdn);
safestrncpy(config.c_aideroom, "Aide", sizeof config.c_aideroom);
config.c_port_number = 504;
config.c_sleeping = 900;
- config.c_instant_expunge = 1;
- if (config.c_ctdluid == 0) {
- pw = getpwnam("citadel");
- if (pw != NULL) {
- config.c_ctdluid = pw->pw_uid;
- }
- }
- if (config.c_ctdluid == 0) {
- pw = getpwnam("bbs");
- if (pw != NULL) {
- config.c_ctdluid = pw->pw_uid;
- }
- }
- if (config.c_ctdluid == 0) {
- pw = getpwnam("guest");
- if (pw != NULL) {
- config.c_ctdluid = pw->pw_uid;
- }
- }
if (config.c_createax == 0) {
config.c_createax = 3;
}
config.c_managesieve_port = 2020;
config.c_xmpp_c2s_port = 5222;
config.c_xmpp_s2s_port = 5269;
+ config.c_nntp_port = 119;
+ config.c_nntps_port = 563;
}
/*
- * get_config() is called during the initialization of Citadel server.
+ * Called during the initialization of Citadel server.
* It verifies the system's integrity and reads citadel.config into memory.
*/
-void get_config(void) {
+void initialize_config_system(void) {
FILE *cfp;
int rv;
+ ctdlconfig = NewHash(1, NULL);
if (chdir(ctdl_bbsbase_dir) != 0) {
fprintf(stderr,
}
}
+long config_msgnum = 0;
/*
* Occasionally, we will need to write the config file, because some operations
FILE *cfp;
int blocks_written = 0;
- if ((cfp = fopen(file_citadel_config, "w")) != NULL) {
+ cfp = fopen(file_citadel_config, "w");
+ if (cfp != NULL) {
blocks_written = fwrite((char *) &config, sizeof(struct config), 1, cfp);
if (blocks_written == 1) {
- fclose(cfp);
chown(file_citadel_config, CTDLUID, (-1));
chmod(file_citadel_config, 0600);
+ fclose(cfp);
return;
}
+ fclose(cfp);
}
syslog(LOG_EMERG, "%s: %s", file_citadel_config, strerror(errno));
}
+
+
+
+/*
+ * Called when Citadel server is shutting down.
+ * Clears out the config hash table.
+ */
+void shutdown_config_system(void)
+{
+ DeleteHash(&ctdlconfig);
+}
+
+
+
+/*
+ * Set a system config value. Simple key/value here.
+ */
+void CtdlSetConfigStr(char *key, char *value)
+{
+ int key_len = strlen(key);
+ int value_len = strlen(value);
+
+ /* Save it in memory */
+ Put(ctdlconfig, key, key_len, strdup(value), NULL);
+
+ /* Also write it to the config database */
+
+ int dbv_size = key_len + value_len + 2;
+ char *dbv = malloc(dbv_size);
+ strcpy(dbv, key);
+ strcpy(&dbv[key_len + 1], value);
+ cdb_store(CDB_CONFIG, key, key_len, dbv, dbv_size);
+ free(dbv);
+}
+
+
+/*
+ * Set a numeric system config value (long integer)
+ */
+void CtdlSetConfigLong(char *key, long value)
+{
+ char longstr[256];
+ sprintf(longstr, "%ld", value);
+ CtdlSetConfigStr(key, longstr);
+}
+
+
+/*
+ * Set a numeric system config value (integer)
+ */
+void CtdlSetConfigInt(char *key, int value)
+{
+ char intstr[256];
+ sprintf(intstr, "%d", value);
+ CtdlSetConfigStr(key, intstr);
+}
+
+
+/*
+ * Fetch a system config value. Caller does *not* own the returned value and may not alter it.
+ */
+char *CtdlGetConfigStr(char *key)
+{
+ char *value = NULL;
+ struct cdbdata *cdb;
+ int key_len = strlen(key);
+
+ /* First look in memory */
+ if (GetHash(ctdlconfig, key, key_len, (void *)&value))
+ {
+ return value;
+ }
+
+ /* Then look in the database. */
+
+ cdb = cdb_fetch(CDB_CONFIG, key, key_len);
+
+ if (cdb == NULL) { /* nope, not there either. */
+ return(NULL);
+ }
+
+ /* Got it. Save it in memory for the next fetch. */
+ value = strdup(cdb->ptr + key_len + 1); /* The key was stored there too; skip past it */
+ cdb_free(cdb);
+ Put(ctdlconfig, key, key_len, value, NULL);
+ return value;
+}
+
+
+
+
+
+/**********************************************************************/
+
+
+
+
+
+
+
+
+
+
+void CtdlGetSysConfigBackend(long msgnum, void *userdata) {
+ config_msgnum = msgnum;
+}
+
+
+char *CtdlGetSysConfig(char *sysconfname) {
+ char hold_rm[ROOMNAMELEN];
+ long msgnum;
+ char *conf;
+ struct CtdlMessage *msg;
+ char buf[SIZ];
+
+ strcpy(hold_rm, CC->room.QRname);
+ if (CtdlGetRoom(&CC->room, SYSCONFIGROOM) != 0) {
+ CtdlGetRoom(&CC->room, hold_rm);
+ return NULL;
+ }
+
+
+ /* We want the last (and probably only) config in this room */
+ begin_critical_section(S_CONFIG);
+ config_msgnum = (-1L);
+ CtdlForEachMessage(MSGS_LAST, 1, NULL, sysconfname, NULL,
+ CtdlGetSysConfigBackend, NULL);
+ msgnum = config_msgnum;
+ end_critical_section(S_CONFIG);
+
+ if (msgnum < 0L) {
+ conf = NULL;
+ }
+ else {
+ msg = CtdlFetchMessage(msgnum, 1);
+ if (msg != NULL) {
+ conf = strdup(msg->cm_fields[eMesageText]);
+ CM_Free(msg);
+ }
+ else {
+ conf = NULL;
+ }
+ }
+
+ CtdlGetRoom(&CC->room, hold_rm);
+
+ if (conf != NULL) do {
+ extract_token(buf, conf, 0, '\n', sizeof buf);
+ strcpy(conf, &conf[strlen(buf)+1]);
+ } while ( (!IsEmptyStr(conf)) && (!IsEmptyStr(buf)) );
+
+ return(conf);
+}
+
+
+void CtdlPutSysConfig(char *sysconfname, char *sysconfdata) {
+ CtdlWriteObject(SYSCONFIGROOM, sysconfname, sysconfdata, (strlen(sysconfdata)+1), NULL, 0, 1, 0);
+}
+