]> code.citadel.org Git - citadel.git/blobdiff - citadel/setup.c
* Added a separate authentication mode AUTHMODE_LDAP_AD for Active Directory's nonsta...
[citadel.git] / citadel / setup.c
index 114323eeab3fc18fc7bdd73d61b2ffa10671ae32..e72c6d476ff6df4b9116dc60599ae2b06ad04d58 100644 (file)
 #include <limits.h>
 #include <pwd.h>
 #include <time.h>
-
+#include <libcitadel.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>
+#if HAVE_BACKTRACE
+#include <execinfo.h>
 #endif
 
 
-#define MAXSETUP     /* How many setup questions to ask */
+#define MAXSETUP 11    /* 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"
@@ -49,16 +46,47 @@ int setup_type;
 char setup_directory[PATH_MAX];
 int using_web_installer = 0;
 int enable_home = 1;
+char admin_pass[SIZ];
+char admin_cmd[SIZ];
 
 char *setup_titles[] =
 {
        "Citadel Home Directory",
        "System Administrator",
+       "Administrator Password",
        "Citadel User ID",
        "Server IP address",
        "Server port number",
+       "Authentication mode",
+       "LDAP host",
+       "LDAP port number",
+       "LDAP base DN",
+       "LDAP bind DN",
+       "LDAP bind password"
 };
 
+/**
+ * \brief print the actual stack frame.
+ */
+void cit_backtrace(void)
+{
+#ifdef HAVE_BACKTRACE
+       void *stack_frames[50];
+       size_t size, i;
+       char **strings;
+
+
+       size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
+       strings = backtrace_symbols(stack_frames, size);
+       for (i = 0; i < size; i++) {
+               if (strings != NULL)
+                       fprintf(stderr, "%s\n", strings[i]);
+               else
+                       fprintf(stderr, "%p\n", stack_frames[i]);
+       }
+       free(strings);
+#endif
+}
 
 struct config config;
 
