]> code.citadel.org Git - citadel.git/blobdiff - citadel/utils/setup.c
* get long message texts translateable
[citadel.git] / citadel / utils / setup.c
index 61e415ddb3e6ac578ef422dbbd3ab115d27696cf..7a38bc2f731e5205baba9190c59ef226b59f8e1e 100644 (file)
@@ -1,13 +1,9 @@
 /*
- * $Id$
- *
  * Citadel setup utility
- *
  */
 
+#define SHOW_ME_VAPPEND_PRINTF
 #include "ctdl_module.h"
-
-
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <execinfo.h>
 #endif
 
+#ifdef ENABLE_NLS
+#ifdef HAVE_XLOCALE_H
+#include <xlocale.h>
+#endif
+#include <libintl.h>
+#include <locale.h>
+#define _(string)      gettext(string)
+#else
+#define _(string)      (string)
+#endif
+
 
 #define MAXSETUP 11    /* How many setup questions to ask */
 
 #define PROTO_NAME     "tcp"
 #define NSSCONF                "/etc/nsswitch.conf"
 
+
+typedef enum _SetupStep {
+       eCitadelHomeDir = 0,
+       eSysAdminName = 1,
+       eSysAdminPW = 2,
+       eUID = 3,
+       eIP_ADDR = 4,
+       eCTDL_Port = 5,
+       eAuthType = 6,
+       eLDAP_Host = 7,
+       eLDAP_Port = 8,
+       eLDAP_Base_DN = 9,
+       eLDAP_Bind_DN = 10,
+       eLDAP_Bind_PW = 11,
+       eMaxQuestions = 12
+} eSteupStep;
+
+///"CREATE_XINETD_ENTRY";
+/* Environment variables, don't translate! */
+const char *EnvNames [eMaxQuestions] = {
+        "HOME_DIRECTORY",
+       "SYSADMIN_NAME",
+       "SYSADMIN_PW",
+       "CITADEL_UID",
+       "IP_ADDR",
+       "CITADEL_PORT",
+       "ENABLE_UNIX_AUTH",
+       "LDAP_HOST",
+       "LDAP_PORT",
+       "LDAP_BASE_DN",
+       "LDAP_BIND_DN",
+       "LDAP_BIND_PW"
+};
+
 int setup_type;
-char setup_directory[PATH_MAX];
 int using_web_installer = 0;
 int enable_home = 1;
 char admin_pass[SIZ];
 char admin_cmd[SIZ];
 
-char *setup_titles[] =
-{
-       "Citadel Home Directory",
-       "System Administrator",
-       "Administrator Password",
-       "Citadel User ID",
-       "Server IP address",
-       "Server port number",
-       "Authentication mode",
-       "LDAP host",
-       "LDAP port number",
-       "LDAP base DN",
-       "LDAP bind DN",
-       "LDAP bind password"
-};
-
-/**
- * \brief print the actual stack frame.
- */
-void cit_backtrace(void)
-{
-#ifdef HAVE_BACKTRACE
-       void *stack_frames[50];
-       size_t size, i;
-       char **strings;
-
-
-       size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
-       strings = backtrace_symbols(stack_frames, size);
-       for (i = 0; i < size; i++) {
-               if (strings != NULL)
-                       fprintf(stderr, "%s\n", strings[i]);
-               else
-                       fprintf(stderr, "%p\n", stack_frames[i]);
-       }
-       free(strings);
-#endif
-}
-
-struct config config;
+const char *setup_titles[eMaxQuestions];
+const char *setup_text[eMaxQuestions];
 
