]> code.citadel.org Git - citadel.git/blob - citadel/setup.c
use ncurses in preference to curses if it's installed; it handles
[citadel.git] / citadel / setup.c
1 /*
2  * $Id$
3  *
4  * Citadel/UX setup utility
5  *
6  */
7
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <fcntl.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/utsname.h>
17 #include <netdb.h>
18 #include <errno.h>
19 #include <limits.h>
20 #include <pwd.h>
21
22 #include "citadel.h"
23 #include "axdefs.h"
24 #include "sysdep.h"
25 #include "config.h"
26 #include "tools.h"
27
28 #if defined(HAVE_CURSES_H) || defined(HAVE_NCURSES_H)
29 #ifdef OK
30 #undef OK
31 #endif
32
33 #ifdef HAVE_NCURSES_H
34 #include <ncurses.h>
35 #else
36 #include <curses.h>
37 #endif
38
39 #endif
40
41 #define MAXSETUP 5
42
43 #define UI_TEXT         0       /* Default setup type -- text only */
44 #define UI_DIALOG       1       /* Use the 'dialog' program (REMOVED) */
45 #define UI_CURSES       2       /* Use curses */
46 #define UI_SILENT       3       /* Silent running, for use in scripts */
47
48 #define SERVICE_NAME    "citadel"
49 #define PROTO_NAME      "tcp"
50
51 int setup_type;
52 char setup_directory[128];
53 int need_init_q = 0;
54
55 char *setup_titles[] =
56 {
57         "BBS Home Directory",
58         "System Administrator",
59         "BBS User ID",
60         "Name of bit bucket subdirectory",
61         "Server port number",
62 };
63
64
65 char *setup_text[] =
66 {
67
68 "0",
69 "Enter the full pathname of the directory in which the BBS you are",
70 "creating or updating resides.  If you specify a directory other than the",
71 "default, you will need to specify the -h flag to the server when you start",
72 "it up.",
73
74 "1",
75 "Enter the name of the system administrator (which is probably you).",
76 "When an account is created with this name, it will automatically be",
77 "assigned the highest access level.",
78
79 "2",
80 "You should create a user called 'bbs', 'guest', 'citadel', or something",
81 "similar, that will allow users a way into your BBS.  The server will run",
82 "under this user ID.  Please specify that (numeric) user ID here.",
83
84 "3",
85 "Select the name of a subdirectory (relative to the main",
86 "Citadel directory - do not type an absolute pathname!) in",
87 "which to place arriving file transfers that otherwise",
88 "don't have a home.",
89
90 "4",
91 "Specify the TCP port number on which your server will run.  Normally, this",
92 "will be port 504, which is the official port assigned by the IANA for",
93 "Citadel servers.  You'll only need to specify a different port number if",
94 "you run multiple BBS's on the same computer and there's something else",
95 "already using port 504.",
96
97 "5",
98 "6",
99 "7",
100 "8",
101 "9",
102 "10",
103 "11",
104 "12",
105 "13",
106 "14",
107 "15",
108 "16",
109 "17",
110 "18",
111 "19",
112 "20",
113 "21",
114 "22",
115 "23",
116 "24",
117 "25",
118 "26",
119 "27",
120 "28",
121 "29",
122 "30",
123
124 "31",
125 "Setup has detected that you currently have data files from a Citadel/UX",
126 "version 3.2x installation.  The program 'conv_32_40' can upgrade your",
127 "files to version 4.0x format.",
128 " Setup will now exit.  Please either run 'conv_32_40' or delete your data",
129 "files, and run setup again.",
130
131 "32",
132
133 };
134
135 struct config config;
136 int direction;
137
138 void cleanup(int exitcode)
139 {
140 #ifdef HAVE_CURSES_H
141         if (setup_type == UI_CURSES) {
142                 clear();
143                 refresh();
144                 endwin();
145         }
146 #endif
147
148         /* Do an 'init q' if we need to.  When we hit the right one, init
149          * will take over and setup won't come back because we didn't do a
150          * fork().  If init isn't found, we fall through the bottom of the
151          * loop and setup exits quietly.
152          */
153         if (need_init_q) {
154                 execlp("/sbin/init", "init", "q", NULL);
155                 execlp("/usr/sbin/init", "init", "q", NULL);
156                 execlp("/bin/init", "init", "q", NULL);
157                 execlp("/usr/bin/init", "init", "q", NULL);
158                 execlp("init", "init", "q", NULL);
159         }
160         exit(exitcode);
161 }
162
163
164 /* Gets a line from the terminal */
165 /* Where on the screen to start */
166 /* Pointer to string buffer */
167 /* Maximum length - if negative, no-show */
168 #ifdef HAVE_CURSES_H
169 void getlin(int yp, int xp, char *string, int lim) {
170         int a, b;
171         char flag;
172
173         flag = 0;
174         if (lim < 0) {
175                 lim = (0 - lim);
176                 flag = 1;
177         }
178         move(yp, xp);
179         standout();
180         for (a = 0; a < lim; ++a)
181                 addch('-');
182         refresh();
183         move(yp, xp);
184         for (a = 0; a < lim; ++a)
185                 addch(' ');
186         move(yp, xp);
187         printw("%s", string);
188       GLA:move(yp, xp + strlen(string));
189         refresh();
190         a = getch();
191         if (a == 127)
192                 a = 8;
193         a = (a & 127);
194         if (a == 10)
195                 a = 13;
196         if ((a == 8) && (strlen(string) == 0))
197                 goto GLA;
198         if ((a != 13) && (a != 8) && (strlen(string) == lim))
199                 goto GLA;
200         if ((a == 8) && (string[0] != 0)) {
201                 string[strlen(string) - 1] = 0;
202                 move(yp, xp + strlen(string));
203                 addch(' ');
204                 goto GLA;
205         }
206         if ((a == 13) || (a == 10)) {
207                 standend();
208                 move(yp, xp);
209                 for (a = 0; a < lim; ++a)
210                         addch(' ');
211                 mvprintw(yp, xp, "%s", string);
212                 refresh();
213                 return;
214         }
215         b = strlen(string);
216         string[b] = a;
217         string[b + 1] = 0;
218         if (flag == 0)
219                 addch(a);
220         if (flag == 1)
221                 addch('*');
222         goto GLA;
223 }
224 #endif
225
226
227
228 void title(char *text)
229 {
230         if (setup_type == UI_TEXT) {
231                 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<%s>\n", text);
232         }
233 }
234
235
236 void hit_any_key(void)
237 {
238         char junk[5];
239
240 #ifdef HAVE_CURSES_H
241         if (setup_type == UI_CURSES) {
242                 mvprintw(20, 0, "Press any key to continue... ");
243                 refresh();
244                 getch();
245                 return;
246         }
247 #endif
248         if (setup_type == UI_TEXT) {
249                 printf("Press return to continue...");
250                 fgets(junk, 5, stdin);
251         }
252 }
253
254 int yesno(char *question)
255 {
256         int answer = 0;
257         char buf[4096];
258
259         switch (setup_type) {
260
261         case UI_TEXT:
262                 do {
263                         printf("%s\nYes/No --> ", question);
264                         fgets(buf, 4096, stdin);
265                         answer = tolower(buf[0]);
266                         if (answer == 'y')
267                                 answer = 1;
268                         else if (answer == 'n')
269                                 answer = 0;
270                 } while ((answer < 0) || (answer > 1));
271                 break;
272
273 #ifdef HAVE_CURSES_H
274         case UI_CURSES:
275                 do {
276                         clear();
277                         standout();
278                         mvprintw(1, 20, "Question");
279                         standend();
280                         mvprintw(10, 0, "%-80s", question);
281                         mvprintw(20, 0, "%80s", "");
282                         mvprintw(20, 0, "Yes/No -> ");
283                         refresh();
284                         answer = getch();
285                         answer = tolower(answer);
286                         if (answer == 'y')
287                                 answer = 1;
288                         else if (answer == 'n')
289                                 answer = 0;
290                 } while ((answer < 0) || (answer > 1));
291                 break;
292 #endif
293
294         }
295         return (answer);
296 }
297
298
299
300 void get_setup_msg(char *dispbuf, int msgnum)
301 {
302         int a, b;
303
304         a = 0;
305         b = 0;
306         while (atol(setup_text[a]) != msgnum)
307                 ++a;
308         ++a;
309         strcpy(dispbuf, "");
310         do {
311                 strcat(dispbuf, setup_text[a++]);
312                 strcat(dispbuf, "\n");
313         } while (atol(setup_text[a]) != (msgnum + 1));
314 }
315
316 void print_setup(int msgnum)
317 {
318         char dispbuf[4096];
319
320         get_setup_msg(dispbuf, msgnum);
321         printf("\n\n%s\n\n", dispbuf);
322 }
323
324
325 void important_message(char *title, char *msgtext)
326 {
327
328         switch (setup_type) {
329
330         case UI_TEXT:
331                 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");
332                 printf("       %s \n\n%s\n\n", title, msgtext);
333                 hit_any_key();
334                 break;
335
336 #ifdef HAVE_CURSES_H
337         case UI_CURSES:
338                 clear();
339                 move(1, 20);
340                 standout();
341                 printw("  Important Message  ");
342                 standend();
343                 move(3, 0);
344                 printw("%s", msgtext);
345                 refresh();
346                 hit_any_key();
347                 break;
348 #endif
349
350         }
351 }
352
353 void important_msgnum(int msgnum)
354 {
355         char dispbuf[4096];
356
357         get_setup_msg(dispbuf, msgnum);
358         important_message("Important Message", dispbuf);
359 }
360
361 void display_error(char *error_message)
362 {
363         important_message("Error", error_message);
364 }
365
366 void progress(char *text, long int curr, long int cmax)
367 {
368         static long dots_printed;
369         long a;
370
371         switch (setup_type) {
372
373         case UI_TEXT:
374                 if (curr == 0) {
375                         printf("%s\n", text);
376                         printf("..........................");
377                         printf("..........................");
378                         printf("..........................\r");
379                         fflush(stdout);
380                         dots_printed = 0;
381                 } else if (curr == cmax) {
382                         printf("\r%79s\n", "");
383                 } else {
384                         a = (curr * 100) / cmax;
385                         a = a * 78;
386                         a = a / 100;
387                         while (dots_printed < a) {
388                                 printf("*");
389                                 ++dots_printed;
390                                 fflush(stdout);
391                         }
392                 }
393                 break;
394
395 #ifdef HAVE_CURSES_H
396         case UI_CURSES:
397                 if (curr == 0) {
398                         clear();
399                         move(5, 20);
400                         printw("%s\n", text);
401                         move(10, 1);
402                         printf("..........................");
403                         printf("..........................");
404                         printf("..........................\r");
405                         refresh();
406                         dots_printed = 0;
407                 } else if (curr == cmax) {
408                         clear();
409                         refresh();
410                 } else {
411                         a = (curr * 100) / cmax;
412                         a = a * 78;
413                         a = a / 100;
414                         move(10, 1);
415                         dots_printed = 0;
416                         while (dots_printed < a) {
417                                 printw("*");
418                                 ++dots_printed;
419                         }
420                         refresh();
421                 }
422                 break;
423 #endif
424
425         }
426 }
427
428
429
430 /*
431  * check_services_entry()  -- Make sure "citadel" is in /etc/services
432  *
433  */
434 void check_services_entry(void)
435 {
436         char question[128];
437         FILE *sfp;
438
439         snprintf(question, sizeof question,
440                 "There is no '%s' entry in /etc/services.  Would you like to add one?",
441                 SERVICE_NAME);
442
443         if (getservbyname(SERVICE_NAME, PROTO_NAME) == NULL) {
444                 if (yesno(question) == 1) {
445                         sfp = fopen("/etc/services", "a");
446                         if (sfp == NULL) {
447                                 display_error(strerror(errno));
448                         } else {
449                                 fprintf(sfp, "%s                504/tcp\n",
450                                         SERVICE_NAME);
451                                 fclose(sfp);
452                         }
453                 }
454         }
455 }
456
457
458 /*
459  * check_inittab_entry()  -- Make sure "citadel" is in /etc/inittab
460  *
461  */
462 void check_inittab_entry(void)
463 {
464         FILE *infp;
465         char buf[SIZ];
466         char looking_for[SIZ];
467         char question[128];
468         char *ptr;
469         int have_entry = 0;
470         char entryname[5];
471
472         /* Determine the fully qualified path name of citserver */
473         snprintf(looking_for, sizeof looking_for, "%s/citserver ", BBSDIR);
474
475         /* Pound through /etc/inittab line by line.  Set have_entry to 1 if
476          * an entry is found which we believe starts citserver.
477          */
478         infp = fopen("/etc/inittab", "r");
479         if (infp == NULL) {
480                 return;
481         } else {
482                 while (fgets(buf, sizeof buf, infp) != NULL) {
483                         buf[strlen(buf) - 1] = 0;
484                         ptr = strtok(buf, ":");
485                         ptr = strtok(NULL, ":");
486                         ptr = strtok(NULL, ":");
487                         ptr = strtok(NULL, ":");
488                         if (ptr != NULL) {
489                                 if (!strncmp(ptr, looking_for,
490                                    strlen(looking_for))) {
491                                         ++have_entry;
492                                 }
493                         }
494                 }
495                 fclose(infp);
496         }
497
498         /* If there's already an entry, then we have nothing left to do. */
499         if (have_entry > 0)
500                 return;
501
502         /* Otherwise, prompt the user to create an entry. */
503         snprintf(question, sizeof question,
504                 "There is no '%s' entry in /etc/inittab.\n"
505                 "Would you like to add one?",
506                 looking_for);
507         if (yesno(question) == 0)
508                 return;
509
510         /* Generate a unique entry name for /etc/inittab */
511         snprintf(entryname, sizeof entryname, "c0");
512         do {
513                 ++entryname[1];
514                 if (entryname[1] > '9') {
515                         entryname[1] = 0;
516                         ++entryname[0];
517                         if (entryname[0] > 'z') {
518                                 display_error(
519                                    "Can't generate a unique entry name");
520                                 return;
521                         }
522                 }
523                 snprintf(buf, sizeof buf,
524                      "grep %s: /etc/inittab >/dev/null 2>&1", entryname);
525         } while (system(buf) == 0);
526
527         /* Now write it out to /etc/inittab */
528         infp = fopen("/etc/inittab", "a");
529         if (infp == NULL) {
530                 display_error(strerror(errno));
531         } else {
532                 fprintf(infp, "# Start the Citadel/UX server...\n");
533                 fprintf(infp, "%s:2345:respawn:%s -h%s\n",
534                         entryname, looking_for, setup_directory);
535                 fclose(infp);
536                 need_init_q = 1;
537         }
538 }
539
540
541
542 void set_str_val(int msgpos, char str[])
543 {
544         char buf[4096];
545         char tempfile[64];
546         char setupmsg[SIZ];
547
548         strcpy(tempfile, tmpnam(NULL));
549         strcpy(setupmsg, "");
550
551         switch (setup_type) {
552         case UI_TEXT:
553                 title(setup_titles[msgpos]);
554                 print_setup(msgpos);
555                 printf("This is currently set to:\n%s\n", str);
556                 printf("Enter new value or press return to leave unchanged:\n");
557                 fgets(buf, 4096, stdin);
558                 buf[strlen(buf) - 1] = 0;
559                 if (strlen(buf) != 0)
560                         strcpy(str, buf);
561                 break;
562 #ifdef HAVE_CURSES_H
563         case UI_CURSES:
564                 clear();
565                 move(1, ((80 - strlen(setup_titles[msgpos])) / 2));
566                 standout();
567                 printw("%s", setup_titles[msgpos]);
568                 standend();
569                 move(3, 0);
570                 get_setup_msg(setupmsg, msgpos);
571                 printw("%s", setupmsg);
572                 refresh();
573                 getlin(20, 0, str, 80);
574                 break;
575 #endif
576         }
577 }
578
579 void set_int_val(int msgpos, int *ip)
580 {
581         char buf[16];
582         snprintf(buf, sizeof buf, "%d", (int) *ip);
583         set_str_val(msgpos, buf);
584         *ip = atoi(buf);
585 }
586
587
588 void set_char_val(int msgpos, char *ip)
589 {
590         char buf[16];
591         snprintf(buf, sizeof buf, "%d", (int) *ip);
592         set_str_val(msgpos, buf);
593         *ip = (char) atoi(buf);
594 }
595
596
597 void set_long_val(int msgpos, long int *ip)
598 {
599         char buf[16];
600         snprintf(buf, sizeof buf, "%ld", *ip);
601         set_str_val(msgpos, buf);
602         *ip = atol(buf);
603 }
604
605
606 void edit_value(int curr)
607 {
608         int a;
609         long l;
610
611         switch (curr) {
612
613         case 1:
614                 set_str_val(curr, config.c_sysadm);
615                 break;
616
617         case 2:
618                 l = config.c_bbsuid;
619                 set_long_val(curr, &l);
620                 config.c_bbsuid = l;
621                 break;
622
623         case 3:
624                 set_str_val(curr, config.c_bucket_dir);
625                 config.c_bucket_dir[14] = 0;
626                 for (a = 0; a < strlen(config.c_bucket_dir); ++a)
627                         if (!isalpha(config.c_bucket_dir[a]))
628                                 strcpy(&config.c_bucket_dir[a],
629                                        &config.c_bucket_dir[a + 1]);
630                 break;
631
632         case 4:
633                 set_int_val(curr, &config.c_port_number);
634                 break;
635
636
637         }
638 }
639
640 /*
641  * (re-)write the config data to disk
642  */
643 void write_config_to_disk(void)
644 {
645         FILE *fp;
646         int fd;
647
648         if ((fd = creat("citadel.config", S_IRUSR | S_IWUSR)) == -1) {
649                 display_error("setup: cannot open citadel.config");
650                 cleanup(1);
651         }
652         fp = fdopen(fd, "wb");
653         if (fp == NULL) {
654                 display_error("setup: cannot open citadel.config");
655                 cleanup(1);
656         }
657         fwrite((char *) &config, sizeof(struct config), 1, fp);
658         fclose(fp);
659 }
660
661
662
663
664 /*
665  * Figure out what type of user interface we're going to use
666  */
667 int discover_ui(void)
668 {
669
670 #ifdef HAVE_CURSES_H
671         return UI_CURSES;
672 #endif
673         return UI_TEXT;
674 }
675
676
677
678
679
680 int main(int argc, char *argv[])
681 {
682         int a;
683         int curr;
684         char aaa[128];
685         FILE *fp;
686         int old_setup_level = 0;
687         int info_only = 0;
688         struct utsname my_utsname;
689         struct passwd *pw;
690         struct hostent *he;
691         gid_t gid;
692
693         /* set an invalid setup type */
694         setup_type = (-1);
695
696         /* parse command line args */
697         for (a = 0; a < argc; ++a) {
698                 if (!strncmp(argv[a], "-u", 2)) {
699                         strcpy(aaa, argv[a]);
700                         strcpy(aaa, &aaa[2]);
701                         setup_type = atoi(aaa);
702                 }
703                 if (!strcmp(argv[a], "-i")) {
704                         info_only = 1;
705                 }
706                 if (!strcmp(argv[a], "-q")) {
707                         setup_type = UI_SILENT;
708                 }
709         }
710
711
712         /* If a setup type was not specified, try to determine automatically
713          * the best one to use out of all available types.
714          */
715         if (setup_type < 0) {
716                 setup_type = discover_ui();
717         }
718 #ifdef HAVE_CURSES_H
719         if (setup_type == UI_CURSES) {
720                 initscr();
721                 raw();
722                 noecho();
723         }
724 #endif
725
726         if (info_only == 1) {
727                 important_message("Citadel/UX Setup", CITADEL);
728                 cleanup(0);
729         }
730         /* Get started in a valid setup directory. */
731         strcpy(setup_directory, BBSDIR);
732         set_str_val(0, setup_directory);
733         if (chdir(setup_directory) != 0) {
734                 important_message("Citadel/UX Setup",
735                           "The directory you specified does not exist.");
736                 cleanup(errno);
737         }
738         /* Determine our host name, in case we need to use it as a default */
739         uname(&my_utsname);
740
741         /* Now begin. */
742         switch (setup_type) {
743
744         case UI_TEXT:
745                 printf("\n\n\n"
746                         "               *** Citadel/UX setup program ***\n\n");
747                 break;
748
749         }
750
751         /*
752          * What we're going to try to do here is append a whole bunch of
753          * nulls to the citadel.config file, so we can keep the old config
754          * values if they exist, but if the file is missing or from an
755          * earlier version with a shorter config structure, when setup tries
756          * to read the old config parameters, they'll all come up zero.
757          * The length of the config file will be set to what it's supposed
758          * to be when we rewrite it, because we replace the old file with a
759          * completely new copy.  (Neat, eh?)
760          */
761
762         if ((a = open("citadel.config", O_WRONLY | O_CREAT | O_APPEND,
763                       S_IRUSR | S_IWUSR)) == -1) {
764                 display_error("setup: cannot append citadel.config");
765                 cleanup(errno);
766         }
767         fp = fdopen(a, "ab");
768         if (fp == NULL) {
769                 display_error("setup: cannot append citadel.config");
770                 cleanup(errno);
771         }
772         for (a = 0; a < sizeof(struct config); ++a)
773                 putc(0, fp);
774         fclose(fp);
775
776         /* now we re-open it, and read the old or blank configuration */
777         fp = fopen("citadel.config", "rb");
778         if (fp == NULL) {
779                 display_error("setup: cannot open citadel.config");
780                 cleanup(errno);
781         }
782         fread((char *) &config, sizeof(struct config), 1, fp);
783         fclose(fp);
784
785
786         /* set some sample/default values in place of blanks... */
787         if (strlen(config.c_nodename) == 0)
788                 safestrncpy(config.c_nodename, my_utsname.nodename,
789                             sizeof config.c_nodename);
790         strtok(config.c_nodename, ".");
791         if (strlen(config.c_fqdn) == 0) {
792                 if ((he = gethostbyname(my_utsname.nodename)) != NULL)
793                         safestrncpy(config.c_fqdn, he->h_name,
794                                     sizeof config.c_fqdn);
795                 else
796                         safestrncpy(config.c_fqdn, my_utsname.nodename,
797                                     sizeof config.c_fqdn);
798         }
799         if (strlen(config.c_humannode) == 0)
800                 strcpy(config.c_humannode, "My System");
801         if (strlen(config.c_phonenum) == 0)
802                 strcpy(config.c_phonenum, "US 800 555 1212");
803         if (config.c_initax == 0) {
804                 config.c_initax = 4;
805         }
806         if (strlen(config.c_moreprompt) == 0)
807                 strcpy(config.c_moreprompt, "<more>");
808         if (strlen(config.c_twitroom) == 0)
809                 strcpy(config.c_twitroom, "Trashcan");
810         if (strlen(config.c_bucket_dir) == 0)
811                 strcpy(config.c_bucket_dir, "bitbucket");
812         if (strlen(config.c_net_password) == 0)
813                 strcpy(config.c_net_password, "netpassword");
814         if (config.c_port_number == 0) {
815                 config.c_port_number = 504;
816         }
817         if (config.c_ipgm_secret == 0) {
818                 srand(getpid());
819                 config.c_ipgm_secret = rand();
820         }
821         if (config.c_sleeping == 0) {
822                 config.c_sleeping = 900;
823         }
824         if (config.c_bbsuid == 0) {
825                 pw = getpwnam("citadel");
826                 if (pw != NULL)
827                         config.c_bbsuid = pw->pw_uid;
828         }
829         if (config.c_bbsuid == 0) {
830                 pw = getpwnam("bbs");
831                 if (pw != NULL)
832                         config.c_bbsuid = pw->pw_uid;
833         }
834         if (config.c_bbsuid == 0) {
835                 pw = getpwnam("guest");
836                 if (pw != NULL)
837                         config.c_bbsuid = pw->pw_uid;
838         }
839         if (config.c_createax == 0) {
840                 config.c_createax = 3;
841         }
842         /*
843          * Negative values for maxsessions are not allowed.
844          */
845         if (config.c_maxsessions < 0) {
846                 config.c_maxsessions = 0;
847         }
848         /* We need a system default message expiry policy, because this is
849          * the top level and there's no 'higher' policy to fall back on.
850          */
851         if (config.c_ep.expire_mode == 0) {
852                 config.c_ep.expire_mode = EXPIRE_NUMMSGS;
853                 config.c_ep.expire_value = 150;
854         }
855
856         /*
857          * Default port numbers for various services
858          */
859         if (config.c_smtp_port == 0) config.c_smtp_port = 25;
860         if (config.c_pop3_port == 0) config.c_pop3_port = 110;
861         if (config.c_imap_port == 0) config.c_imap_port = 143;
862
863
864         /* Go through a series of dialogs prompting for config info */
865         if (setup_type != UI_SILENT) {
866                 for (curr = 1; curr <= MAXSETUP; ++curr) {
867                         edit_value(curr);
868                 }
869         }
870
871         /*
872            if (setuid(config.c_bbsuid) != 0) {
873            important_message("Citadel/UX Setup",
874            "Failed to change the user ID to your BBS user.");
875            cleanup(errno);
876            }
877          */
878
879 /***** begin version update section ***** */
880         /* take care of any updating that is necessary */
881
882         old_setup_level = config.c_setup_level;
883
884         if (old_setup_level == 0)
885                 goto NEW_INST;
886
887         if (old_setup_level < 323) {
888                 important_message("Citadel/UX Setup",
889                                   "This Citadel/UX installation is too old "
890                                   "to be upgraded.");
891                 cleanup(1);
892         }
893         write_config_to_disk();
894
895         if ((config.c_setup_level / 10) == 32) {
896                 important_msgnum(31);
897                 cleanup(0);
898         }
899         if (config.c_setup_level < 400) {
900                 config.c_setup_level = 400;
901         }
902         /* end of 3.23 -> 4.00 update section */
903
904         /* end of 4.00 -> 4.02 update section */
905
906         old_setup_level = config.c_setup_level;
907
908         /* end of version update section */
909
910 NEW_INST:
911         config.c_setup_level = REV_LEVEL;
912
913 /******************************************/
914
915         write_config_to_disk();
916
917         mkdir("info", 0700);
918         mkdir("bio", 0700);
919         mkdir("userpics", 0700);
920         mkdir("messages", 0700);
921         mkdir("help", 0700);
922         mkdir("images", 0700);
923         mkdir("netconfigs", 0700);
924         mkdir(config.c_bucket_dir, 0700);
925
926         /* Delete a bunch of old files from Citadel v4; don't need anymore */
927         system("rm -fr ./chatpipes ./expressmsgs sessions 2>/dev/null");
928
929         check_services_entry(); /* Check /etc/services */
930         check_inittab_entry();  /* Check /etc/inittab */
931
932         if ((pw = getpwuid(config.c_bbsuid)) == NULL)
933                 gid = getgid();
934         else
935                 gid = pw->pw_gid;
936
937         progress("Setting file permissions", 0, 5);
938         chown(".", config.c_bbsuid, gid);
939         progress("Setting file permissions", 1, 5);
940         chown("citadel.config", config.c_bbsuid, gid);
941         progress("Setting file permissions", 2, 5);
942         snprintf(aaa, sizeof aaa,
943                 "find . | grep -v chkpwd | xargs chown %ld:%ld 2>/dev/null",
944                 (long)config.c_bbsuid, (long)gid);
945         system(aaa);
946         progress("Setting file permissions", 3, 5);
947         chmod("citadel.config", S_IRUSR | S_IWUSR);
948         progress("Setting file permissions", 4, 5);
949
950         important_message("Setup finished",
951             "Setup is finished.  You may now start the Citadel server.");
952
953         cleanup(0);
954         return 0;
955 }