@@ -84,6 +112,10 @@ char *setup_text[] = {
 "you).  When an account is created with this name, it will\n"
 "automatically be given administrator-level access.\n",
 
+"Enter a password for the system administrator. When setup\n"
+"completes it will attempt to create the administrator user\n"
+"and set the password specified here.\n",
+
 "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"
@@ -103,6 +135,40 @@ char *setup_text[] = {
 "of Citadel on the same computer and there is something else\n"
 "already using port 504.\n",
 
+
+
+"How would you like to authenticate users on your Citadel system?\n"
+"\n"
+" 0. Self contained authentication - Citadel maintains its own user database\n"
+"    (This mode is *strongly* recommended)\n"
+"\n"
+" 1. Authenticate users against the host system (unix or linux accounts)\n"
+"\n"
+" 2. Authenticate users against an external LDAP directory (RFC 2307 compliant)\n"
+"\n"
+" 3. Authenticate users against nonstandard MS Active Directory LDAP\n"
+"\n"
+"WARNING: do *not* change this setting once your system is installed.\n"
+"\n"
+"(Answer \"0\" unless you completely understand this option)\n"
+"Which authentication mode do you want to use?\n",
+
+"Please enter the host name or IP address of your LDAP server.\n",
+
+"Please enter the port number of the LDAP service (usually 389).\n",
+
+"Please enter the Base DN to search for authentication\n"
+"(for example: dc=example,dc=com)\n",
+
+"Please enter the DN of an account to use for binding to the LDAP server\n"
+"for performing queries.  The account does not require any other\n"
+"privileges.  If your LDAP server allows anonymous queries, you can.\n"
+"leave this blank.\n",
+
+"If you entered a Bind DN in the previous question, you must now enter\n"
+"the password associated with that account.  Otherwise, you can leave this\n"
+"blank.\n"
+
 };
 
 struct config config;
@@ -111,11 +177,8 @@ int direction;
 
 void cleanup(int exitcode)
 {
-#ifdef HAVE_NEWT
-       newtCls();
-       newtRefresh();
-       newtFinished();
-#endif
+//     printf("Exitcode: %d\n", exitcode);
+//     cit_backtrace();
        exit(exitcode);
 }
 
@@ -130,14 +193,8 @@ void title(char *text)
 
 
 
-int yesno(char *question)
+int yesno(char *question, int default_value)
 {
-#ifdef HAVE_NEWT
-       newtComponent form = NULL;
-       newtComponent yesbutton = NULL;
-       newtComponent nobutton = NULL;
-       int prompt_window_height = 0;
-#endif
        int i = 0;
        int answer = 0;
        char buf[SIZ];
@@ -146,10 +203,15 @@ int yesno(char *question)
 
        case UI_TEXT:
                do {
-                       printf("%s\nYes/No --> ", question);
+                       printf("%s\nYes/No [%s] --> ",
+                               question,
+                               ( default_value ? "Yes" : "No" )
+                       );
                        fgets(buf, sizeof buf, stdin);
                        answer = tolower(buf[0]);
-                       if (answer == 'y')
+                       if ((buf[0]==0) || (buf[0]==13) || (buf[0]==10))
+                               answer = default_value;
+                       else if (answer == 'y')
                                answer = 1;
                        else if (answer == 'n')
                                answer = 0;
@@ -157,8 +219,9 @@ int yesno(char *question)
                break;
 
        case UI_DIALOG:
-               sprintf(buf, "exec %s --yesno '%s' 10 72",
+               sprintf(buf, "exec %s %s --yesno '%s' 15 75",
                        getenv("CTDL_DIALOG"),
+                       ( default_value ? "" : "--defaultno" ),
                        question);
                i = system(buf);
                if (i == 0) {
@@ -168,31 +231,8 @@ int yesno(char *question)
                        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) {
-                       extract_token(buf, question, i, '\n', sizeof buf);
-                       newtFormAddComponent(form, newtLabel(1, 1+i, buf));
-               }
-               yesbutton = newtButton(10, (prompt_window_height - 4), "Yes");
-               nobutton = newtButton(60, (prompt_window_height - 4), "No");
-               newtFormAddComponent(form, yesbutton);
-               newtFormAddComponent(form, nobutton);
-               if (newtRunForm(form) == yesbutton) {
-                       answer = 1;
-               }
-               else {
-                       answer = 0;
-               }
-               newtPopWindow();
-               newtFormDestroy(form);  
-
+       case UI_SILENT:
                break;
-#endif
 
        }
        return (answer);
@@ -201,10 +241,6 @@ int yesno(char *question)
 
 void important_message(char *title, char *msgtext)
 {
-#ifdef HAVE_NEWT
-       newtComponent form = NULL;
-       int i = 0;
-#endif
        char buf[SIZ];
 
        switch (setup_type) {
@@ -222,22 +258,9 @@ void important_message(char *title, char *msgtext)
                        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) {
-                       extract_token(buf, msgtext, i, '\n', sizeof buf);
-                       newtFormAddComponent(form, newtLabel(1, 1+i, buf));
-               }
-               newtFormAddComponent(form, newtButton(35, 5, "OK"));
-               newtRunForm(form);
-               newtPopWindow();
-               newtFormDestroy(form);  
+       case UI_SILENT:
+               fprintf(stderr, "%s\n", msgtext);
                break;
-#endif
-
        }
 }
 
@@ -253,16 +276,6 @@ void display_error(char *error_message)
 
 void progress(char *text, long int curr, long int cmax)
 {
-#ifdef HAVE_NEWT
-
-       /* These variables are static because progress() gets called
-        * multiple times during the course of whatever operation is
-        * being performed.  This makes setup non-threadsafe, but who
-        * cares?
-        */
-       static newtComponent form = NULL;
-       static newtComponent scale = NULL;
-#endif
        static long dots_printed = 0L;
        long a = 0;
        static FILE *fp = NULL;
@@ -318,28 +331,8 @@ void progress(char *text, long int curr, long int cmax)
                        }
                }
                break;
-
-#ifdef HAVE_NEWT
-       case UI_NEWT:
-               if (curr == 0) {
-                       newtCenteredWindow(76, 8, text);
-                       form = newtForm(NULL, NULL, 0);
-                       scale = newtScale(1, 3, 74, cmax);
-                       newtFormAddComponent(form, scale);
-                       newtDrawForm(form);
-                       newtRefresh();
-               }
-               if ((curr > 0) && (curr <= cmax)) {
-                       newtScaleSet(scale, curr);
-                       newtRefresh();
-               }
-               if (curr == cmax) {
-                       newtFormDestroy(form);  
-                       newtPopWindow();
-                       newtRefresh();
-               }
+       case UI_SILENT:
                break;
-#endif
 
        }
 }
