4 * Citadel setup utility
14 #include <sys/types.h>
16 #include <sys/utsname.h>
35 #define MAXSETUP 4 /* How many setup questions to ask */
37 #define UI_TEXT 0 /* Default setup type -- text only */
38 #define UI_SILENT 3 /* Silent running, for use in scripts */
39 #define UI_NEWT 4 /* Use the "newt" window library */
41 #define SERVICE_NAME "citadel"
42 #define PROTO_NAME "tcp"
45 char setup_directory[SIZ];
46 char citserver_init_entry[SIZ];
47 int using_web_installer = 0;
50 void contemplate_ldap(void);
53 char *setup_titles[] =
55 "Citadel Home Directory",
56 "System Administrator",
65 "Enter the full pathname of the directory in which the Citadel installation\n"
66 "you are creating or updating resides. If you specify a directory other\n"
67 "than the default, you will need to specify the -h flag to the server when\n"
70 "Enter the name of the system administrator (which is probably you).\n"
71 "When an account is created with this name, it will automatically be\n"
72 "assigned the highest access level.\n",
74 "Citadel needs to run under its own user ID. This would typically be\n"
75 "called \"citadel\", but if you are running Citadel as a public BBS, you\n"
76 "might also call it \"bbs\" or \"guest\". The server will run under this\n"
77 "user ID. Please specify that user ID here. You may specify either a\n"
78 "user name or a numeric UID.\n",
80 "Specify the IP address on which your server will run. If you leave this\n"
81 "blank, or if you specify 0.0.0.0, Citadel will listen on all addresses.\n"
82 "You can usually skip this unless you're running multiple instances of\n"
83 "Citadel on the same computer.\n",
85 "Specify the TCP port number on which your server will run. Normally, this\n"
86 "will be port 504, which is the official port assigned by the IANA for\n"
87 "Citadel servers. You'll only need to specify a different port number if\n"
88 "you run multiple instances of Citadel on the same computer and there's\n"
89 "something else already using port 504.\n",
91 "Setup has detected that you currently have data files from a Citadel\n"
92 "version 3.2x installation. The program 'conv_32_40' can upgrade your\n"
93 "files to version 4.0x format.\n"
94 " Setup will now exit. Please either run 'conv_32_40' or delete your data\n"
95 "files, and run setup again.\n"
103 * Set an entry in inittab to the desired state
105 void set_init_entry(char *which_entry, char *new_state) {
106 char *inittab = NULL;
114 if (which_entry == NULL) return;
115 if (strlen(which_entry) == 0) return;
117 inittab = strdup("");
118 if (inittab == NULL) return;
120 fp = fopen("/etc/inittab", "r");
121 if (fp == NULL) return;
123 while(fgets(buf, sizeof buf, fp) != NULL) {
125 if (num_tokens(buf, ':') == 4) {
126 extract_token(entry, buf, 0, ':');
127 extract_token(levels, buf, 1, ':');
128 extract_token(state, buf, 2, ':');
129 extract_token(prog, buf, 3, ':'); /* includes 0x0a LF */
131 if (!strcmp(entry, which_entry)) {
132 strcpy(state, new_state);
133 sprintf(buf, "%s:%s:%s:%s",
134 entry, levels, state, prog);
138 inittab = realloc(inittab, strlen(inittab) + strlen(buf) + 2);
139 if (inittab == NULL) {
144 strcat(inittab, buf);
147 fp = fopen("/etc/inittab", "w");
149 fwrite(inittab, strlen(inittab), 1, fp);
151 kill(1, SIGHUP); /* Tell init to re-read /etc/inittab */
158 * Locate the name of an inittab entry for a specific program
160 void locate_init_entry(char *entrybuf, char *program) {
165 char looking_for[SIZ];
168 char init_entry[SIZ];
170 strcpy(init_entry, "");
172 /* Pound through /etc/inittab line by line. Set have_entry to 1 if
173 * an entry is found which we believe starts citserver.
175 infp = fopen("/etc/inittab", "r");
179 while (fgets(buf, sizeof buf, infp) != NULL) {
180 buf[strlen(buf) - 1] = 0;
181 extract_token(entry, buf, 0, ':');
182 extract_token(prog, buf, 3, ':');
183 if (!strncasecmp(prog, looking_for,
184 strlen(looking_for))) {
186 strcpy(init_entry, entry);
196 * Shut down the Citadel service if necessary, during setup.
198 void shutdown_service(void) {
199 char looking_for[SIZ];
201 snprintf(looking_for, sizeof looking_for, "%s/citserver ", BBSDIR);
202 locate_init_entry(citserver_init_entry, looking_for);
203 if (strlen(citserver_init_entry) > 0) {
204 set_init_entry(citserver_init_entry, "off");
210 * Start the Citadel service.
212 void start_the_service(void) {
213 if (strlen(citserver_init_entry) > 0) {
214 set_init_entry(citserver_init_entry, "respawn");
220 void cleanup(int exitcode)
232 void title(char *text)
234 if (setup_type == UI_TEXT) {
235 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<%s>\n", text);
241 int yesno(char *question)
244 newtComponent form = NULL;
245 newtComponent yesbutton = NULL;
246 newtComponent nobutton = NULL;
252 switch (setup_type) {
256 printf("%s\nYes/No --> ", question);
257 fgets(buf, sizeof buf, stdin);
258 answer = tolower(buf[0]);
261 else if (answer == 'n')
263 } while ((answer < 0) || (answer > 1));
268 newtCenteredWindow(76, 10, "Question");
269 form = newtForm(NULL, NULL, 0);
270 for (i=0; i<num_tokens(question, '\n'); ++i) {
271 extract_token(buf, question, i, '\n');
272 newtFormAddComponent(form, newtLabel(1, 1+i, buf));
274 yesbutton = newtButton(10, 5, "Yes");
275 nobutton = newtButton(60, 5, "No");
276 newtFormAddComponent(form, yesbutton);
277 newtFormAddComponent(form, nobutton);
278 if (newtRunForm(form) == yesbutton) {
285 newtFormDestroy(form);
295 void important_message(char *title, char *msgtext)
298 newtComponent form = NULL;
303 switch (setup_type) {
306 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");
307 printf(" %s \n\n%s\n\n", title, msgtext);
308 printf("Press return to continue...");
309 fgets(buf, sizeof buf, stdin);
314 newtCenteredWindow(76, 10, title);
315 form = newtForm(NULL, NULL, 0);
316 for (i=0; i<num_tokens(msgtext, '\n'); ++i) {
317 extract_token(buf, msgtext, i, '\n');
318 newtFormAddComponent(form, newtLabel(1, 1+i, buf));
320 newtFormAddComponent(form, newtButton(35, 5, "OK"));
323 newtFormDestroy(form);
330 void important_msgnum(int msgnum)
332 important_message("Important Message", setup_text[msgnum]);
335 void display_error(char *error_message)
337 important_message("Error", error_message);
340 void progress(char *text, long int curr, long int cmax)
344 /* These variables are static because progress() gets called
345 * multiple times during the course of whatever operation is
346 * being performed. This makes setup non-threadsafe, but who
349 static newtComponent form = NULL;
350 static newtComponent scale = NULL;
352 static long dots_printed = 0L;
355 switch (setup_type) {
359 printf("%s\n", text);
360 printf("..........................");
361 printf("..........................");
362 printf("..........................\r");
365 } else if (curr == cmax) {
366 printf("\r%79s\n", "");
368 a = (curr * 100) / cmax;
371 while (dots_printed < a) {
382 newtCenteredWindow(76, 8, text);
383 form = newtForm(NULL, NULL, 0);
384 scale = newtScale(1, 3, 74, cmax);
385 newtFormAddComponent(form, scale);
389 if ((curr > 0) && (curr <= cmax)) {
390 newtScaleSet(scale, curr);
394 newtFormDestroy(form);
407 * check_services_entry() -- Make sure "citadel" is in /etc/services
410 void check_services_entry(void)
415 if (getservbyname(SERVICE_NAME, PROTO_NAME) == NULL) {
416 for (i=0; i<3; ++i) {
417 progress("Adding service entry...", i, 3);
419 sfp = fopen("/etc/services", "a");
421 display_error(strerror(errno));
423 fprintf(sfp, "%s 504/tcp\n",
435 * check_inittab_entry() -- Make sure "citadel" is in /etc/inittab
438 void check_inittab_entry(void)
442 char looking_for[SIZ];
446 /* Determine the fully qualified path name of citserver */
447 snprintf(looking_for, sizeof looking_for, "%s/citserver ", BBSDIR);
448 locate_init_entry(citserver_init_entry, looking_for);
450 /* If there's already an entry, then we have nothing left to do. */
451 if (strlen(citserver_init_entry) > 0) {
455 /* Otherwise, prompt the user to create an entry. */
456 snprintf(question, sizeof question,
457 "Do you want this computer configured to start the Citadel\n"
458 "service automatically? (If you answer yes, an entry in\n"
459 "/etc/inittab pointing to %s will be added.)\n",
461 if (yesno(question) == 0)
464 /* Generate a unique entry name for /etc/inittab */
465 snprintf(entryname, sizeof entryname, "c0");
468 if (entryname[1] > '9') {
471 if (entryname[0] > 'z') {
473 "Can't generate a unique entry name");
477 snprintf(buf, sizeof buf,
478 "grep %s: /etc/inittab >/dev/null 2>&1", entryname);
479 } while (system(buf) == 0);
481 /* Now write it out to /etc/inittab */
482 infp = fopen("/etc/inittab", "a");
484 display_error(strerror(errno));
486 fprintf(infp, "# Start the Citadel server...\n");
487 fprintf(infp, "%s:2345:respawn:%s -h%s -x3 -llocal4\n",
488 entryname, looking_for, setup_directory);
490 strcpy(citserver_init_entry, entryname);
496 * On systems which use xinetd, see if we can offer to install Citadel as
497 * the default telnet target.
499 void check_xinetd_entry(void) {
500 char *filename = "/etc/xinetd.d/telnet";
503 int already_citadel = 0;
505 fp = fopen(filename, "r+");
506 if (fp == NULL) return; /* Not there. Oh well... */
508 while (fgets(buf, sizeof buf, fp) != NULL) {
509 if (strstr(buf, setup_directory) != NULL) already_citadel = 1;
512 if (already_citadel) return; /* Already set up this way. */
514 /* Otherwise, prompt the user to create an entry. */
515 snprintf(buf, sizeof buf,
516 "Setup can configure the 'xinetd' service to automatically\n"
517 "connect incoming telnet sessions to Citadel, bypassing the\n"
518 "host system's login prompt. Would you like to do this?\n"
523 fp = fopen(filename, "w");
525 "# description: telnet service for Citadel users\n"
530 " socket_type = stream\n"
533 " server = /usr/sbin/in.telnetd\n"
534 " server_args = -h -L %s/citadel\n"
535 " log_on_failure += USERID\n"
541 /* Now try to restart the service */
542 system("/etc/init.d/xinetd restart >/dev/null 2>&1");
548 * Offer to disable other MTA's
550 void disable_other_mta(char *mta) {
555 sprintf(buf, "/bin/ls -l /etc/rc*.d/S*%s 2>/dev/null", mta);
556 fp = popen(buf, "r");
557 if (fp == NULL) return;
559 while (fgets(buf, sizeof buf, fp) != NULL) {
563 if (lines == 0) return; /* Nothing to do. */
565 /* Offer to replace other MTA with the vastly superior Citadel :) */
566 snprintf(buf, sizeof buf,
567 "You appear to have the '%s' email program\n"
568 "running on your system. Would you like to disable it,\n"
569 "allowing Citadel to handle your system's Internet mail\n"
576 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);
578 sprintf(buf, "/etc/init.d/%s stop >/dev/null 2>&1", mta);
586 * Check to see if our server really works. Returns 0 on success.
588 int test_server(void) {
595 /* Generate a silly little cookie. We're going to write it out
596 * to the server and try to get it back. The cookie does not
597 * have to be secret ... just unique.
599 sprintf(cookie, "%ld.%d", time(NULL), getpid());
601 sprintf(cmd, "%s/sendcommand -h%s ECHO %s 2>&1",
606 fp = popen(cmd, "r");
607 if (fp == NULL) return(errno);
609 while (fgets(buf, sizeof buf, fp) != NULL) {
611 && (strstr(buf, cookie) != NULL) ) {
623 void strprompt(char *prompt_title, char *prompt_text, char *str)
633 strcpy(setupmsg, "");
635 switch (setup_type) {
638 printf("\n%s\n", prompt_text);
639 printf("This is currently set to:\n%s\n", str);
640 printf("Enter new value or press return to leave unchanged:\n");
641 fgets(buf, sizeof buf, stdin);
642 buf[strlen(buf) - 1] = 0;
643 if (strlen(buf) != 0)
649 newtCenteredWindow(76, 10, prompt_title);
650 form = newtForm(NULL, NULL, 0);
651 for (i=0; i<num_tokens(prompt_text, '\n'); ++i) {
652 extract_token(buf, prompt_text, i, '\n');
653 newtFormAddComponent(form, newtLabel(1, 1+i, buf));
655 newtFormAddComponent(form, newtEntry(1, 8, str, 74, &result,
656 NEWT_FLAG_RETURNEXIT));
661 newtFormDestroy(form);
667 void set_str_val(int msgpos, char *str) {
668 strprompt(setup_titles[msgpos], setup_text[msgpos], str);
673 void set_int_val(int msgpos, int *ip)
676 snprintf(buf, sizeof buf, "%d", (int) *ip);
677 set_str_val(msgpos, buf);
682 void set_char_val(int msgpos, char *ip)
685 snprintf(buf, sizeof buf, "%d", (int) *ip);
686 set_str_val(msgpos, buf);
687 *ip = (char) atoi(buf);
691 void set_long_val(int msgpos, long int *ip)
694 snprintf(buf, sizeof buf, "%ld", *ip);
695 set_str_val(msgpos, buf);
700 void edit_value(int curr)
704 char bbsuidname[SIZ];
709 set_str_val(curr, config.c_sysadm);
714 config.c_bbsuid = 0; /* XXX Windows hack, prob. insecure */
719 set_int_val(curr, &i);
723 strcpy(bbsuidname, pw->pw_name);
724 set_str_val(curr, bbsuidname);
725 pw = getpwnam(bbsuidname);
727 config.c_bbsuid = pw->pw_uid;
729 else if (atoi(bbsuidname) > 0) {
730 config.c_bbsuid = atoi(bbsuidname);
737 set_str_val(curr, config.c_ip_addr);
741 set_int_val(curr, &config.c_port_number);
749 * (re-)write the config data to disk
751 void write_config_to_disk(void)
756 if ((fd = creat("citadel.config", S_IRUSR | S_IWUSR)) == -1) {
757 display_error("setup: cannot open citadel.config");
760 fp = fdopen(fd, "wb");
762 display_error("setup: cannot open citadel.config");
765 fwrite((char *) &config, sizeof(struct config), 1, fp);
773 * Figure out what type of user interface we're going to use
775 int discover_ui(void)
781 newtDrawRootText(0, 0, "Citadel Setup");
791 int main(int argc, char *argv[])
797 int old_setup_level = 0;
799 struct utsname my_utsname;
804 /* set an invalid setup type */
807 /* Check to see if we're running the web installer */
808 if (getenv("CITADEL_INSTALLER") != NULL) {
809 using_web_installer = 1;
812 /* parse command line args */
813 for (a = 0; a < argc; ++a) {
814 if (!strncmp(argv[a], "-u", 2)) {
815 strcpy(aaa, argv[a]);
816 strcpy(aaa, &aaa[2]);
817 setup_type = atoi(aaa);
819 if (!strcmp(argv[a], "-i")) {
822 if (!strcmp(argv[a], "-q")) {
823 setup_type = UI_SILENT;
828 /* If a setup type was not specified, try to determine automatically
829 * the best one to use out of all available types.
831 if (setup_type < 0) {
832 setup_type = discover_ui();
834 if (info_only == 1) {
835 important_message("Citadel Setup", CITADEL);
839 /* Get started in a valid setup directory. */
840 strcpy(setup_directory, BBSDIR);
841 if ( (using_web_installer) && (getenv("CITADEL") != NULL) ) {
842 strcpy(setup_directory, getenv("CITADEL"));
845 set_str_val(0, setup_directory);
848 if (chdir(setup_directory) != 0) {
849 important_message("Citadel Setup",
850 "The directory you specified does not exist.");
854 /* Determine our host name, in case we need to use it as a default */
857 /* See if we need to shut down the Citadel service. */
858 for (a=0; a<=3; ++a) {
859 progress("Shutting down the Citadel service...", a, 3);
860 if (a == 0) shutdown_service();
864 /* Make sure it's stopped. */
865 if (test_server() == 0) {
866 important_message("Citadel Setup",
867 "The Citadel service is still running.\n"
868 "Please stop the service manually and run "
874 switch (setup_type) {
878 " *** Citadel setup program ***\n\n");
884 * What we're going to try to do here is append a whole bunch of
885 * nulls to the citadel.config file, so we can keep the old config
886 * values if they exist, but if the file is missing or from an
887 * earlier version with a shorter config structure, when setup tries
888 * to read the old config parameters, they'll all come up zero.
889 * The length of the config file will be set to what it's supposed
890 * to be when we rewrite it, because we replace the old file with a
891 * completely new copy.
894 if ((a = open("citadel.config", O_WRONLY | O_CREAT | O_APPEND,
895 S_IRUSR | S_IWUSR)) == -1) {
896 display_error("setup: cannot append citadel.config");
899 fp = fdopen(a, "ab");
901 display_error("setup: cannot append citadel.config");
904 for (a = 0; a < sizeof(struct config); ++a)
908 /* now we re-open it, and read the old or blank configuration */
909 fp = fopen("citadel.config", "rb");
911 display_error("setup: cannot open citadel.config");
914 fread((char *) &config, sizeof(struct config), 1, fp);
917 /* set some sample/default values in place of blanks... */
918 if (strlen(config.c_nodename) == 0)
919 safestrncpy(config.c_nodename, my_utsname.nodename,
920 sizeof config.c_nodename);
921 strtok(config.c_nodename, ".");
922 if (strlen(config.c_fqdn) == 0) {
923 if ((he = gethostbyname(my_utsname.nodename)) != NULL)
924 safestrncpy(config.c_fqdn, he->h_name,
925 sizeof config.c_fqdn);
927 safestrncpy(config.c_fqdn, my_utsname.nodename,
928 sizeof config.c_fqdn);
930 if (strlen(config.c_humannode) == 0)
931 strcpy(config.c_humannode, "My System");
932 if (strlen(config.c_phonenum) == 0)
933 strcpy(config.c_phonenum, "US 800 555 1212");
934 if (config.c_initax == 0) {
937 if (strlen(config.c_moreprompt) == 0)
938 strcpy(config.c_moreprompt, "<more>");
939 if (strlen(config.c_twitroom) == 0)
940 strcpy(config.c_twitroom, "Trashcan");
941 if (strlen(config.c_baseroom) == 0)
942 strcpy(config.c_baseroom, "Lobby");
943 if (strlen(config.c_aideroom) == 0)
944 strcpy(config.c_aideroom, "Aide");
945 if (config.c_port_number == 0) {
946 config.c_port_number = 504;
948 if (config.c_sleeping == 0) {
949 config.c_sleeping = 900;
951 if (config.c_bbsuid == 0) {
952 pw = getpwnam("citadel");
954 config.c_bbsuid = pw->pw_uid;
956 if (config.c_bbsuid == 0) {
957 pw = getpwnam("bbs");
959 config.c_bbsuid = pw->pw_uid;
961 if (config.c_bbsuid == 0) {
962 pw = getpwnam("guest");
964 config.c_bbsuid = pw->pw_uid;
966 if (config.c_createax == 0) {
967 config.c_createax = 3;
970 * Negative values for maxsessions are not allowed.
972 if (config.c_maxsessions < 0) {
973 config.c_maxsessions = 0;
975 /* We need a system default message expiry policy, because this is
976 * the top level and there's no 'higher' policy to fall back on.
978 if (config.c_ep.expire_mode == 0) {
979 config.c_ep.expire_mode = EXPIRE_NUMMSGS;
980 config.c_ep.expire_value = 150;
984 * Default port numbers for various services
986 if (config.c_smtp_port == 0) config.c_smtp_port = 25;
987 if (config.c_pop3_port == 0) config.c_pop3_port = 110;
988 if (config.c_imap_port == 0) config.c_imap_port = 143;
990 /* Go through a series of dialogs prompting for config info */
991 if (setup_type != UI_SILENT) {
992 for (curr = 1; curr <= MAXSETUP; ++curr) {
998 if (setuid(config.c_bbsuid) != 0) {
999 important_message("Citadel Setup",
1000 "Failed to change the user ID to your Citadel user.");
1005 /***** begin version update section ***** */
1006 /* take care of any updating that is necessary */
1008 old_setup_level = config.c_setup_level;
1010 if (old_setup_level == 0) {
1014 if (old_setup_level < 555) {
1015 important_message("Citadel Setup",
1016 "This Citadel installation is too old "
1020 write_config_to_disk();
1022 old_setup_level = config.c_setup_level;
1024 /* end of version update section */
1027 config.c_setup_level = REV_LEVEL;
1029 /******************************************/
1031 write_config_to_disk();
1033 mkdir("info", 0700);
1034 chmod("info", 0700);
1037 mkdir("userpics", 0700);
1038 chmod("userpics", 0700);
1039 mkdir("messages", 0700);
1040 chmod("messages", 0700);
1041 mkdir("help", 0700);
1042 chmod("help", 0700);
1043 mkdir("images", 0700);
1044 chmod("images", 0700);
1045 mkdir("netconfigs", 0700);
1046 chmod("netconfigs", 0700);
1048 /* Delete files and directories used by older Citadel versions */
1049 system("exec /bin/rm -fr ./rooms ./chatpipes ./expressmsgs ./sessions 2>/dev/null");
1050 unlink("citadel.log");
1053 check_services_entry(); /* Check /etc/services */
1055 check_inittab_entry(); /* Check /etc/inittab */
1056 check_xinetd_entry(); /* Check /etc/xinetd.d/telnet */
1058 /* Offer to disable other MTA's on the system. */
1059 disable_other_mta("sendmail");
1060 disable_other_mta("postfix");
1061 disable_other_mta("qmail");
1062 disable_other_mta("cyrus");
1063 disable_other_mta("cyrmaster");
1064 disable_other_mta("saslauthd");
1065 disable_other_mta("mta");
1066 disable_other_mta("courier-imap");
1067 disable_other_mta("courier-imap-ssl");
1068 disable_other_mta("courier-authdaemon");
1069 disable_other_mta("courier-pop3");
1070 disable_other_mta("courier-pop3d");
1071 disable_other_mta("courier-pop");
1072 disable_other_mta("vmailmgrd");
1073 disable_other_mta("imapd");
1074 disable_other_mta("popd");
1075 disable_other_mta("pop3d");
1076 disable_other_mta("exim");
1079 if ((pw = getpwuid(config.c_bbsuid)) == NULL)
1084 progress("Setting file permissions", 0, 4);
1085 chown(".", config.c_bbsuid, gid);
1086 progress("Setting file permissions", 1, 4);
1087 chown("citadel.config", config.c_bbsuid, gid);
1088 progress("Setting file permissions", 2, 4);
1089 snprintf(aaa, sizeof aaa,
1090 "find . | grep -v chkpwd | xargs chown %ld:%ld 2>/dev/null",
1091 (long)config.c_bbsuid, (long)gid);
1093 progress("Setting file permissions", 3, 4);
1094 chmod("citadel.config", S_IRUSR | S_IWUSR);
1095 progress("Setting file permissions", 4, 4);
1098 /* Contemplate the possibility of auto-configuring OpenLDAP */
1102 /* See if we can start the Citadel service. */
1103 if (strlen(citserver_init_entry) > 0) {
1104 for (a=0; a<=3; ++a) {
1105 progress("Starting the Citadel service...", a, 3);
1106 if (a == 0) start_the_service();
1109 if (test_server() == 0) {
1110 important_message("Setup finished",
1111 "Setup is finished. You may now log in.");
1114 important_message("Setup finished",
1115 "Setup is finished, but the Citadel service "
1116 "failed to start.\n"
1117 "Go back and check your configuration.");
1121 important_message("Setup finished",
1122 "Setup is finished. You may now start the server.");
1132 * If we're in the middle of an Easy Install, we might just be able to
1133 * auto-configure a standalone OpenLDAP server.
1135 void contemplate_ldap(void) {
1139 /* If conditions are not ideal, give up on this idea. */
1140 if (using_web_installer == 0) return;
1141 if (getenv("LDAP_CONFIG") == NULL) return;
1142 if (getenv("SUPPORT") == NULL) return;
1143 if (getenv("SLAPD_BINARY") == NULL) return;
1144 if (getenv("CITADEL") == NULL) return;
1146 /* Otherwise, prompt the user to create an entry. */
1147 snprintf(question, sizeof question,
1149 "Do you want this computer configured to start a standalone\n"
1150 "LDAP service automatically? (If you answer yes, a custom\n"
1151 "slapd.conf will be written, and an /etc/inittab entry\n"
1152 "pointing to %s will be added.)\n"
1154 getenv("SLAPD_BINARY")
1156 if (yesno(question) == 0)
1159 strcpy(config.c_ldap_base_dn, "dc=example,dc=com");
1160 strprompt("Base DN",
1162 "Please enter the Base DN for your directory. This will\n"
1163 "generally be something based on the primary DNS domain in\n"
1164 "which you receive mail, but it doesn't have to be. Your\n"
1165 "LDAP tree will be built using this Distinguished Name.\n"
1167 config.c_ldap_base_dn
1170 strcpy(config.c_ldap_host, "localhost");
1171 config.c_ldap_port = 389;
1172 sprintf(config.c_ldap_bind_dn, "cn=manager,%s", config.c_ldap_base_dn);
1174 /* FIXME ... make the generated password harder to guess */
1175 sprintf(config.c_ldap_bind_pw, "%d%ld", getpid(), time(NULL));
1177 write_config_to_disk();
1179 fp = fopen(getenv("LDAP_CONFIG"), "w");
1181 sprintf(question, "\nCannot create %s:\n%s\n\n"
1182 "Citadel will still function, but you will "
1183 "not have an LDAP service.\n\n",
1184 getenv("LDAP_CONFIG"),
1187 important_message("Error", question);
1191 fprintf(fp, "include %s/citadel-openldap.schema\n",
1193 fprintf(fp, "pidfile %s/openldap-data/slapd.pid\n",
1195 fprintf(fp, "argsfile %s/openldap-data/slapd.args\n",
1197 fprintf(fp, "allow bind_v2\n"
1201 fprintf(fp, "suffix \"%s\"\n", config.c_ldap_base_dn);
1202 fprintf(fp, "rootdn \"%s\"\n", config.c_ldap_bind_dn);
1203 fprintf(fp, "rootpw %s\n", config.c_ldap_bind_pw);
1204 fprintf(fp, "directory %s/openldap-data\n",
1206 fprintf(fp, "index objectClass eq\n");
1210 /* This is where our OpenLDAP server will keep its data. */
1211 mkdir("openldap-data", 0700);
1213 #endif /* HAVE_LDAP */