]> code.citadel.org Git - citadel.git/blobdiff - citadel/utils/setup.c
* remove setup_dir and lean on what citadel_dirs.c calculated for us.
[citadel.git] / citadel / utils / setup.c
index c87563c4f7e236e90920369761041f3efe9f1863..f2e1c8efb72b98ce8fe9c7adba3550b168838dfb 100644 (file)
@@ -5,6 +5,8 @@
  *
  */
 
+#define SHOW_ME_VAPPEND_PRINTF
+
 #include "ctdl_module.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";
+const char *EnvNames [eMaxQuestions] = {
+       "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[] =
+const char *setup_titles[eMaxQuestions];
+
+void SetTitles(void)
 {
-       "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"
-};
+       setup_titles[eCitadelHomeDir] = _("Citadel Home Directory");
+       setup_titles[eSysAdminName] = _("Citadel administrator username:");////
+       setup_titles[eSysAdminPW] = _("Administrator password:");//
+       setup_titles[eUID] = _("Citadel User ID:");
+       setup_titles[eIP_ADDR] = _("Listening address for the Citadel server:");///
+       setup_titles[eCTDL_Port] = _("Server port number:");
+       setup_titles[eAuthType] = _("Authentication method to use:");////
+       setup_titles[eLDAP_Host] = _("LDAP host:");///
+       setup_titles[eLDAP_Port] = _("LDAP port number:");////
+       setup_titles[eLDAP_Base_DN] = _("LDAP base DN:");///
+       setup_titles[eLDAP_Bind_DN] = _("LDAP bind DN:");//
+       setup_titles[eLDAP_Bind_PW] = _("LDAP bind password:");//
+}
 
 /**
  * \brief print the actual stack frame.
@@ -182,7 +229,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);
@@ -242,6 +289,7 @@ int yesno(char *question, int default_value)
 void important_message(char *title, char *msgtext)
 {
        char buf[SIZ];
+       int rv;
 
        switch (setup_type) {
 
@@ -256,7 +304,7 @@ void important_message(char *title, char *msgtext)
                sprintf(buf, "exec %s --msgbox '%s' 19 72",
                        getenv("CTDL_DIALOG"),
                        msgtext);
-               system(buf);
+               rv = system(buf);
                break;
        case UI_SILENT:
                fprintf(stderr, "%s\n", msgtext);
@@ -381,6 +429,7 @@ void delete_inittab_entry(void)
        char buf[1024];
        char outfilename[32];
        int changes_made = 0;
+       int rv;
 
        /* Determine the fully qualified path name of citserver */
        snprintf(looking_for, 
@@ -418,10 +467,10 @@ void delete_inittab_entry(void)
 
        while (fgets(buf, sizeof buf, infp) != NULL) {
                if (strstr(buf, looking_for) != NULL) {
-                       fwrite("#", 1, 1, outfp);
+                       rv = fwrite("#", 1, 1, outfp);
                        ++changes_made;
                }
-               fwrite(buf, strlen(buf), 1, outfp);
+               rv = fwrite(buf, strlen(buf), 1, outfp);
        }
 
        fclose(infp);
@@ -429,8 +478,8 @@ void delete_inittab_entry(void)
 
        if (changes_made) {
                sprintf(buf, "/bin/mv -f %s /etc/inittab 2>/dev/null", outfilename);
-               system(buf);
-               system("/sbin/init q 2>/dev/null");
+               rv = system(buf);
+               rv = system("/sbin/init q 2>/dev/null");
        }
        else {
                unlink(outfilename);
@@ -448,6 +497,7 @@ void install_init_scripts(void)
        FILE *fp;
        char *initfile = "/etc/init.d/citadel";
        char command[SIZ];
+       int rv;
 
        if ((stat("/etc/init.d/", &etcinitd) == -1) && 
            (errno == ENOENT))
@@ -493,8 +543,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"
@@ -502,7 +552,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"
@@ -517,7 +567,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"
@@ -536,11 +586,11 @@ void install_init_scripts(void)
        chmod(initfile, 0755);
 
        /* Set up the run levels. */
-       system("/bin/rm -f /etc/rc?.d/[SK]??citadel 2>/dev/null");
+       rv = system("/bin/rm -f /etc/rc?.d/[SK]??citadel 2>/dev/null");
        snprintf(command, sizeof(command), "for x in 2 3 4 5 ; do [ -d /etc/rc$x.d ] && ln -s %s /etc/rc$x.d/S79citadel ; done 2>/dev/null", initfile);
-       system(command);
+       rv = system(command);
        snprintf(command, sizeof(command),"for x in 0 6 S; do [ -d /etc/rc$x.d ] && ln -s %s /etc/rc$x.d/K30citadel ; done 2>/dev/null", initfile);
-       system(command);
+       rv = system(command);
 
 }
 
@@ -558,12 +608,13 @@ void check_xinetd_entry(void) {
        FILE *fp;
        char buf[SIZ];
        int already_citadel = 0;
+       int rv;
 
        fp = fopen(filename, "r+");
        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. */
@@ -603,7 +654,7 @@ void check_xinetd_entry(void) {
        fclose(fp);
 
        /* Now try to restart the service */
-       system("/etc/init.d/xinetd restart >/dev/null 2>&1");
+       rv = system("/etc/init.d/xinetd restart >/dev/null 2>&1");
 }
 
 
@@ -611,10 +662,11 @@ 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;
+       int rv;
 
        sprintf(buf, "/bin/ls -l /etc/rc*.d/S*%s 2>/dev/null; "
                "/bin/ls -l /etc/rc.d/rc*.d/S*%s 2>/dev/null",
@@ -647,18 +699,54 @@ void disable_other_mta(char *mta) {
        
 
        sprintf(buf, "for x in /etc/rc*.d/S*%s; do mv $x `echo $x |sed s/S/K/g`; done >/dev/null 2>&1", mta);
-       system(buf);
+       rv = system(buf);
        sprintf(buf, "/etc/init.d/%s stop >/dev/null 2>&1", mta);
-       system(buf);
+       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;
@@ -698,12 +786,13 @@ 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, char *prompt_text, char *Target, char *DefValue)
 {
        char buf[SIZ] = "";
        char setupmsg[SIZ];
        char dialog_result[PATH_MAX];
        FILE *fp = NULL;
+       int rv;
 
        strcpy(setupmsg, "");
 
@@ -711,13 +800,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:
@@ -725,14 +814,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);
-               system(buf);
+               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);
@@ -740,42 +829,46 @@ 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);
 }
 