@@ -369,7 +362,6 @@ void check_services_entry(void)
                                        fclose(sfp);
                                }
                        }
-                       sleep(1);
                }
        }
 }
@@ -392,14 +384,10 @@ void delete_inittab_entry(void)
 
        /* Determine the fully qualified path name of citserver */
        snprintf(looking_for, 
-                        sizeof looking_for,
-                        "%s/citserver", 
-#ifndef HAVE_RUN_DIR
-                        setup_directory
-#else
-                        CTDLDIR
-#endif
-        );
+                sizeof looking_for,
+                "%s/citserver", 
+                ctdl_sbin_dir
+                );
 
        /* Now tweak /etc/inittab */
        infp = fopen("/etc/inittab", "r");
@@ -456,31 +444,62 @@ void delete_inittab_entry(void)
  */
 void install_init_scripts(void)
 {
+       struct stat etcinitd;
        FILE *fp;
+       char *initfile = "/etc/init.d/citadel";
+       char command[SIZ];
+
+       if ((stat("/etc/init.d/", &etcinitd) == -1) && 
+           (errno == ENOENT))
+       {
+               if ((stat("/etc/rc.d/init.d/", &etcinitd) == -1) &&
+                   (errno == ENOENT))
+                       initfile = CTDLDIR"/citadel.init";
+               else
+                       initfile = "/etc/rc.d/init.d/citadel";
+       }
 
-       if (yesno("Would you like to automatically start Citadel at boot?\n") == 0) {
+       fp = fopen(initfile, "r");
+       if (fp != NULL) {
+               if (yesno("Citadel already appears to be configured to start at boot.\n"
+                  "Would you like to keep your boot configuration as is?\n", 1) == 1) {
+                       return;
+               }
+               fclose(fp);
+               
+       }
+
+       if (yesno("Would you like to automatically start Citadel at boot?\n", 1) == 0) {
                return;
        }
 
-       fp = fopen("/etc/init.d/citadel", "w");
+       fp = fopen(initfile, "w");
        if (fp == NULL) {
                display_error("Cannot create /etc/init.d/citadel");
                return;
        }
 
        fprintf(fp,     "#!/bin/sh\n"
+                       "#\n"
+                       "# Init file for Citadel\n"
+                       "#\n"
+                       "# chkconfig: - 79 30\n"
+                       "# description: Citadel service\n"
+                       "# processname: citserver\n"
+                       "# pidfile: %s/citadel.pid\n"
                        "\n"
-                       "CITADEL_DIR=%s\n", setup_directory);
+                       "CITADEL_DIR=%s\n"
+                       ,
+                               setup_directory,
+                               setup_directory
+                       );
        fprintf(fp,     "\n"
-                       "test -x $CITADEL_DIR/ctdlsvc || exit 0\n"
                        "test -d /var/run || exit 0\n"
                        "\n"
                        "case \"$1\" in\n"
                        "\n"
                        "start)         echo -n \"Starting Citadel... \"\n"
-                       "               if $CITADEL_DIR/ctdlsvc /var/run/citadel.pid "
-                                                       "$CITADEL_DIR/citserver "
-                                                       "-t/dev/null\n"
+                       "               if $CITADEL_DIR/citserver -d -h$CITADEL_DIR\n"
                        "               then\n"
                        "                       echo \"ok\"\n"
                        "               else\n"
@@ -493,11 +512,17 @@ void install_init_scripts(void)
                        "               else\n"
                        "                       echo \"failed\"\n"
                        "               fi\n"
-                       "               rm -f /var/run/citadel.pid 2>/dev/null\n");
+                       "               rm -f %s/citadel.pid 2>/dev/null\n"
+                       ,
+                               setup_directory
+                       );
        fprintf(fp,     "               ;;\n"
-                       "restart)       $0 stop\n"
-                       "               $0 start\n"
-                       "               ;;\n"
+                       "restart)       if $CITADEL_DIR/sendcommand DOWN 1 >/dev/null 2>&1 ; then\n"
+                       "                       echo \"ok\"\n"
+                       "               else\n"
+                       "                       echo \"failed\"\n"
+                       "               fi\n"
+                       "               ;;\n"
                        "*)             echo \"Usage: $0 {start|stop|restart}\"\n"
                        "               exit 1\n"
                        "               ;;\n"
@@ -505,12 +530,14 @@ void install_init_scripts(void)
        );
 
        fclose(fp);
