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 11 /* 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",
60 "Authentication mode",
69 * \brief print the actual stack frame.
71 void cit_backtrace(void)
74 void *stack_frames[50];
79 size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
80 strings = backtrace_symbols(stack_frames, size);
81 for (i = 0; i < size; i++) {
83 fprintf(stderr, "%s\n", strings[i]);
85 fprintf(stderr, "%p\n", stack_frames[i]);
93 /* calculate all our path on a central place */
94 /* where to keep our config */
97 char *setup_text[] = {
99 "Enter the full pathname of the directory in which the Citadel\n"
100 "installation you are creating or updating resides. If you\n"
101 "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",
104 "Enter the subdirectory name for an alternate installation of "
105 "Citadel. To do a default installation just leave it blank."
106 "If you specify a directory other than the default, you will need to\n"
107 "specify the -h flag to the server when you start it up.\n"
108 "note that it may not have a leading /",
111 "Enter the name of the system administrator (which is probably\n"
112 "you). When an account is created with this name, it will\n"
113 "automatically be given administrator-level access.\n",
115 "Enter a password for the system administrator. When setup\n"
116 "completes it will attempt to create the administrator user\n"
117 "and set the password specified here.\n",
119 "Citadel needs to run under its own user ID. This would\n"
120 "typically be called \"citadel\", but if you are running Citadel\n"
121 "as a public BBS, you might also call it \"bbs\" or \"guest\".\n"
122 "The server will run under this user ID. Please specify that\n"
123 "user ID here. You may specify either a user name or a numeric\n"
126 "Specify the IP address on which your server will run. If you\n"
127 "leave this blank, or if you specify 0.0.0.0, Citadel will listen\n"
128 "on all addresses. You can usually skip this unless you are\n"
129 "running multiple instances of Citadel on the same computer.\n",
131 "Specify the TCP port number on which your server will run.\n"
132 "Normally, this will be port 504, which is the official port\n"
133 "assigned by the IANA for Citadel servers. You will only need\n"
134 "to specify a different port number if you run multiple instances\n"
135 "of Citadel on the same computer and there is something else\n"
136 "already using port 504.\n",
140 "How would you like to authenticate users on your Citadel system?\n"
142 " 0. Self contained authentication - Citadel maintains its own user database\n"
143 " (This mode is *strongly* recommended)\n"
145 " 1. Authenticate users against the host system (unix or linux accounts)\n"
147 " 2. Authenticate users against an external LDAP directory\n"
149 "WARNING: do *not* change this setting once your system is installed.\n"
151 "(Answer \"0\" unless you completely understand this option)\n"
152 "Which authentication mode do you want to use?\n",
155 "LDAP port number FIXME\n",
156 "LDAP base DN FIXME\n",
157 "LDAP bind DN FIXME\n",
158 "LDAP bind password FIXME\n"
162 struct config config;
166 void cleanup(int exitcode)
168 // printf("Exitcode: %d\n", exitcode);
175 void title(char *text)
177 if (setup_type == UI_TEXT) {
178 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<%s>\n", text);
184 int yesno(char *question, int default_value)
190 switch (setup_type) {
194 printf("%s\nYes/No [%s] --> ",
196 ( default_value ? "Yes" : "No" )
198 fgets(buf, sizeof buf, stdin);
199 answer = tolower(buf[0]);
200 if ((buf[0]==0) || (buf[0]==13) || (buf[0]==10))
201 answer = default_value;
202 else if (answer == 'y')
204 else if (answer == 'n')
206 } while ((answer < 0) || (answer > 1));
210 sprintf(buf, "exec %s %s --yesno '%s' 15 75",
211 getenv("CTDL_DIALOG"),
212 ( default_value ? "" : "--defaultno" ),
230 void important_message(char *title, char *msgtext)
234 switch (setup_type) {
237 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");
238 printf(" %s \n\n%s\n\n", title, msgtext);
239 printf("Press return to continue...");
240 fgets(buf, sizeof buf, stdin);
244 sprintf(buf, "exec %s --msgbox '%s' 19 72",
245 getenv("CTDL_DIALOG"),
250 fprintf(stderr, "%s\n", msgtext);
255 void important_msgnum(int msgnum)
257 important_message("Important Message", setup_text[msgnum]);
260 void display_error(char *error_message)
262 important_message("Error", error_message);
265 void progress(char *text, long int curr, long int cmax)
267 static long dots_printed = 0L;
269 static FILE *fp = NULL;
272 switch (setup_type) {
276 printf("%s\n", text);
277 printf("..........................");
278 printf("..........................");
279 printf("..........................\r");
282 } else if (curr == cmax) {
283 printf("\r%79s\n", "");
285 a = (curr * 100) / cmax;
288 while (dots_printed < a) {
298 sprintf(buf, "exec %s --gauge '%s' 7 72 0",
299 getenv("CTDL_DIALOG"),
301 fp = popen(buf, "w");
307 else if (curr == cmax) {
309 fprintf(fp, "100\n");
315 a = (curr * 100) / cmax;
317 fprintf(fp, "%ld\n", a);
331 * check_services_entry() -- Make sure "citadel" is in /etc/services
334 void check_services_entry(void)
340 if (getservbyname(SERVICE_NAME, PROTO_NAME) == NULL) {
341 for (i=0; i<=2; ++i) {
342 progress("Adding service entry...", i, 2);
344 sfp = fopen("/etc/services", "a");
346 sprintf(errmsg, "Cannot open /etc/services: %s", strerror(errno));
347 display_error(errmsg);
349 fprintf(sfp, "%s 504/tcp\n", SERVICE_NAME);
361 * delete_inittab_entry() -- Remove obsolete /etc/inittab entry for Citadel
364 void delete_inittab_entry(void)
368 char looking_for[256];
370 char outfilename[32];
371 int changes_made = 0;
373 /* Determine the fully qualified path name of citserver */
374 snprintf(looking_for,
380 /* Now tweak /etc/inittab */
381 infp = fopen("/etc/inittab", "r");
384 /* If /etc/inittab does not exist, return quietly.
385 * Not all host platforms have it.
387 if (errno == ENOENT) {
391 /* Other errors might mean something really did go wrong.
393 sprintf(buf, "Cannot open /etc/inittab: %s", strerror(errno));
398 strcpy(outfilename, "/tmp/ctdlsetup.XXXXXX");
399 outfp = fdopen(mkstemp(outfilename), "w+");
401 sprintf(buf, "Cannot open %s: %s", outfilename, strerror(errno));
407 while (fgets(buf, sizeof buf, infp) != NULL) {
408 if (strstr(buf, looking_for) != NULL) {
409 fwrite("#", 1, 1, outfp);
412 fwrite(buf, strlen(buf), 1, outfp);
419 sprintf(buf, "/bin/mv -f %s /etc/inittab 2>/dev/null", outfilename);
421 system("/sbin/init q 2>/dev/null");
430 * install_init_scripts() -- Try to configure to start Citadel at boot
433 void install_init_scripts(void)
435 struct stat etcinitd;
437 char *initfile = "/etc/init.d/citadel";
440 if ((stat("/etc/init.d/", &etcinitd) == -1) &&
443 if ((stat("/etc/rc.d/init.d/", &etcinitd) == -1) &&
445 initfile = CTDLDIR"/citadel.init";
447 initfile = "/etc/rc.d/init.d/citadel";
450 fp = fopen(initfile, "r");
452 if (yesno("Citadel already appears to be configured to start at boot.\n"
453 "Would you like to keep your boot configuration as is?\n", 1) == 1) {
460 if (yesno("Would you like to automatically start Citadel at boot?\n", 1) == 0) {
464 fp = fopen(initfile, "w");
466 display_error("Cannot create /etc/init.d/citadel");
470 fprintf(fp, "#!/bin/sh\n"
472 "# Init file for Citadel\n"
474 "# chkconfig: - 79 30\n"
475 "# description: Citadel service\n"
476 "# processname: citserver\n"
477 "# pidfile: %s/citadel.pid\n"
485 "test -d /var/run || exit 0\n"
489 "start) echo -n \"Starting Citadel... \"\n"
490 " if $CITADEL_DIR/citserver -d -h$CITADEL_DIR\n"
497 "stop) echo -n \"Stopping Citadel... \"\n"
498 " if $CITADEL_DIR/sendcommand DOWN >/dev/null 2>&1 ; then\n"
503 " rm -f %s/citadel.pid 2>/dev/null\n"
508 "restart) if $CITADEL_DIR/sendcommand DOWN 1 >/dev/null 2>&1 ; then\n"
514 "*) echo \"Usage: $0 {start|stop|restart}\"\n"
521 chmod(initfile, 0755);
523 /* Set up the run levels. */
524 system("/bin/rm -f /etc/rc?.d/[SK]??citadel 2>/dev/null");
525 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);
527 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);
538 * On systems which use xinetd, see if we can offer to install Citadel as
539 * the default telnet target.
541 void check_xinetd_entry(void) {
542 char *filename = "/etc/xinetd.d/telnet";
545 int already_citadel = 0;
547 fp = fopen(filename, "r+");
548 if (fp == NULL) return; /* Not there. Oh well... */
550 while (fgets(buf, sizeof buf, fp) != NULL) {
551 if (strstr(buf, setup_directory) != NULL) already_citadel = 1;
554 if (already_citadel) return; /* Already set up this way. */
556 /* Otherwise, prompt the user to create an entry. */
557 if (getenv("CREATE_XINETD_ENTRY") != NULL) {
558 if (strcasecmp(getenv("CREATE_XINETD_ENTRY"), "yes")) {
563 snprintf(buf, sizeof buf,
564 "Setup can configure the \"xinetd\" service to automatically\n"
565 "connect incoming telnet sessions to Citadel, bypassing the\n"
566 "host system login: prompt. Would you like to do this?\n"
568 if (yesno(buf, 1) == 0) {
573 fp = fopen(filename, "w");
575 "# description: telnet service for Citadel users\n"
580 " socket_type = stream\n"
583 " server = /usr/sbin/in.telnetd\n"
584 " server_args = -h -L %s/citadel\n"
585 " log_on_failure += USERID\n"
590 /* Now try to restart the service */
591 system("/etc/init.d/xinetd restart >/dev/null 2>&1");
597 * Offer to disable other MTA's
599 void disable_other_mta(char *mta) {
604 sprintf(buf, "/bin/ls -l /etc/rc*.d/S*%s 2>/dev/null; "
605 "/bin/ls -l /etc/rc.d/rc*.d/S*%s 2>/dev/null",
607 fp = popen(buf, "r");
608 if (fp == NULL) return;
610 while (fgets(buf, sizeof buf, fp) != NULL) {
614 if (lines == 0) return; /* Nothing to do. */
617 /* Offer to replace other MTA with the vastly superior Citadel :) */
619 snprintf(buf, sizeof buf,
620 "You appear to have the \"%s\" email program\n"
621 "running on your system. If you want Citadel mail\n"
622 "connected with %s, you will have to manually integrate\n"
623 "them. It is preferable to disable %s, and use Citadel's\n"
624 "SMTP, POP3, and IMAP services.\n\n"
625 "May we disable %s so that Citadel has access to ports\n"
626 "25, 110, and 143?\n",
629 if (yesno(buf, 1) == 0) {
634 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);
636 sprintf(buf, "/etc/init.d/%s stop >/dev/null 2>&1", mta);
644 * Check to see if our server really works. Returns 0 on success.
646 int test_server(char *setup_directory, char *relhomestr, int relhome) {
653 /* Generate a silly little cookie. We're going to write it out
654 * to the server and try to get it back. The cookie does not
655 * have to be secret ... just unique.
657 sprintf(cookie, "--test--%d--", getpid());
660 sprintf(cmd, "%s/sendcommand -h%s ECHO %s 2>&1",
665 sprintf(cmd, "%s/sendcommand ECHO %s 2>&1",
669 fp = popen(cmd, "r");
670 if (fp == NULL) return(errno);
672 while (fgets(buf, sizeof buf, fp) != NULL) {
674 && (strstr(buf, cookie) != NULL) ) {
686 void strprompt(char *prompt_title, char *prompt_text, char *str)
690 char dialog_result[PATH_MAX];
693 strcpy(setupmsg, "");
695 switch (setup_type) {
698 printf("\n%s\n", prompt_text);
699 printf("This is currently set to:\n%s\n", str);
700 printf("Enter new value or press return to leave unchanged:\n");
701 fgets(buf, sizeof buf, stdin);
702 buf[strlen(buf) - 1] = 0;
703 if (!IsEmptyStr(buf))
708 CtdlMakeTempFileName(dialog_result, sizeof dialog_result);
709 sprintf(buf, "exec %s --inputbox '%s' 19 72 '%s' 2>%s",
710 getenv("CTDL_DIALOG"),
715 fp = fopen(dialog_result, "r");
717 fgets(str, sizeof buf, fp);
718 if (str[strlen(str)-1] == 10) {
719 str[strlen(str)-1] = 0;
722 unlink(dialog_result);
730 void set_bool_val(int msgpos, int *ip) {
731 title(setup_titles[msgpos]);
732 *ip = yesno(setup_text[msgpos], *ip);
735 void set_str_val(int msgpos, char *str) {
736 strprompt(setup_titles[msgpos], setup_text[msgpos], str);
739 void set_int_val(int msgpos, int *ip)
742 snprintf(buf, sizeof buf, "%d", (int) *ip);
743 set_str_val(msgpos, buf);
748 void set_char_val(int msgpos, char *ip)
751 snprintf(buf, sizeof buf, "%d", (int) *ip);
752 set_str_val(msgpos, buf);
753 *ip = (char) atoi(buf);
757 void set_long_val(int msgpos, long int *ip)
760 snprintf(buf, sizeof buf, "%ld", *ip);
761 set_str_val(msgpos, buf);
766 void edit_value(int curr)
770 char ctdluidname[256];
775 if (setup_type == UI_SILENT)
777 if (getenv("SYSADMIN_NAME")) {
778 strcpy(config.c_sysadm, getenv("SYSADMIN_NAME"));
782 set_str_val(curr, config.c_sysadm);
787 if (setup_type == UI_SILENT)
789 if (getenv("SYSADMIN_PW")) {
790 strcpy(admin_pass, getenv("SYSADMIN_PW"));
794 set_str_val(curr, admin_pass);
799 if (setup_type == UI_SILENT)
801 if (getenv("CITADEL_UID")) {
802 config.c_ctdluid = atoi(getenv("CITADEL_UID"));
808 config.c_ctdluid = 0; /* XXX Windows hack, prob. insecure */
810 i = config.c_ctdluid;
813 set_int_val(curr, &i);
814 config.c_ctdluid = i;
817 strcpy(ctdluidname, pw->pw_name);
818 set_str_val(curr, ctdluidname);
819 pw = getpwnam(ctdluidname);
821 config.c_ctdluid = pw->pw_uid;
823 else if (atoi(ctdluidname) > 0) {
824 config.c_ctdluid = atoi(ctdluidname);
832 if (setup_type == UI_SILENT)
834 if (getenv("IP_ADDR")) {
835 strcpy(config.c_ip_addr, getenv("IP_ADDR"));
839 set_str_val(curr, config.c_ip_addr);
844 if (setup_type == UI_SILENT)
846 if (getenv("CITADEL_PORT")) {
847 config.c_port_number = atoi(getenv("CITADEL_PORT"));
852 set_int_val(curr, &config.c_port_number);
857 if (setup_type == UI_SILENT)
859 if (getenv("ENABLE_UNIX_AUTH")) {
860 if (!strcasecmp(getenv("ENABLE_UNIX_AUTH"), "yes")) {
861 config.c_auth_mode = AUTHMODE_HOST;
864 config.c_auth_mode = AUTHMODE_NATIVE;
869 set_int_val(curr, &config.c_auth_mode);
874 if (setup_type == UI_SILENT)
876 if (getenv("LDAP_HOST")) {
877 strcpy(config.c_ldap_host, getenv("LDAP_HOST"));
882 set_str_val(curr, config.c_ldap_host);
887 if (setup_type == UI_SILENT)
889 if (getenv("LDAP_PORT")) {
890 config.c_ldap_port = atoi(getenv("LDAP_PORT"));
895 set_int_val(curr, &config.c_ldap_port);
900 if (setup_type == UI_SILENT)
902 if (getenv("LDAP_BASE_DN")) {
903 strcpy(config.c_ldap_base_dn, getenv("LDAP_BASE_DN"));
908 set_str_val(curr, config.c_ldap_base_dn);
913 if (setup_type == UI_SILENT)
915 if (getenv("LDAP_BIND_DN")) {
916 strcpy(config.c_ldap_bind_dn, getenv("LDAP_BIND_DN"));
921 set_str_val(curr, config.c_ldap_bind_dn);
926 if (setup_type == UI_SILENT)
928 if (getenv("LDAP_BIND_PW")) {
929 strcpy(config.c_ldap_bind_pw, getenv("LDAP_BIND_PW"));
934 set_str_val(curr, config.c_ldap_bind_pw);
943 * (re-)write the config data to disk
945 void write_config_to_disk(void)
950 if ((fd = creat(file_citadel_config, S_IRUSR | S_IWUSR)) == -1) {
951 display_error("setup: cannot open citadel.config");
954 fp = fdopen(fd, "wb");
956 display_error("setup: cannot open citadel.config");
959 fwrite((char *) &config, sizeof(struct config), 1, fp);
967 * Figure out what type of user interface we're going to use
969 int discover_ui(void)
972 /* Use "dialog" if we have it */
973 if (getenv("CTDL_DIALOG") != NULL) {
985 * Strip "db" entries out of /etc/nsswitch.conf
995 int file_changed = 0;
996 char new_filename[64];
998 fp_read = fopen(NSSCONF, "r");
999 if (fp_read == NULL) {
1003 strcpy(new_filename, "/tmp/ctdl_fixnss_XXXXXX");
1004 fd_write = mkstemp(new_filename);
1010 while (fgets(buf, sizeof buf, fp_read) != NULL) {
1012 strcpy(buf_nc, buf);
1013 for (i=0; i<strlen(buf_nc); ++i) {
1014 if (buf_nc[i] == '#') {
1018 for (i=0; i<strlen(buf_nc); ++i) {
1019 if (!strncasecmp(&buf_nc[i], "db", 2)) {
1021 if ((isspace(buf_nc[i+2])) || (buf_nc[i+2]==0)) {
1024 strcpy(&buf_nc[i], &buf_nc[i+2]);
1025 strcpy(&buf[i], &buf[i+2]);
1027 strcpy(&buf_nc[i], &buf_nc[i+1]);
1028 strcpy(&buf[i], &buf[i+1]);
1034 if (write(fd_write, buf, strlen(buf)) != strlen(buf)) {
1037 unlink(new_filename);
1044 if (!file_changed) {
1045 unlink(new_filename);
1049 snprintf(question, sizeof question,
1051 "/etc/nsswitch.conf is configured to use the 'db' module for\n"
1052 "one or more services. This is not necessary on most systems,\n"
1053 "and it is known to crash the Citadel server when delivering\n"
1054 "mail to the Internet.\n"
1056 "Do you want this module to be automatically disabled?\n"
1060 if (yesno(question, 1)) {
1061 sprintf(buf, "/bin/mv -f %s %s", new_filename, NSSCONF);
1063 chmod(NSSCONF, 0644);
1065 unlink(new_filename);
1075 int main(int argc, char *argv[])
1081 int old_setup_level = 0;
1083 struct utsname my_utsname;
1089 char relhome[PATH_MAX]="";
1090 char ctdldir[PATH_MAX]=CTDLDIR;
1092 /* set an invalid setup type */
1095 /* Check to see if we're running the web installer */
1096 if (getenv("CITADEL_INSTALLER") != NULL) {
1097 using_web_installer = 1;
1100 /* parse command line args */
1101 for (a = 0; a < argc; ++a) {
1102 if (!strncmp(argv[a], "-u", 2)) {
1103 strcpy(aaa, argv[a]);
1104 strcpy(aaa, &aaa[2]);
1105 setup_type = atoi(aaa);
1107 else if (!strcmp(argv[a], "-i")) {
1110 else if (!strcmp(argv[a], "-q")) {
1111 setup_type = UI_SILENT;
1113 else if (!strncmp(argv[a], "-h", 2)) {
1114 relh=argv[a][2]!='/';
1115 if (!relh) safestrncpy(ctdl_home_directory, &argv[a][2],
1116 sizeof ctdl_home_directory);
1118 safestrncpy(relhome, &argv[a][2],
1125 calc_dirs_n_files(relh, home, relhome, ctdldir, 0);
1127 /* If a setup type was not specified, try to determine automatically
1128 * the best one to use out of all available types.
1130 if (setup_type < 0) {
1131 setup_type = discover_ui();
1133 if (info_only == 1) {
1134 important_message("Citadel Setup", CITADEL);
1138 /* Get started in a valid setup directory. */
1139 strcpy(setup_directory, ctdl_run_dir);
1140 if ( (using_web_installer) && (getenv("CITADEL") != NULL) ) {
1141 strcpy(setup_directory, getenv("CITADEL"));
1144 set_str_val(0, setup_directory);
1147 enable_home = ( relh | home );
1149 if (chdir(setup_directory) != 0) {
1151 sprintf(errmsg, "The directory you specified does not exist: [%s]\n", setup_directory);
1153 important_message("Citadel Setup", errmsg);
1157 /* Determine our host name, in case we need to use it as a default */
1160 /* Try to stop Citadel if we can */
1161 if (!access("/etc/init.d/citadel", X_OK)) {
1162 system("/etc/init.d/citadel stop");
1165 /* Make sure Citadel is not running. */
1166 if (test_server(setup_directory, relhome, enable_home) == 0) {
1167 important_message("Citadel Setup",
1168 "The Citadel service is still running.\n"
1169 "Please stop the service manually and run "
1175 switch (setup_type) {
1179 " *** Citadel setup program ***\n\n");
1185 * What we're going to try to do here is append a whole bunch of
1186 * nulls to the citadel.config file, so we can keep the old config
1187 * values if they exist, but if the file is missing or from an
1188 * earlier version with a shorter config structure, when setup tries
1189 * to read the old config parameters, they'll all come up zero.
1190 * The length of the config file will be set to what it's supposed
1191 * to be when we rewrite it, because we replace the old file with a
1192 * completely new copy.
1194 if ((a = open(file_citadel_config, O_WRONLY | O_CREAT | O_APPEND,
1195 S_IRUSR | S_IWUSR)) == -1) {
1196 display_error("setup: cannot append citadel.config");
1199 fp = fdopen(a, "ab");
1201 display_error("setup: cannot append citadel.config");
1204 for (a = 0; a < sizeof(struct config); ++a)
1208 /* now we re-open it, and read the old or blank configuration */
1209 fp = fopen(file_citadel_config, "rb");
1211 display_error("setup: cannot open citadel.config");
1214 fread((char *) &config, sizeof(struct config), 1, fp);
1217 /* set some sample/default values in place of blanks... */
1218 if (IsEmptyStr(config.c_nodename))
1219 safestrncpy(config.c_nodename, my_utsname.nodename,
1220 sizeof config.c_nodename);
1221 strtok(config.c_nodename, ".");
1222 if (IsEmptyStr(config.c_fqdn) ) {
1223 if ((he = gethostbyname(my_utsname.nodename)) != NULL)
1224 safestrncpy(config.c_fqdn, he->h_name,
1225 sizeof config.c_fqdn);
1227 safestrncpy(config.c_fqdn, my_utsname.nodename,
1228 sizeof config.c_fqdn);
1230 if (IsEmptyStr(config.c_humannode))
1231 strcpy(config.c_humannode, "My System");
1232 if (IsEmptyStr(config.c_phonenum))
1233 strcpy(config.c_phonenum, "US 800 555 1212");
1234 if (config.c_initax == 0) {
1235 config.c_initax = 4;
1237 if (IsEmptyStr(config.c_moreprompt))
1238 strcpy(config.c_moreprompt, "<more>");
1239 if (IsEmptyStr(config.c_twitroom))
1240 strcpy(config.c_twitroom, "Trashcan");
1241 if (IsEmptyStr(config.c_baseroom))
1242 strcpy(config.c_baseroom, BASEROOM);
1243 if (IsEmptyStr(config.c_aideroom))
1244 strcpy(config.c_aideroom, "Aide");
1245 if (config.c_port_number == 0) {
1246 config.c_port_number = 504;
1248 if (config.c_sleeping == 0) {
1249 config.c_sleeping = 900;
1251 if (config.c_ctdluid == 0) {
1252 pw = getpwnam("citadel");
1254 config.c_ctdluid = pw->pw_uid;
1256 if (config.c_ctdluid == 0) {
1257 pw = getpwnam("bbs");
1259 config.c_ctdluid = pw->pw_uid;
1261 if (config.c_ctdluid == 0) {
1262 pw = getpwnam("guest");
1264 config.c_ctdluid = pw->pw_uid;
1266 if (config.c_createax == 0) {
1267 config.c_createax = 3;
1270 * Negative values for maxsessions are not allowed.
1272 if (config.c_maxsessions < 0) {
1273 config.c_maxsessions = 0;
1275 /* We need a system default message expiry policy, because this is
1276 * the top level and there's no 'higher' policy to fall back on.
1277 * By default, do not expire messages at all.
1279 if (config.c_ep.expire_mode == 0) {
1280 config.c_ep.expire_mode = EXPIRE_MANUAL;
1281 config.c_ep.expire_value = 0;
1285 * Default port numbers for various services
1287 if (config.c_smtp_port == 0) config.c_smtp_port = 25;
1288 if (config.c_pop3_port == 0) config.c_pop3_port = 110;
1289 if (config.c_imap_port == 0) config.c_imap_port = 143;
1290 if (config.c_msa_port == 0) config.c_msa_port = 587;
1291 if (config.c_smtps_port == 0) config.c_smtps_port = 465;
1292 if (config.c_pop3s_port == 0) config.c_pop3s_port = 995;
1293 if (config.c_imaps_port == 0) config.c_imaps_port = 993;
1294 if (config.c_pftcpdict_port == 0) config.c_pftcpdict_port = -1;
1295 if (config.c_managesieve_port == 0) config.c_managesieve_port = 2020;
1296 if (config.c_xmpp_c2s_port == 0) config.c_xmpp_c2s_port = 5222;
1297 if (config.c_xmpp_s2s_port == 0) config.c_xmpp_s2s_port = 5269;
1299 /* Go through a series of dialogs prompting for config info */
1300 for (curr = 1; curr <= MAXSETUP; ++curr) {
1302 if ((curr == 6) && (config.c_auth_mode != AUTHMODE_LDAP)) curr += 5; /* skip LDAP questions */
1305 /***** begin version update section ***** */
1306 /* take care of any updating that is necessary */
1308 old_setup_level = config.c_setup_level;
1310 if (old_setup_level == 0) {
1314 if (old_setup_level < 555) {
1315 important_message("Citadel Setup",
1316 "This Citadel installation is too old "
1320 write_config_to_disk();
1322 old_setup_level = config.c_setup_level;
1324 /* end of version update section */
1327 config.c_setup_level = REV_LEVEL;
1329 /******************************************/
1331 write_config_to_disk();
1333 mkdir(ctdl_info_dir, 0700);
1334 chmod(ctdl_info_dir, 0700);
1335 chown(ctdl_info_dir, config.c_ctdluid, -1);
1337 mkdir(ctdl_bio_dir, 0700);
1338 chmod(ctdl_bio_dir, 0700);
1339 chown(ctdl_bio_dir, config.c_ctdluid, -1);
1341 mkdir(ctdl_usrpic_dir, 0700);
1342 chmod(ctdl_usrpic_dir, 0700);
1343 chown(ctdl_usrpic_dir, config.c_ctdluid, -1);
1345 mkdir(ctdl_message_dir, 0700);
1346 chmod(ctdl_message_dir, 0700);
1347 chown(ctdl_message_dir, config.c_ctdluid, -1);
1349 mkdir(ctdl_hlp_dir, 0700);
1350 chmod(ctdl_hlp_dir, 0700);
1351 chown(ctdl_hlp_dir, config.c_ctdluid, -1);
1353 mkdir(ctdl_image_dir, 0700);
1354 chmod(ctdl_image_dir, 0700);
1355 chown(ctdl_image_dir, config.c_ctdluid, -1);
1357 mkdir(ctdl_bb_dir, 0700);
1358 chmod(ctdl_bb_dir, 0700);
1359 chown(ctdl_bb_dir, config.c_ctdluid, -1);
1361 mkdir(ctdl_file_dir, 0700);
1362 chmod(ctdl_file_dir, 0700);
1363 chown(ctdl_file_dir, config.c_ctdluid, -1);
1365 mkdir(ctdl_netcfg_dir, 0700);
1366 chmod(ctdl_netcfg_dir, 0700);
1367 chown(ctdl_netcfg_dir, config.c_ctdluid, -1);
1369 /* Delete files and directories used by older Citadel versions */
1370 system("exec /bin/rm -fr ./rooms ./chatpipes ./expressmsgs ./sessions 2>/dev/null");
1371 unlink("citadel.log");
1374 if (((setup_type == UI_SILENT) && (getenv("ALTER_ETC_SERVICES")!=NULL)) ||
1375 (setup_type != UI_SILENT))
1376 check_services_entry(); /* Check /etc/services */
1378 delete_inittab_entry(); /* Remove obsolete /etc/inittab entry */
1379 check_xinetd_entry(); /* Check /etc/xinetd.d/telnet */
1381 if ((getenv("ACT_AS_MTA") == NULL) ||
1382 (getenv("ACT_AS_MTA") &&
1383 strcasecmp(getenv("ACT_AS_MTA"), "yes") == 0)) {
1384 /* Offer to disable other MTA's on the system. */
1385 disable_other_mta("courier-authdaemon");
1386 disable_other_mta("courier-imap");
1387 disable_other_mta("courier-imap-ssl");
1388 disable_other_mta("courier-pop");
1389 disable_other_mta("courier-pop3");
1390 disable_other_mta("courier-pop3d");
1391 disable_other_mta("cyrmaster");
1392 disable_other_mta("cyrus");
1393 disable_other_mta("dovecot");
1394 disable_other_mta("exim");
1395 disable_other_mta("exim4");
1396 disable_other_mta("imapd");
1397 disable_other_mta("mta");
1398 disable_other_mta("pop3d");
1399 disable_other_mta("popd");
1400 disable_other_mta("postfix");
1401 disable_other_mta("qmail");
1402 disable_other_mta("saslauthd");
1403 disable_other_mta("sendmail");
1404 disable_other_mta("vmailmgrd");
1408 /* Check for the 'db' nss and offer to disable it */
1411 if ((pw = getpwuid(config.c_ctdluid)) == NULL)
1416 progress("Setting file permissions", 0, 3);
1417 chown(ctdl_run_dir, config.c_ctdluid, gid);
1418 progress("Setting file permissions", 1, 3);
1419 chown(file_citadel_config, config.c_ctdluid, gid);
1420 progress("Setting file permissions", 2, 3);
1421 chmod(file_citadel_config, S_IRUSR | S_IWUSR);
1422 progress("Setting file permissions", 3, 3);
1425 * If we're running on SysV, install init scripts.
1427 if (!access("/var/run", W_OK)) {
1429 if (getenv("NO_INIT_SCRIPTS") == NULL) {
1430 install_init_scripts();
1433 if (!access("/etc/init.d/citadel", X_OK)) {
1434 system("/etc/init.d/citadel start");
1438 if (test_server(setup_directory, relhome, enable_home) == 0) {
1442 snprintf (admin_cmd, sizeof(admin_cmd), "%s/sendcommand \"CREU %s|%s\" 2>&1",
1443 ctdl_sbin_dir, config.c_sysadm, admin_pass);
1444 fp = popen(admin_cmd, "r");
1446 while (fgets(buf, sizeof buf, fp) != NULL)
1448 if ((atol(buf) == 574) || (atol(buf) == 200))
1455 important_message("Error","Setup failed to create your admin user");
1457 if (setup_type != UI_SILENT)
1458 important_message("Setup finished",
1459 "Setup of the Citadel server is complete.\n"
1460 "If you will be using WebCit, please run its\n"
1461 "setup program now; otherwise, run './citadel'\n"
1465 important_message("Setup failed",
1466 "Setup is finished, but the Citadel server failed to start.\n"
1467 "Go back and check your configuration.\n"
1474 important_message("Setup finished",
1475 "Setup is finished. You may now start the server.");