@@ -785,38 +878,29 @@ 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]);
+       }
+
 
        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
@@ -827,12 +911,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;
@@ -845,37 +929,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) ||
@@ -893,77 +960,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
-               {
-                       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;
 
        }
-
 }
 
 /*
@@ -973,6 +997,7 @@ void write_config_to_disk(void)
 {
        FILE *fp;
        int fd;
+       int rv;
 
        if ((fd = creat(file_citadel_config, S_IRUSR | S_IWUSR)) == -1) {
                display_error("setup: cannot open citadel.config");
@@ -983,7 +1008,7 @@ void write_config_to_disk(void)
                display_error("setup: cannot open citadel.config");
                cleanup(1);
        }
-       fwrite((char *) &config, sizeof(struct config), 1, fp);
+       rv = fwrite((char *) &config, sizeof(struct config), 1, fp);
        fclose(fp);
 }
 
@@ -1006,6 +1031,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");
+}
 
 
 /*
@@ -1021,6 +1053,7 @@ void fixnss(void) {
        int changed = 0;
        int file_changed = 0;
        char new_filename[64];
+       int rv;
 
        fp_read = fopen(NSSCONF, "r");
        if (fp_read == NULL) {
@@ -1086,163 +1119,84 @@ void fixnss(void) {
 
        if (yesno(question, 1)) {
                sprintf(buf, "/bin/mv -f %s %s", new_filename, NSSCONF);
-               system(buf);
+               rv = system(buf);
                chmod(NSSCONF, 0644);
        }
        unlink(new_filename);
 }
 
-
-
-
-
-
-
-
-int main(int argc, char *argv[])
+void check_init_script (char *relhome)
 {
-       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 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);
+       FILE *fp;
 
-       /* Check to see if we're running the web installer */
-       if (getenv("CITADEL_INSTALLER") != NULL) {
-               using_web_installer = 1;
-       }
+       /* 
+        * If we're running on SysV, install init scripts.
+        */
+       if (!access("/var/run", W_OK)) {
 
-       /* 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;
+               if (getenv("NO_INIT_SCRIPTS") == NULL) {
+                       install_init_scripts();
                }
-               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;
+
+               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;
 
-       calc_dirs_n_files(relh, home, relhome, ctdldir, 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 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);
-       }
+                       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"
+                       );
+               }
 
-       /* 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);
+               important_message("Setup finished",
+                       "Setup is finished.  You may now start the server.");
        }
+}
 
-       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);
-       }
+void set_default_values(void)
+{
+       struct passwd *pw;
+       struct utsname my_utsname;
+       struct hostent *he;
 
        /* 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);
-
        /* set some sample/default values in place of blanks... */
        if (IsEmptyStr(config.c_nodename))
                safestrncpy(config.c_nodename, my_utsname.nodename,
@@ -1324,6 +1278,150 @@ 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);
+
+       /* 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) {
@@ -1358,49 +1456,17 @@ NEW_INST:
        config.c_setup_level = REV_LEVEL;
 
 /******************************************/
+       if ((pw = getpwuid(config.c_ctdluid)) == NULL) {
+               gid = getgid();
+       } else {
+               gid = pw->pw_gid;
+       }
 
-       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);
-
-       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))
@@ -1408,108 +1474,18 @@ NEW_INST:
 #ifndef __CYGWIN__
        delete_inittab_entry(); /* Remove obsolete /etc/inittab entry */
        check_xinetd_entry();   /* Check /etc/xinetd.d/telnet */
+       disable_other_mtas();   /* Offer to disable other MTAs */
 
-       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");
-       }
 #endif
+       fixnss();       /* Check for the 'db' nss and offer to disable it */
 
-       /* 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;
 }