]> code.citadel.org Git - citadel.git/blobdiff - citadel/setup.c
* added message subject to all those tiny messages
[citadel.git] / citadel / setup.c
index e51a036154a5314354419b796c62d822b3568bc2..8a178efeec6b81abc32e807b96efecf3b4ccd090 100644 (file)
 #include <errno.h>
 #include <limits.h>
 #include <pwd.h>
 #include <errno.h>
 #include <limits.h>
 #include <pwd.h>
+#include <time.h>
 
 #include "citadel.h"
 #include "axdefs.h"
 #include "sysdep.h"
 #include "config.h"
 #include "tools.h"
 
 #include "citadel.h"
 #include "axdefs.h"
 #include "sysdep.h"
 #include "config.h"
 #include "tools.h"
+#include "citadel_dirs.h"
 
 #ifdef HAVE_NEWT
 #include <newt.h>
 
 #ifdef HAVE_NEWT
 #include <newt.h>
 #define MAXSETUP 4     /* How many setup questions to ask */
 
 #define UI_TEXT                0       /* Default setup type -- text only */
 #define MAXSETUP 4     /* How many setup questions to ask */
 
 #define UI_TEXT                0       /* Default setup type -- text only */
+#define UI_DIALOG      2       /* Use the 'dialog' program */
 #define UI_SILENT      3       /* Silent running, for use in scripts */
 #define UI_NEWT                4       /* Use the "newt" window library */
 
 #define SERVICE_NAME   "citadel"
 #define PROTO_NAME     "tcp"
 #define UI_SILENT      3       /* Silent running, for use in scripts */
 #define UI_NEWT                4       /* Use the "newt" window library */
 
 #define SERVICE_NAME   "citadel"
 #define PROTO_NAME     "tcp"
+#define NSSCONF                "/etc/nsswitch.conf"
 
 int setup_type;
 char setup_directory[SIZ];
 char citserver_init_entry[SIZ];
 int using_web_installer = 0;
 
 int setup_type;
 char setup_directory[SIZ];
 char citserver_init_entry[SIZ];
 int using_web_installer = 0;
+int enable_home = 1;
+
+/**
+ *     We will set have_sysv_init to nonzero if the host operating system
+ *     has a System V style init driven by /etc/inittab.  This will cause
+ *     setup to offer to automatically start and stop the Citadel service.
+ */
+int have_sysv_init = 0;
 
 #ifdef HAVE_LDAP
 void contemplate_ldap(void);
 
 #ifdef HAVE_LDAP
 void contemplate_ldap(void);
@@ -60,39 +72,48 @@ char *setup_titles[] =
 };
 
 
 };
 
 
-char *setup_text[] =
-{
-"Enter the full pathname of the directory in which the Citadel installation\n"
-"you are creating or updating resides.  If you specify a directory other\n"
-"than the default, you will need to specify the -h flag to the server when\n"
-"you start it up.\n",
-
-"Enter the name of the system administrator (which is probably you).\n"
-"When an account is created with this name, it will automatically be\n"
-"assigned the highest access level.\n",
-
-"Citadel needs to run under its own user ID.  This would typically be\n"
-"called \"citadel\", but if you are running Citadel as a public BBS, you\n"
-"might also call it \"bbs\" or \"guest\".  The server will run under this\n"
-"user ID.  Please specify that user ID here.  You may specify either a\n"
-"user name or a numeric UID.\n",
-
-"Specify the IP address on which your server will run.  If you leave this\n"
-"blank, or if you specify 0.0.0.0, Citadel will listen on all addresses.\n"
-"You can usually skip this unless you're running multiple instances of\n"
-"Citadel on the same computer.\n",
-
-"Specify the TCP port number on which your server will run.  Normally, this\n"
-"will be port 504, which is the official port assigned by the IANA for\n"
-"Citadel servers.  You'll only need to specify a different port number if\n"
-"you run multiple instances of Citadel on the same computer and there's\n"
-"something else already using port 504.\n",
-
-"Setup has detected that you currently have data files from a Citadel\n"
-"version 3.2x installation.  The program 'conv_32_40' can upgrade your\n"
-"files to version 4.0x format.\n"
-" Setup will now exit.  Please either run 'conv_32_40' or delete your data\n"
-"files, and run setup again.\n"
+struct config config;
+
+       /* calculate all our path on a central place */
+    /* where to keep our config */
+       
+
+char *setup_text[] = {
+#ifndef HAVE_RUN_DIR
+"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
+"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
+
+"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",
+
+"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",
+
+"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",
 
 };
 
 
 };
 
