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",
135 "How would you like to authenticate users on your Citadel system?\n"
137 " 0. Self contained authentication - Citadel maintains its own user database\n"
138 " (This mode is *strongly* recommended)\n"
140 " 1. Authenticate users against the host system (unix or linux accounts)\n"
142 " 2. Authenticate users against an external LDAP directory\n"
144 "WARNING: do *not* change this setting once your system is installed.\n"
146 "(Answer \"0\" unless you completely understand this option)\n"
147 "Which authentication mode do you want to use?\n"
151 struct config config;
155 void cleanup(int exitcode)
157 // printf("Exitcode: %d\n", exitcode);
164 void title(char *text)
166 if (setup_type == UI_TEXT) {
167 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<%s>\n", text);
173 int yesno(char *question, int default_value)
179 switch (setup_type) {
183 printf("%s\nYes/No [%s] --> ",
185 ( default_value ? "Yes" : "No" )
187 fgets(buf, sizeof buf, stdin);
188 answer = tolower(buf[0]);
189 if ((buf[0]==0) || (buf[0]==13) || (buf[0]==10))
190 answer = default_value;
191 else if (answer == 'y')
193 else if (answer == 'n')
195 } while ((answer < 0) || (answer > 1));
199 sprintf(buf, "exec %s %s --yesno '%s' 15 75",
200 getenv("CTDL_DIALOG"),
201 ( default_value ? "" : "--defaultno" ),
219 void important_message(char *title, char *msgtext)
223 switch (setup_type) {
226 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");
227 printf(" %s \n\n%s\n\n", title, msgtext);
228 printf("Press return to continue...");
229 fgets(buf, sizeof buf, stdin);
233 sprintf(buf, "exec %s --msgbox '%s' 19 72",
234 getenv("CTDL_DIALOG"),
239 fprintf(stderr, "%s\n", msgtext);
244 void important_msgnum(int msgnum)
246 important_message("Important Message", setup_text[msgnum]);
249 void display_error(char *error_message)
251 important_message("Error", error_message);
254 void progress(char *text, long int curr, long int cmax)
256 static long dots_printed = 0L;
258 static FILE *fp = NULL;
261 switch (setup_type) {
265 printf("%s\n", text);
266 printf("..........................");
267 printf("..........................");
268 printf("..........................\r");
271 } else if (curr == cmax) {
272 printf("\r%79s\n", "");
274 a = (curr * 100) / cmax;
277 while (dots_printed < a) {
287 sprintf(buf, "exec %s --gauge '%s' 7 72 0",
288 getenv("CTDL_DIALOG"),
290 fp = popen(buf, "w");
296 else if (curr == cmax) {
298 fprintf(fp, "100\n");
304 a = (curr * 100) / cmax;
306 fprintf(fp, "%ld\n", a);
320 * check_services_entry() -- Make sure "citadel" is in /etc/services
323 void check_services_entry(void)
329 if (getservbyname(SERVICE_NAME, PROTO_NAME) == NULL) {
330 for (i=0; i<=2; ++i) {
331 progress("Adding service entry...", i, 2);
333 sfp = fopen("/etc/services", "a");
335 sprintf(errmsg, "Cannot open /etc/services: %s", strerror(errno));
336 display_error(errmsg);
338 fprintf(sfp, "%s 504/tcp\n", SERVICE_NAME);
350 * delete_inittab_entry() -- Remove obsolete /etc/inittab entry for Citadel
353 void delete_inittab_entry(void)
357 char looking_for[256];
359 char outfilename[32];
360 int changes_made = 0;
362 /* Determine the fully qualified path name of citserver */
363 snprintf(looking_for,
369 /* Now tweak /etc/inittab */
370 infp = fopen("/etc/inittab", "r");
373 /* If /etc/inittab does not exist, return quietly.
374 * Not all host platforms have it.
376 if (errno == ENOENT) {
380 /* Other errors might mean something really did go wrong.
382 sprintf(buf, "Cannot open /etc/inittab: %s", strerror(errno));
387 strcpy(outfilename, "/tmp/ctdlsetup.XXXXXX");
388 outfp = fdopen(mkstemp(outfilename), "w+");
390 sprintf(buf, "Cannot open %s: %s", outfilename, strerror(errno));
396 while (fgets(buf, sizeof buf, infp) != NULL) {
397 if (strstr(buf, looking_for) != NULL) {
398 fwrite("#", 1, 1, outfp);
401 fwrite(buf, strlen(buf), 1, outfp);
408 sprintf(buf, "/bin/mv -f %s /etc/inittab 2>/dev/null", outfilename);
410 system("/sbin/init q 2>/dev/null");
419 * install_init_scripts() -- Try to configure to start Citadel at boot
422 void install_init_scripts(void)
424 struct stat etcinitd;
426 char *initfile = "/etc/init.d/citadel";
429 if ((stat("/etc/init.d/", &etcinitd) == -1) &&
432 if ((stat("/etc/rc.d/init.d/", &etcinitd) == -1) &&
434 initfile = CTDLDIR"/citadel.init";
436 initfile = "/etc/rc.d/init.d/citadel";
439 fp = fopen(initfile, "r");
441 if (yesno("Citadel already appears to be configured to start at boot.\n"
442 "Would you like to keep your boot configuration as is?\n", 1) == 1) {
449 if (yesno("Would you like to automatically start Citadel at boot?\n", 1) == 0) {
453 fp = fopen(initfile, "w");
455 display_error("Cannot create /etc/init.d/citadel");
459 fprintf(fp, "#!/bin/sh\n"
461 "# Init file for Citadel\n"
463 "# chkconfig: - 79 30\n"
464 "# description: Citadel service\n"
465 "# processname: citserver\n"
466 "# pidfile: %s/citadel.pid\n"
474 "test -d /var/run || exit 0\n"
478 "start) echo -n \"Starting Citadel... \"\n"
479 " if $CITADEL_DIR/citserver -d -h$CITADEL_DIR\n"
486 "stop) echo -n \"Stopping Citadel... \"\n"
487 " if $CITADEL_DIR/sendcommand DOWN >/dev/null 2>&1 ; then\n"
492 " rm -f %s/citadel.pid 2>/dev/null\n"
497 "restart) if $CITADEL_DIR/sendcommand DOWN 1 >/dev/null 2>&1 ; then\n"
503 "*) echo \"Usage: $0 {start|stop|restart}\"\n"
510 chmod(initfile, 0755);
512 /* Set up the run levels. */
513 system("/bin/rm -f /etc/rc?.d/[SK]??citadel 2>/dev/null");
514 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);
516 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);
527 * On systems which use xinetd, see if we can offer to install Citadel as
528 * the default telnet target.
530 void check_xinetd_entry(void) {
531 char *filename = "/etc/xinetd.d/telnet";
534 int already_citadel = 0;
536 fp = fopen(filename, "r+");
537 if (fp == NULL) return; /* Not there. Oh well... */
539 while (fgets(buf, sizeof buf, fp) != NULL) {
540 if (strstr(buf, setup_directory) != NULL) already_citadel = 1;
543 if (already_citadel) return; /* Already set up this way. */
545 /* Otherwise, prompt the user to create an entry. */
546 if (getenv("CREATE_XINETD_ENTRY") != NULL) {
547 if (strcasecmp(getenv("CREATE_XINETD_ENTRY"), "yes")) {
552 snprintf(buf, sizeof buf,
553 "Setup can configure the \"xinetd\" service to automatically\n"
554 "connect incoming telnet sessions to Citadel, bypassing the\n"
555 "host system login: prompt. Would you like to do this?\n"
557 if (yesno(buf, 1) == 0) {
562 fp = fopen(filename, "w");
564 "# description: telnet service for Citadel users\n"
569 " socket_type = stream\n"
572 " server = /usr/sbin/in.telnetd\n"
573 " server_args = -h -L %s/citadel\n"
574 " log_on_failure += USERID\n"
579 /* Now try to restart the service */
580 system("/etc/init.d/xinetd restart >/dev/null 2>&1");
586 * Offer to disable other MTA's
588 void disable_other_mta(char *mta) {
593 sprintf(buf, "/bin/ls -l /etc/rc*.d/S*%s 2>/dev/null; "
594 "/bin/ls -l /etc/rc.d/rc*.d/S*%s 2>/dev/null",
596 fp = popen(buf, "r");
597 if (fp == NULL) return;
599 while (fgets(buf, sizeof buf, fp) != NULL) {
603 if (lines == 0) return; /* Nothing to do. */
606 /* Offer to replace other MTA with the vastly superior Citadel :) */
608 snprintf(buf, sizeof buf,
609 "You appear to have the \"%s\" email program\n"
610 "running on your system. If you want Citadel mail\n"
611 "connected with %s, you will have to manually integrate\n"
612 "them. It is preferable to disable %s, and use Citadel's\n"
613 "SMTP, POP3, and IMAP services.\n\n"
614 "May we disable %s so that Citadel has access to ports\n"
615 "25, 110, and 143?\n",
618 if (yesno(buf, 1) == 0) {
623 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);
625 sprintf(buf, "/etc/init.d/%s stop >/dev/null 2>&1", mta);
633 * Check to see if our server really works. Returns 0 on success.
635 int test_server(char *setup_directory, char *relhomestr, int relhome) {
642 /* Generate a silly little cookie. We're going to write it out
643 * to the server and try to get it back. The cookie does not
644 * have to be secret ... just unique.
646 sprintf(cookie, "--test--%d--", getpid());
649 sprintf(cmd, "%s/sendcommand -h%s ECHO %s 2>&1",
654 sprintf(cmd, "%s/sendcommand ECHO %s 2>&1",
658 fp = popen(cmd, "r");
659 if (fp == NULL) return(errno);
661 while (fgets(buf, sizeof buf, fp) != NULL) {
663 && (strstr(buf, cookie) != NULL) ) {
675 void strprompt(char *prompt_title, char *prompt_text, char *str)
679 char dialog_result[PATH_MAX];
682 strcpy(setupmsg, "");
684 switch (setup_type) {
687 printf("\n%s\n", prompt_text);
688 printf("This is currently set to:\n%s\n", str);
689 printf("Enter new value or press return to leave unchanged:\n");
690 fgets(buf, sizeof buf, stdin);
691 buf[strlen(buf) - 1] = 0;
692 if (!IsEmptyStr(buf))
697 CtdlMakeTempFileName(dialog_result, sizeof dialog_result);
698 sprintf(buf, "exec %s --inputbox '%s' 19 72 '%s' 2>%s",
699 getenv("CTDL_DIALOG"),
704 fp = fopen(dialog_result, "r");
706 fgets(str, sizeof buf, fp);
707 if (str[strlen(str)-1] == 10) {
708 str[strlen(str)-1] = 0;
711 unlink(dialog_result);
719 void set_bool_val(int msgpos, int *ip) {
720 title(setup_titles[msgpos]);
721 *ip = yesno(setup_text[msgpos], *ip);
724 void set_str_val(int msgpos, char *str) {
725 strprompt(setup_titles[msgpos], setup_text[msgpos], str);
728 void set_int_val(int msgpos, int *ip)
731 snprintf(buf, sizeof buf, "%d", (int) *ip);
732 set_str_val(msgpos, buf);
737 void set_char_val(int msgpos, char *ip)
740 snprintf(buf, sizeof buf, "%d", (int) *ip);
741 set_str_val(msgpos, buf);
742 *ip = (char) atoi(buf);
746 void set_long_val(int msgpos, long int *ip)
749 snprintf(buf, sizeof buf, "%ld", *ip);
750 set_str_val(msgpos, buf);
755 void edit_value(int curr)
759 char ctdluidname[256];
764 if (setup_type == UI_SILENT)
766 if (getenv("SYSADMIN_NAME")) {
767 strcpy(config.c_sysadm, getenv("SYSADMIN_NAME"));
771 set_str_val(curr, config.c_sysadm);
776 if (setup_type == UI_SILENT)
778 if (getenv("SYSADMIN_PW")) {
779 strcpy(admin_pass, getenv("SYSADMIN_PW"));
783 set_str_val(curr, admin_pass);
788 if (setup_type == UI_SILENT)
790 if (getenv("CITADEL_UID")) {
791 config.c_ctdluid = atoi(getenv("CITADEL_UID"));
797 config.c_ctdluid = 0; /* XXX Windows hack, prob. insecure */
799 i = config.c_ctdluid;
802 set_int_val(curr, &i);
803 config.c_ctdluid = i;
806 strcpy(ctdluidname, pw->pw_name);
807 set_str_val(curr, ctdluidname);
808 pw = getpwnam(ctdluidname);
810 config.c_ctdluid = pw->pw_uid;
812 else if (atoi(ctdluidname) > 0) {
813 config.c_ctdluid = atoi(ctdluidname);
821 if (setup_type == UI_SILENT)
823 if (getenv("IP_ADDR")) {
824 strcpy(config.c_ip_addr, getenv("IP_ADDR"));
828 set_str_val(curr, config.c_ip_addr);
833 if (setup_type == UI_SILENT)
835 if (getenv("CITADEL_PORT")) {
836 config.c_port_number = atoi(getenv("CITADEL_PORT"));
841 set_int_val(curr, &config.c_port_number);
846 if (setup_type == UI_SILENT)
848 if (getenv("ENABLE_UNIX_AUTH")) {
849 if (!strcasecmp(getenv("ENABLE_UNIX_AUTH"), "yes")) {
850 config.c_auth_mode = AUTHMODE_HOST;
853 config.c_auth_mode = AUTHMODE_NATIVE;
858 set_int_val(curr, &config.c_auth_mode);
866 * (re-)write the config data to disk
868 void write_config_to_disk(void)
873 if ((fd = creat(file_citadel_config, S_IRUSR | S_IWUSR)) == -1) {
874 display_error("setup: cannot open citadel.config");
877 fp = fdopen(fd, "wb");
879 display_error("setup: cannot open citadel.config");
882 fwrite((char *) &config, sizeof(struct config), 1, fp);
890 * Figure out what type of user interface we're going to use
892 int discover_ui(void)
895 /* Use "dialog" if we have it */
896 if (getenv("CTDL_DIALOG") != NULL) {
908 * Strip "db" entries out of /etc/nsswitch.conf
918 int file_changed = 0;
919 char new_filename[64];
921 fp_read = fopen(NSSCONF, "r");
922 if (fp_read == NULL) {
926 strcpy(new_filename, "/tmp/ctdl_fixnss_XXXXXX");
927 fd_write = mkstemp(new_filename);
933 while (fgets(buf, sizeof buf, fp_read) != NULL) {
936 for (i=0; i<strlen(buf_nc); ++i) {
937 if (buf_nc[i] == '#') {
941 for (i=0; i<strlen(buf_nc); ++i) {
942 if (!strncasecmp(&buf_nc[i], "db", 2)) {
944 if ((isspace(buf_nc[i+2])) || (buf_nc[i+2]==0)) {
947 strcpy(&buf_nc[i], &buf_nc[i+2]);
948 strcpy(&buf[i], &buf[i+2]);
950 strcpy(&buf_nc[i], &buf_nc[i+1]);
951 strcpy(&buf[i], &buf[i+1]);
957 if (write(fd_write, buf, strlen(buf)) != strlen(buf)) {
960 unlink(new_filename);
968 unlink(new_filename);
972 snprintf(question, sizeof question,
974 "/etc/nsswitch.conf is configured to use the 'db' module for\n"
975 "one or more services. This is not necessary on most systems,\n"
976 "and it is known to crash the Citadel server when delivering\n"
977 "mail to the Internet.\n"
979 "Do you want this module to be automatically disabled?\n"
983 if (yesno(question, 1)) {
984 sprintf(buf, "/bin/mv -f %s %s", new_filename, NSSCONF);
986 chmod(NSSCONF, 0644);
988 unlink(new_filename);
998 int main(int argc, char *argv[])
1004 int old_setup_level = 0;
1006 struct utsname my_utsname;
1012 char relhome[PATH_MAX]="";
1013 char ctdldir[PATH_MAX]=CTDLDIR;
1015 /* set an invalid setup type */
1018 /* Check to see if we're running the web installer */
1019 if (getenv("CITADEL_INSTALLER") != NULL) {
1020 using_web_installer = 1;
1023 /* parse command line args */
1024 for (a = 0; a < argc; ++a) {
1025 if (!strncmp(argv[a], "-u", 2)) {
1026 strcpy(aaa, argv[a]);
1027 strcpy(aaa, &aaa[2]);
1028 setup_type = atoi(aaa);
1030 else if (!strcmp(argv[a], "-i")) {
1033 else if (!strcmp(argv[a], "-q")) {
1034 setup_type = UI_SILENT;
1036 else if (!strncmp(argv[a], "-h", 2)) {
1037 relh=argv[a][2]!='/';
1038 if (!relh) safestrncpy(ctdl_home_directory, &argv[a][2],
1039 sizeof ctdl_home_directory);
1041 safestrncpy(relhome, &argv[a][2],
1048 calc_dirs_n_files(relh, home, relhome, ctdldir, 0);
1050 /* If a setup type was not specified, try to determine automatically
1051 * the best one to use out of all available types.
1053 if (setup_type < 0) {
1054 setup_type = discover_ui();
1056 if (info_only == 1) {
1057 important_message("Citadel Setup", CITADEL);
1061 /* Get started in a valid setup directory. */
1062 strcpy(setup_directory, ctdl_run_dir);
1063 if ( (using_web_installer) && (getenv("CITADEL") != NULL) ) {
1064 strcpy(setup_directory, getenv("CITADEL"));
1067 set_str_val(0, setup_directory);
1070 enable_home = ( relh | home );
1072 if (chdir(setup_directory) != 0) {
1074 sprintf(errmsg, "The directory you specified does not exist: [%s]\n", setup_directory);
1076 important_message("Citadel Setup", errmsg);
1080 /* Determine our host name, in case we need to use it as a default */
1083 /* Try to stop Citadel if we can */
1084 if (!access("/etc/init.d/citadel", X_OK)) {
1085 system("/etc/init.d/citadel stop");
1088 /* Make sure Citadel is not running. */
1089 if (test_server(setup_directory, relhome, enable_home) == 0) {
1090 important_message("Citadel Setup",
1091 "The Citadel service is still running.\n"
1092 "Please stop the service manually and run "
1098 switch (setup_type) {
1102 " *** Citadel setup program ***\n\n");
1108 * What we're going to try to do here is append a whole bunch of
1109 * nulls to the citadel.config file, so we can keep the old config
1110 * values if they exist, but if the file is missing or from an
1111 * earlier version with a shorter config structure, when setup tries
1112 * to read the old config parameters, they'll all come up zero.
1113 * The length of the config file will be set to what it's supposed
1114 * to be when we rewrite it, because we replace the old file with a
1115 * completely new copy.
1117 if ((a = open(file_citadel_config, O_WRONLY | O_CREAT | O_APPEND,
1118 S_IRUSR | S_IWUSR)) == -1) {
1119 display_error("setup: cannot append citadel.config");
1122 fp = fdopen(a, "ab");
1124 display_error("setup: cannot append citadel.config");
1127 for (a = 0; a < sizeof(struct config); ++a)
1131 /* now we re-open it, and read the old or blank configuration */
1132 fp = fopen(file_citadel_config, "rb");
1134 display_error("setup: cannot open citadel.config");
1137 fread((char *) &config, sizeof(struct config), 1, fp);
1140 /* set some sample/default values in place of blanks... */
1141 if (IsEmptyStr(config.c_nodename))
1142 safestrncpy(config.c_nodename, my_utsname.nodename,
1143 sizeof config.c_nodename);
1144 strtok(config.c_nodename, ".");
1145 if (IsEmptyStr(config.c_fqdn) ) {
1146 if ((he = gethostbyname(my_utsname.nodename)) != NULL)
1147 safestrncpy(config.c_fqdn, he->h_name,
1148 sizeof config.c_fqdn);
1150 safestrncpy(config.c_fqdn, my_utsname.nodename,
1151 sizeof config.c_fqdn);
1153 if (IsEmptyStr(config.c_humannode))
1154 strcpy(config.c_humannode, "My System");
1155 if (IsEmptyStr(config.c_phonenum))
1156 strcpy(config.c_phonenum, "US 800 555 1212");
1157 if (config.c_initax == 0) {
1158 config.c_initax = 4;
1160 if (IsEmptyStr(config.c_moreprompt))
1161 strcpy(config.c_moreprompt, "<more>");
1162 if (IsEmptyStr(config.c_twitroom))
1163 strcpy(config.c_twitroom, "Trashcan");
1164 if (IsEmptyStr(config.c_baseroom))
1165 strcpy(config.c_baseroom, BASEROOM);
1166 if (IsEmptyStr(config.c_aideroom))
1167 strcpy(config.c_aideroom, "Aide");
1168 if (config.c_port_number == 0) {
1169 config.c_port_number = 504;
1171 if (config.c_sleeping == 0) {
1172 config.c_sleeping = 900;
1174 if (config.c_ctdluid == 0) {
1175 pw = getpwnam("citadel");
1177 config.c_ctdluid = pw->pw_uid;
1179 if (config.c_ctdluid == 0) {
1180 pw = getpwnam("bbs");
1182 config.c_ctdluid = pw->pw_uid;
1184 if (config.c_ctdluid == 0) {
1185 pw = getpwnam("guest");
1187 config.c_ctdluid = pw->pw_uid;
1189 if (config.c_createax == 0) {
1190 config.c_createax = 3;
1193 * Negative values for maxsessions are not allowed.
1195 if (config.c_maxsessions < 0) {
1196 config.c_maxsessions = 0;
1198 /* We need a system default message expiry policy, because this is
1199 * the top level and there's no 'higher' policy to fall back on.
1200 * By default, do not expire messages at all.
1202 if (config.c_ep.expire_mode == 0) {
1203 config.c_ep.expire_mode = EXPIRE_MANUAL;
1204 config.c_ep.expire_value = 0;
1208 * Default port numbers for various services
1210 if (config.c_smtp_port == 0) config.c_smtp_port = 25;
1211 if (config.c_pop3_port == 0) config.c_pop3_port = 110;
1212 if (config.c_imap_port == 0) config.c_imap_port = 143;
1213 if (config.c_msa_port == 0) config.c_msa_port = 587;
1214 if (config.c_smtps_port == 0) config.c_smtps_port = 465;
1215 if (config.c_pop3s_port == 0) config.c_pop3s_port = 995;
1216 if (config.c_imaps_port == 0) config.c_imaps_port = 993;
1217 if (config.c_pftcpdict_port == 0) config.c_pftcpdict_port = -1;
1218 if (config.c_managesieve_port == 0) config.c_managesieve_port = 2020;
1219 if (config.c_xmpp_c2s_port == 0) config.c_xmpp_c2s_port = 5222;
1220 if (config.c_xmpp_s2s_port == 0) config.c_xmpp_s2s_port = 5269;
1222 /* Go through a series of dialogs prompting for config info */
1223 for (curr = 1; curr <= MAXSETUP; ++curr) {
1227 /***** begin version update section ***** */
1228 /* take care of any updating that is necessary */
1230 old_setup_level = config.c_setup_level;
1232 if (old_setup_level == 0) {
1236 if (old_setup_level < 555) {
1237 important_message("Citadel Setup",
1238 "This Citadel installation is too old "
1242 write_config_to_disk();
1244 old_setup_level = config.c_setup_level;
1246 /* end of version update section */
1249 config.c_setup_level = REV_LEVEL;
1251 /******************************************/
1253 write_config_to_disk();
1255 mkdir(ctdl_info_dir, 0700);
1256 chmod(ctdl_info_dir, 0700);
1257 chown(ctdl_info_dir, config.c_ctdluid, -1);
1259 mkdir(ctdl_bio_dir, 0700);
1260 chmod(ctdl_bio_dir, 0700);
1261 chown(ctdl_bio_dir, config.c_ctdluid, -1);
1263 mkdir(ctdl_usrpic_dir, 0700);
1264 chmod(ctdl_usrpic_dir, 0700);
1265 chown(ctdl_usrpic_dir, config.c_ctdluid, -1);
1267 mkdir(ctdl_message_dir, 0700);
1268 chmod(ctdl_message_dir, 0700);
1269 chown(ctdl_message_dir, config.c_ctdluid, -1);
1271 mkdir(ctdl_hlp_dir, 0700);
1272 chmod(ctdl_hlp_dir, 0700);
1273 chown(ctdl_hlp_dir, config.c_ctdluid, -1);
1275 mkdir(ctdl_image_dir, 0700);
1276 chmod(ctdl_image_dir, 0700);
1277 chown(ctdl_image_dir, config.c_ctdluid, -1);
1279 mkdir(ctdl_bb_dir, 0700);
1280 chmod(ctdl_bb_dir, 0700);
1281 chown(ctdl_bb_dir, config.c_ctdluid, -1);
1283 mkdir(ctdl_file_dir, 0700);
1284 chmod(ctdl_file_dir, 0700);
1285 chown(ctdl_file_dir, config.c_ctdluid, -1);
1287 mkdir(ctdl_netcfg_dir, 0700);
1288 chmod(ctdl_netcfg_dir, 0700);
1289 chown(ctdl_netcfg_dir, config.c_ctdluid, -1);
1291 /* Delete files and directories used by older Citadel versions */
1292 system("exec /bin/rm -fr ./rooms ./chatpipes ./expressmsgs ./sessions 2>/dev/null");
1293 unlink("citadel.log");
1296 if (((setup_type == UI_SILENT) && (getenv("ALTER_ETC_SERVICES")!=NULL)) ||
1297 (setup_type != UI_SILENT))
1298 check_services_entry(); /* Check /etc/services */
1300 delete_inittab_entry(); /* Remove obsolete /etc/inittab entry */
1301 check_xinetd_entry(); /* Check /etc/xinetd.d/telnet */
1303 if ((getenv("ACT_AS_MTA") == NULL) ||
1304 (getenv("ACT_AS_MTA") &&
1305 strcasecmp(getenv("ACT_AS_MTA"), "yes") == 0)) {
1306 /* Offer to disable other MTA's on the system. */
1307 disable_other_mta("courier-authdaemon");
1308 disable_other_mta("courier-imap");
1309 disable_other_mta("courier-imap-ssl");
1310 disable_other_mta("courier-pop");
1311 disable_other_mta("courier-pop3");
1312 disable_other_mta("courier-pop3d");
1313 disable_other_mta("cyrmaster");
1314 disable_other_mta("cyrus");
1315 disable_other_mta("dovecot");
1316 disable_other_mta("exim");
1317 disable_other_mta("exim4");
1318 disable_other_mta("imapd");
1319 disable_other_mta("mta");
1320 disable_other_mta("pop3d");
1321 disable_other_mta("popd");
1322 disable_other_mta("postfix");
1323 disable_other_mta("qmail");
1324 disable_other_mta("saslauthd");
1325 disable_other_mta("sendmail");
1326 disable_other_mta("vmailmgrd");
1330 /* Check for the 'db' nss and offer to disable it */
1333 if ((pw = getpwuid(config.c_ctdluid)) == NULL)
1338 progress("Setting file permissions", 0, 3);
1339 chown(ctdl_run_dir, config.c_ctdluid, gid);
1340 progress("Setting file permissions", 1, 3);
1341 chown(file_citadel_config, config.c_ctdluid, gid);
1342 progress("Setting file permissions", 2, 3);
1343 chmod(file_citadel_config, S_IRUSR | S_IWUSR);
1344 progress("Setting file permissions", 3, 3);
1347 * If we're running on SysV, install init scripts.
1349 if (!access("/var/run", W_OK)) {
1351 if (getenv("NO_INIT_SCRIPTS") == NULL) {
1352 install_init_scripts();
1355 if (!access("/etc/init.d/citadel", X_OK)) {
1356 system("/etc/init.d/citadel start");
1360 if (test_server(setup_directory, relhome, enable_home) == 0) {
1364 snprintf (admin_cmd, sizeof(admin_cmd), "%s/sendcommand \"CREU %s|%s\" 2>&1",
1365 ctdl_sbin_dir, config.c_sysadm, admin_pass);
1366 fp = popen(admin_cmd, "r");
1368 while (fgets(buf, sizeof buf, fp) != NULL)
1370 if ((atol(buf) == 574) || (atol(buf) == 200))
1377 important_message("Error","Setup failed to create your admin user");
1379 if (setup_type != UI_SILENT)
1380 important_message("Setup finished",
1381 "Setup of the Citadel server is complete.\n"
1382 "If you will be using WebCit, please run its\n"
1383 "setup program now; otherwise, run './citadel'\n"
1387 important_message("Setup failed",
1388 "Setup is finished, but the Citadel server failed to start.\n"
1389 "Go back and check your configuration.\n"
1396 important_message("Setup finished",
1397 "Setup is finished. You may now start the server.");