4 * Citadel setup utility
14 #include <sys/types.h>
16 #include <sys/utsname.h>
24 #include <libcitadel.h>
29 #include "citadel_dirs.h"
35 #define MAXSETUP 6 /* How many setup questions to ask */
37 #define UI_TEXT 0 /* Default setup type -- text only */
38 #define UI_DIALOG 2 /* Use the 'dialog' program */
39 #define UI_SILENT 3 /* Silent running, for use in scripts */
41 #define SERVICE_NAME "citadel"
42 #define PROTO_NAME "tcp"
43 #define NSSCONF "/etc/nsswitch.conf"
46 char setup_directory[PATH_MAX];
47 int using_web_installer = 0;
52 char *setup_titles[] =
54 "Citadel Home Directory",
55 "System Administrator",
56 "Administrator Password",
64 * \brief print the actual stack frame.
66 void cit_backtrace(void)
69 void *stack_frames[50];
74 size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
75 strings = backtrace_symbols(stack_frames, size);
76 for (i = 0; i < size; i++) {
78 fprintf(stderr, "%s\n", strings[i]);
80 fprintf(stderr, "%p\n", stack_frames[i]);
88 /* calculate all our path on a central place */
89 /* where to keep our config */
92 char *setup_text[] = {
94 "Enter the full pathname of the directory in which the Citadel\n"
95 "installation you are creating or updating resides. If you\n"
96 "specify a directory other than the default, you will need to\n"
97 "specify the -h flag to the server when you start it up.\n",
99 "Enter the subdirectory name for an alternate installation of "
100 "Citadel. To do a default installation just leave it blank."
101 "If you specify a directory other than the default, you will need to\n"
102 "specify the -h flag to the server when you start it up.\n"
103 "note that it may not have a leading /",
106 "Enter the name of the system administrator (which is probably\n"
107 "you). When an account is created with this name, it will\n"
108 "automatically be given administrator-level access.\n",
110 "Enter a password for the system administrator. When setup\n"
111 "completes it will attempt to create the administrator user\n"
112 "and set the password specified here.\n",
114 "Citadel needs to run under its own user ID. This would\n"
115 "typically be called \"citadel\", but if you are running Citadel\n"
116 "as a public BBS, you might also call it \"bbs\" or \"guest\".\n"
117 "The server will run under this user ID. Please specify that\n"
118 "user ID here. You may specify either a user name or a numeric\n"
121 "Specify the IP address on which your server will run. If you\n"
122 "leave this blank, or if you specify 0.0.0.0, Citadel will listen\n"
123 "on all addresses. You can usually skip this unless you are\n"
124 "running multiple instances of Citadel on the same computer.\n",
126 "Specify the TCP port number on which your server will run.\n"
127 "Normally, this will be port 504, which is the official port\n"
128 "assigned by the IANA for Citadel servers. You will only need\n"
129 "to specify a different port number if you run multiple instances\n"
130 "of Citadel on the same computer and there is something else\n"
131 "already using port 504.\n",
133 "Normally, a Citadel system uses a \"black box\" authentication mode.\n"
134 "This means that users do not have accounts or home directories on\n"
135 "the underlying host system -- Citadel manages its own user database.\n"
136 "However, if you wish to override this behavior, you can enable the\n"
137 "host based authentication mode which is traditional for Unix systems.\n"
138 "WARNING: do *not* change this setting once your system is installed.\n"
140 "(Answer \"no\" unless you completely understand this option)\n"
141 "Do you want to enable host based authentication mode?\n"
145 struct config config;
149 void cleanup(int exitcode)
151 // printf("Exitcode: %d\n", exitcode);
158 void title(char *text)
160 if (setup_type == UI_TEXT) {
161 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<%s>\n", text);
167 int yesno(char *question, int default_value)
173 switch (setup_type) {
177 printf("%s\nYes/No [%s] --> ",
179 ( default_value ? "Yes" : "No" )
181 fgets(buf, sizeof buf, stdin);
182 answer = tolower(buf[0]);
183 if ((buf[0]==0) || (buf[0]==13) || (buf[0]==10))
184 answer = default_value;
185 else if (answer == 'y')
187 else if (answer == 'n')
189 } while ((answer < 0) || (answer > 1));
193 sprintf(buf, "exec %s %s --yesno '%s' 15 75",
194 getenv("CTDL_DIALOG"),
195 ( default_value ? "" : "--defaultno" ),
211 void important_message(char *title, char *msgtext)
215 switch (setup_type) {
218 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");
219 printf(" %s \n\n%s\n\n", title, msgtext);
220 printf("Press return to continue...");
221 fgets(buf, sizeof buf, stdin);
225 sprintf(buf, "exec %s --msgbox '%s' 19 72",
226 getenv("CTDL_DIALOG"),
231 fprintf(stderr, "%s\n", msgtext);
236 void important_msgnum(int msgnum)
238 important_message("Important Message", setup_text[msgnum]);
241 void display_error(char *error_message)
243 important_message("Error", error_message);
246 void progress(char *text, long int curr, long int cmax)
248 static long dots_printed = 0L;
250 static FILE *fp = NULL;
253 switch (setup_type) {
257 printf("%s\n", text);
258 printf("..........................");
259 printf("..........................");
260 printf("..........................\r");
263 } else if (curr == cmax) {
264 printf("\r%79s\n", "");
266 a = (curr * 100) / cmax;
269 while (dots_printed < a) {
279 sprintf(buf, "exec %s --gauge '%s' 7 72 0",
280 getenv("CTDL_DIALOG"),
282 fp = popen(buf, "w");
288 else if (curr == cmax) {
290 fprintf(fp, "100\n");
296 a = (curr * 100) / cmax;
298 fprintf(fp, "%ld\n", a);
310 * check_services_entry() -- Make sure "citadel" is in /etc/services
313 void check_services_entry(void)
319 if (getservbyname(SERVICE_NAME, PROTO_NAME) == NULL) {
320 for (i=0; i<=2; ++i) {
321 progress("Adding service entry...", i, 2);
323 sfp = fopen("/etc/services", "a");
325 sprintf(errmsg, "Cannot open /etc/services: %s", strerror(errno));
326 display_error(errmsg);
328 fprintf(sfp, "%s 504/tcp\n", SERVICE_NAME);
340 * delete_inittab_entry() -- Remove obsolete /etc/inittab entry for Citadel
343 void delete_inittab_entry(void)
347 char looking_for[256];
349 char outfilename[32];
350 int changes_made = 0;
352 /* Determine the fully qualified path name of citserver */
353 snprintf(looking_for,
359 /* Now tweak /etc/inittab */
360 infp = fopen("/etc/inittab", "r");
363 /* If /etc/inittab does not exist, return quietly.
364 * Not all host platforms have it.
366 if (errno == ENOENT) {
370 /* Other errors might mean something really did go wrong.
372 sprintf(buf, "Cannot open /etc/inittab: %s", strerror(errno));
377 strcpy(outfilename, "/tmp/ctdlsetup.XXXXXX");
378 outfp = fdopen(mkstemp(outfilename), "w+");
380 sprintf(buf, "Cannot open %s: %s", outfilename, strerror(errno));
386 while (fgets(buf, sizeof buf, infp) != NULL) {
387 if (strstr(buf, looking_for) != NULL) {
388 fwrite("#", 1, 1, outfp);
391 fwrite(buf, strlen(buf), 1, outfp);
398 sprintf(buf, "/bin/mv -f %s /etc/inittab 2>/dev/null", outfilename);
400 system("/sbin/init q 2>/dev/null");
409 * install_init_scripts() -- Try to configure to start Citadel at boot
412 void install_init_scripts(void)
414 struct stat etcinitd;
416 char *initfile = "/etc/init.d/citadel";
419 if ((stat("/etc/init.d/", &etcinitd) == -1) &&
422 if ((stat("/etc/rc.d/init.d/", &etcinitd) == -1) &&
424 initfile = CTDLDIR"/citadel.init";
426 initfile = "/etc/rc.d/init.d/citadel";
429 fp = fopen(initfile, "r");
431 if (yesno("Citadel already appears to be configured to start at boot.\n"
432 "Would you like to keep your boot configuration as is?\n", 1) == 1) {
439 if (yesno("Would you like to automatically start Citadel at boot?\n", 1) == 0) {
443 fp = fopen(initfile, "w");
445 display_error("Cannot create /etc/init.d/citadel");
449 fprintf(fp, "#!/bin/sh\n"
451 "# Init file for Citadel\n"
453 "# chkconfig: - 79 30\n"
454 "# description: Citadel service\n"
455 "# processname: citserver\n"
456 "# pidfile: %s/citadel.pid\n"
464 "test -d /var/run || exit 0\n"
468 "start) echo -n \"Starting Citadel... \"\n"
469 " if $CITADEL_DIR/citserver -d -h$CITADEL_DIR\n"
476 "stop) echo -n \"Stopping Citadel... \"\n"
477 " if $CITADEL_DIR/sendcommand DOWN >/dev/null 2>&1 ; then\n"
482 " rm -f %s/citadel.pid 2>/dev/null\n"
487 "restart) if $CITADEL_DIR/sendcommand DOWN 1 >/dev/null 2>&1 ; then\n"
493 "*) echo \"Usage: $0 {start|stop|restart}\"\n"
500 chmod(initfile, 0755);
502 /* Set up the run levels. */
503 system("/bin/rm -f /etc/rc?.d/[SK]??citadel 2>/dev/null");
504 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);
506 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);
517 * On systems which use xinetd, see if we can offer to install Citadel as
518 * the default telnet target.
520 void check_xinetd_entry(void) {
521 char *filename = "/etc/xinetd.d/telnet";
524 int already_citadel = 0;
526 fp = fopen(filename, "r+");
527 if (fp == NULL) return; /* Not there. Oh well... */
529 while (fgets(buf, sizeof buf, fp) != NULL) {
530 if (strstr(buf, setup_directory) != NULL) already_citadel = 1;
533 if (already_citadel) return; /* Already set up this way. */
535 /* Otherwise, prompt the user to create an entry. */
536 if (getenv("CREATE_XINETD_ENTRY") != NULL) {
537 if (strcasecmp(getenv("CREATE_XINETD_ENTRY"), "yes")) {
542 snprintf(buf, sizeof buf,
543 "Setup can configure the \"xinetd\" service to automatically\n"
544 "connect incoming telnet sessions to Citadel, bypassing the\n"
545 "host system login: prompt. Would you like to do this?\n"
547 if (yesno(buf, 1) == 0) {
552 fp = fopen(filename, "w");
554 "# description: telnet service for Citadel users\n"
559 " socket_type = stream\n"
562 " server = /usr/sbin/in.telnetd\n"
563 " server_args = -h -L %s/citadel\n"
564 " log_on_failure += USERID\n"
569 /* Now try to restart the service */
570 system("/etc/init.d/xinetd restart >/dev/null 2>&1");
576 * Offer to disable other MTA's
578 void disable_other_mta(char *mta) {
583 sprintf(buf, "/bin/ls -l /etc/rc*.d/S*%s 2>/dev/null; "
584 "/bin/ls -l /etc/rc.d/rc*.d/S*%s 2>/dev/null",
586 fp = popen(buf, "r");
587 if (fp == NULL) return;
589 while (fgets(buf, sizeof buf, fp) != NULL) {
593 if (lines == 0) return; /* Nothing to do. */
596 /* Offer to replace other MTA with the vastly superior Citadel :) */
598 snprintf(buf, sizeof buf,
599 "You appear to have the \"%s\" email program\n"
600 "running on your system. If you want Citadel mail\n"
601 "connected with %s, you will have to manually integrate\n"
602 "them. It is preferable to disable %s, and use Citadel's\n"
603 "SMTP, POP3, and IMAP services.\n\n"
604 "May we disable %s so that Citadel has access to ports\n"
605 "25, 110, and 143?\n",
608 if (yesno(buf, 1) == 0) {
613 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);
615 sprintf(buf, "/etc/init.d/%s stop >/dev/null 2>&1", mta);
623 * Check to see if our server really works. Returns 0 on success.
625 int test_server(char *setup_directory, char *relhomestr, int relhome) {
632 /* Generate a silly little cookie. We're going to write it out
633 * to the server and try to get it back. The cookie does not
634 * have to be secret ... just unique.
636 sprintf(cookie, "--test--%d--", getpid());
639 sprintf(cmd, "%s/sendcommand -h%s ECHO %s 2>&1",
644 sprintf(cmd, "%s/sendcommand ECHO %s 2>&1",
648 fp = popen(cmd, "r");
649 if (fp == NULL) return(errno);
651 while (fgets(buf, sizeof buf, fp) != NULL) {
653 && (strstr(buf, cookie) != NULL) ) {
665 void strprompt(char *prompt_title, char *prompt_text, char *str)
669 char dialog_result[PATH_MAX];
672 strcpy(setupmsg, "");
674 switch (setup_type) {
677 printf("\n%s\n", prompt_text);
678 printf("This is currently set to:\n%s\n", str);
679 printf("Enter new value or press return to leave unchanged:\n");
680 fgets(buf, sizeof buf, stdin);
681 buf[strlen(buf) - 1] = 0;
682 if (!IsEmptyStr(buf))
687 CtdlMakeTempFileName(dialog_result, sizeof dialog_result);
688 sprintf(buf, "exec %s --inputbox '%s' 19 72 '%s' 2>%s",
689 getenv("CTDL_DIALOG"),
694 fp = fopen(dialog_result, "r");
696 fgets(str, sizeof buf, fp);
697 if (str[strlen(str)-1] == 10) {
698 str[strlen(str)-1] = 0;
701 unlink(dialog_result);
708 void set_bool_val(int msgpos, int *ip) {
709 title(setup_titles[msgpos]);
710 *ip = yesno(setup_text[msgpos], *ip);
713 void set_str_val(int msgpos, char *str) {
714 strprompt(setup_titles[msgpos], setup_text[msgpos], str);
717 void set_int_val(int msgpos, int *ip)
720 snprintf(buf, sizeof buf, "%d", (int) *ip);
721 set_str_val(msgpos, buf);
726 void set_char_val(int msgpos, char *ip)
729 snprintf(buf, sizeof buf, "%d", (int) *ip);
730 set_str_val(msgpos, buf);
731 *ip = (char) atoi(buf);
735 void set_long_val(int msgpos, long int *ip)
738 snprintf(buf, sizeof buf, "%ld", *ip);
739 set_str_val(msgpos, buf);
744 void edit_value(int curr)
748 char ctdluidname[256];
753 if (setup_type == UI_SILENT)
755 if (getenv("SYSADMIN_NAME")) {
756 strcpy(config.c_sysadm, getenv("SYSADMIN_NAME"));
760 set_str_val(curr, config.c_sysadm);
765 if (setup_type == UI_SILENT)
767 if (getenv("SYSADMIN_PW")) {
768 strcpy(admin_pass, getenv("SYSADMIN_PW"));
772 set_str_val(curr, admin_pass);
777 if (setup_type == UI_SILENT)
779 if (getenv("CITADEL_UID")) {
780 config.c_ctdluid = atoi(getenv("CITADEL_UID"));
786 config.c_ctdluid = 0; /* XXX Windows hack, prob. insecure */
788 i = config.c_ctdluid;
791 set_int_val(curr, &i);
792 config.c_ctdluid = i;
795 strcpy(ctdluidname, pw->pw_name);
796 set_str_val(curr, ctdluidname);
797 pw = getpwnam(ctdluidname);
799 config.c_ctdluid = pw->pw_uid;
801 else if (atoi(ctdluidname) > 0) {
802 config.c_ctdluid = atoi(ctdluidname);
810 if (setup_type == UI_SILENT)
812 if (getenv("IP_ADDR")) {
813 strcpy(config.c_ip_addr, getenv("IP_ADDR"));
817 set_str_val(curr, config.c_ip_addr);
822 if (setup_type == UI_SILENT)
824 if (getenv("CITADEL_PORT")) {
825 config.c_port_number = atoi(getenv("CITADEL_PORT"));
830 set_int_val(curr, &config.c_port_number);
835 if (setup_type == UI_SILENT)
837 if (getenv("ENABLE_UNIX_AUTH")) {
838 if (!strcasecmp(getenv("ENABLE_UNIX_AUTH"), "yes")) {
839 config.c_auth_mode = AUTHMODE_HOST;
842 config.c_auth_mode = AUTHMODE_NATIVE;
847 set_bool_val(curr, &config.c_auth_mode);
855 * (re-)write the config data to disk
857 void write_config_to_disk(void)
862 if ((fd = creat(file_citadel_config, S_IRUSR | S_IWUSR)) == -1) {
863 display_error("setup: cannot open citadel.config");
866 fp = fdopen(fd, "wb");
868 display_error("setup: cannot open citadel.config");
871 fwrite((char *) &config, sizeof(struct config), 1, fp);
879 * Figure out what type of user interface we're going to use
881 int discover_ui(void)
884 /* Use "dialog" if we have it */
885 if (getenv("CTDL_DIALOG") != NULL) {
897 * Strip "db" entries out of /etc/nsswitch.conf
907 int file_changed = 0;
908 char new_filename[64];
910 fp_read = fopen(NSSCONF, "r");
911 if (fp_read == NULL) {
915 strcpy(new_filename, "/tmp/ctdl_fixnss_XXXXXX");
916 fd_write = mkstemp(new_filename);
922 while (fgets(buf, sizeof buf, fp_read) != NULL) {
925 for (i=0; i<strlen(buf_nc); ++i) {
926 if (buf_nc[i] == '#') {
930 for (i=0; i<strlen(buf_nc); ++i) {
931 if (!strncasecmp(&buf_nc[i], "db", 2)) {
933 if ((isspace(buf_nc[i+2])) || (buf_nc[i+2]==0)) {
936 strcpy(&buf_nc[i], &buf_nc[i+2]);
937 strcpy(&buf[i], &buf[i+2]);
939 strcpy(&buf_nc[i], &buf_nc[i+1]);
940 strcpy(&buf[i], &buf[i+1]);
946 if (write(fd_write, buf, strlen(buf)) != strlen(buf)) {
949 unlink(new_filename);
957 unlink(new_filename);
961 snprintf(question, sizeof question,
963 "/etc/nsswitch.conf is configured to use the 'db' module for\n"
964 "one or more services. This is not necessary on most systems,\n"
965 "and it is known to crash the Citadel server when delivering\n"
966 "mail to the Internet.\n"
968 "Do you want this module to be automatically disabled?\n"
972 if (yesno(question, 1)) {
973 sprintf(buf, "/bin/mv -f %s %s", new_filename, NSSCONF);
976 unlink(new_filename);
986 int main(int argc, char *argv[])
992 int old_setup_level = 0;
994 struct utsname my_utsname;
1000 char relhome[PATH_MAX]="";
1001 char ctdldir[PATH_MAX]=CTDLDIR;
1003 /* set an invalid setup type */
1006 /* Check to see if we're running the web installer */
1007 if (getenv("CITADEL_INSTALLER") != NULL) {
1008 using_web_installer = 1;
1011 /* parse command line args */
1012 for (a = 0; a < argc; ++a) {
1013 if (!strncmp(argv[a], "-u", 2)) {
1014 strcpy(aaa, argv[a]);
1015 strcpy(aaa, &aaa[2]);
1016 setup_type = atoi(aaa);
1018 else if (!strcmp(argv[a], "-i")) {
1021 else if (!strcmp(argv[a], "-q")) {
1022 setup_type = UI_SILENT;
1024 else if (!strncmp(argv[a], "-h", 2)) {
1025 relh=argv[a][2]!='/';
1026 if (!relh) safestrncpy(ctdl_home_directory, &argv[a][2],
1027 sizeof ctdl_home_directory);
1029 safestrncpy(relhome, &argv[a][2],
1036 calc_dirs_n_files(relh, home, relhome, ctdldir, 0);
1038 /* If a setup type was not specified, try to determine automatically
1039 * the best one to use out of all available types.
1041 if (setup_type < 0) {
1042 setup_type = discover_ui();
1044 if (info_only == 1) {
1045 important_message("Citadel Setup", CITADEL);
1049 /* Get started in a valid setup directory. */
1050 strcpy(setup_directory, ctdl_run_dir);
1051 if ( (using_web_installer) && (getenv("CITADEL") != NULL) ) {
1052 strcpy(setup_directory, getenv("CITADEL"));
1055 set_str_val(0, setup_directory);
1058 enable_home = ( relh | home );
1060 if (chdir(setup_directory) != 0) {
1062 sprintf(errmsg, "The directory you specified does not exist: [%s]\n", setup_directory);
1064 important_message("Citadel Setup", errmsg);
1068 /* Determine our host name, in case we need to use it as a default */
1071 /* Try to stop Citadel if we can */
1072 if (!access("/etc/init.d/citadel", X_OK)) {
1073 system("/etc/init.d/citadel stop");
1076 /* Make sure Citadel is not running. */
1077 if (test_server(setup_directory, relhome, enable_home) == 0) {
1078 important_message("Citadel Setup",
1079 "The Citadel service is still running.\n"
1080 "Please stop the service manually and run "
1086 switch (setup_type) {
1090 " *** Citadel setup program ***\n\n");
1096 * What we're going to try to do here is append a whole bunch of
1097 * nulls to the citadel.config file, so we can keep the old config
1098 * values if they exist, but if the file is missing or from an
1099 * earlier version with a shorter config structure, when setup tries
1100 * to read the old config parameters, they'll all come up zero.
1101 * The length of the config file will be set to what it's supposed
1102 * to be when we rewrite it, because we replace the old file with a
1103 * completely new copy.
1105 if ((a = open(file_citadel_config, O_WRONLY | O_CREAT | O_APPEND,
1106 S_IRUSR | S_IWUSR)) == -1) {
1107 display_error("setup: cannot append citadel.config");
1110 fp = fdopen(a, "ab");
1112 display_error("setup: cannot append citadel.config");
1115 for (a = 0; a < sizeof(struct config); ++a)
1119 /* now we re-open it, and read the old or blank configuration */
1120 fp = fopen(file_citadel_config, "rb");
1122 display_error("setup: cannot open citadel.config");
1125 fread((char *) &config, sizeof(struct config), 1, fp);
1128 /* set some sample/default values in place of blanks... */
1129 if (IsEmptyStr(config.c_nodename))
1130 safestrncpy(config.c_nodename, my_utsname.nodename,
1131 sizeof config.c_nodename);
1132 strtok(config.c_nodename, ".");
1133 if (IsEmptyStr(config.c_fqdn) ) {
1134 if ((he = gethostbyname(my_utsname.nodename)) != NULL)
1135 safestrncpy(config.c_fqdn, he->h_name,
1136 sizeof config.c_fqdn);
1138 safestrncpy(config.c_fqdn, my_utsname.nodename,
1139 sizeof config.c_fqdn);
1141 if (IsEmptyStr(config.c_humannode))
1142 strcpy(config.c_humannode, "My System");
1143 if (IsEmptyStr(config.c_phonenum))
1144 strcpy(config.c_phonenum, "US 800 555 1212");
1145 if (config.c_initax == 0) {
1146 config.c_initax = 4;
1148 if (IsEmptyStr(config.c_moreprompt))
1149 strcpy(config.c_moreprompt, "<more>");
1150 if (IsEmptyStr(config.c_twitroom))
1151 strcpy(config.c_twitroom, "Trashcan");
1152 if (IsEmptyStr(config.c_baseroom))
1153 strcpy(config.c_baseroom, BASEROOM);
1154 if (IsEmptyStr(config.c_aideroom))
1155 strcpy(config.c_aideroom, "Aide");
1156 if (config.c_port_number == 0) {
1157 config.c_port_number = 504;
1159 if (config.c_sleeping == 0) {
1160 config.c_sleeping = 900;
1162 if (config.c_ctdluid == 0) {
1163 pw = getpwnam("citadel");
1165 config.c_ctdluid = pw->pw_uid;
1167 if (config.c_ctdluid == 0) {
1168 pw = getpwnam("bbs");
1170 config.c_ctdluid = pw->pw_uid;
1172 if (config.c_ctdluid == 0) {
1173 pw = getpwnam("guest");
1175 config.c_ctdluid = pw->pw_uid;
1177 if (config.c_createax == 0) {
1178 config.c_createax = 3;
1181 * Negative values for maxsessions are not allowed.
1183 if (config.c_maxsessions < 0) {
1184 config.c_maxsessions = 0;
1186 /* We need a system default message expiry policy, because this is
1187 * the top level and there's no 'higher' policy to fall back on.
1188 * By default, do not expire messages at all.
1190 if (config.c_ep.expire_mode == 0) {
1191 config.c_ep.expire_mode = EXPIRE_MANUAL;
1192 config.c_ep.expire_value = 0;
1196 * Default port numbers for various services
1198 if (config.c_smtp_port == 0) config.c_smtp_port = 25;
1199 if (config.c_pop3_port == 0) config.c_pop3_port = 110;
1200 if (config.c_imap_port == 0) config.c_imap_port = 143;
1201 if (config.c_msa_port == 0) config.c_msa_port = 587;
1202 if (config.c_smtps_port == 0) config.c_smtps_port = 465;
1203 if (config.c_pop3s_port == 0) config.c_pop3s_port = 995;
1204 if (config.c_imaps_port == 0) config.c_imaps_port = 993;
1205 if (config.c_pftcpdict_port == 0) config.c_pftcpdict_port = -1;
1206 if (config.c_managesieve_port == 0) config.c_managesieve_port = 2020;
1207 if (config.c_xmpp_c2s_port == 0) config.c_xmpp_c2s_port = 5222;
1208 if (config.c_xmpp_s2s_port == 0) config.c_xmpp_s2s_port = 5269;
1210 /* Go through a series of dialogs prompting for config info */
1211 for (curr = 1; curr <= MAXSETUP; ++curr) {
1215 /***** begin version update section ***** */
1216 /* take care of any updating that is necessary */
1218 old_setup_level = config.c_setup_level;
1220 if (old_setup_level == 0) {
1224 if (old_setup_level < 555) {
1225 important_message("Citadel Setup",
1226 "This Citadel installation is too old "
1230 write_config_to_disk();
1232 old_setup_level = config.c_setup_level;
1234 /* end of version update section */
1237 config.c_setup_level = REV_LEVEL;
1239 /******************************************/
1241 write_config_to_disk();
1243 mkdir(ctdl_info_dir, 0700);
1244 chmod(ctdl_info_dir, 0700);
1245 chown(ctdl_info_dir, config.c_ctdluid, -1);
1247 mkdir(ctdl_bio_dir, 0700);
1248 chmod(ctdl_bio_dir, 0700);
1249 chown(ctdl_bio_dir, config.c_ctdluid, -1);
1251 mkdir(ctdl_usrpic_dir, 0700);
1252 chmod(ctdl_usrpic_dir, 0700);
1253 chown(ctdl_usrpic_dir, config.c_ctdluid, -1);
1255 mkdir(ctdl_message_dir, 0700);
1256 chmod(ctdl_message_dir, 0700);
1257 chown(ctdl_message_dir, config.c_ctdluid, -1);
1259 mkdir(ctdl_hlp_dir, 0700);
1260 chmod(ctdl_hlp_dir, 0700);
1261 chown(ctdl_hlp_dir, config.c_ctdluid, -1);
1263 mkdir(ctdl_image_dir, 0700);
1264 chmod(ctdl_image_dir, 0700);
1265 chown(ctdl_image_dir, config.c_ctdluid, -1);
1267 mkdir(ctdl_bb_dir, 0700);
1268 chmod(ctdl_bb_dir, 0700);
1269 chown(ctdl_bb_dir, config.c_ctdluid, -1);
1271 mkdir(ctdl_file_dir, 0700);
1272 chmod(ctdl_file_dir, 0700);
1273 chown(ctdl_file_dir, config.c_ctdluid, -1);
1275 mkdir(ctdl_netcfg_dir, 0700);
1276 chmod(ctdl_netcfg_dir, 0700);
1277 chown(ctdl_netcfg_dir, config.c_ctdluid, -1);
1279 /* Delete files and directories used by older Citadel versions */
1280 system("exec /bin/rm -fr ./rooms ./chatpipes ./expressmsgs ./sessions 2>/dev/null");
1281 unlink("citadel.log");
1284 if (((setup_type == UI_SILENT) && (getenv("ALTER_ETC_SERVICES")!=NULL)) ||
1285 (setup_type != UI_SILENT))
1286 check_services_entry(); /* Check /etc/services */
1288 delete_inittab_entry(); /* Remove obsolete /etc/inittab entry */
1289 check_xinetd_entry(); /* Check /etc/xinetd.d/telnet */
1291 if ((getenv("ACT_AS_MTA") == NULL) ||
1292 (getenv("ACT_AS_MTA") &&
1293 strcasecmp(getenv("ACT_AS_MTA"), "yes") == 0)) {
1294 /* Offer to disable other MTA's on the system. */
1295 disable_other_mta("courier-authdaemon");
1296 disable_other_mta("courier-imap");
1297 disable_other_mta("courier-imap-ssl");
1298 disable_other_mta("courier-pop");
1299 disable_other_mta("courier-pop3");
1300 disable_other_mta("courier-pop3d");
1301 disable_other_mta("cyrmaster");
1302 disable_other_mta("cyrus");
1303 disable_other_mta("dovecot");
1304 disable_other_mta("exim");
1305 disable_other_mta("exim4");
1306 disable_other_mta("imapd");
1307 disable_other_mta("mta");
1308 disable_other_mta("pop3d");
1309 disable_other_mta("popd");
1310 disable_other_mta("postfix");
1311 disable_other_mta("qmail");
1312 disable_other_mta("saslauthd");
1313 disable_other_mta("sendmail");
1314 disable_other_mta("vmailmgrd");
1318 /* Check for the 'db' nss and offer to disable it */
1321 if ((pw = getpwuid(config.c_ctdluid)) == NULL)
1326 progress("Setting file permissions", 0, 3);
1327 chown(ctdl_run_dir, config.c_ctdluid, gid);
1328 progress("Setting file permissions", 1, 3);
1329 chown(file_citadel_config, config.c_ctdluid, gid);
1330 progress("Setting file permissions", 2, 3);
1331 chmod(file_citadel_config, S_IRUSR | S_IWUSR);
1332 progress("Setting file permissions", 3, 3);
1335 * If we're running on SysV, install init scripts.
1337 if (!access("/var/run", W_OK)) {
1339 if (getenv("NO_INIT_SCRIPTS") == NULL) {
1340 install_init_scripts();
1343 if (!access("/etc/init.d/citadel", X_OK)) {
1344 system("/etc/init.d/citadel start");
1348 if (test_server(setup_directory, relhome, enable_home) == 0) {
1352 snprintf (admin_cmd, sizeof(admin_cmd), "%s/sendcommand \"CREU %s|%s\" 2>&1",
1353 ctdl_sbin_dir, config.c_sysadm, admin_pass);
1354 fp = popen(admin_cmd, "r");
1356 while (fgets(buf, sizeof buf, fp) != NULL)
1358 if ((atol(buf) == 574) || (atol(buf) == 200))
1365 important_message("Error","Setup failed to create your admin user");
1367 if (setup_type != UI_SILENT)
1368 important_message("Setup finished",
1369 "Setup of the Citadel server is complete.\n"
1370 "If you will be using WebCit, please run its\n"
1371 "setup program now; otherwise, run './citadel'\n"
1375 important_message("Setup failed",
1376 "Setup is finished, but the Citadel server failed to start.\n"
1377 "Go back and check your configuration.\n"
1384 important_message("Setup finished",
1385 "Setup is finished. You may now start the server.");