-       chmod("/etc/init.d/citadel", 0755);
+       chmod(initfile, 0755);
 
        /* Set up the run levels. */
        system("/bin/rm -f /etc/rc?.d/[SK]??citadel 2>/dev/null");
-       system("for x in 2 3 4 5 ; do [ -d /etc/rc$x.d ] && ln -s /etc/init.d/citadel /etc/rc$x.d/S79citadel ; done 2>/dev/null");
-       system("for x in 0 6 S; do [ -d /etc/rc$x.d ] && ln -s /etc/init.d/citadel /etc/rc$x.d/K30citadel ; done 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);
+       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);
 
 }
 
@@ -550,7 +577,7 @@ void check_xinetd_entry(void) {
                        "connect incoming telnet sessions to Citadel, bypassing the\n"
                        "host system login: prompt.  Would you like to do this?\n"
                );
-               if (yesno(buf) == 0) {
+               if (yesno(buf, 1) == 0) {
                        return;
                }
        }
@@ -569,12 +596,7 @@ void check_xinetd_entry(void) {
                "       server_args     = -h -L %s/citadel\n"
                "       log_on_failure  += USERID\n"
                "}\n",
-#ifndef HAVE_RUN_DIR
-                       setup_directory
-#else
-                       RUN_DIR
-#endif
-                       );
+               ctdl_bin_dir);
        fclose(fp);
 
        /* Now try to restart the service */
