2 * Citadel/UX setup program
4 * see copyright.txt for copyright information
6 * *** YOU MUST EDIT sysconfig.h >BEFORE< COMPILING SETUP ***
15 #include <sys/types.h>
33 #define UI_TEXT 0 /* Default setup type -- text only */
34 #define UI_DIALOG 1 /* Use the 'dialog' program */
35 #define UI_CURSES 2 /* Use curses */
37 #define SERVICE_NAME "citadel"
38 #define PROTO_NAME "tcp"
41 char setup_directory[128];
44 char *setup_titles[] = {
47 "Fully Qualified Domain Name (FQDN)",
48 "Human-readable node name",
51 "System Administrator",
53 "Password encryption seed",
54 "'Room Creator = Room Aide' flag",
55 "Server timeout period",
56 "Initial access level",
57 "Registration requirements",
59 "Twit Detect target room",
60 "Maximum concurrent sessions",
62 "Restrict Internet mail flag",
64 "Name of bit bucket subdirectory",
65 "System net password",
70 char *setup_text[] = {
73 "Enter the full pathname of the directory in which the BBS you are",
74 "creating or updating resides. If you specify a directory other than the",
75 "default, you will need to specify the -h flag to the server when you start",
79 "This is the name your system is known by on a Citadel/UX network. It",
80 "should be 8 characters or less, and should generally be comprised only of",
81 "letters. You can also use numbers and hyphens if necessary.",
84 "This is the name your system is known by on the Internet.",
85 "If you're not on the Internet, simply set this to your",
86 "node name followed by '.UUCP'.",
89 "This is a longer description of your system, readable by",
90 "us mere humans. It can be up to 20 characters long and it",
91 "can have spaces in it. Note that if you are part of a",
92 "Cit86Net, this is the name your system will be known by on",
96 "This is the main dialup number for your system. If yours",
97 "can not be dialed into, then make one up! It should be in",
98 "the format 'US 000 000 0000' - the US is your country code",
99 "(look it up if you're not in the United States) and the",
100 "rest is, of course, your area code and phone number.",
101 "This doesn't have any use in Citadel/UX, but gateways to",
102 "other networks may require it, and someday we may use this",
103 "to have the networker automatically build a BBS list.",
106 "Enter the city and state your system is located in.",
109 "Enter the name of the system administrator (which is probably you).",
110 "When an account is created with this name, it will automatically be",
111 "assigned the highest access level.",
114 "You should create a user called 'bbs', 'guest', 'citadel', or something",
115 "similar, that will allow users a way into your BBS. The server will run",
116 "under this user ID. Please specify that (numeric) user ID here.",
119 "Citadel uses a (very) simple password encryption scheme",
120 "to thwart breakins that could occur if someone snatched",
121 "a copy of your userlog. This parameter is part of the",
122 "algorithm, so that the code can be different on each",
123 "system. Once it has been set, DO NOT change it --",
124 "otherwise no one will be able to log in!",
127 "This is a boolean value. If you set it to 1, anyone who",
128 "creates a class 3 (passworded) or class 4 (invitation",
129 "only) room will automatically become the Room Aide for",
130 "that room, allowing them to edit it, delete/move messages,",
131 "etc. This is an administrative decision: it works well on",
132 "some systems, and not so well on others. Set this to 0 to",
133 "disable this function.",
136 "This setting specifies how long a server session may sit idle before it is",
137 "automatically terminated. The recommended value is 900 seconds (15",
138 "minutes). Note that this has *nothing* to do with any watchdog timer that",
139 "is presented to the user. The server's timeout is intended to kill idle or",
140 "zombie sessions running on a network, etc. ",
141 "You MUST set this to a reasonable value. Setting it to zero will cause",
142 "the server to malfunction.",
145 "This is the access level new users are assigned.",
147 "The most common settings for this will be either 1, for",
148 "systems which require new user validation by the system",
149 "administrator ('sysop' is a word for people who run DOS",
150 "boards!), or 4, for systems which give instant access.",
151 "The current access levels available are:",
154 "'Registration' refers to the boring part of logging into a BBS for the first",
155 "time: typing your name, address, and telephone number. Set this value to 1",
156 "to automatically do registration for new users, or 0 to not auto-register.",
157 "Optionally, you could set it to, say, 2, to auto-register on a user's second",
158 "call, but there really isn't much point to doing this. The recommended",
159 "value is 1 if you've set your inital access level to 1, or 0 if you've set",
160 "your initial access level to something higher.",
163 "Every BBS has its share of problem users. This is one",
164 "good way to deal with them: if you enable this option,",
165 "anyone you flag as a 'problem user' (access level 2) can",
166 "post anywhere they want, but their messages will all be",
167 "automatically moved to a room of your choosing. Set this",
168 "value to 1 to enable Twit Detect, or 0 to disable it.",
171 "This is the name of the room that problem user messages",
172 "get moved to if you have Twit Detect enabled.",
173 "(Note: don't forget to *create* this room!)",
176 "This is the maximum number of concurrent Citadel sessions which may be",
177 "running at any given time. Use this to keep very busy systems from being",
179 " Set this value to 0 to allow an unlimited number of sessions.",
182 "This is the prompt that appears after each screenful of",
183 "text - for users that have chosen that option. Usually",
184 "a simple '<more>' will do, but some folks like to be",
188 "If you have a gateway set up to allow Citadel users to",
189 "send Internet mail, with sendmail, qmail, or whatever, and",
190 "you wish to restrict this to only users to whom you have",
191 "given this privilege, set this flag to 1. Otherwise, set",
192 "it to 0 to allow everyone to send Internet mail.",
193 "(Obviously, if your system doesn't have the ability to",
194 "send mail to the outside world, this is all irrelevant.)",
197 "This parameter is meaningless and should be removed.",
200 "Select the name of a subdirectory (relative to the main",
201 "Citadel directory - do not type an absolute pathname!) in",
202 "which to place arriving file transfers that otherwise",
203 "don't have a home.",
206 "If you use Citadel client/server sessions to transport network spool data",
207 "between systems, this is the password other systems will use to authenticate",
208 "themselves as network nodes rather than regular callers.",
211 "Specify the TCP port number on which your server will run. Normally, this",
212 "will be port 504, which is the official port assigned by the IANA for",
213 "Citadel servers. You'll only need to specify a different port number if",
214 "you run multiple BBS's on the same computer and there's something else",
215 "already using port 504.",
226 "DO NOT re-create files that you wish to keep intact!",
227 "They will be permanently ERASED if you do so!",
228 "(Obviously, if this is the first time you are setting up the BBS,",
229 "then you will want to create all of the files.)",
232 "Setup has detected that you currently have data files from a Citadel/UX",
233 "version 3.2x installation. The program 'conv_32_40' can upgrade your",
234 "files to version 4.0x format.",
235 " Setup will now exit. Please either run 'conv_32_40' or delete your data",
236 "files, and run setup again.",
245 struct config config;
248 void cleanup(int exitcode) {
250 if (setup_type == UI_CURSES) {
257 /* Do an 'init q' if we need to. When we hit the right one, init
258 * will take over and setup won't come back because we didn't do a
259 * fork(). If init isn't found, we fall through the bottom of the
260 * loop and setup exits quietly.
263 execlp("/sbin/init", "init", "q", NULL);
264 execlp("/usr/sbin/init", "init", "q", NULL);
265 execlp("/bin/init", "init", "q", NULL);
266 execlp("/usr/bin/init", "init", "q", NULL);
267 execlp("init", "init", "q", NULL);
275 void getlin(yp,xp,string,lim) /* Gets a line from the terminal */
276 int yp,xp; /* Where on the screen to start */
277 char string[]; /* Pointer to string buffer */
278 int lim; /* Maximum length - if negative, no-show */
283 if (lim<0) { lim=(0-lim); flag=1; }
286 for (a=0; a<lim; ++a) addch('-');
289 for (a=0; a<lim; ++a) addch(' ');
291 printw("%s", string);
292 GLA: move(yp,xp+strlen(string));
298 if ((a==8)&&(strlen(string)==0)) goto GLA;
299 if ((a!=13)&&(a!=8)&&(strlen(string)==lim)) goto GLA;
300 if ((a==8)&&(string[0]!=0)) {
301 string[strlen(string)-1]=0;
302 move(yp,xp+strlen(string));
306 if ((a==13)||(a==10)) {
309 for (a=0; a<lim; ++a) addch(' ');
310 mvprintw(yp,xp,"%s",string);
317 if (flag==0) addch(a);
318 if (flag==1) addch('*');
327 if (setup_type == UI_TEXT) {
328 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<%s>\n",text);
337 if (setup_type == UI_CURSES) {
338 mvprintw(20, 0, "Press any key to continue... ");
344 printf("Press return to continue...");
345 fgets(junk, 5, stdin);
357 printf("%s\nYes/No --> ",question);
358 fgets(buf, 4096, stdin);
359 answer=tolower(buf[0]);
360 if (answer=='y') answer=1;
361 else if (answer=='n') answer=0;
362 } while ((answer<0)||(answer>1));
366 sprintf(buf, "dialog --yesno \"%s\" 7 80", question);
367 answer = ( (system(buf)==0) ? 1 : 0);
374 mvprintw(1, 20, "Question");
376 mvprintw(10, 0, "%-80s", question);
377 mvprintw(20, 0, "%80s", "");
378 mvprintw(20, 0, "Yes/No -> ");
381 answer=tolower(answer);
382 if (answer=='y') answer=1;
383 else if (answer=='n') answer=0;
384 } while ((answer<0)||(answer>1));
394 void dump_access_levels() {
396 for (a=0; a<=6; ++a) printf("%d %s\n",a,axdefs[a]);
399 void get_setup_msg(char *dispbuf, int msgnum) {
404 while (atol(setup_text[a]) != msgnum) ++a;
408 strcat(dispbuf, setup_text[a++]);
409 strcat(dispbuf, "\n");
410 } while(atol(setup_text[a])!=(msgnum+1));
413 void print_setup(msgnum) {
416 get_setup_msg(dispbuf, msgnum);
417 printf("\n\n%s\n\n", dispbuf);
421 void important_message(char *title, char *msgtext) {
427 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");
428 printf(" %s \n\n%s\n\n", title, msgtext);
433 sprintf(buf, "dialog --title \"%s\" --msgbox \"\n%s\" 20 80",
442 printw(" Important Message ");
445 printw("%s", msgtext);
454 void important_msgnum(int msgnum) {
457 get_setup_msg(dispbuf, msgnum);
458 important_message("Important Message", dispbuf);
461 void display_error(char *error_message) {
462 important_message("Error", error_message);
465 void progress(text,curr,cmax)
469 static long dots_printed;
472 static FILE *gauge = NULL;
480 printf("..........................");
481 printf("..........................");
482 printf("..........................\r");
486 else if (curr==cmax) {
487 printf("\r%79s\n","");
490 a=(curr * 100) / cmax;
492 while (dots_printed < a) {
507 printf("..........................");
508 printf("..........................");
509 printf("..........................\r");
513 else if (curr==cmax) {
518 a=(curr * 100) / cmax;
522 while (dots_printed < a) {
532 if ( (curr == 0) && (gauge == NULL) ) {
533 sprintf(gcmd, "dialog --guage \"%s\" 7 80 0",
535 gauge = (FILE *) popen(gcmd, "w");
538 else if (curr==cmax) {
539 fprintf(gauge, "100\n");
544 a=(curr * 100) / cmax;
546 fprintf(gauge, "%ld\n", a);
557 int a,main_ref_count;
559 struct quickroom quickroom;
560 struct floor floor_rec;
563 * first, put all existing rooms on floor 0 (the main floor) and
564 * count the room records that are in use so we can set the main
565 * floor's reference count
568 fp = fopen("quickroom", "rb+");
569 for (a=0; a<MAXROOMS; ++a) {
570 progress("Preparing room files for addition of floors",
573 fseek(fp, (a*((long)sizeof(struct quickroom))), 0);
574 fread((char *)&quickroom,sizeof(struct quickroom),1,fp);
575 if (quickroom.QRflags & QR_INUSE) ++main_ref_count;
576 quickroom.QRfloor = 0;
577 fseek(fp, (a*((long)sizeof(struct quickroom))), 0);
578 fwrite((char *)&quickroom,sizeof(struct quickroom),1,fp);
582 /* Open a new floortab file */
583 fp=fopen("floortab","wb");
585 /* Create the main floor */
586 floor_rec.f_flags = (F_INUSE);
587 strcpy(floor_rec.f_name, "Main Floor");
588 floor_rec.f_ref_count = main_ref_count;
589 floor_rec.f_reserved = 0;
590 fwrite((char *)&floor_rec,sizeof(struct floor),1,fp);
593 /* make the remaining floors blanks */
594 floor_rec.f_flags = 0;
595 strcpy(floor_rec.f_name, "");
596 floor_rec.f_ref_count = 0;
597 floor_rec.f_reserved = 0;
599 for (a=1; a<MAXFLOORS; ++a) {
600 progress("Creating floor table (floortab)",
604 fwrite((char *)&floor_rec,sizeof(struct floor),1,fp);
612 * check (and fix) floor reference counts
614 void check_ref_counts() {
618 struct quickroom qrbuf;
621 for (a=0; a<MAXFLOORS; ++a) ref[a] = 0;
623 fp = fopen("quickroom","rb");
624 for (a=0; a<MAXROOMS; ++a) {
625 progress("Checking reference counts - phase 1 of 2",
627 fread((char *)&qrbuf,sizeof(struct quickroom),1,fp);
628 if (qrbuf.QRflags & QR_INUSE) {
629 ++ref[(int)qrbuf.QRfloor];
634 fp = fopen("floortab","rb+");
635 for (a=0; a<MAXFLOORS; ++a) {
636 progress("Checking reference counts - phase 2 of 2",
638 fseek(fp,(long)a*(long)sizeof(struct floor),0);
639 fread((char *)&flbuf,sizeof(struct floor),1,fp);
640 flbuf.f_ref_count = ref[a];
641 fseek(fp,(long)a*(long)sizeof(struct floor),0);
642 fwrite((char *)&flbuf,sizeof(struct floor),1,fp);
649 * check_services_entry() -- Make sure "citadel" is in /etc/services
652 void check_services_entry() {
657 "There is no '%s' entry in /etc/services. Would you like to add one?",
660 if (getservbyname(SERVICE_NAME, PROTO_NAME) == NULL) {
661 if (yesno(question)==1) {
662 sfp = fopen("/etc/services", "a");
664 display_error(strerror(errno));
667 fprintf(sfp, "%s 504/tcp\n",
678 * check_inittab_entry() -- Make sure "citadel" is in /etc/inittab
681 void check_inittab_entry() {
684 char looking_for[256];
690 /* Determine the fully qualified path name of citserver */
691 sprintf(looking_for, "%s/citserver ", BBSDIR);
693 /* Pound through /etc/inittab line by line. Set have_entry to 1 if
694 * an entry is found which we believe starts citserver.
696 infp = fopen("/etc/inittab", "r");
698 display_error(strerror(errno));
701 while (fgets(buf, 256, infp) != NULL) {
702 buf[strlen(buf) - 1] = 0;
703 ptr = strtok(buf, ":");
704 ptr = strtok(NULL, ":");
705 ptr = strtok(NULL, ":");
706 ptr = strtok(NULL, ":");
708 if (!strncmp(ptr, looking_for, strlen(looking_for))) {
716 /* If there's already an entry, then we have nothing left to do. */
717 if (have_entry > 0) return;
719 /* Otherwise, prompt the user to create an entry. */
721 "There is no '%s' entry in /etc/inittab.\nWould you like to add one?",
723 if (yesno(question)==0) return;
725 /* Generate a unique entry name for /etc/inittab */
726 sprintf(entryname, "c0");
729 if (entryname[1] > '9') {
732 if (entryname[0] > 'z') {
734 "Can't generate a unique entry name");
739 "grep %s: /etc/inittab >/dev/null 2>&1", entryname);
740 } while(system(buf)==0);
742 /* Now write it out to /etc/inittab */
743 infp = fopen("/etc/inittab", "a");
745 display_error(strerror(errno));
748 fprintf(infp, "# Start the Citadel/UX server...\n");
749 fprintf(infp,"%s:2345:respawn:%s -h%s\n",
750 entryname, looking_for, setup_directory);
759 * Create a blank call log
763 struct calllog calllog;
765 calllog.CLfullname[0]=0;
770 file=creat("calllog.pos",0666);
771 chmod("calllog.pos",0666);
772 write(file,&a,sizeof(int));
775 file=creat("calllog",0666);
776 chmod("calllog",0666);
777 for (a=0; a<CALLLOG; ++a) {
778 progress("Creating call log file",
782 write(file,&calllog,sizeof(struct calllog));
788 void set_str_val(int msgpos, char str[]) {
794 sprintf(tempfile, "/tmp/setup.%d", getpid());
796 switch (setup_type) {
798 title(setup_titles[msgpos]);
800 if (msgpos==11) dump_access_levels();
801 printf("This is currently set to:\n%s\n",str);
802 printf("Enter new value or press return to leave unchanged:\n");
803 fgets(buf, 4096, stdin);
804 buf[strlen(buf)-1] = 0;
805 if (strlen(buf)!=0) strcpy(str,buf);
808 get_setup_msg(setupmsg, msgpos);
810 "dialog --title \"%s\" --inputbox \"\n%s\n\" 20 80 \"%s\" 2>%s",
811 setup_titles[msgpos],
814 if (system(buf)==0) {
815 fp = fopen(tempfile, "rb");
816 fgets(str, 4095, fp);
819 if (str[strlen(str)-1]==10)
820 str[strlen(str)-1]=0;
826 move(1, ((80-strlen(setup_titles[msgpos]))/2) );
828 printw("%s", setup_titles[msgpos]);
831 get_setup_msg(setupmsg, msgpos);
832 printw("%s", setupmsg);
834 getlin(20, 0, str, 80);
840 void set_int_val(msgpos, ip)
844 sprintf(buf,"%d",(int)*ip);
845 set_str_val(msgpos, buf);
850 void set_char_val(msgpos, ip)
854 sprintf(buf,"%d",(int)*ip);
855 set_str_val(msgpos, buf);
856 *ip = (char)atoi(buf);
860 void set_long_val(msgpos, ip)
864 sprintf(buf,"%ld",*ip);
865 set_str_val(msgpos, buf);
870 int yesno_s(question) {
876 sprintf(tempfile, "/tmp/setup.%d", getpid());
877 switch (setup_type) {
881 if (a==1) a=yesno("Are you SURE you want to reinitialize this file? ");
887 if (a==1) a=yesno("Are you SURE you want to reinitialize this file? ");
894 sprintf(buf, "dialog --title \"Confirm file overwrite\" --menu \"\nAre you SURE you want to reinitialize this file?\n\" 13 80 2 NO \"No, don't overwrite\" YES \"Yes, overwrite the existing file\" 2>%s", tempfile);
896 if (a != 0) return(0);
897 fp = fopen(tempfile, "rb");
898 fgets(buf, 4095, fp);
901 if (buf[strlen(buf)-1]==10)
902 buf[strlen(buf)-1]=0;
903 return( (!strcmp(buf, "YES")) ? 1 : 0 );
908 return(0); /* just in case */
912 void edit_value(curr)
919 set_str_val(curr, config.c_nodename);
923 set_str_val(curr, config.c_fqdn);
927 set_str_val(curr, config.c_humannode);
931 set_str_val(curr, config.c_phonenum);
935 set_str_val(curr, config.c_bbs_city);
939 set_str_val(curr, config.c_sysadm);
943 set_int_val(curr, &config.c_bbsuid);
947 set_int_val(curr, &config.c_pwcrypt);
951 set_char_val(curr, &config.c_creataide);
955 set_int_val(curr, &config.c_sleeping);
959 set_char_val(curr, &config.c_initax);
963 set_char_val(curr, &config.c_regiscall);
967 set_char_val(curr, &config.c_twitdetect);
971 set_str_val(curr, config.c_twitroom);
975 set_int_val(curr, &config.c_maxsessions);
979 set_str_val(curr, config.c_moreprompt);
983 set_char_val(curr, &config.c_restrict);
987 set_long_val(curr, &config.c_msgbase);
991 set_str_val(curr, config.c_bucket_dir);
992 config.c_bucket_dir[14] = 0;
993 for (a=0; a<strlen(config.c_bucket_dir); ++a)
994 if (!isalpha(config.c_bucket_dir[a]))
995 strcpy(&config.c_bucket_dir[a],
996 &config.c_bucket_dir[a+1]);
1000 set_str_val(curr, config.c_net_password);
1004 set_int_val(curr, &config.c_port_number);
1012 * (re-)write the config data to disk
1014 void write_config_to_disk() {
1017 fp=fopen("citadel.config","wb");
1019 display_error("setup: cannot open citadel.config");
1022 fwrite((char *)&config,sizeof(struct config),1,fp);
1030 * Figure out what type of user interface we're going to use
1038 if (system("dialog -h </dev/null 2>&1 |grep Savio")==0) {
1049 void main(int argc, char *argv[]) {
1054 int old_setup_level = 0;
1057 /* set an invalid setup type */
1060 /* parse command line args */
1061 for (a=0; a<argc; ++a) {
1062 if (!strncmp(argv[a], "-u", 2)) {
1063 strcpy(aaa, argv[a]);
1064 strcpy(aaa, &aaa[2]);
1065 setup_type = atoi(aaa);
1067 if (!strcmp(argv[a], "-i")) {
1073 /* If a setup type was not specified, try to determine automatically
1074 * the best one to use out of all available types.
1076 if (setup_type < 0) {
1077 setup_type = discover_ui();
1081 if (setup_type == UI_CURSES) {
1088 if (info_only == 1) {
1089 important_message("Citadel/UX Setup", CITADEL);
1093 strcpy(setup_directory, BBSDIR);
1094 set_str_val(0, setup_directory);
1095 if (chdir(setup_directory) != 0) {
1096 important_message("Citadel/UX Setup",
1097 "The directory you specified does not exist.");
1102 switch(setup_type) {
1105 printf("\n\n\n *** Citadel/UX setup program ***\n\n");
1109 system("exec clear");
1115 * What we're going to try to do here is append a whole bunch of
1116 * nulls to the citadel.config file, so we can keep the old config
1117 * values if they exist, but if the file is missing or from an
1118 * earlier version with a shorter config structure, when setup tries
1119 * to read the old config parameters, they'll all come up zero.
1120 * The length of the config file will be set to what it's supposed
1121 * to be when we rewrite it, because we replace the old file with a
1122 * completely new copy. (Neat, eh?)
1125 fp=fopen("citadel.config","ab");
1127 display_error("setup: cannot append citadel.config");
1130 for (a=0; a<sizeof(struct config); ++a) putc(0,fp);
1133 /* now we re-open it, and read the old or blank configuration */
1134 fp=fopen("citadel.config","rb");
1136 display_error("setup: cannot open citadel.config");
1139 fread((char *)&config,sizeof(struct config),1,fp);
1143 /* set some sample/default values in place of blanks... */
1144 if (strlen(config.c_nodename)==0)
1145 strcpy(config.c_nodename,"mysystem");
1146 if (strlen(config.c_fqdn)==0)
1147 sprintf(config.c_fqdn,"%s.UUCP",config.c_nodename);
1148 if (strlen(config.c_humannode)==0)
1149 strcpy(config.c_humannode,"My System");
1150 if (strlen(config.c_phonenum)==0)
1151 strcpy(config.c_phonenum,"US 800 555 1212");
1152 if (config.c_initax == 0)
1153 config.c_initax = 1;
1154 /* if (config.c_regiscall == 0)
1155 config.c_regiscall = 1; */
1156 if (strlen(config.c_moreprompt)==0)
1157 strcpy(config.c_moreprompt,"<more>");
1158 if (strlen(config.c_twitroom)==0)
1159 strcpy(config.c_twitroom,"Trashcan");
1160 if (strlen(config.c_bucket_dir)==0)
1161 strcpy(config.c_bucket_dir,"bitbucket");
1162 if (config.c_msgbase == 0L)
1163 config.c_msgbase = 2000000;
1164 if (strlen(config.c_net_password)==0)
1165 strcpy(config.c_net_password,"netpassword");
1166 if (config.c_port_number == 0) {
1167 config.c_port_number = 504;
1169 if (config.c_ipgm_secret == 0) {
1171 config.c_ipgm_secret = rand();
1173 if (config.c_sleeping == 0) {
1174 config.c_sleeping = 900;
1177 /* Go through a series of dialogs prompting for config info */
1178 for (curr = 1; curr <= MAXSETUP; ++curr) {
1183 if (setuid(config.c_bbsuid) != 0) {
1184 important_message("Citadel/UX Setup",
1185 "Failed to change the user ID to your BBS user.");
1190 /***** begin version update section ***** */
1191 /* take care of any updating that is necessary */
1193 old_setup_level = config.c_setup_level;
1195 if (old_setup_level == 0) goto NEW_INST;
1197 if (old_setup_level < 323) {
1198 important_message("Citadel/UX Setup",
1199 "This Citadel/UX installation is too old to be upgraded.");
1203 write_config_to_disk();
1205 if ((config.c_setup_level / 10) == 32) {
1206 important_msgnum(31);
1210 if (config.c_setup_level < 400) {
1211 config.c_setup_level = 400;
1214 /* end of 3.23 -> 4.00 update section */
1216 /* end of 4.00 -> 4.02 update section */
1218 old_setup_level = config.c_setup_level;
1220 /* end of version update section */
1223 config.c_setup_level = REV_LEVEL;
1224 write_config_to_disk();
1226 system("mkdir info 2>/dev/null"); /* Create these */
1227 system("mkdir rooms 2>/dev/null");
1228 system("mkdir bio 2>/dev/null");
1229 system("mkdir userpics 2>/dev/null");
1230 system("mkdir messages 2>/dev/null");
1231 system("mkdir help 2>/dev/null");
1232 system("mkdir images 2>/dev/null");
1233 sprintf(aaa,"mkdir %s 2>/dev/null",config.c_bucket_dir);
1237 system("rm -fr ./chatpipes 2>/dev/null"); /* Don't need these */
1238 system("rm -fr ./expressmsgs 2>/dev/null");
1241 important_msgnum(30);
1245 fp=fopen("calllog","r");
1251 if (yesno_s("Create call log?")==1) cre8clog();
1254 check_ref_counts(); /* Check reference counts */
1255 check_services_entry(); /* Check /etc/services */
1256 check_inittab_entry(); /* Check /etc/inittab */
1258 progress("Setting file permissions", 0, 3);
1259 chown(".", config.c_bbsuid, getgid());
1260 progress("Setting file permissions", 1, 3);
1261 chown("citadel.config", config.c_bbsuid, getgid());
1262 progress("Setting file permissions", 2, 3);
1263 sprintf(aaa, "find . -exec chown %d {} \\; 2>/dev/null",
1266 progress("Setting file permissions", 3, 3);
1268 important_message("Setup finished",
1269 "Setup is finished. You may now start the Citadel server.");