-       /* calculate all our path on a central place */
-    /* where to keep our config */
+/* calculate all our path on a central place */
+/* where to keep our config */
        
 
-char *setup_text[] = {
+
+void SetTitles(void)
+{
+       int have_run_dir;
 #ifndef HAVE_RUN_DIR
+       have_run_dir = 1;
+#else
+       have_run_dir = 0;
+#endif
+       setup_titles[eCitadelHomeDir] = _("Citadel Home Directory");
+       if (have_run_dir)
+               setup_text[eCitadelHomeDir] = _(
 "Enter the full pathname of the directory in which the Citadel\n"
 "installation you are creating or updating resides.  If you\n"
 "specify a directory other than the default, you will need to\n"
-"specify the -h flag to the server when you start it up.\n",
-#else
+"specify the -h flag to the server when you start it up.\n");
+       else
+               setup_text[eCitadelHomeDir] = _(
 "Enter the subdirectory name for an alternate installation of "
 "Citadel. To do a default installation just leave it blank."
 "If you specify a directory other than the default, you will need to\n"
 "specify the -h flag to the server when you start it up.\n"
-"note that it may not have a leading /",
-#endif
+"note that it may not have a leading /");
+
 
+       setup_titles[eSysAdminName] = _("Citadel administrator username:");////
+       setup_text[eSysAdminName] = _(
 "Enter the name of the system administrator (which is probably\n"
 "you).  When an account is created with this name, it will\n"
-"automatically be given administrator-level access.\n",
+"automatically be given administrator-level access.\n");
 
+       setup_titles[eSysAdminPW] = _("Administrator password:");//
+       setup_text[eSysAdminPW] = _(
 "Enter a password for the system administrator. When setup\n"
 "completes it will attempt to create the administrator user\n"
-"and set the password specified here.\n",
+"and set the password specified here.\n");
 
+       setup_titles[eUID] = _("Citadel User ID:");
+       setup_text[eUID] = _(
 "Citadel needs to run under its own user ID.  This would\n"
 "typically be called \"citadel\", but if you are running Citadel\n"
 "as a public BBS, you might also call it \"bbs\" or \"guest\".\n"
 "The server will run under this user ID.  Please specify that\n"
 "user ID here.  You may specify either a user name or a numeric\n"
-"UID.\n",
-
-"Specify the IP address on which your server will run.  If you\n"
-"leave this blank, or if you specify 0.0.0.0, Citadel will listen\n"
-"on all addresses.  You can usually skip this unless you are\n"
-"running multiple instances of Citadel on the same computer.\n",
-
+"UID.\n");
+
+       setup_titles[eIP_ADDR] = _("Listening address for the Citadel server:");///
+       setup_text[eIP_ADDR] = _(
+"Specify the IP address on which your server will run.\n"
+"You can name a specific IPv4 or IPv6 address, or you can specify\n"
+"'*' for 'any address', '::' for 'any IPv6 address', or '0.0.0.0'\n"
+"for 'any IPv4 address'.  If you leave this blank, Citadel will\n"
+"listen on all addresses.  You can usually skip this unless you are\n"
+"running multiple instances of Citadel on the same computer.\n");
+
+       setup_titles[eCTDL_Port] = _("Server port number:");
+       setup_text[eCTDL_Port] = _(
 "Specify the TCP port number on which your server will run.\n"
 "Normally, this will be port 504, which is the official port\n"
 "assigned by the IANA for Citadel servers.  You will only need\n"
 "to specify a different port number if you run multiple instances\n"
 "of Citadel on the same computer and there is something else\n"
-"already using port 504.\n",
-
-
+"already using port 504.\n");
 
+       setup_titles[eAuthType] = _("Authentication method to use:");////
+       setup_text[eAuthType] = _(
 "Specify which authentication mode you wish to use.\n"
 "\n"
 " 0. Self contained authentication\n"
@@ -149,25 +174,59 @@ char *setup_text[] = {
 "\n"
 "For help: http://www.citadel.org/doku.php/faq:installation:authmodes\n"
 "\n"
-"ANSWER \"0\" UNLESS YOU COMPLETELY UNDERSTAND THIS OPTION.\n",
+"ANSWER \"0\" UNLESS YOU COMPLETELY UNDERSTAND THIS OPTION.\n");
 
-"Please enter the host name or IP address of your LDAP server.\n",
+       setup_titles[eLDAP_Host] = _("LDAP host:");///
+       setup_text[eLDAP_Host] = _(
+"Please enter the host name or IP address of your LDAP server.\n");
 
-"Please enter the port number of the LDAP service (usually 389).\n",
+       setup_titles[eLDAP_Port] = _("LDAP port number:");////
+       setup_text[eLDAP_Port] = _(
+"Please enter the port number of the LDAP service (usually 389).\n");
 
+       setup_titles[eLDAP_Base_DN] = _("LDAP base DN:");///
+       setup_text[eLDAP_Base_DN] = _(
 "Please enter the Base DN to search for authentication\n"
-"(for example: dc=example,dc=com)\n",
+"(for example: dc=example,dc=com)\n");
 
+       setup_titles[eLDAP_Bind_DN] = _("LDAP bind DN:");//
+       setup_text[eLDAP_Bind_DN] = _(
 "Please enter the DN of an account to use for binding to the LDAP server\n"
 "for performing queries.  The account does not require any other\n"
 "privileges.  If your LDAP server allows anonymous queries, you can.\n"
-"leave this blank.\n",
+"leave this blank.\n");
 
+       setup_titles[eLDAP_Bind_PW] = _("LDAP bind password:");//
+       setup_text[eLDAP_Bind_PW] = _(
 "If you entered a Bind DN in the previous question, you must now enter\n"
 "the password associated with that account.  Otherwise, you can leave this\n"
-"blank.\n"
+"blank.\n");
+}
+
+/*
+ * print the actual stack frame.
+ */
+void cit_backtrace(void)
+{
+#ifdef HAVE_BACKTRACE
+       void *stack_frames[50];
+       size_t size, i;
+       char **strings;
+
+       size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
+       strings = backtrace_symbols(stack_frames, size);
+       for (i = 0; i < size; i++) {
+               if (strings != NULL)
+                       fprintf(stderr, "%s\n", strings[i]);
+               else
+                       fprintf(stderr, "%p\n", stack_frames[i]);
+       }
+       free(strings);
+#endif
+}
+
+struct config config;
 
-};
 
 struct config config;
 int direction;
@@ -182,7 +241,7 @@ void cleanup(int exitcode)
 
 
 
-void title(char *text)
+void title(const char *text)
 {
        if (setup_type == UI_TEXT) {
                printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<%s>\n", text);
@@ -191,7 +250,7 @@ void title(char *text)
 
 
 
-int yesno(char *question, int default_value)
+int yesno(const char *question, int default_value)
 {
        int i = 0;
        int answer = 0;
@@ -239,7 +298,7 @@ int yesno(char *question, int default_value)
 }
 
 
-void important_message(char *title, char *msgtext)
+void important_message(const char *title, const char *msgtext)
 {
        char buf[SIZ];
        int rv;
@@ -287,8 +346,7 @@ void progress(char *text, long int curr, long int cmax)
        case UI_TEXT:
                if (curr == 0) {
                        printf("%s\n", text);
-                       printf("..........................");
-                       printf("..........................");
+                       printf("....................................................");
                        printf("..........................\r");
                        fflush(stdout);
                        dots_printed = 0;
@@ -372,7 +430,6 @@ void check_services_entry(void)
 
 /*
  * delete_inittab_entry()  -- Remove obsolete /etc/inittab entry for Citadel
- *
  */
 void delete_inittab_entry(void)
 {
@@ -442,7 +499,6 @@ void delete_inittab_entry(void)
 
 /*
  * install_init_scripts()  -- Try to configure to start Citadel at boot
- *
  */
 void install_init_scripts(void)
 {
@@ -496,8 +552,8 @@ void install_init_scripts(void)
                "\n"
                "CITADEL_DIR=%s\n"
                ,
-               setup_directory,
-               setup_directory
+               ctdl_run_dir,
+               ctdl_sbin_dir
                );
        fprintf(fp,     "\n"
                "test -d /var/run || exit 0\n"
@@ -505,7 +561,7 @@ void install_init_scripts(void)
                "case \"$1\" in\n"
                "\n"
                "start)         echo -n \"Starting Citadel... \"\n"
-               "               if $CITADEL_DIR/citserver -lmail -d -h$CITADEL_DIR\n"
+               "               if $CITADEL_DIR/citserver -lmail -d\n"
                "               then\n"
                "                       echo \"ok\"\n"
                "               else\n"
@@ -520,7 +576,7 @@ void install_init_scripts(void)
                "               fi\n"
                "               rm -f %s/citadel.pid 2>/dev/null\n"
                ,
-               setup_directory
+               ctdl_run_dir
                );
        fprintf(fp,     "               ;;\n"
                "restart)       if $CITADEL_DIR/sendcommand DOWN 1 >/dev/null 2>&1 ; then\n"
@@ -549,9 +605,6 @@ void install_init_scripts(void)
 
 
 
-
-
-
 /*
  * On systems which use xinetd, see if we can offer to install Citadel as
  * the default telnet target.
@@ -567,7 +620,7 @@ void check_xinetd_entry(void) {
        if (fp == NULL) return;         /* Not there.  Oh well... */
 
        while (fgets(buf, sizeof buf, fp) != NULL) {
-               if (strstr(buf, setup_directory) != NULL) already_citadel = 1;
+               if (strstr(buf, "/citadel") != NULL) already_citadel = 1;
        }
        fclose(fp);
        if (already_citadel) return;    /* Already set up this way. */
@@ -615,7 +668,7 @@ void check_xinetd_entry(void) {
 /*
  * Offer to disable other MTA's
  */
-void disable_other_mta(char *mta) {
+void disable_other_mta(const char *mta) {
        char buf[SIZ];
        FILE *fp;
        int lines = 0;
@@ -657,13 +710,49 @@ void disable_other_mta(char *mta) {
        rv = system(buf);
 }
 
+const char *other_mtas[] = {
+       "courier-authdaemon",
+       "courier-imap",
+       "courier-imap-ssl",
+       "courier-pop",
+       "courier-pop3",
+       "courier-pop3d",
+       "cyrmaster",
+       "cyrus",
+       "dovecot",
+       "exim",
+       "exim4",
+       "imapd",
+       "mta",
+       "pop3d",
+       "popd",
+       "postfix",
+       "qmail",
+       "saslauthd",
+       "sendmail",
+       "vmailmgrd",
+       ""
+};
 
-
+void disable_other_mtas(void)
+{
+       int i = 0;
+       if ((getenv("ACT_AS_MTA") == NULL) || 
+           (getenv("ACT_AS_MTA") &&
+            strcasecmp(getenv("ACT_AS_MTA"), "yes") == 0)) {
+               /* Offer to disable other MTA's on the system. */
+               while (!IsEmptyStr(other_mtas[i]))
+               {
+                       disable_other_mta(other_mtas[i]);
+                       i++;
+               }
+       }
+}
 
 /* 
  * Check to see if our server really works.  Returns 0 on success.
  */
-int test_server(char *setup_directory, char *relhomestr, int relhome) {
+int test_server(char *relhomestr, int relhome) {
        char cmd[256];
        char cookie[256];
        FILE *fp;
@@ -703,7 +792,7 @@ int test_server(char *setup_directory, char *relhomestr, int relhome) {
        return(-1);
 }
 
-void strprompt(char *prompt_title, char *prompt_text, char *str)
+void strprompt(const char *prompt_title, const char *prompt_text, char *Target, char *DefValue)
 {
        char buf[SIZ] = "";
        char setupmsg[SIZ];
@@ -717,13 +806,13 @@ void strprompt(char *prompt_title, char *prompt_text, char *str)
        case UI_TEXT:
                title(prompt_title);
                printf("\n%s\n", prompt_text);
-               printf("This is currently set to:\n%s\n", str);
+               printf("This is currently set to:\n%s\n", Target);
                printf("Enter new value or press return to leave unchanged:\n");
                if (fgets(buf, sizeof buf, stdin)){
                        buf[strlen(buf) - 1] = 0;
                }
                if (!IsEmptyStr(buf))
-                       strcpy(str, buf);
+                       strcpy(Target, buf);
                break;
 
        case UI_DIALOG:
@@ -731,14 +820,14 @@ void strprompt(char *prompt_title, char *prompt_text, char *str)
                sprintf(buf, "exec %s --inputbox '%s' 19 72 '%s' 2>%s",
                        getenv("CTDL_DIALOG"),
                        prompt_text,
-                       str,
+                       Target,
                        dialog_result);
                rv = system(buf);
                fp = fopen(dialog_result, "r");
                if (fp != NULL) {
-                       if (fgets(str, sizeof buf, fp)) {
-                               if (str[strlen(str)-1] == 10) {
-                                       str[strlen(str)-1] = 0;
+                       if (fgets(Target, sizeof buf, fp)) {
+                               if (Target[strlen(Target)-1] == 10) {
+                                       Target[strlen(Target)-1] = 0;
                                }
                        }
                        fclose(fp);
@@ -746,42 +835,48 @@ void strprompt(char *prompt_title, char *prompt_text, char *str)
                }
                break;
        case UI_SILENT:
+               strcpy(Target, DefValue);
                break;
        }
 }
 
-void set_bool_val(int msgpos, int *ip) {
+void set_bool_val(int msgpos, int *ip, char *DefValue) 
+{
        title(setup_titles[msgpos]);
        *ip = yesno(setup_text[msgpos], *ip);
 }
 
-void set_str_val(int msgpos, char *str) {
-       strprompt(setup_titles[msgpos], setup_text[msgpos], str);
+void set_str_val(int msgpos, char *Target, char *DefValue) 
+{
+       strprompt(setup_titles[msgpos], 
+                 setup_text[msgpos], 
+                 Target, 
+                 DefValue);
 }
 
-void set_int_val(int msgpos, int *ip)
+void set_int_val(int msgpos, int *ip, char *DefValue)
 {
        char buf[16];
        snprintf(buf, sizeof buf, "%d", (int) *ip);
-       set_str_val(msgpos, buf);
+       set_str_val(msgpos, buf, DefValue);
        *ip = atoi(buf);
 }
 
 
-void set_char_val(int msgpos, char *ip)
+void set_char_val(int msgpos, char *ip, char *DefValue)
 {
        char buf[16];
        snprintf(buf, sizeof buf, "%d", (int) *ip);
-       set_str_val(msgpos, buf);
+       set_str_val(msgpos, buf, DefValue);
        *ip = (char) atoi(buf);
 }
 
 
-void set_long_val(int msgpos, long int *ip)
+void set_long_val(int msgpos, long int *ip, char *DefValue)
 {
        char buf[16];
        snprintf(buf, sizeof buf, "%ld", *ip);
-       set_str_val(msgpos, buf);
+       set_str_val(msgpos, buf, DefValue);
        *ip = atol(buf);
 }
 
@@ -791,38 +886,31 @@ void edit_value(int curr)
        int i;
        struct passwd *pw;
        char ctdluidname[256];
+       char *Value = NULL;
+
+       if (setup_type == UI_SILENT)
+       {
+               Value = getenv(EnvNames[curr]);
+       }
+       if (Value == NULL)
+               Value = "";
+
 
        switch (curr) {
 
-       case 1:
-               if (setup_type == UI_SILENT)
-               {
-                       if (getenv("SYSADMIN_NAME")) {
-                               strcpy(config.c_sysadm, getenv("SYSADMIN_NAME"));
-                       }
-               }
-               else {
-                       set_str_val(curr, config.c_sysadm);
-               }
+       case eSysAdminName:
+               set_str_val(curr, config.c_sysadm, Value);
                break;
 
-       case 2:
-               if (setup_type == UI_SILENT)
-               {
-                       if (getenv("SYSADMIN_PW")) {
-                               strcpy(admin_pass, getenv("SYSADMIN_PW"));
-                       }
-               }
-               else {
-                       set_str_val(curr, admin_pass);
-               }
+       case eSysAdminPW:
+               set_str_val(curr, admin_pass, Value);
                break;
        
-       case 3:
+       case eUID:
                if (setup_type == UI_SILENT)
                {               
-                       if (getenv("CITADEL_UID")) {
-                               config.c_ctdluid = atoi(getenv("CITADEL_UID"));
+                       if (Value) {
+                               config.c_ctdluid = atoi(Value);
                        }                                       
                }
                else
@@ -833,12 +921,12 @@ void edit_value(int curr)
                        i = config.c_ctdluid;
                        pw = getpwuid(i);
                        if (pw == NULL) {
-                               set_int_val(curr, &i);
+                               set_int_val(curr, &i, Value);
                                config.c_ctdluid = i;
                        }
                        else {
                                strcpy(ctdluidname, pw->pw_name);
-                               set_str_val(curr, ctdluidname);
+                               set_str_val(curr, ctdluidname, Value);
                                pw = getpwnam(ctdluidname);
                                if (pw != NULL) {
                                        config.c_ctdluid = pw->pw_uid;
@@ -851,37 +939,20 @@ void edit_value(int curr)
                }
                break;
 
-       case 4:
-               if (setup_type == UI_SILENT)
-               {
-                       if (getenv("IP_ADDR")) {
-                               strcpy(config.c_ip_addr, getenv("IP_ADDR"));
-                       }
-               }
-               else {
-                       set_str_val(curr, config.c_ip_addr);
-               }
+       case eIP_ADDR:
+               set_str_val(curr, config.c_ip_addr, Value);
                break;
 
-       case 5:
-               if (setup_type == UI_SILENT)
-               {
-                       if (getenv("CITADEL_PORT")) {
-                               config.c_port_number = atoi(getenv("CITADEL_PORT"));
-                       }
-               }
-               else
-               {
-                       set_int_val(curr, &config.c_port_number);
-               }
+       case eCTDL_Port:
+               set_int_val(curr, &config.c_port_number, Value);
                break;
 
-       case 6:
+       case eAuthType:
                if (setup_type == UI_SILENT)
                {
                        const char *auth;
                        config.c_auth_mode = AUTHMODE_NATIVE;
-                       auth = getenv("ENABLE_UNIX_AUTH");
+                       auth = Value;
                        if (auth != NULL)
                        {
                                if ((strcasecmp(auth, "yes") == 0) ||
@@ -899,80 +970,34 @@ void edit_value(int curr)
                        }
                }
                else {
-                       set_int_val(curr, &config.c_auth_mode);
+                       set_int_val(curr, &config.c_auth_mode, Value);
                }
                break;
 
-       case 7:
-               if (setup_type == UI_SILENT)
-               {
-                       if (getenv("LDAP_HOST")) {
-                               strcpy(config.c_ldap_host, getenv("LDAP_HOST"));
-                       }
-               }
-               else
-               {
-                       set_str_val(curr, config.c_ldap_host);
-               }
+       case eLDAP_Host:
+               set_str_val(curr, config.c_ldap_host, Value);
                break;
 
-       case 8:
-               if (setup_type == UI_SILENT)
-               {
-                       if (getenv("LDAP_PORT")) {
-                               config.c_ldap_port = atoi(getenv("LDAP_PORT"));
-                       }
-               }
-               else
-               {
-                       if (config.c_ldap_port == 0) {
-                               config.c_ldap_port = 389;
-                       }
-                       set_int_val(curr, &config.c_ldap_port);
+       case eLDAP_Port:
+               if (config.c_ldap_port == 0) {
+                       config.c_ldap_port = 389;
                }
+               set_int_val(curr, &config.c_ldap_port, Value);
                break;
 
-       case 9:
-               if (setup_type == UI_SILENT)
-               {
-                       if (getenv("LDAP_BASE_DN")) {
-                               strcpy(config.c_ldap_base_dn, getenv("LDAP_BASE_DN"));
-                       }
-               }
-               else
-               {
-                       set_str_val(curr, config.c_ldap_base_dn);
-               }
+       case eLDAP_Base_DN:
+               set_str_val(curr, config.c_ldap_base_dn, Value);
                break;
 
-       case 10:
-               if (setup_type == UI_SILENT)
-               {
-                       if (getenv("LDAP_BIND_DN")) {
-                               strcpy(config.c_ldap_bind_dn, getenv("LDAP_BIND_DN"));
-                       }
-               }
-               else
-               {
-                       set_str_val(curr, config.c_ldap_bind_dn);
-               }
+       case eLDAP_Bind_DN:
+               set_str_val(curr, config.c_ldap_bind_dn, Value);
                break;
 
-       case 11:
-               if (setup_type == UI_SILENT)
-               {
-                       if (getenv("LDAP_BIND_PW")) {
-                               strcpy(config.c_ldap_bind_pw, getenv("LDAP_BIND_PW"));
-                       }
-               }
-               else
-               {
-                       set_str_val(curr, config.c_ldap_bind_pw);
-               }
+       case eLDAP_Bind_PW:
+               set_str_val(curr, config.c_ldap_bind_pw, Value);
                break;
 
        }
-
 }
 
 /*
@@ -1016,6 +1041,13 @@ int discover_ui(void)
 
 
 
+void migrate_old_installs(void)
+{
+       int rv;
+       rv = system("exec /bin/rm -fr ./rooms ./chatpipes ./expressmsgs ./sessions 2>/dev/null");
+       unlink("citadel.log");
+       unlink("weekly");
+}
 
 
 /*
@@ -1103,156 +1135,77 @@ void fixnss(void) {
        unlink(new_filename);
 }
 
+void check_init_script (char *relhome)
+{
+       int rv;
+       FILE *fp;
+
+       /* 
+        * If we're running on SysV, install init scripts.
+        */
+       if (!access("/var/run", W_OK)) {
+
+               if (getenv("NO_INIT_SCRIPTS") == NULL) {
+                       install_init_scripts();
+               }
 
+               if (!access("/etc/init.d/citadel", X_OK)) {
+                       rv = system("/etc/init.d/citadel start");
+                       sleep(3);
+               }
 
+               if (test_server(relhome, enable_home) == 0) {
+                       char buf[SIZ];
+                       int found_it = 0;
 
+                       if (config.c_auth_mode == AUTHMODE_NATIVE) {
+                               snprintf (admin_cmd, sizeof(admin_cmd), "%s/sendcommand \"CREU %s|%s\" 2>&1", 
+                                       ctdl_sbin_dir, config.c_sysadm, admin_pass);
+                               fp = popen(admin_cmd, "r");
+                               if (fp != NULL) {
+                                       while (fgets(buf, sizeof buf, fp) != NULL) 
+                                       {
+                                               if ((atol(buf) == 574) || (atol(buf) == 200))
+                                                       ++found_it;
+                                       }
+                                       pclose(fp);
+                               }
+                       
+                               if (found_it == 0) {
+                                       important_message("Error","Setup failed to create your admin user");
+                               }
+                       }
 
+                       if (setup_type != UI_SILENT)
+                               important_message("Setup finished",
+                                                 "Setup of the Citadel server is complete.\n"
+                                                 "If you will be using WebCit, please run its\n"
+                                                 "setup program now; otherwise, run './citadel'\n"
+                                                 "to log in.\n");
+               }
+               else {
+                       important_message("Setup failed",
+                               "Setup is finished, but the Citadel server failed to start.\n"
+                               "Go back and check your configuration.\n"
+                       );
+               }
 
+       }
 
+       else {
+               important_message("Setup finished",
+                       "Setup is finished.  You may now start the server.");
+       }
+}
 
-int main(int argc, char *argv[])
+void set_default_values(void)
 {
-       int a;
-       int curr; 
-       char aaa[128];
-       FILE *fp;
-       int old_setup_level = 0;
-       int info_only = 0;
-       struct utsname my_utsname;
        struct passwd *pw;
+       struct utsname my_utsname;
        struct hostent *he;
-       gid_t gid;
-       int relh=0;
-       int home=0;
-       char relhome[PATH_MAX]="";
-       char ctdldir[PATH_MAX]=CTDLDIR;
-       int rv;
-       
-       /* set an invalid setup type */
-       setup_type = (-1);
 
-       /* Check to see if we're running the web installer */
-       if (getenv("CITADEL_INSTALLER") != NULL) {
-               using_web_installer = 1;
-       }
-
-       /* parse command line args */
-       for (a = 0; a < argc; ++a) {
-               if (!strncmp(argv[a], "-u", 2)) {
-                       strcpy(aaa, argv[a]);
-                       strcpy(aaa, &aaa[2]);
-                       setup_type = atoi(aaa);
-               }
-               else if (!strcmp(argv[a], "-i")) {
-                       info_only = 1;
-               }
-               else if (!strcmp(argv[a], "-q")) {
-                       setup_type = UI_SILENT;
-               }
-               else if (!strncmp(argv[a], "-h", 2)) {
-                       relh=argv[a][2]!='/';
-                       if (!relh) {
-                               safestrncpy(ctdl_home_directory, &argv[a][2], sizeof ctdl_home_directory);
-                       } else {
-                               safestrncpy(relhome, &argv[a][2], sizeof relhome);
-                       }
-                       home = 1;
-               }
-
-       }
-
-       calc_dirs_n_files(relh, home, relhome, ctdldir, 0);
-
-       /* If a setup type was not specified, try to determine automatically
-        * the best one to use out of all available types.
-        */
-       if (setup_type < 0) {
-               setup_type = discover_ui();
-       }
-       if (info_only == 1) {
-               important_message("Citadel Setup", CITADEL);
-               cleanup(0);
-       }
-
-       /* Get started in a valid setup directory. */
-       strcpy(setup_directory, ctdl_run_dir);
-       if ( (using_web_installer) && (getenv("CITADEL") != NULL) ) {
-               strcpy(setup_directory, getenv("CITADEL"));
-       }
-       else {
-               set_str_val(0, setup_directory);
-       }
-
-       enable_home = ( relh | home );
-
-       if (chdir(setup_directory) != 0) {
-               char errmsg[SIZ];
-               sprintf(errmsg, "The directory you specified does not exist: [%s]\n", setup_directory);
-               
-               important_message("Citadel Setup", errmsg);
-               cleanup(errno);
-       }
-
-       /* Determine our host name, in case we need to use it as a default */
-       uname(&my_utsname);
-
-       /* Try to stop Citadel if we can */
-       if (!access("/etc/init.d/citadel", X_OK)) {
-               rv = system("/etc/init.d/citadel stop");
-       }
-
-       /* Make sure Citadel is not running. */
-       if (test_server(setup_directory, relhome, enable_home) == 0) {
-               important_message("Citadel Setup",
-                       "The Citadel service is still running.\n"
-                       "Please stop the service manually and run "
-                       "setup again.");
-               cleanup(1);
-       }
-
-       /* Now begin. */
-       switch (setup_type) {
-
-       case UI_TEXT:
-               printf("\n\n\n"
-                       "              *** Citadel setup program ***\n\n");
-               break;
-
-       }
-
-       /*
-        * What we're going to try to do here is append a whole bunch of
-        * nulls to the citadel.config file, so we can keep the old config
-        * values if they exist, but if the file is missing or from an
-        * earlier version with a shorter config structure, when setup tries
-        * to read the old config parameters, they'll all come up zero.
-        * The length of the config file will be set to what it's supposed
-        * to be when we rewrite it, because we replace the old file with a
-        * completely new copy.
-        */
-       if ((a = open(file_citadel_config, O_WRONLY | O_CREAT | O_APPEND,
-                     S_IRUSR | S_IWUSR)) == -1) {
-               display_error("setup: cannot append citadel.config");
-               cleanup(errno);
-       }
-       fp = fdopen(a, "ab");
-       if (fp == NULL) {
-               display_error("setup: cannot append citadel.config");
-               cleanup(errno);
-       }
-       for (a = 0; a < sizeof(struct config); ++a) {
-               putc(0, fp);
-       }
-       fclose(fp);
-
-       /* now we re-open it, and read the old or blank configuration */
-       fp = fopen(file_citadel_config, "rb");
-       if (fp == NULL) {
-               display_error("setup: cannot open citadel.config");
-               cleanup(errno);
-       }
-       rv = fread((char *) &config, sizeof(struct config), 1, fp);
-       fclose(fp);
+       /* Determine our host name, in case we need to use it as a default */
+       uname(&my_utsname);
 
        /* set some sample/default values in place of blanks... */
        if (IsEmptyStr(config.c_nodename))
@@ -1335,6 +1288,151 @@ int main(int argc, char *argv[])
        if (config.c_managesieve_port == 0) config.c_managesieve_port = 2020;
        if (config.c_xmpp_c2s_port == 0) config.c_xmpp_c2s_port = 5222;
        if (config.c_xmpp_s2s_port == 0) config.c_xmpp_s2s_port = 5269;
+}
+
+
+void get_config (void)
+{
+       int a;
+       int rv;
+       FILE *fp;
+
+       /*
+        * What we're going to try to do here is append a whole bunch of
+        * nulls to the citadel.config file, so we can keep the old config
+        * values if they exist, but if the file is missing or from an
+        * earlier version with a shorter config structure, when setup tries
+        * to read the old config parameters, they'll all come up zero.
+        * The length of the config file will be set to what it's supposed
+        * to be when we rewrite it, because we replace the old file with a
+        * completely new copy.
+        */
+       if ((a = open(file_citadel_config, O_WRONLY | O_CREAT | O_APPEND,
+                     S_IRUSR | S_IWUSR)) == -1) {
+               display_error("setup: cannot append citadel.config");
+               cleanup(errno);
+       }
+       fp = fdopen(a, "ab");
+       if (fp == NULL) {
+               display_error("setup: cannot append citadel.config");
+               cleanup(errno);
+       }
+       for (a = 0; a < sizeof(struct config); ++a) {
+               putc(0, fp);
+       }
+       fclose(fp);
+
+       /* now we re-open it, and read the old or blank configuration */
+       fp = fopen(file_citadel_config, "rb");
+       if (fp == NULL) {
+               display_error("setup: cannot open citadel.config");
+               cleanup(errno);
+       }
+       rv = fread((char *) &config, sizeof(struct config), 1, fp);
+       fclose(fp);
+
+}
+
+int main(int argc, char *argv[])
+{
+       int a;
+       int curr; 
+       char aaa[128];
+       int old_setup_level = 0;
+       int info_only = 0;
+       int relh=0;
+       int home=0;
+       char relhome[PATH_MAX]="";
+       char ctdldir[PATH_MAX]=CTDLDIR;
+       int rv;
+       struct passwd *pw;
+       gid_t gid;
+       
+       /* set an invalid setup type */
+       setup_type = (-1);
+
+       /* Check to see if we're running the web installer */
+       if (getenv("CITADEL_INSTALLER") != NULL) {
+               using_web_installer = 1;
+       }
+
+       /* parse command line args */
+       for (a = 0; a < argc; ++a) {
+               if (!strncmp(argv[a], "-u", 2)) {
+                       strcpy(aaa, argv[a]);
+                       strcpy(aaa, &aaa[2]);
+                       setup_type = atoi(aaa);
+               }
+               else if (!strcmp(argv[a], "-i")) {
+                       info_only = 1;
+               }
+               else if (!strcmp(argv[a], "-q")) {
+                       setup_type = UI_SILENT;
+               }
+               else if (!strncmp(argv[a], "-h", 2)) {
+                       relh=argv[a][2]!='/';
+                       if (!relh) {
+                               safestrncpy(ctdl_home_directory, &argv[a][2], sizeof ctdl_home_directory);
+                       } else {
+                               safestrncpy(relhome, &argv[a][2], sizeof relhome);
+                       }
+                       home = 1;
+               }
+
+       }
+
+       calc_dirs_n_files(relh, home, relhome, ctdldir, 0);
+       SetTitles();
+
+       /* If a setup type was not specified, try to determine automatically
+        * the best one to use out of all available types.
+        */
+       if (setup_type < 0) {
+               setup_type = discover_ui();
+       }
+       if (info_only == 1) {
+               important_message("Citadel Setup", CITADEL);
+               cleanup(0);
+       }
+
+       enable_home = ( relh | home );
+
+       if (chdir(ctdl_run_dir) != 0) {
+               char errmsg[SIZ];
+               sprintf(errmsg, "The directory you specified does not exist: [%s]\n", ctdl_run_dir);
+               
+               important_message("Citadel Setup", errmsg);
+               cleanup(errno);
+       }
+
+
+       /* Try to stop Citadel if we can */
+       if (!access("/etc/init.d/citadel", X_OK)) {
+               rv = system("/etc/init.d/citadel stop");
+       }
+
+       /* Make sure Citadel is not running. */
+       if (test_server(relhome, enable_home) == 0) {
+               important_message("Citadel Setup",
+                       "The Citadel service is still running.\n"
+                       "Please stop the service manually and run "
+                       "setup again.");
+               cleanup(1);
+       }
+
+       /* Now begin. */
+       switch (setup_type) {
+
+       case UI_TEXT:
+               printf("\n\n\n"
+                       "              *** Citadel setup program ***\n\n");
+               break;
+
+       }
+
+       get_config ();
+
+       set_default_values();
 
        /* Go through a series of dialogs prompting for config info */
        for (curr = 1; curr <= MAXSETUP; ++curr) {
@@ -1344,8 +1442,7 @@ int main(int argc, char *argv[])
                }
        }
 
-/***** begin version update section ***** */
-       /* take care of any updating that is necessary */
+       /***** begin version update section *****/
 
        old_setup_level = config.c_setup_level;
 
@@ -1354,173 +1451,54 @@ int main(int argc, char *argv[])
        }
 
        if (old_setup_level < 555) {
-               important_message("Citadel Setup",
-                                 "This Citadel installation is too old "
-                                 "to be upgraded.");
+               important_message(
+                       "Citadel Setup",
+                       "This Citadel installation is too old to be upgraded."
+               );
                cleanup(1);
        }
        write_config_to_disk();
 
        old_setup_level = config.c_setup_level;
 
-       /* end of version update section */
+       /***** end of version update section *****/
 
 NEW_INST:
        config.c_setup_level = REV_LEVEL;
 
-/******************************************/
-
-       write_config_to_disk();
-
-       rv = mkdir(ctdl_info_dir, 0700);
-       rv = chmod(ctdl_info_dir, 0700);
-       rv = chown(ctdl_info_dir, config.c_ctdluid, -1);
-
-       rv = mkdir(ctdl_bio_dir, 0700);
-       rv = chmod(ctdl_bio_dir, 0700);
-       rv = chown(ctdl_bio_dir, config.c_ctdluid, -1);
-
-       rv = mkdir(ctdl_usrpic_dir, 0700);
-       rv = chmod(ctdl_usrpic_dir, 0700);
-       rv = chown(ctdl_usrpic_dir, config.c_ctdluid, -1);
-
-       rv = mkdir(ctdl_message_dir, 0700);
-       rv = chmod(ctdl_message_dir, 0700);
-       rv = chown(ctdl_message_dir, config.c_ctdluid, -1);
-
-       rv = mkdir(ctdl_hlp_dir, 0700);
-       rv = chmod(ctdl_hlp_dir, 0700);
-       rv = chown(ctdl_hlp_dir, config.c_ctdluid, -1);
-
-       rv = mkdir(ctdl_image_dir, 0700);
-       rv = chmod(ctdl_image_dir, 0700);
-       rv = chown(ctdl_image_dir, config.c_ctdluid, -1);
-
-       rv = mkdir(ctdl_bb_dir, 0700);
-       rv = chmod(ctdl_bb_dir, 0700);
-       rv = chown(ctdl_bb_dir, config.c_ctdluid, -1);
+       if ((pw = getpwuid(config.c_ctdluid)) == NULL) {
+               gid = getgid();
+       } else {
+               gid = pw->pw_gid;
+       }
 
-       rv = mkdir(ctdl_file_dir, 0700);
-       rv = chmod(ctdl_file_dir, 0700);
-       rv = chown(ctdl_file_dir, config.c_ctdluid, -1);
+       create_run_directories(config.c_ctdluid, gid);
 
-       rv = mkdir(ctdl_netcfg_dir, 0700);
-       rv = chmod(ctdl_netcfg_dir, 0700);
-       rv = chown(ctdl_netcfg_dir, config.c_ctdluid, -1);
+       write_config_to_disk();
 
-       /* Delete files and directories used by older Citadel versions */
-       rv = system("exec /bin/rm -fr ./rooms ./chatpipes ./expressmsgs ./sessions 2>/dev/null");
-       unlink("citadel.log");
-       unlink("weekly");
+        migrate_old_installs();        /* Delete files and directories used by older Citadel versions */
 
-       if (((setup_type == UI_SILENT) && (getenv("ALTER_ETC_SERVICES")!=NULL)) || 
-           (setup_type != UI_SILENT))
+       if (    ((setup_type == UI_SILENT)
+               && (getenv("ALTER_ETC_SERVICES")!=NULL))
+               || (setup_type != UI_SILENT)
+       ) {
                check_services_entry(); /* Check /etc/services */
+       }
+
 #ifndef __CYGWIN__
        delete_inittab_entry(); /* Remove obsolete /etc/inittab entry */
        check_xinetd_entry();   /* Check /etc/xinetd.d/telnet */
-
-       if ((getenv("ACT_AS_MTA") == NULL) || 
-           (getenv("ACT_AS_MTA") &&
-            strcasecmp(getenv("ACT_AS_MTA"), "yes") == 0)) {
-               /* Offer to disable other MTA's on the system. */
-               disable_other_mta("courier-authdaemon");
-               disable_other_mta("courier-imap");
-               disable_other_mta("courier-imap-ssl");
-               disable_other_mta("courier-pop");
-               disable_other_mta("courier-pop3");
-               disable_other_mta("courier-pop3d");
-               disable_other_mta("cyrmaster");
-               disable_other_mta("cyrus");
-               disable_other_mta("dovecot");
-               disable_other_mta("exim");
-               disable_other_mta("exim4");
-               disable_other_mta("imapd");
-               disable_other_mta("mta");
-               disable_other_mta("pop3d");
-               disable_other_mta("popd");
-               disable_other_mta("postfix");
-               disable_other_mta("qmail");
-               disable_other_mta("saslauthd");
-               disable_other_mta("sendmail");
-               disable_other_mta("vmailmgrd");
-       }
+       disable_other_mtas();   /* Offer to disable other MTAs */
+       fixnss();               /* Check for the 'db' nss and offer to disable it */
 #endif
 
-       /* Check for the 'db' nss and offer to disable it */
-       fixnss();
-
-       if ((pw = getpwuid(config.c_ctdluid)) == NULL) {
-               gid = getgid();
-       } else {
-               gid = pw->pw_gid;
-       }
-
-       progress("Setting file permissions", 0, 3);
-       rv = chown(ctdl_run_dir, config.c_ctdluid, gid);
        progress("Setting file permissions", 1, 3);
        rv = chown(file_citadel_config, config.c_ctdluid, gid);
        progress("Setting file permissions", 2, 3);
        rv = chmod(file_citadel_config, S_IRUSR | S_IWUSR);
        progress("Setting file permissions", 3, 3);
 
-       /* 
-        * If we're running on SysV, install init scripts.
-        */
-       if (!access("/var/run", W_OK)) {
-
-               if (getenv("NO_INIT_SCRIPTS") == NULL) {
-                       install_init_scripts();
-               }
-
-               if (!access("/etc/init.d/citadel", X_OK)) {
-                       rv = system("/etc/init.d/citadel start");
-                       sleep(3);
-               }
-
-               if (test_server(setup_directory, relhome, enable_home) == 0) {
-                       char buf[SIZ];
-                       int found_it = 0;
-
-                       if (config.c_auth_mode == AUTHMODE_NATIVE) {
-                               snprintf (admin_cmd, sizeof(admin_cmd), "%s/sendcommand \"CREU %s|%s\" 2>&1", 
-                                       ctdl_sbin_dir, config.c_sysadm, admin_pass);
-                               fp = popen(admin_cmd, "r");
-                               if (fp != NULL) {
-                                       while (fgets(buf, sizeof buf, fp) != NULL) 
-                                       {
-                                               if ((atol(buf) == 574) || (atol(buf) == 200))
-                                                       ++found_it;
-                                       }
-                                       pclose(fp);
-                               }
-                       
-                               if (found_it == 0) {
-                                       important_message("Error","Setup failed to create your admin user");
-                               }
-                       }
-
-                       if (setup_type != UI_SILENT)
-                               important_message("Setup finished",
-                                                 "Setup of the Citadel server is complete.\n"
-                                                 "If you will be using WebCit, please run its\n"
-                                                 "setup program now; otherwise, run './citadel'\n"
-                                                 "to log in.\n");
-               }
-               else {
-                       important_message("Setup failed",
-                               "Setup is finished, but the Citadel server failed to start.\n"
-                               "Go back and check your configuration.\n"
-                       );
-               }
-
-       }
-
-       else {
-               important_message("Setup finished",
-                       "Setup is finished.  You may now start the server.");
-       }
-
+       check_init_script(relhome);
        cleanup(0);
        return 0;
 }