@@ -606,26 +628,20 @@ void disable_other_mta(char *mta) {
 
        /* Offer to replace other MTA with the vastly superior Citadel :)  */
 
-       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
+       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;
-               }
+       if (yesno(buf, 1) == 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);
@@ -639,7 +655,7 @@ void disable_other_mta(char *mta) {
 /* 
  * Check to see if our server really works.  Returns 0 on success.
  */
-int test_server(void) {
+int test_server(char *setup_directory, char *relhomestr, int relhome) {
        char cmd[256];
        char cookie[256];
        FILE *fp;
@@ -652,14 +668,14 @@ int test_server(void) {
         */
        sprintf(cookie, "--test--%d--", getpid());
 
-       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:"",
+       if (relhome)
+               sprintf(cmd, "%s/sendcommand -h%s ECHO %s 2>&1",
+                       ctdl_sbin_dir,
+                       relhomestr,
+                       cookie);
+       else
+               sprintf(cmd, "%s/sendcommand ECHO %s 2>&1",
+                       ctdl_sbin_dir,
                        cookie);
 
        fp = popen(cmd, "r");
@@ -681,12 +697,6 @@ int test_server(void) {
 
 void strprompt(char *prompt_title, char *prompt_text, char *str)
 {
-#ifdef HAVE_NEWT
-       newtComponent form;
-       char *result;
-       int i;
-       int prompt_window_height = 0;
-#endif
        char buf[SIZ];
        char setupmsg[SIZ];
        char dialog_result[PATH_MAX];
@@ -702,7 +712,7 @@ void strprompt(char *prompt_title, char *prompt_text, char *str)
                printf("Enter new value or press return to leave unchanged:\n");
                fgets(buf, sizeof buf, stdin);
                buf[strlen(buf) - 1] = 0;
-               if (strlen(buf) != 0)
+               if (!IsEmptyStr(buf))
                        strcpy(str, buf);
                break;
 
@@ -724,43 +734,20 @@ void strprompt(char *prompt_title, char *prompt_text, char *str)
                        unlink(dialog_result);
                }
                break;
-
-#ifdef HAVE_NEWT
-       case UI_NEWT:
-
-               prompt_window_height = num_tokens(prompt_text, '\n') + 5 ;
-               newtCenteredWindow(76,
-                               prompt_window_height,
-                               prompt_title);
-               form = newtForm(NULL, NULL, 0);
-               for (i=0; i<num_tokens(prompt_text, '\n'); ++i) {
-                       extract_token(buf, prompt_text, i, '\n', sizeof buf);
-                       newtFormAddComponent(form, newtLabel(1, 1+i, buf));
-               }
-               newtFormAddComponent(form,
-                       newtEntry(1,
-                               (prompt_window_height - 2),
-                               str,
-                               74,
-                               (const char **) &result,
-                               NEWT_FLAG_RETURNEXIT)
-               );
-               newtRunForm(form);
-               strcpy(str, result);
-
-               newtPopWindow();
-               newtFormDestroy(form);  
-
-#endif
+       case UI_SILENT:
+               break;
        }
 }
 
+void set_bool_val(int msgpos, int *ip) {
+       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_int_val(int msgpos, int *ip)
 {
        char buf[16];
@@ -792,13 +779,16 @@ void edit_value(int curr)
 {
        int i;
        struct passwd *pw;
-       char ctdluidname[SIZ];
+       char ctdluidname[256];
 
        switch (curr) {
 
        case 1:
-               if (getenv("SYSADMIN_NAME")) {
-                       strcpy(config.c_sysadm, getenv("SYSADMIN_NAME"));
+               if (setup_type == UI_SILENT)
+               {
+                       if (getenv("SYSADMIN_NAME")) {
+                               strcpy(config.c_sysadm, getenv("SYSADMIN_NAME"));
+                       }
                }
                else {
                        set_str_val(curr, config.c_sysadm);
@@ -806,39 +796,159 @@ void edit_value(int curr)
                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);
+               }
+               break;
+       
+       case 3:
+               if (setup_type == UI_SILENT)
+               {               
+                       if (getenv("CITADEL_UID")) {
+                               config.c_ctdluid = atoi(getenv("CITADEL_UID"));
+                       }                                       
+               }
+               else
+               {
 #ifdef __CYGWIN__
-               config.c_ctdluid = 0;   /* XXX Windows hack, prob. insecure */
+                       config.c_ctdluid = 0;   /* XXX Windows hack, prob. insecure */
 #else
-               i = config.c_ctdluid;
-               pw = getpwuid(i);
-               if (pw == NULL) {
-                       set_int_val(curr, &i);
-                       config.c_ctdluid = i;
+                       i = config.c_ctdluid;
+                       pw = getpwuid(i);
+                       if (pw == NULL) {
+                               set_int_val(curr, &i);
+                               config.c_ctdluid = i;
+                       }
+                       else {
+                               strcpy(ctdluidname, pw->pw_name);
+                               set_str_val(curr, ctdluidname);
+                               pw = getpwnam(ctdluidname);
+                               if (pw != NULL) {
+                                       config.c_ctdluid = pw->pw_uid;
+                               }
+                               else if (atoi(ctdluidname) > 0) {
+                                       config.c_ctdluid = atoi(ctdluidname);
+                               }
+                       }
+#endif
+               }
+               break;
+
+       case 4:
+               if (setup_type == UI_SILENT)
+               {
+                       if (getenv("IP_ADDR")) {
+                               strcpy(config.c_ip_addr, getenv("IP_ADDR"));
+                       }
                }
                else {
-                       strcpy(ctdluidname, pw->pw_name);
-                       set_str_val(curr, ctdluidname);
-                       pw = getpwnam(ctdluidname);
-                       if (pw != NULL) {
-                               config.c_ctdluid = pw->pw_uid;
+                       set_str_val(curr, config.c_ip_addr);
+               }
+               break;
+
+       case 5:
+               if (setup_type == UI_SILENT)
+               {
+                       if (getenv("CITADEL_PORT")) {
+                               config.c_port_number = atoi(getenv("CITADEL_PORT"));
                        }
-                       else if (atoi(ctdluidname) > 0) {
-                               config.c_ctdluid = atoi(ctdluidname);
+               }
+               else
+               {
+                       set_int_val(curr, &config.c_port_number);
+               }
+               break;
+
+       case 6:
+               if (setup_type == UI_SILENT)
+               {
+                       if (getenv("ENABLE_UNIX_AUTH")) {
+                               if (!strcasecmp(getenv("ENABLE_UNIX_AUTH"), "yes")) {
+                                       config.c_auth_mode = AUTHMODE_HOST;
+                               }
+                               else {
+                                       config.c_auth_mode = AUTHMODE_NATIVE;
+                               }
                        }
                }
-#endif
+               else {
+                       set_int_val(curr, &config.c_auth_mode);
+               }
                break;
 
-       case 3:
-               set_str_val(curr, config.c_ip_addr);
+       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);
+               }
                break;
 
-       case 4:
-               set_int_val(curr, &config.c_port_number);
+       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);
+               }
+               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);
+               }
+               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);
+               }
                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);
+               }
+               break;
 
        }
