]> code.citadel.org Git - citadel.git/blobdiff - citadel/setup.c
* Replaced all "Citadel/UX" references with "Citadel"
[citadel.git] / citadel / setup.c
index 9e6f0e1a93a825208e9d92b87d256e2158b82183..038c5c3e225cafaf70baa7baeca3574ac2005327 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * $Id$
  *
- * Citadel/UX setup utility
+ * Citadel setup utility
  *
  */
 
@@ -15,6 +15,7 @@
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <sys/wait.h>
+#include <signal.h>
 #include <netdb.h>
 #include <errno.h>
 #include <limits.h>
 #include "config.h"
 #include "tools.h"
 
-#if defined(HAVE_CURSES_H) || defined(HAVE_NCURSES_H)
-
-#ifdef HAVE_NCURSES_H
-#include <ncurses.h>
-#else
-#include <curses.h>
+#ifdef HAVE_NEWT
+#include <newt.h>
 #endif
 
-#endif
 
 #define MAXSETUP 4     /* How many setup questions to ask */
 
 #define UI_TEXT                0       /* Default setup type -- text only */
-#define UI_DIALOG      1       /* Use the 'dialog' program (REMOVED) */
-#define UI_CURSES      2       /* Use curses */
 #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"
 int setup_type;
 char setup_directory[SIZ];
 char init_entry[SIZ];