@@ -123,10 +144,10 @@ void set_init_entry(char *which_entry, char *new_state) {
        while(fgets(buf, sizeof buf, fp) != NULL) {
 
                if (num_tokens(buf, ':') == 4) {
        while(fgets(buf, sizeof buf, fp) != NULL) {
 
                if (num_tokens(buf, ':') == 4) {
-                       extract_token(entry, buf, 0, ':');
-                       extract_token(levels, buf, 1, ':');
-                       extract_token(state, buf, 2, ':');
-                       extract_token(prog, buf, 3, ':'); /* includes 0x0a LF */
+                       extract_token(entry, buf, 0, ':', sizeof entry);
+                       extract_token(levels, buf, 1, ':', sizeof levels);
+                       extract_token(state, buf, 2, ':', sizeof state);
+                       extract_token(prog, buf, 3, ':', sizeof prog); /* includes 0x0a LF */
 
                        if (!strcmp(entry, which_entry)) {
                                strcpy(state, new_state);
 
                        if (!strcmp(entry, which_entry)) {
                                strcpy(state, new_state);
@@ -157,12 +178,11 @@ void set_init_entry(char *which_entry, char *new_state) {
 /*
  * Locate the name of an inittab entry for a specific program
  */
 /*
  * Locate the name of an inittab entry for a specific program
  */
-void locate_init_entry(char *init_entry, char *program) {
+void locate_init_entry(char *init_entry, char *looking_for) {
 
        FILE *infp;
        char buf[SIZ];
        int have_entry = 0;
 
        FILE *infp;
        char buf[SIZ];
        int have_entry = 0;
-       char looking_for[SIZ];
        char entry[SIZ];
        char prog[SIZ];
 
        char entry[SIZ];
        char prog[SIZ];
 
@@ -177,8 +197,8 @@ void locate_init_entry(char *init_entry, char *program) {
        } else {
                while (fgets(buf, sizeof buf, infp) != NULL) {
                        buf[strlen(buf) - 1] = 0;
        } else {
                while (fgets(buf, sizeof buf, infp) != NULL) {
                        buf[strlen(buf) - 1] = 0;
-                       extract_token(entry, buf, 0, ':');      
-                       extract_token(prog, buf, 3, ':');
+                       extract_token(entry, buf, 0, ':', sizeof entry);
+                       extract_token(prog, buf, 3, ':', sizeof prog);
                        if (!strncasecmp(prog, looking_for,
                           strlen(looking_for))) {
                                ++have_entry;
                        if (!strncasecmp(prog, looking_for,
                           strlen(looking_for))) {
                                ++have_entry;
@@ -197,7 +217,15 @@ void locate_init_entry(char *init_entry, char *program) {
 void shutdown_citserver(void) {
        char looking_for[SIZ];
 
 void shutdown_citserver(void) {
        char looking_for[SIZ];
 
-       snprintf(looking_for, sizeof looking_for, "%s/citserver", BBSDIR);
+       snprintf(looking_for, 
+                        sizeof looking_for,
+                        "%s/citserver", 
+#ifndef HAVE_RUN_DIR
+                        setup_directory
+#else
+                        CTDLDIR
+#endif
+                        );
        locate_init_entry(citserver_init_entry, looking_for);
        if (strlen(citserver_init_entry) > 0) {
                set_init_entry(citserver_init_entry, "off");
        locate_init_entry(citserver_init_entry, looking_for);
        if (strlen(citserver_init_entry) > 0) {
                set_init_entry(citserver_init_entry, "off");
@@ -243,9 +271,9 @@ int yesno(char *question)
        newtComponent form = NULL;
        newtComponent yesbutton = NULL;
        newtComponent nobutton = NULL;
        newtComponent form = NULL;
        newtComponent yesbutton = NULL;
        newtComponent nobutton = NULL;
-       int i = 0;
        int prompt_window_height = 0;
 #endif
        int prompt_window_height = 0;
 #endif
+       int i = 0;
        int answer = 0;
        char buf[SIZ];
 
        int answer = 0;
        char buf[SIZ];
 
@@ -263,13 +291,26 @@ int yesno(char *question)
                } while ((answer < 0) || (answer > 1));
                break;
 
                } while ((answer < 0) || (answer > 1));
                break;
 
+       case UI_DIALOG:
+               sprintf(buf, "exec %s --yesno '%s' 10 72",
+                       getenv("CTDL_DIALOG"),
+                       question);
+               i = system(buf);
+               if (i == 0) {
+                       answer = 1;
+               }
+               else {
+                       answer = 0;
+               }
+               break;
+
 #ifdef HAVE_NEWT
        case UI_NEWT:
                prompt_window_height = num_tokens(question, '\n') + 5;
                newtCenteredWindow(76, prompt_window_height, "Question");
                form = newtForm(NULL, NULL, 0);
                for (i=0; i<num_tokens(question, '\n'); ++i) {
 #ifdef HAVE_NEWT
        case UI_NEWT:
                prompt_window_height = num_tokens(question, '\n') + 5;
                newtCenteredWindow(76, prompt_window_height, "Question");
                form = newtForm(NULL, NULL, 0);
                for (i=0; i<num_tokens(question, '\n'); ++i) {
-                       extract_token(buf, question, i, '\n');
+                       extract_token(buf, question, i, '\n', sizeof buf);
                        newtFormAddComponent(form, newtLabel(1, 1+i, buf));
                }
                yesbutton = newtButton(10, (prompt_window_height - 4), "Yes");
                        newtFormAddComponent(form, newtLabel(1, 1+i, buf));
                }
                yesbutton = newtButton(10, (prompt_window_height - 4), "Yes");
@@ -310,12 +351,19 @@ void important_message(char *title, char *msgtext)
                fgets(buf, sizeof buf, stdin);
                break;
 
                fgets(buf, sizeof buf, stdin);
                break;
 
+       case UI_DIALOG:
+               sprintf(buf, "exec %s --msgbox '%s' 19 72",
+                       getenv("CTDL_DIALOG"),
+                       msgtext);
+               system(buf);
+               break;
+
 #ifdef HAVE_NEWT
        case UI_NEWT:
                newtCenteredWindow(76, 10, title);
                form = newtForm(NULL, NULL, 0);
                for (i=0; i<num_tokens(msgtext, '\n'); ++i) {
 #ifdef HAVE_NEWT
        case UI_NEWT:
                newtCenteredWindow(76, 10, title);
                form = newtForm(NULL, NULL, 0);
                for (i=0; i<num_tokens(msgtext, '\n'); ++i) {
-                       extract_token(buf, msgtext, i, '\n');
+                       extract_token(buf, msgtext, i, '\n', sizeof buf);
                        newtFormAddComponent(form, newtLabel(1, 1+i, buf));
                }
                newtFormAddComponent(form, newtButton(35, 5, "OK"));
                        newtFormAddComponent(form, newtLabel(1, 1+i, buf));
                }
                newtFormAddComponent(form, newtButton(35, 5, "OK"));
@@ -352,6 +400,8 @@ void progress(char *text, long int curr, long int cmax)
 #endif
        static long dots_printed = 0L;
        long a = 0;
 #endif
        static long dots_printed = 0L;
        long a = 0;
+       static FILE *fp = NULL;
+       char buf[SIZ];
 
        switch (setup_type) {
 
 
        switch (setup_type) {
 
@@ -377,6 +427,33 @@ void progress(char *text, long int curr, long int cmax)
                }
                break;
 
                }
                break;
 
+       case UI_DIALOG:
+               if (curr == 0) {
+                       sprintf(buf, "exec %s --gauge '%s' 7 72 0",
+                               getenv("CTDL_DIALOG"),
+                               text);
+                       fp = popen(buf, "w");
+                       if (fp != NULL) {
+                               fprintf(fp, "0\n");
+                               fflush(fp);
+                       }
+               } 
+               else if (curr == cmax) {
+                       if (fp != NULL) {
+                               fprintf(fp, "100\n");
+                               pclose(fp);
+                               fp = NULL;
+                       }
+               }
+               else {
+                       a = (curr * 100) / cmax;
+                       if (fp != NULL) {
+                               fprintf(fp, "%ld\n", a);
+                               fflush(fp);
+                       }
+               }
+               break;
+
 #ifdef HAVE_NEWT
        case UI_NEWT:
                if (curr == 0) {
 #ifdef HAVE_NEWT
        case UI_NEWT:
                if (curr == 0) {
@@ -414,7 +491,7 @@ void check_services_entry(void)
        FILE *sfp;
 
        if (getservbyname(SERVICE_NAME, PROTO_NAME) == NULL) {
        FILE *sfp;
 
        if (getservbyname(SERVICE_NAME, PROTO_NAME) == NULL) {
-               for (i=0; i<3; ++i) {
+               for (i=0; i<=3; ++i) {
                        progress("Adding service entry...", i, 3);
                        if (i == 0) {
                                sfp = fopen("/etc/services", "a");
                        progress("Adding service entry...", i, 3);
                        if (i == 0) {
                                sfp = fopen("/etc/services", "a");
@@ -469,7 +546,15 @@ void check_inittab_entry(void)
        char entryname[5];
 
        /* Determine the fully qualified path name of citserver */
        char entryname[5];
 
        /* Determine the fully qualified path name of citserver */
-       snprintf(looking_for, sizeof looking_for, "%s/citserver", BBSDIR);
+       snprintf(looking_for, 
+                        sizeof looking_for,
+                        "%s/citserver", 
+#ifndef HAVE_RUN_DIR
+                        setup_directory
+#else
+                        CTDLDIR
+#endif
+                        );
        locate_init_entry(citserver_init_entry, looking_for);
 
        /* If there's already an entry, then we have nothing left to do. */
        locate_init_entry(citserver_init_entry, looking_for);
 
        /* If there's already an entry, then we have nothing left to do. */
@@ -478,13 +563,21 @@ void check_inittab_entry(void)
        }
 
        /* Otherwise, prompt the user to create an entry. */
        }
 
        /* Otherwise, prompt the user to create an entry. */
-       snprintf(question, sizeof question,
-               "Do you want this computer configured to start the Citadel\n"
-               "service automatically?  (If you answer yes, an entry in\n"
-               "/etc/inittab pointing to %s will be added.)\n",
-               looking_for);
-       if (yesno(question) == 0)
-               return;
+       if (getenv("CREATE_INITTAB_ENTRY") != NULL) {
+               if (strcasecmp(getenv("CREATE_INITTAB_ENTRY"), "yes")) {
+                       return;
+               }
+       }
+       else {
+               snprintf(question, sizeof question,
+                       "Do you want this computer configured to start the Citadel\n"
+                       "service automatically?  (If you answer yes, an entry in\n"
+                       "/etc/inittab pointing to %s will be added.)\n",
+                       looking_for);
+               if (yesno(question) == 0) {
+                       return;
+               }
+       }
 
        /* Generate a unique entry name for /etc/inittab */
        generate_entry_name(entryname);
 
        /* Generate a unique entry name for /etc/inittab */
        generate_entry_name(entryname);
@@ -495,8 +588,11 @@ void check_inittab_entry(void)
                display_error(strerror(errno));
        } else {
                fprintf(infp, "# Start the Citadel server...\n");
                display_error(strerror(errno));
        } else {
                fprintf(infp, "# Start the Citadel server...\n");
-               fprintf(infp, "%s:2345:respawn:%s -h%s -x3 -llocal4\n",
-                       entryname, looking_for, setup_directory);
+               fprintf(infp, "%s:2345:respawn:%s %s%s -llocal4\n",
+                               entryname, 
+                               looking_for, 
+                               (enable_home)?"-h":"", 
+                               (enable_home)?setup_directory:"");
                fclose(infp);
                strcpy(citserver_init_entry, entryname);
        }
                fclose(infp);
                strcpy(citserver_init_entry, entryname);
        }
@@ -523,13 +619,21 @@ void check_xinetd_entry(void) {
        if (already_citadel) return;    /* Already set up this way. */
 
        /* Otherwise, prompt the user to create an entry. */
        if (already_citadel) return;    /* Already set up this way. */
 
        /* Otherwise, prompt the user to create an entry. */
-       snprintf(buf, sizeof buf,
-               "Setup can configure the 'xinetd' service to automatically\n"
-               "connect incoming telnet sessions to Citadel, bypassing the\n"
-               "host system's login prompt.  Would you like to do this?\n"
-       );
-       if (yesno(buf) == 0)
-               return;
+       if (getenv("CREATE_XINETD_ENTRY") != NULL) {
+               if (strcasecmp(getenv("CREATE_XINETD_ENTRY"), "yes")) {
+                       return;
+               }
+       }
+       else {
+               snprintf(buf, sizeof buf,
+                       "Setup can configure the \"xinetd\" service to automatically\n"
+                       "connect incoming telnet sessions to Citadel, bypassing the\n"
+                       "host system login: prompt.  Would you like to do this?\n"
+               );
+               if (yesno(buf) == 0) {
+                       return;
+               }
+       }
 
        fp = fopen(filename, "w");
        fprintf(fp,
 
        fp = fopen(filename, "w");
        fprintf(fp,
@@ -545,8 +649,12 @@ void check_xinetd_entry(void) {
                "       server_args     = -h -L %s/citadel\n"
                "       log_on_failure  += USERID\n"
                "}\n",
                "       server_args     = -h -L %s/citadel\n"
                "       log_on_failure  += USERID\n"
                "}\n",
-               setup_directory
-       );
+#ifndef HAVE_RUN_DIR
+                       setup_directory
+#else
+                       RUN_DIR
+#endif
+                       );
        fclose(fp);
 
        /* Now try to restart the service */
        fclose(fp);
 
        /* Now try to restart the service */
@@ -563,7 +671,9 @@ void disable_other_mta(char *mta) {
        FILE *fp;
        int lines = 0;
 
        FILE *fp;
        int lines = 0;
 
-       sprintf(buf, "/bin/ls -l /etc/rc*.d/S*%s 2>/dev/null", mta);
+       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",
+               mta, mta);
        fp = popen(buf, "r");
        if (fp == NULL) return;
 
        fp = popen(buf, "r");
        if (fp == NULL) return;
 
@@ -573,16 +683,29 @@ void disable_other_mta(char *mta) {
        fclose(fp);
        if (lines == 0) return;         /* Nothing to do. */
 
        fclose(fp);
        if (lines == 0) return;         /* Nothing to do. */
 
+
        /* Offer to replace other MTA with the vastly superior Citadel :)  */
        /* Offer to replace other MTA with the vastly superior Citadel :)  */
-       snprintf(buf, sizeof buf,
-               "You appear to have the '%s' email program\n"
-               "running on your system.  Would you like to disable it,\n"
-               "allowing Citadel to handle your system's Internet mail\n"
-               "instead?\n",
-               mta
-       );
-       if (yesno(buf) == 0)
-               return;
+
+       if (getenv("ACT_AS_MTA")) {
+               if (strcasecmp(getenv("ACT_AS_MTA"), "yes")) {
+                       return;
+               }
+       }
+       else {
+               snprintf(buf, sizeof buf,
+                       "You appear to have the \"%s\" email program\n"
+                       "running on your system.  If you want Citadel mail\n"
+                       "connected with %s, you will have to manually integrate\n"
+                       "them.  It is preferable to disable %s, and use Citadel's\n"
+                       "SMTP, POP3, and IMAP services.\n\n"
+                       "May we disable %s so that Citadel has access to ports\n"
+                       "25, 110, and 143?\n",
+                       mta, mta, mta, mta
+               );
+               if (yesno(buf) == 0) {
+                       return;
+               }
+       }
 
        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);
 
        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);
@@ -607,12 +730,17 @@ int test_server(void) {
         * to the server and try to get it back.  The cookie does not
         * have to be secret ... just unique.
         */
         * to the server and try to get it back.  The cookie does not
         * have to be secret ... just unique.
         */
-       sprintf(cookie, "%ld.%d", time(NULL), getpid());
+       sprintf(cookie, "--test--%d--", getpid());
 
 
-       sprintf(cmd, "%s/sendcommand -h%s ECHO %s 2>&1",
-               setup_directory,
-               setup_directory,
-               cookie);
+       sprintf(cmd, "%s/sendcommand %s%s ECHO %s 2>&1",
+#ifndef HAVE_RUN_DIR
+                       setup_directory,
+#else
+                       CTDLDIR,
+#endif
+                       (enable_home)?"-h":"", 
+                       (enable_home)?setup_directory:"",
+                       cookie);
 
        fp = popen(cmd, "r");
        if (fp == NULL) return(errno);
 
        fp = popen(cmd, "r");
        if (fp == NULL) return(errno);
@@ -641,6 +769,8 @@ void strprompt(char *prompt_title, char *prompt_text, char *str)
 #endif
        char buf[SIZ];
        char setupmsg[SIZ];
 #endif
        char buf[SIZ];
        char setupmsg[SIZ];
+       char dialog_result[PATH_MAX];
+       FILE *fp = NULL;
 
        strcpy(setupmsg, "");
 
 
        strcpy(setupmsg, "");
 
@@ -655,6 +785,26 @@ void strprompt(char *prompt_title, char *prompt_text, char *str)
                if (strlen(buf) != 0)
                        strcpy(str, buf);
                break;
                if (strlen(buf) != 0)
                        strcpy(str, buf);
                break;
+
+       case UI_DIALOG:
+               CtdlMakeTempFileName(dialog_result, sizeof dialog_result);
+               sprintf(buf, "exec %s --inputbox '%s' 19 72 '%s' 2>%s",
+                       getenv("CTDL_DIALOG"),
+                       prompt_text,
+                       str,
+                       dialog_result);
+               system(buf);
+               fp = fopen(dialog_result, "r");
+               if (fp != NULL) {
+                       fgets(str, sizeof buf, fp);
+                       if (str[strlen(str)-1] == 10) {
+                               str[strlen(str)-1] = 0;
+                       }
+                       fclose(fp);
+                       unlink(dialog_result);
+               }
+               break;
+
 #ifdef HAVE_NEWT
        case UI_NEWT:
 
 #ifdef HAVE_NEWT
        case UI_NEWT:
 
@@ -664,7 +814,7 @@ void strprompt(char *prompt_title, char *prompt_text, char *str)
                                prompt_title);
                form = newtForm(NULL, NULL, 0);
                for (i=0; i<num_tokens(prompt_text, '\n'); ++i) {
                                prompt_title);
                form = newtForm(NULL, NULL, 0);
                for (i=0; i<num_tokens(prompt_text, '\n'); ++i) {
-                       extract_token(buf, prompt_text, i, '\n');
+                       extract_token(buf, prompt_text, i, '\n', sizeof buf);
                        newtFormAddComponent(form, newtLabel(1, 1+i, buf));
                }
                newtFormAddComponent(form,
                        newtFormAddComponent(form, newtLabel(1, 1+i, buf));
                }
                newtFormAddComponent(form,
@@ -672,7 +822,7 @@ void strprompt(char *prompt_title, char *prompt_text, char *str)
                                (prompt_window_height - 2),
                                str,
                                74,
                                (prompt_window_height - 2),
                                str,
                                74,
-                               &result,
+                               (const char **) &result,
                                NEWT_FLAG_RETURNEXIT)
                );
                newtRunForm(form);
                                NEWT_FLAG_RETURNEXIT)
                );
                newtRunForm(form);
@@ -722,33 +872,38 @@ void edit_value(int curr)
 {
        int i;
        struct passwd *pw;
 {
        int i;
        struct passwd *pw;
-       char bbsuidname[SIZ];
+       char ctdluidname[SIZ];
 
        switch (curr) {
 
        case 1:
 
        switch (curr) {
 
        case 1:
-               set_str_val(curr, config.c_sysadm);
+               if (getenv("SYSADMIN_NAME")) {
+                       strcpy(config.c_sysadm, getenv("SYSADMIN_NAME"));
+               }
+               else {
+                       set_str_val(curr, config.c_sysadm);
+               }
                break;
 
        case 2:
 #ifdef __CYGWIN__
                break;
 
        case 2:
 #ifdef __CYGWIN__
-               config.c_bbsuid = 0;    /* XXX Windows hack, prob. insecure */
+               config.c_ctdluid = 0;   /* XXX Windows hack, prob. insecure */
 #else
 #else
-               i = config.c_bbsuid;
+               i = config.c_ctdluid;
                pw = getpwuid(i);
                if (pw == NULL) {
                        set_int_val(curr, &i);
                pw = getpwuid(i);
                if (pw == NULL) {
                        set_int_val(curr, &i);
-                       config.c_bbsuid = i;
+                       config.c_ctdluid = i;
                }
                else {
                }
                else {
-                       strcpy(bbsuidname, pw->pw_name);
-                       set_str_val(curr, bbsuidname);
-                       pw = getpwnam(bbsuidname);
+                       strcpy(ctdluidname, pw->pw_name);
+                       set_str_val(curr, ctdluidname);
+                       pw = getpwnam(ctdluidname);
                        if (pw != NULL) {
                        if (pw != NULL) {
-                               config.c_bbsuid = pw->pw_uid;
+                               config.c_ctdluid = pw->pw_uid;
                        }
                        }
-                       else if (atoi(bbsuidname) > 0) {
-                               config.c_bbsuid = atoi(bbsuidname);
+                       else if (atoi(ctdluidname) > 0) {
+                               config.c_ctdluid = atoi(ctdluidname);
                        }
                }
 #endif
                        }
                }
 #endif
@@ -774,7 +929,7 @@ void write_config_to_disk(void)
        FILE *fp;
        int fd;
 
        FILE *fp;
        int fd;
 
-       if ((fd = creat("citadel.config", S_IRUSR | S_IWUSR)) == -1) {
+       if ((fd = creat(file_citadel_config, S_IRUSR | S_IWUSR)) == -1) {
                display_error("setup: cannot open citadel.config");
                cleanup(1);
        }
                display_error("setup: cannot open citadel.config");
                cleanup(1);
        }
@@ -796,6 +951,12 @@ void write_config_to_disk(void)
 int discover_ui(void)
 {
 
 int discover_ui(void)
 {
 
+       /* Use "dialog" if we have it */
+       if (getenv("CTDL_DIALOG") != NULL) {
+               return UI_DIALOG;
+       }
+               
+
 #ifdef HAVE_NEWT
        newtInit();
        newtCls();
 #ifdef HAVE_NEWT
        newtInit();
        newtCls();
@@ -809,10 +970,100 @@ int discover_ui(void)
 
 
 
 
 
 
+/*
+ * Strip "db" entries out of /etc/nsswitch.conf
+ */
+void fixnss(void) {
+       FILE *fp_read;
+       int fd_write;
+       char buf[256];
+       char buf_nc[256];
+       char question[512];
+       int i;
+       int changed = 0;
+       int file_changed = 0;
+       char new_filename[64];
+
+       fp_read = fopen(NSSCONF, "r");
+       if (fp_read == NULL) {
+               return;
+       }
+
+       strcpy(new_filename, "/tmp/ctdl_fixnss_XXXXXX");
+       fd_write = mkstemp(new_filename);
+       if (fd_write < 0) {
+               fclose(fp_read);
+               return;
+       }
+
+       while (fgets(buf, sizeof buf, fp_read) != NULL) {
+               changed = 0;
+               strcpy(buf_nc, buf);
+               for (i=0; i<strlen(buf_nc); ++i) {
+                       if (buf_nc[i] == '#') {
+                               buf_nc[i] = 0;
+                       }
+               }
+               for (i=0; i<strlen(buf_nc); ++i) {
+                       if (!strncasecmp(&buf_nc[i], "db", 2)) {
+                               if (i > 0) {
+                                       if ((isspace(buf_nc[i+2])) || (buf_nc[i+2]==0)) {
+                                               changed = 1;
+                                               file_changed = 1;
+                                               strcpy(&buf_nc[i], &buf_nc[i+2]);
+                                               strcpy(&buf[i], &buf[i+2]);
+                                               if (buf[i]==32) {
+                                                       strcpy(&buf_nc[i], &buf_nc[i+1]);
+                                                       strcpy(&buf[i], &buf[i+1]);
+                                               }
+                                       }
+                               }
+                       }
+               }
+               if (write(fd_write, buf, strlen(buf)) != strlen(buf)) {
+                       fclose(fp_read);
+                       close(fd_write);
+                       unlink(new_filename);
+                       return;
+               }
+       }
+
+       fclose(fp_read);
+       
+       if (!file_changed) {
+               unlink(new_filename);
+               return;
+       }
+
+       snprintf(question, sizeof question,
+               "\n"
+               "/etc/nsswitch.conf is configured to use the 'db' module for\n"
+               "one or more services.  This is not necessary on most systems,\n"
+               "and it is known to crash the Citadel server when delivering\n"
+               "mail to the Internet.\n"
+               "\n"
+               "Do you want this module to be automatically disabled?\n"
+               "\n"
+       );
+
+       if (yesno(question)) {
+               sprintf(buf, "/bin/mv -f %s %s", new_filename, NSSCONF);
+               system(buf);
+       }
+       unlink(new_filename);
+}
+
+
+
+
+
+
+
+
 int main(int argc, char *argv[])
 {
        int a;
 int main(int argc, char *argv[])
 {
        int a;
-       int curr;
+       int curr; 
        char aaa[128];
        FILE *fp;
        int old_setup_level = 0;
        char aaa[128];
        FILE *fp;
        int old_setup_level = 0;
@@ -821,11 +1072,22 @@ int main(int argc, char *argv[])
        struct passwd *pw;
        struct hostent *he;
        gid_t gid;
        struct passwd *pw;
        struct hostent *he;
        gid_t gid;
-
+       int relh=0;
+       int home=0;
+       char relhome[PATH_MAX]="";
+       char ctdldir[PATH_MAX]=CTDLDIR;
+       
        /* set an invalid setup type */
        setup_type = (-1);
 
        /* set an invalid setup type */
        setup_type = (-1);
 
-        /* Check to see if we're running the web installer */
+       /* Learn whether to skip the auto-service-start questions */
+       fp = fopen("/etc/inittab", "r");
+       if (fp != NULL) {
+               have_sysv_init = 1;
+               fclose(fp);
+       }
+
+       /* Check to see if we're running the web installer */
        if (getenv("CITADEL_INSTALLER") != NULL) {
                using_web_installer = 1;
        }
        if (getenv("CITADEL_INSTALLER") != NULL) {
                using_web_installer = 1;
        }
@@ -858,7 +1120,13 @@ int main(int argc, char *argv[])
        }
 
        /* Get started in a valid setup directory. */
        }
 
        /* Get started in a valid setup directory. */
-       strcpy(setup_directory, BBSDIR);
+       strcpy(setup_directory, 
+#ifdef HAVE_RUN_DIR
+                  ""
+#else
+                  CTDLDIR
+#endif
+                  );
        if ( (using_web_installer) && (getenv("CITADEL") != NULL) ) {
                strcpy(setup_directory, getenv("CITADEL"));
        }
        if ( (using_web_installer) && (getenv("CITADEL") != NULL) ) {
                strcpy(setup_directory, getenv("CITADEL"));
        }
@@ -866,29 +1134,49 @@ int main(int argc, char *argv[])
                set_str_val(0, setup_directory);
        }
 
                set_str_val(0, setup_directory);
        }
 
-       if (chdir(setup_directory) != 0) {
-               important_message("Citadel Setup",
-                         "The directory you specified does not exist.");
-               cleanup(errno);
+       home=(setup_directory[1]!='\0');
+       relh=home&(setup_directory[1]!='/');
+       if (!relh) {
+               safestrncpy(ctdl_home_directory, setup_directory, sizeof ctdl_home_directory);
+       }
+       else {
+               safestrncpy(relhome, ctdl_home_directory, sizeof relhome);
+       }
+
+       calc_dirs_n_files(relh, home, relhome, ctdldir);
+       
+       enable_home=(relh|home);
+
+       if (home) {
+               if (chdir(setup_directory) == 0) {
+                       strcpy(file_citadel_config, "./citadel.config");
+               }
+               else {
+                       important_message("Citadel Setup",
+                               "The directory you specified does not exist.");
+                       cleanup(errno);
+               }
        }
 
        /* Determine our host name, in case we need to use it as a default */
        uname(&my_utsname);
 
        }
 
        /* Determine our host name, in case we need to use it as a default */
        uname(&my_utsname);
 
-       /* See if we need to shut down the Citadel service. */
-       for (a=0; a<=3; ++a) {
-               progress("Shutting down the Citadel service...", a, 3);
-               if (a == 0) shutdown_citserver();
-               sleep(1);
-       }
+       if (have_sysv_init) {
+               /* See if we need to shut down the Citadel service. */
+               for (a=0; a<=3; ++a) {
+                       progress("Shutting down the Citadel service...", a, 3);
+                       if (a == 0) shutdown_citserver();
+                       sleep(1);
+               }
 
 
-       /* Make sure it's stopped. */
-       if (test_server() == 0) {
-               important_message("Citadel Setup",
-                       "The Citadel service is still running.\n"
-                       "Please stop the service manually and run "
-                       "setup again.");
-               cleanup(1);
+               /* Make sure it's stopped. */
+               if (test_server() == 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. */
        }
 
        /* Now begin. */
@@ -896,7 +1184,7 @@ int main(int argc, char *argv[])
 
        case UI_TEXT:
                printf("\n\n\n"
 
        case UI_TEXT:
                printf("\n\n\n"
-                       "               *** Citadel setup program ***\n\n");
+                       "              *** Citadel setup program ***\n\n");
                break;
 
        }
                break;
 
        }
@@ -911,8 +1199,7 @@ int main(int argc, char *argv[])
         * to be when we rewrite it, because we replace the old file with a
         * completely new copy.
         */
         * to be when we rewrite it, because we replace the old file with a
         * completely new copy.
         */
-
-       if ((a = open("citadel.config", O_WRONLY | O_CREAT | O_APPEND,
+       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);
                      S_IRUSR | S_IWUSR)) == -1) {
                display_error("setup: cannot append citadel.config");
                cleanup(errno);
@@ -927,7 +1214,7 @@ int main(int argc, char *argv[])
        fclose(fp);
 
        /* now we re-open it, and read the old or blank configuration */
        fclose(fp);
 
        /* now we re-open it, and read the old or blank configuration */
-       fp = fopen("citadel.config", "rb");
+       fp = fopen(file_citadel_config, "rb");
        if (fp == NULL) {
                display_error("setup: cannot open citadel.config");
                cleanup(errno);
        if (fp == NULL) {
                display_error("setup: cannot open citadel.config");
                cleanup(errno);
@@ -960,7 +1247,7 @@ int main(int argc, char *argv[])
        if (strlen(config.c_twitroom) == 0)
                strcpy(config.c_twitroom, "Trashcan");
        if (strlen(config.c_baseroom) == 0)
        if (strlen(config.c_twitroom) == 0)
                strcpy(config.c_twitroom, "Trashcan");
        if (strlen(config.c_baseroom) == 0)
-               strcpy(config.c_baseroom, "Lobby");
+               strcpy(config.c_baseroom, BASEROOM);
        if (strlen(config.c_aideroom) == 0)
                strcpy(config.c_aideroom, "Aide");
        if (config.c_port_number == 0) {
        if (strlen(config.c_aideroom) == 0)
                strcpy(config.c_aideroom, "Aide");
        if (config.c_port_number == 0) {
@@ -969,20 +1256,20 @@ int main(int argc, char *argv[])
        if (config.c_sleeping == 0) {
                config.c_sleeping = 900;
        }
        if (config.c_sleeping == 0) {
                config.c_sleeping = 900;
        }
-       if (config.c_bbsuid == 0) {
+       if (config.c_ctdluid == 0) {
                pw = getpwnam("citadel");
                if (pw != NULL)
                pw = getpwnam("citadel");
                if (pw != NULL)
-                       config.c_bbsuid = pw->pw_uid;
+                       config.c_ctdluid = pw->pw_uid;
        }
        }
-       if (config.c_bbsuid == 0) {
+       if (config.c_ctdluid == 0) {
                pw = getpwnam("bbs");
                if (pw != NULL)
                pw = getpwnam("bbs");
                if (pw != NULL)
-                       config.c_bbsuid = pw->pw_uid;
+                       config.c_ctdluid = pw->pw_uid;
        }
        }
-       if (config.c_bbsuid == 0) {
+       if (config.c_ctdluid == 0) {
                pw = getpwnam("guest");
                if (pw != NULL)
                pw = getpwnam("guest");
                if (pw != NULL)
-                       config.c_bbsuid = pw->pw_uid;
+                       config.c_ctdluid = pw->pw_uid;
        }
        if (config.c_createax == 0) {
                config.c_createax = 3;
        }
        if (config.c_createax == 0) {
                config.c_createax = 3;
@@ -995,10 +1282,11 @@ int main(int argc, char *argv[])
        }
        /* We need a system default message expiry policy, because this is
         * the top level and there's no 'higher' policy to fall back on.
        }
        /* We need a system default message expiry policy, because this is
         * the top level and there's no 'higher' policy to fall back on.
+        * By default, do not expire messages at all.
         */
        if (config.c_ep.expire_mode == 0) {
         */
        if (config.c_ep.expire_mode == 0) {
-               config.c_ep.expire_mode = EXPIRE_NUMMSGS;
-               config.c_ep.expire_value = 150;
+               config.c_ep.expire_mode = EXPIRE_MANUAL;
+               config.c_ep.expire_value = 0;
        }
 
        /*
        }
 
        /*
@@ -1007,6 +1295,12 @@ int main(int argc, char *argv[])
        if (config.c_smtp_port == 0) config.c_smtp_port = 25;
        if (config.c_pop3_port == 0) config.c_pop3_port = 110;
        if (config.c_imap_port == 0) config.c_imap_port = 143;
        if (config.c_smtp_port == 0) config.c_smtp_port = 25;
        if (config.c_pop3_port == 0) config.c_pop3_port = 110;
        if (config.c_imap_port == 0) config.c_imap_port = 143;
+       if (config.c_msa_port == 0) config.c_msa_port = 587;
+       if (config.c_smtps_port == 0) config.c_smtps_port = 465;
+       if (config.c_pop3s_port == 0) config.c_pop3s_port = 995;
+       if (config.c_imaps_port == 0) config.c_imaps_port = 993;
+       if (config.c_pftcpdict_port == 0) config.c_pftcpdict_port = -1;
+       if (config.c_managesieve_port == 0) config.c_managesieve_port = 2020;
 
        /* Go through a series of dialogs prompting for config info */
        if (setup_type != UI_SILENT) {
 
        /* Go through a series of dialogs prompting for config info */
        if (setup_type != UI_SILENT) {
@@ -1015,14 +1309,6 @@ int main(int argc, char *argv[])
                }
        }
 
                }
        }
 
-       /*
-          if (setuid(config.c_bbsuid) != 0) {
-          important_message("Citadel Setup",
-          "Failed to change the user ID to your Citadel user.");
-          cleanup(errno);
-          }
-        */
-
 /***** begin version update section ***** */
        /* take care of any updating that is necessary */
 
 /***** begin version update section ***** */
        /* take care of any updating that is necessary */
 
@@ -1051,20 +1337,46 @@ NEW_INST:
 
        write_config_to_disk();
 
 
        write_config_to_disk();
 
-       mkdir("info", 0700);
-       chmod("info", 0700);
-       mkdir("bio", 0700);
-       chmod("bio", 0700);
-       mkdir("userpics", 0700);
-       chmod("userpics", 0700);
-       mkdir("messages", 0700);
-       chmod("messages", 0700);
-       mkdir("help", 0700);
-       chmod("help", 0700);
-       mkdir("images", 0700);
-       chmod("images", 0700);
+       mkdir(ctdl_info_dir, 0700);
+       chmod(ctdl_info_dir, 0700);
+       chown(ctdl_info_dir, config.c_ctdluid, -1);
+
+       mkdir(ctdl_bio_dir, 0700);
+       chmod(ctdl_bio_dir, 0700);
+       chown(ctdl_bio_dir, config.c_ctdluid, -1);
+
+       mkdir(ctdl_usrpic_dir, 0700);
+       chmod(ctdl_usrpic_dir, 0700);
+       chown(ctdl_usrpic_dir, config.c_ctdluid, -1);
+
+       mkdir(ctdl_message_dir, 0700);
+       chmod(ctdl_message_dir, 0700);
+       chown(ctdl_message_dir, config.c_ctdluid, -1);
+
+       mkdir(ctdl_hlp_dir, 0700);
+       chmod(ctdl_hlp_dir, 0700);
+       chown(ctdl_hlp_dir, config.c_ctdluid, -1);
+
+       mkdir(ctdl_image_dir, 0700);
+       chmod(ctdl_image_dir, 0700);
+       chown(ctdl_image_dir, config.c_ctdluid, -1);
+
+       mkdir(ctdl_bb_dir, 0700);
+       chmod(ctdl_bb_dir, 0700);
+       chown(ctdl_bb_dir, config.c_ctdluid, -1);
+
+       mkdir(ctdl_file_dir, 0700);
+       chmod(ctdl_file_dir, 0700);
+       chown(ctdl_file_dir, config.c_ctdluid, -1);
+
+       mkdir(ctdl_netcfg_dir, 0700);
+       chmod(ctdl_netcfg_dir, 0700);
+       chown(ctdl_netcfg_dir, config.c_ctdluid, -1);
+
+       /* TODO: where to put this? */
        mkdir("netconfigs", 0700);
        chmod("netconfigs", 0700);
        mkdir("netconfigs", 0700);
        chmod("netconfigs", 0700);
+       chown("netconfigs", config.c_ctdluid, -1);
 
        /* Delete files and directories used by older Citadel versions */
        system("exec /bin/rm -fr ./rooms ./chatpipes ./expressmsgs ./sessions 2>/dev/null");
 
        /* Delete files and directories used by older Citadel versions */
        system("exec /bin/rm -fr ./rooms ./chatpipes ./expressmsgs ./sessions 2>/dev/null");
@@ -1073,46 +1385,64 @@ NEW_INST:
 
        check_services_entry(); /* Check /etc/services */
 #ifndef __CYGWIN__
 
        check_services_entry(); /* Check /etc/services */
 #ifndef __CYGWIN__
-       check_inittab_entry();  /* Check /etc/inittab */
+       if (have_sysv_init) {
+               check_inittab_entry();  /* Check /etc/inittab */
+       }
        check_xinetd_entry();   /* Check /etc/xinetd.d/telnet */
 
        /* Offer to disable other MTA's on the system. */
        check_xinetd_entry();   /* Check /etc/xinetd.d/telnet */
 
        /* Offer to disable other MTA's on the system. */
-       disable_other_mta("sendmail");
-       disable_other_mta("postfix");
-       disable_other_mta("qmail");
-       disable_other_mta("cyrus");
-       disable_other_mta("cyrmaster");
-       disable_other_mta("saslauthd");
-       disable_other_mta("mta");
+       disable_other_mta("courier-authdaemon");
        disable_other_mta("courier-imap");
        disable_other_mta("courier-imap-ssl");
        disable_other_mta("courier-imap");
        disable_other_mta("courier-imap-ssl");
-       disable_other_mta("courier-authdaemon");
+       disable_other_mta("courier-pop");
        disable_other_mta("courier-pop3");
        disable_other_mta("courier-pop3d");
        disable_other_mta("courier-pop3");
        disable_other_mta("courier-pop3d");
-       disable_other_mta("courier-pop");
-       disable_other_mta("vmailmgrd");
+       disable_other_mta("cyrmaster");
+       disable_other_mta("cyrus");
+       disable_other_mta("dovecot");
+       disable_other_mta("exim");
+       disable_other_mta("exim4");
+       disable_other_mta("hula");
        disable_other_mta("imapd");
        disable_other_mta("imapd");
-       disable_other_mta("popd");
+       disable_other_mta("mta");
        disable_other_mta("pop3d");
        disable_other_mta("pop3d");
-       disable_other_mta("exim");
+       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_mta("zimbra");
 #endif
 
 #endif
 
-       if ((pw = getpwuid(config.c_bbsuid)) == NULL)
+       /* 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, 4);
                gid = getgid();
        else
                gid = pw->pw_gid;
 
        progress("Setting file permissions", 0, 4);
-       chown(".", config.c_bbsuid, gid);
+       chown(".", config.c_ctdluid, gid);
+       sleep(1);
        progress("Setting file permissions", 1, 4);
        progress("Setting file permissions", 1, 4);
-       chown("citadel.config", config.c_bbsuid, gid);
+       chown(file_citadel_config, config.c_ctdluid, gid);
+       sleep(1);
        progress("Setting file permissions", 2, 4);
        progress("Setting file permissions", 2, 4);
+
        snprintf(aaa, sizeof aaa,
        snprintf(aaa, sizeof aaa,
-               "find . | grep -v chkpwd | xargs chown %ld:%ld 2>/dev/null",
-               (long)config.c_bbsuid, (long)gid);
-       system(aaa);
+                        "%schkpwd",
+                        ctdl_sbin_dir);
+       chown(aaa,0,0); /*  config.c_ctdluid, gid); chkpwd needs to be root owned*/
+       sleep(1);
        progress("Setting file permissions", 3, 4);
        progress("Setting file permissions", 3, 4);
-       chmod("citadel.config", S_IRUSR | S_IWUSR);
+       chmod(aaa, 04755); 
+
+       sleep(1);
+       progress("Setting file permissions", 3, 4);
+       chmod(file_citadel_config, S_IRUSR | S_IWUSR);
+       sleep(1);
        progress("Setting file permissions", 4, 4);
 
 #ifdef HAVE_LDAP
        progress("Setting file permissions", 4, 4);
 
 #ifdef HAVE_LDAP
@@ -1121,7 +1451,7 @@ NEW_INST:
 #endif
 
        /* See if we can start the Citadel service. */
 #endif
 
        /* See if we can start the Citadel service. */
-       if (strlen(citserver_init_entry) > 0) {
+       if ( (have_sysv_init) && (strlen(citserver_init_entry) > 0) ) {
                for (a=0; a<=3; ++a) {
                        progress("Starting the Citadel service...", a, 3);
                        if (a == 0) start_citserver();
                for (a=0; a<=3; ++a) {
                        progress("Starting the Citadel service...", a, 3);
                        if (a == 0) start_citserver();
@@ -1129,7 +1459,10 @@ NEW_INST:
                }
                if (test_server() == 0) {
                        important_message("Setup finished",
                }
                if (test_server() == 0) {
                        important_message("Setup finished",
-                               "Setup is finished.  You may now log in.");
+                               "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 finished",
                }
                else {
                        important_message("Setup finished",
@@ -1158,18 +1491,35 @@ void contemplate_ldap(void) {
        char slapd_init_entry[SIZ];
        FILE *fp;
 
        char slapd_init_entry[SIZ];
        FILE *fp;
 
-       /* If conditions are not ideal, give up on this idea. */
+       /* If conditions are not ideal, give up on this idea... */
+       if (!have_sysv_init) return;
        if (using_web_installer == 0) return;
        if (getenv("LDAP_CONFIG") == NULL) return;
        if (getenv("SUPPORT") == NULL) return;
        if (getenv("SLAPD_BINARY") == NULL) return;
        if (getenv("CITADEL") == NULL) return;
 
        if (using_web_installer == 0) return;
        if (getenv("LDAP_CONFIG") == NULL) return;
        if (getenv("SUPPORT") == NULL) return;
        if (getenv("SLAPD_BINARY") == NULL) return;
        if (getenv("CITADEL") == NULL) return;
 
-       /* Otherwise, prompt the user to create an entry. */
+       /* And if inittab is already starting slapd, bail out... */
+       locate_init_entry(slapd_init_entry, getenv("SLAPD_BINARY"));
+       if (strlen(slapd_init_entry) > 0) {
+               important_message("Citadel Setup",
+                       "You appear to already have a standalone LDAP "
+                       "service\nconfigured for use with Citadel.  No "
+                       "changes will be made.\n");
+               /* set_init_entry(slapd_init_entry, "off"); */
+               return;
+       }
+
+       /* Generate a unique entry name for slapd if we don't have one. */
+       else {
+               generate_entry_name(slapd_init_entry);
+       }
+
+       /* Ask the user if it's ok to set up slapd automatically. */
        snprintf(question, sizeof question,
                "\n"
                "Do you want this computer configured to start a standalone\n"
        snprintf(question, sizeof question,
                "\n"
                "Do you want this computer configured to start a standalone\n"
-               "LDAP service automatically?  (If you answer yes, a custom\n"
+               "LDAP service automatically?  (If you answer yes, a new\n"
                "slapd.conf will be written, and an /etc/inittab entry\n"
                "pointing to %s will be added.)\n"
                "\n",
                "slapd.conf will be written, and an /etc/inittab entry\n"
                "pointing to %s will be added.)\n"
                "\n",
@@ -1183,7 +1533,7 @@ void contemplate_ldap(void) {
                "\n"
                "Please enter the Base DN for your directory.  This will\n"
                "generally be something based on the primary DNS domain in\n"
                "\n"
                "Please enter the Base DN for your directory.  This will\n"
                "generally be something based on the primary DNS domain in\n"
-               "which you receive mail, but it doesn't have to be.  Your\n"
+               "which you receive mail, but it does not have to be.  Your\n"
                "LDAP tree will be built using this Distinguished Name.\n"
                "\n",
                config.c_ldap_base_dn
                "LDAP tree will be built using this Distinguished Name.\n"
                "\n",
                config.c_ldap_base_dn
@@ -1193,8 +1543,13 @@ void contemplate_ldap(void) {
        config.c_ldap_port = 389;
        sprintf(config.c_ldap_bind_dn, "cn=manager,%s", config.c_ldap_base_dn);
 
        config.c_ldap_port = 389;
        sprintf(config.c_ldap_bind_dn, "cn=manager,%s", config.c_ldap_base_dn);
 
-       /* FIXME ... make the generated password harder to guess */
-       sprintf(config.c_ldap_bind_pw, "%d%ld", getpid(), time(NULL));
+       /*
+        * Generate a bind password.  If you're some grey hat hacker who
+        * is just dying to get some street cred on Bugtraq, and you think
+        * this password generation scheme is too weak, please submit a patch
+        * instead of just whining about it, ok?
+        */
+       sprintf(config.c_ldap_bind_pw, "%d%ld", getpid(), (long)time(NULL));
 
        write_config_to_disk();
 
 
        write_config_to_disk();
 
@@ -1232,23 +1587,17 @@ void contemplate_ldap(void) {
        /* This is where our OpenLDAP server will keep its data. */
        mkdir("openldap-data", 0700);
 
        /* This is where our OpenLDAP server will keep its data. */
        mkdir("openldap-data", 0700);
 
-       /* If inittab is already starting slapd, disable the old entry. */
-       locate_init_entry(slapd_init_entry, getenv("SLAPD_BINARY"));
-       if (strlen(slapd_init_entry) > 0) {
-               set_init_entry(slapd_init_entry, "off");
-       }
-
-       /* Generate a unique entry name for slapd */
-       generate_entry_name(slapd_init_entry);
-
-       /* Now write it out to /etc/inittab */
-       /* FIXME make it run as some non-root user */
+       /* Now write it out to /etc/inittab.
+        * FIXME make it run as some non-root user.
+        * The "-d 0" seems superfluous, but it's actually a way to make
+        * slapd run in the foreground without spewing messages to the console.
+        */
        fp = fopen("/etc/inittab", "a");
        if (fp == NULL) {
                display_error(strerror(errno));
        } else {
                fprintf(fp, "# Start the OpenLDAP server for Citadel...\n");
        fp = fopen("/etc/inittab", "a");
        if (fp == NULL) {
                display_error(strerror(errno));
        } else {
                fprintf(fp, "# Start the OpenLDAP server for Citadel...\n");
-               fprintf(fp, "%s:2345:respawn:%s -d 1 -f %s\n",
+               fprintf(fp, "%s:2345:respawn:%s -d 0 -f %s\n",
                        slapd_init_entry,
                        getenv("SLAPD_BINARY"),
                        getenv("LDAP_CONFIG")
                        slapd_init_entry,
                        getenv("SLAPD_BINARY"),
                        getenv("LDAP_CONFIG")