+
 }
 
 /*
@@ -876,13 +986,6 @@ int discover_ui(void)
                return UI_DIALOG;
        }
                
-
-#ifdef HAVE_NEWT
-       newtInit();
-       newtCls();
-       newtDrawRootText(0, 0, "Citadel Setup");
-       return UI_NEWT;
-#endif
        return UI_TEXT;
 }
 
@@ -966,9 +1069,10 @@ void fixnss(void) {
                "\n"
        );
 
-       if (yesno(question)) {
+       if (yesno(question, 1)) {
                sprintf(buf, "/bin/mv -f %s %s", new_filename, NSSCONF);
                system(buf);
+               chmod(NSSCONF, 0644);
        }
        unlink(new_filename);
 }
@@ -1012,14 +1116,25 @@ int main(int argc, char *argv[])
                        strcpy(aaa, &aaa[2]);
                        setup_type = atoi(aaa);
                }
-               if (!strcmp(argv[a], "-i")) {
+               else if (!strcmp(argv[a], "-i")) {
                        info_only = 1;
                }
-               if (!strcmp(argv[a], "-q")) {
+               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.
@@ -1033,13 +1148,7 @@ int main(int argc, char *argv[])
        }
 
        /* Get started in a valid setup directory. */
-       strcpy(setup_directory, 
-#ifdef HAVE_RUN_DIR
-                  ""
-#else
-                  CTDLDIR
-#endif
-                  );
+       strcpy(setup_directory, ctdl_run_dir);
        if ( (using_web_installer) && (getenv("CITADEL") != NULL) ) {
                strcpy(setup_directory, getenv("CITADEL"));
        }
@@ -1047,28 +1156,14 @@ int main(int argc, char *argv[])
                set_str_val(0, setup_directory);
        }
 
-       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);
+       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);
-               }
+       if (chdir(setup_directory) != 0) {
+               char errmsg[SIZ];
+               sprintf(errmsg, "The directory you specified does not exist: [%s]\n", setup_directory);
+               
+               important_message("Citadel Setup", errmsg);
+               cleanup(errno);
        }
 
        /* Determine our host name, in case we need to use it as a default */
@@ -1080,7 +1175,7 @@ int main(int argc, char *argv[])
        }
 
        /* Make sure Citadel is not running. */