+int using_web_installer = 0;
 
 char *setup_titles[] =
 {
-       "BBS Home Directory",
+       "Citadel Home Directory",
        "System Administrator",
-       "BBS User ID",
+       "Citadel User ID",
+       "Server IP address",
        "Server port number",
 };
 
 
 char *setup_text[] =
 {
-"Enter the full pathname of the directory in which the BBS you are\n"
-"creating or updating resides.  If you specify a directory other than the\n"
-"default, you will need to specify the -h flag to the server when you start\n"
-"it up.\n",
+"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",
 
-"You should create a user called 'bbs', 'guest', 'citadel', or something\n"
-"similar, that will allow users a way into your BBS.  The server will run\n"
-"under this user ID.  Please specify that (numeric) user ID here.\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 BBS's on the same computer and there's something else\n"
-"already using port 504.\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/UX\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"
@@ -91,41 +95,6 @@ char *setup_text[] =
 struct config config;
 int direction;
 
-/* 
- * Do an "init q" to tell init to re-read its configuration file
- */
-void init_q(void) {
-       pid_t cpid;
-       int status;
-
-       cpid = fork();
-       if (cpid==0) {
-               /*
-                * We can't guarantee that telinit or init will be in the right
-                * place, so we try a couple of different paths.  The first one
-                * will work 99% of the time, though.
-                */
-               execlp("/sbin/telinit", "telinit", "q", NULL);
-               execlp("/sbin/init", "init", "q", NULL);
-               execlp("/usr/sbin/init", "init", "q", NULL);
-               execlp("/bin/init", "init", "q", NULL);
-               execlp("/usr/bin/init", "init", "q", NULL);
-               execlp("init", "init", "q", NULL);
-
-               /*
-                * Didn't find it?  Fail silently.  Perhaps we're running on
-                * some sort of BSD system and there's no init at all.  If so,
-                * the person installing Citadel probably knows how to handle
-                * this task manually.
-                */
-               exit(1);
-       }
-       else if (cpid > 0) {
-               while (waitpid(cpid, &status, 0) == -1) ;;
-       }
-}
-
-
 /*
  * Set an entry in inittab to the desired state
  */
@@ -172,7 +141,7 @@ void set_init_entry(char *which_entry, char *new_state) {
        if (fp != NULL) {
                fwrite(inittab, strlen(inittab), 1, fp);
                fclose(fp);
-               init_q();
+               kill(1, SIGHUP);        /* Tell init to re-read /etc/inittab */
        }
        free(inittab);
 }
@@ -236,81 +205,15 @@ void start_the_service(void) {
 
 void cleanup(int exitcode)
 {
-#ifdef HAVE_CURSES_H
-       if (setup_type == UI_CURSES) {
-               clear();
-               refresh();
-               endwin();
-       }
+#ifdef HAVE_NEWT
+       newtCls();
+       newtRefresh();
+       newtFinished();
 #endif
-
        exit(exitcode);
 }
 
 
-/* Gets a line from the terminal */
-/* Where on the screen to start */
-/* Pointer to string buffer */
-/* Maximum length - if negative, no-show */
-#ifdef HAVE_CURSES_H
-void getlin(int yp, int xp, char *string, int lim) {
-       int a, b;
-       char flag;
-
-       flag = 0;
-       if (lim < 0) {
-               lim = (0 - lim);
-               flag = 1;
-       }
-       move(yp, xp);
-       standout();
-       for (a = 0; a < lim; ++a)
-               addch('-');
-       refresh();
-       move(yp, xp);
-       for (a = 0; a < lim; ++a)
-               addch(' ');
-       move(yp, xp);
-       printw("%s", string);
-      GLA:move(yp, xp + strlen(string));
-       refresh();
-       a = getch();
-       if (a == 127)
-               a = 8;
-       a = (a & 127);
-       if (a == 10)
-               a = 13;
-       if ((a == 8) && (strlen(string) == 0))
-               goto GLA;
-       if ((a != 13) && (a != 8) && (strlen(string) == lim))
-               goto GLA;
-       if ((a == 8) && (string[0] != 0)) {
-               string[strlen(string) - 1] = 0;
-               move(yp, xp + strlen(string));
-               addch(' ');
-               goto GLA;
-       }
-       if ((a == 13) || (a == 10)) {
-               standend();
-               move(yp, xp);
-               for (a = 0; a < lim; ++a)
-                       addch(' ');
-               mvprintw(yp, xp, "%s", string);
-               refresh();
-               return;
-       }
-       b = strlen(string);
-       string[b] = a;
-       string[b + 1] = 0;
-       if (flag == 0)
-               addch(a);
-       if (flag == 1)
-               addch('*');
-       goto GLA;
-}
-#endif
-
-
 
 void title(char *text)
 {
@@ -320,35 +223,24 @@ void title(char *text)
 }
 
 
-void hit_any_key(void)
-{
-       char junk[5];
-
-#ifdef HAVE_CURSES_H
-       if (setup_type == UI_CURSES) {
-               mvprintw(20, 0, "Press any key to continue... ");
-               refresh();
-               getch();
-               return;
-       }
-#endif
-       if (setup_type == UI_TEXT) {
-               printf("Press return to continue...");
-               fgets(junk, 5, stdin);
-       }
-}
 
 int yesno(char *question)
 {
+#ifdef HAVE_NEWT
+       newtComponent form = NULL;
+       newtComponent yesbutton = NULL;
+       newtComponent nobutton = NULL;
+       int i = 0;
+#endif
        int answer = 0;
-       char buf[4096];
+       char buf[SIZ];
 
        switch (setup_type) {
 
        case UI_TEXT:
                do {
                        printf("%s\nYes/No --> ", question);
-                       fgets(buf, 4096, stdin);
+                       fgets(buf, sizeof buf, stdin);
                        answer = tolower(buf[0]);
                        if (answer == 'y')
                                answer = 1;
@@ -357,24 +249,27 @@ int yesno(char *question)
                } while ((answer < 0) || (answer > 1));
                break;
 
-#ifdef HAVE_CURSES_H
-       case UI_CURSES:
-               do {
-                       clear();
-                       standout();
-                       mvprintw(1, 20, "Question");
-                       standend();
-                       mvprintw(10, 0, "%-80s", question);
-                       mvprintw(20, 0, "%80s", "");
-                       mvprintw(20, 0, "Yes/No -> ");
-                       refresh();
-                       answer = getch();
-                       answer = tolower(answer);
-                       if (answer == 'y')
-                               answer = 1;
-                       else if (answer == 'n')
-                               answer = 0;
-               } while ((answer < 0) || (answer > 1));
+#ifdef HAVE_NEWT
+       case UI_NEWT:
+               newtCenteredWindow(76, 10, "Question");
+               form = newtForm(NULL, NULL, 0);
+               for (i=0; i<num_tokens(question, '\n'); ++i) {
+                       extract_token(buf, question, i, '\n');
+                       newtFormAddComponent(form, newtLabel(1, 1+i, buf));
+               }
+               yesbutton = newtButton(10, 5, "Yes");
+               nobutton = newtButton(60, 5, "No");
+               newtFormAddComponent(form, yesbutton);
+               newtFormAddComponent(form, nobutton);
+               if (newtRunForm(form) == yesbutton) {
+                       answer = 1;
+               }
+               else {
+                       answer = 0;
+               }
+               newtPopWindow();
+               newtFormDestroy(form);  
+
                break;
 #endif
 
@@ -385,26 +280,33 @@ 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) {
 
        case UI_TEXT:
                printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
                printf("       %s \n\n%s\n\n", title, msgtext);
-               hit_any_key();
+               printf("Press return to continue...");
+               fgets(buf, sizeof buf, stdin);
                break;
 
-#ifdef HAVE_CURSES_H
-       case UI_CURSES:
-               clear();
-               move(1, 20);
-               standout();
-               printw("  Important Message  ");
-               standend();
-               move(3, 0);
-               printw("%s", msgtext);
-               refresh();
-               hit_any_key();
+#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');
+                       newtFormAddComponent(form, newtLabel(1, 1+i, buf));
+               }
+               newtFormAddComponent(form, newtButton(35, 5, "OK"));
+               newtRunForm(form);
+               newtPopWindow();
+               newtFormDestroy(form);  
                break;
 #endif
 
@@ -423,8 +325,18 @@ void display_error(char *error_message)
 
 void progress(char *text, long int curr, long int cmax)
 {
-       static long dots_printed;
-       long a;
+#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;
 
        switch (setup_type) {
 
@@ -450,32 +362,24 @@ void progress(char *text, long int curr, long int cmax)
                }
                break;
 
-#ifdef HAVE_CURSES_H
-       case UI_CURSES:
+#ifdef HAVE_NEWT
+       case UI_NEWT:
                if (curr == 0) {
-                       clear();
-                       move(5, 20);
-                       printw("%s\n", text);
-                       move(10, 1);
-                       printf("..........................");
-                       printf("..........................");
-                       printf("..........................\r");
-                       refresh();
-                       dots_printed = 0;
-               } else if (curr == cmax) {
-                       clear();
-                       refresh();
-               } else {
-                       a = (curr * 100) / cmax;
-                       a = a * 78;
-                       a = a / 100;
-                       move(10, 1);
-                       dots_printed = 0;
-                       while (dots_printed < a) {
-                               printw("*");
-                               ++dots_printed;
-                       }
-                       refresh();
+                       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();
                }
                break;
 #endif
@@ -563,8 +467,8 @@ void check_inittab_entry(void)
        if (infp == NULL) {
                display_error(strerror(errno));
        } else {
-               fprintf(infp, "# Start the Citadel/UX server...\n");
-               fprintf(infp, "%s:2345:respawn:%s -h%s\n",
+               fprintf(infp, "# Start the Citadel server...\n");
+               fprintf(infp, "%s:2345:respawn:%s -h%s -x3 -llocal4\n",
                        entryname, looking_for, setup_directory);
                fclose(infp);
                strcpy(init_entry, entryname);
@@ -572,14 +476,149 @@ void check_inittab_entry(void)
 }
 
 
+/*
+ * On systems which use xinetd, see if we can offer to install Citadel as
+ * the default telnet target.
+ */
+void check_xinetd_entry(void) {
+       char *filename = "/etc/xinetd.d/telnet";
+       FILE *fp;
+       char buf[SIZ];
+       int already_citadel = 0;
+
+       fp = fopen(filename, "r+");
+       if (fp == NULL) return;         /* Not there.  Oh well... */
+
+       while (fgets(buf, sizeof buf, fp) != NULL) {
+               if (strstr(buf, setup_directory) != NULL) already_citadel = 1;
+       }
+       fclose(fp);
+       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;
+
+       fp = fopen(filename, "w");
+       fprintf(fp,
+               "# description: telnet service for Citadel users\n"
+               "service telnet\n"
+               "{\n"
+               "       disable = no\n"
+               "       flags           = REUSE\n"
+               "       socket_type     = stream\n"
+               "       wait            = no\n"
+               "       user            = root\n"
+               "       server          = /usr/sbin/in.telnetd\n"
+               "       server_args     = -h -L %s/citadel\n"
+               "       log_on_failure  += USERID\n"
+               "}\n",
+               setup_directory
+       );
+       fclose(fp);
+
+       /* Now try to restart the service */
+       system("/etc/init.d/xinetd restart >/dev/null 2>&1");
+}
+
+
+
+/*
+ * Offer to disable other MTA's
+ */
+void disable_other_mta(char *mta) {
+       char buf[SIZ];
+       FILE *fp;
+       int lines = 0;
+
+       sprintf(buf, "/bin/ls -l /etc/rc*.d/S*%s 2>/dev/null", mta);
+       fp = popen(buf, "r");
+       if (fp == NULL) return;
+
+       while (fgets(buf, sizeof buf, fp) != NULL) {
+               ++lines;
+       }
+       fclose(fp);
+       if (lines == 0) return;         /* Nothing to do. */
+
+       /* 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;
+
+       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, "/etc/init.d/%s stop >/dev/null 2>&1", mta);
+       system(buf);
+}
+
+
+
+
+/* 
+ * Check to see if our server really works.  Returns 0 on success.
+ */
+int test_server(void) {
+       char cmd[256];
+       char cookie[256];
+       FILE *fp;
+       char buf[4096];
+       int found_it = 0;
+
+       /* Generate a silly little cookie.  We're going to write it out
+        * 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(cmd, "%s/sendcommand -h%s ECHO %s 2>&1",
+               setup_directory,
+               setup_directory,
+               cookie);
+
+       fp = popen(cmd, "r");
+       if (fp == NULL) return(errno);
+
+       while (fgets(buf, sizeof buf, fp) != NULL) {
+               if ( (buf[0]=='2')
+                  && (strstr(buf, cookie) != NULL) ) {
+                       ++found_it;
+               }
+       }
+       pclose(fp);
+
+       if (found_it) {
+               return(0);
+       }
+       return(-1);
+}
+
+
+
+
+
 
 void set_str_val(int msgpos, char str[])
 {
-       char buf[4096];
-       char tempfile[64];
+#ifdef HAVE_NEWT
+       newtComponent form;
+       char *result;
+       int i;
+#endif
+       char buf[SIZ];
        char setupmsg[SIZ];
 
-       strcpy(tempfile, tmpnam(NULL));
        strcpy(setupmsg, "");
 
        switch (setup_type) {
@@ -588,23 +627,28 @@ void set_str_val(int msgpos, char str[])
                printf("\n%s\n", setup_text[msgpos]);
                printf("This is currently set to:\n%s\n", str);
                printf("Enter new value or press return to leave unchanged:\n");
-               fgets(buf, 4096, stdin);
+               fgets(buf, sizeof buf, stdin);
                buf[strlen(buf) - 1] = 0;
                if (strlen(buf) != 0)
                        strcpy(str, buf);
                break;
-#ifdef HAVE_CURSES_H
-       case UI_CURSES:
-               clear();
-               move(1, ((80 - strlen(setup_titles[msgpos])) / 2));
-               standout();
-               printw("%s", setup_titles[msgpos]);
-               standend();
-               move(3, 0);
-               printw("%s", setup_text[msgpos]);
-               refresh();
-               getlin(20, 0, str, 80);
-               break;
+#ifdef HAVE_NEWT
+       case UI_NEWT:
+
+               newtCenteredWindow(76, 10, setup_titles[msgpos]);
+               form = newtForm(NULL, NULL, 0);
+               for (i=0; i<num_tokens(setup_text[msgpos], '\n'); ++i) {
+                       extract_token(buf, setup_text[msgpos], i, '\n');
+                       newtFormAddComponent(form, newtLabel(1, 1+i, buf));
+               }
+               newtFormAddComponent(form, newtEntry(1, 8, str, 74, &result,
+                                       NEWT_FLAG_RETURNEXIT));
+               newtRunForm(form);
+               strcpy(str, result);
+
+               newtPopWindow();
+               newtFormDestroy(form);  
+
 #endif
        }
 }
@@ -638,7 +682,9 @@ void set_long_val(int msgpos, long int *ip)
 
 void edit_value(int curr)
 {
-       long l;
+       int i;
+       struct passwd *pw;
+       char bbsuidname[SIZ];
 
        switch (curr) {
 
@@ -647,12 +693,34 @@ void edit_value(int curr)
                break;
 
        case 2:
-               l = config.c_bbsuid;
-               set_long_val(curr, &l);
-               config.c_bbsuid = l;
+#ifdef __CYGWIN__
+               config.c_bbsuid = 0;    /* XXX Windows hack, prob. insecure */
+#else
+               i = config.c_bbsuid;
+               pw = getpwuid(i);
+               if (pw == NULL) {
+                       set_int_val(curr, &i);
+                       config.c_bbsuid = i;
+               }
+               else {
+                       strcpy(bbsuidname, pw->pw_name);
+                       set_str_val(curr, bbsuidname);
+                       pw = getpwnam(bbsuidname);
+                       if (pw != NULL) {
+                               config.c_bbsuid = pw->pw_uid;
+                       }
+                       else if (atoi(bbsuidname) > 0) {
+                               config.c_bbsuid = atoi(bbsuidname);
+                       }
+               }
+#endif
                break;
 
        case 3:
+               set_str_val(curr, &config.c_ip_addr);
+               break;
+
+       case 4:
                set_int_val(curr, &config.c_port_number);
                break;
 
@@ -690,8 +758,11 @@ void write_config_to_disk(void)
 int discover_ui(void)
 {
 
-#ifdef HAVE_CURSES_H
-       return UI_CURSES;
+#ifdef HAVE_NEWT
+       newtInit();
+       newtCls();
+       newtDrawRootText(0, 0, "Citadel Setup");
+       return UI_NEWT;
 #endif
        return UI_TEXT;
 }
@@ -716,6 +787,11 @@ int main(int argc, char *argv[])
        /* set an invalid setup type */
        setup_type = (-1);
 
+        /* Check to see if we're running the web installer */
+       if (getenv("CITADEL_INSTALLER") != NULL) {
+               using_web_installer = 1;
+       }
+
        /* parse command line args */
        for (a = 0; a < argc; ++a) {
                if (!strncmp(argv[a], "-u", 2)) {
@@ -738,24 +814,22 @@ int main(int argc, char *argv[])
        if (setup_type < 0) {
                setup_type = discover_ui();
        }
-#ifdef HAVE_CURSES_H
-       if (setup_type == UI_CURSES) {
-               initscr();
-               raw();
-               noecho();
-       }
-#endif
-
        if (info_only == 1) {
-               important_message("Citadel/UX Setup", CITADEL);
+               important_message("Citadel Setup", CITADEL);
                cleanup(0);
        }
 
        /* Get started in a valid setup directory. */
        strcpy(setup_directory, BBSDIR);
-       set_str_val(0, setup_directory);
+       if ( (using_web_installer) && (getenv("CITADEL") != NULL) ) {
+               strcpy(setup_directory, getenv("CITADEL"));
+       }
+       else {
+               set_str_val(0, setup_directory);
+       }
+
        if (chdir(setup_directory) != 0) {
-               important_message("Citadel/UX Setup",
+               important_message("Citadel Setup",
                          "The directory you specified does not exist.");
                cleanup(errno);
        }
@@ -764,18 +838,27 @@ int main(int argc, char *argv[])
        uname(&my_utsname);
 
        /* See if we need to shut down the Citadel service. */
-       for (a=0; a<=5; ++a) {
-               progress("Shutting down the Citadel service...", a, 5);
+       for (a=0; a<=3; ++a) {
+               progress("Shutting down the Citadel service...", a, 3);
                if (a == 0) shutdown_service();
                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);
+       }
+
        /* Now begin. */
        switch (setup_type) {
 
        case UI_TEXT:
                printf("\n\n\n"
-                       "               *** Citadel/UX setup program ***\n\n");
+                       "               *** Citadel setup program ***\n\n");
                break;
 
        }
@@ -838,10 +921,6 @@ int main(int argc, char *argv[])
                strcpy(config.c_moreprompt, "<more>");
        if (strlen(config.c_twitroom) == 0)
                strcpy(config.c_twitroom, "Trashcan");
-       if (strlen(config.c_bucket_dir) == 0)
-               strcpy(config.c_bucket_dir, "bitbucket");
-       if (strlen(config.c_net_password) == 0)
-               strcpy(config.c_net_password, "netpassword");
        if (strlen(config.c_baseroom) == 0)
                strcpy(config.c_baseroom, "Lobby");
        if (strlen(config.c_aideroom) == 0)
@@ -849,10 +928,6 @@ int main(int argc, char *argv[])
        if (config.c_port_number == 0) {
                config.c_port_number = 504;
        }
-       if (config.c_ipgm_secret == 0) {
-               srand(getpid());
-               config.c_ipgm_secret = rand();
-       }
        if (config.c_sleeping == 0) {
                config.c_sleeping = 900;
        }
@@ -904,8 +979,8 @@ int main(int argc, char *argv[])
 
        /*
           if (setuid(config.c_bbsuid) != 0) {
-          important_message("Citadel/UX Setup",
-          "Failed to change the user ID to your BBS user.");
+          important_message("Citadel Setup",
+          "Failed to change the user ID to your Citadel user.");
           cleanup(errno);
           }
         */
@@ -915,28 +990,18 @@ int main(int argc, char *argv[])
 
        old_setup_level = config.c_setup_level;
 
-       if (old_setup_level == 0)
+       if (old_setup_level == 0) {
                goto NEW_INST;
+       }
 
-       if (old_setup_level < 323) {
-               important_message("Citadel/UX Setup",
-                                 "This Citadel/UX installation is too old "
+       if (old_setup_level < 555) {
+               important_message("Citadel Setup",
+                                 "This Citadel installation is too old "
                                  "to be upgraded.");
                cleanup(1);
        }
        write_config_to_disk();
 
-       if ((config.c_setup_level / 10) == 32) {
-               important_msgnum(31);
-               cleanup(0);
-       }
-       if (config.c_setup_level < 400) {
-               config.c_setup_level = 400;
-       }
-       /* end of 3.23 -> 4.00 update section */
-
-       /* end of 4.00 -> 4.02 update section */
-
        old_setup_level = config.c_setup_level;
 
        /* end of version update section */
@@ -949,47 +1014,86 @@ NEW_INST:
        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("netconfigs", 0700);
-       mkdir(config.c_bucket_dir, 0700);
+       chmod("netconfigs", 0700);
 
-       /* Delete a bunch of old files from Citadel v4; don't need anymore */
-       system("rm -fr ./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");
+       unlink("citadel.log");
+       unlink("weekly");
 
        check_services_entry(); /* Check /etc/services */
+#ifndef __CYGWIN__
        check_inittab_entry();  /* Check /etc/inittab */
+       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-imap");
+       disable_other_mta("courier-imap-ssl");
+       disable_other_mta("courier-authdaemon");
+       disable_other_mta("courier-pop3");
+       disable_other_mta("courier-pop3d");
+       disable_other_mta("courier-pop");
+       disable_other_mta("vmailmgrd");
+       disable_other_mta("imapd");
+       disable_other_mta("popd");
+       disable_other_mta("pop3d");
+       disable_other_mta("exim");
+#endif
 
        if ((pw = getpwuid(config.c_bbsuid)) == NULL)
                gid = getgid();
        else
                gid = pw->pw_gid;
 
-       progress("Setting file permissions", 0, 5);
+       progress("Setting file permissions", 0, 4);
        chown(".", config.c_bbsuid, gid);
-       progress("Setting file permissions", 1, 5);
+       progress("Setting file permissions", 1, 4);
        chown("citadel.config", config.c_bbsuid, gid);
-       progress("Setting file permissions", 2, 5);
+       progress("Setting file permissions", 2, 4);
        snprintf(aaa, sizeof aaa,
                "find . | grep -v chkpwd | xargs chown %ld:%ld 2>/dev/null",
                (long)config.c_bbsuid, (long)gid);
        system(aaa);
-       progress("Setting file permissions", 3, 5);
+       progress("Setting file permissions", 3, 4);
        chmod("citadel.config", S_IRUSR | S_IWUSR);
-       progress("Setting file permissions", 4, 5);
+       progress("Setting file permissions", 4, 4);
 
        /* See if we can start the Citadel service. */
        if (strlen(init_entry) > 0) {
-               for (a=0; a<=5; ++a) {
-                       progress("Starting the Citadel service...", a, 5);
+               for (a=0; a<=3; ++a) {
+                       progress("Starting the Citadel service...", a, 3);
                        if (a == 0) start_the_service();
                        sleep(1);
                }
-               important_message("Setup finished",
-                       "Setup is finished.  You may now log in.");
+               if (test_server() == 0) {
+                       important_message("Setup finished",
+                               "Setup is finished.  You may now log in.");
+               }
+               else {
+                       important_message("Setup finished",
+                               "Setup is finished, but the Citadel service "
+                               "failed to start.\n"
+                               "Go back and check your configuration.");
+               }
        }
        else {
                important_message("Setup finished",