-       if (test_server() == 0) {
+       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 "
@@ -1132,11 +1227,11 @@ int main(int argc, char *argv[])
        fclose(fp);
 
        /* set some sample/default values in place of blanks... */
-       if (strlen(config.c_nodename) == 0)
+       if (IsEmptyStr(config.c_nodename))
                safestrncpy(config.c_nodename, my_utsname.nodename,
                            sizeof config.c_nodename);
        strtok(config.c_nodename, ".");
-       if (strlen(config.c_fqdn) == 0) {
+       if (IsEmptyStr(config.c_fqdn) ) {
                if ((he = gethostbyname(my_utsname.nodename)) != NULL)
                        safestrncpy(config.c_fqdn, he->h_name,
                                    sizeof config.c_fqdn);
@@ -1144,20 +1239,20 @@ int main(int argc, char *argv[])
                        safestrncpy(config.c_fqdn, my_utsname.nodename,
                                    sizeof config.c_fqdn);
        }
-       if (strlen(config.c_humannode) == 0)
+       if (IsEmptyStr(config.c_humannode))
                strcpy(config.c_humannode, "My System");
-       if (strlen(config.c_phonenum) == 0)
+       if (IsEmptyStr(config.c_phonenum))
                strcpy(config.c_phonenum, "US 800 555 1212");
        if (config.c_initax == 0) {
                config.c_initax = 4;
        }
-       if (strlen(config.c_moreprompt) == 0)
+       if (IsEmptyStr(config.c_moreprompt))
                strcpy(config.c_moreprompt, "<more>");
-       if (strlen(config.c_twitroom) == 0)
+       if (IsEmptyStr(config.c_twitroom))
                strcpy(config.c_twitroom, "Trashcan");
-       if (strlen(config.c_baseroom) == 0)
+       if (IsEmptyStr(config.c_baseroom))
                strcpy(config.c_baseroom, BASEROOM);
-       if (strlen(config.c_aideroom) == 0)
+       if (IsEmptyStr(config.c_aideroom))
                strcpy(config.c_aideroom, "Aide");
        if (config.c_port_number == 0) {
                config.c_port_number = 504;
@@ -1210,11 +1305,14 @@ int main(int argc, char *argv[])
        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;
+       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;
 
        /* Go through a series of dialogs prompting for config info */
-       if (setup_type != UI_SILENT) {
-               for (curr = 1; curr <= MAXSETUP; ++curr) {
-                       edit_value(curr);
+       for (curr = 1; curr <= MAXSETUP; ++curr) {
+               edit_value(curr);
+               if ((curr == 6) && (config.c_auth_mode != AUTHMODE_LDAP) && (config.c_auth_mode != AUTHMODE_LDAP_AD)) {
+                       curr += 5;      /* skip LDAP questions if we're not authenticating against LDAP */
                }
        }
 
@@ -1282,44 +1380,43 @@ NEW_INST:
        chmod(ctdl_netcfg_dir, 0700);
        chown(ctdl_netcfg_dir, config.c_ctdluid, -1);
 
-       /* TODO: where to put this? */
-       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");
        unlink("citadel.log");
        unlink("weekly");
 
-       check_services_entry(); /* Check /etc/services */
+       if (((setup_type == UI_SILENT) && (getenv("ALTER_ETC_SERVICES")!=NULL)) || 
+           (setup_type != UI_SILENT))
+               check_services_entry(); /* Check /etc/services */
 #ifndef __CYGWIN__
        delete_inittab_entry(); /* Remove obsolete /etc/inittab entry */
        check_xinetd_entry();   /* Check /etc/xinetd.d/telnet */
 
-       /* 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("hula");
-       disable_other_mta("imapd");
-       disable_other_mta("mta");
-       disable_other_mta("pop3d");
-       disable_other_mta("popd");
-       disable_other_mta("postfix");
-       disable_other_mta("qmail");
-       disable_other_mta("saslauthd");
-       disable_other_mta("sendmail");
-       disable_other_mta("vmailmgrd");
-       disable_other_mta("zimbra");
+       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
 
        /* Check for the 'db' nss and offer to disable it */
@@ -1330,27 +1427,13 @@ NEW_INST:
        else
                gid = pw->pw_gid;
 
-       progress("Setting file permissions", 0, 4);
-       chown(".", config.c_ctdluid, gid);
-       sleep(1);
-       progress("Setting file permissions", 1, 4);
+       progress("Setting file permissions", 0, 3);
+       chown(ctdl_run_dir, config.c_ctdluid, gid);
+       progress("Setting file permissions", 1, 3);
        chown(file_citadel_config, config.c_ctdluid, gid);
-       sleep(1);
-       progress("Setting file permissions", 2, 4);
-
-       snprintf(aaa, sizeof 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);
-       chmod(aaa, 04755); 
-
-       sleep(1);
-       progress("Setting file permissions", 3, 4);
+       progress("Setting file permissions", 2, 3);
        chmod(file_citadel_config, S_IRUSR | S_IWUSR);
-       sleep(1);
-       progress("Setting file permissions", 4, 4);
+       progress("Setting file permissions", 3, 3);
 
        /* 
         * If we're running on SysV, install init scripts.
@@ -1366,12 +1449,31 @@ NEW_INST:
                        sleep(3);
                }
 
-               if (test_server() == 0) {
-                       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");
+               if (test_server(setup_directory, relhome, enable_home) == 0) {
+                       char buf[SIZ];
+                       int found_it = 0;
+
+                       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",