/*
 * Citadel/UX setup program
 * v2.2 / by Art Cancro
 * see copyright.doc for copyright information
 *
 * *** YOU MUST EDIT sysconfig.h >BEFORE< COMPILING SETUP ***
 */

#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>

#ifdef VISUAL_SETUP
#ifdef USE_NCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#endif

#ifndef KEY_UP
#define KEY_UP 2
#endif
#ifndef KEY_DOWN
#define KEY_DOWN 6
#endif 

#include "citadel.h"
#include "axdefs.h"

char *setup_text[] = {

"1",
"This is the name your system is known by on a Citadel/UX network.  It",
"should be 8 characters or less, and you generally should set it to the",
"same as your system's UUCP node name.  In fact, the rules that apply when",
"choosing a UUCP node name are the same rules that apply when choosing a",
"Citadel node name - which shouldn't be a problem if they're one and the",
"same.",

"2",
"This is the name your system is known by on the Internet.",
"If you're not on the Internet, simply set this to your",
"node name followed by '.UUCP'.",

"3",
"This is a longer description of your system, readable by",
"us mere humans.  It can be up to 20 characters long and it",
"can have spaces in it.  Note that if you are part of a",
"Cit86Net, this is the name your system will be known by on",
"that network.",

"4",
"This is the main dialup number for your system.  If yours",
"can not be dialed into, then make one up!  It should be in",
"the format 'US 000 000 0000' - the US is your country code",
"(look it up if you're not in the United States) and the",
"rest is, of course, your area code and phone number.",
"This doesn't have any use in Citadel/UX, but gateways to",
"other networks may require it, and someday we may use this",
"to have the networker automatically build a BBS list.",

"5",
"Enter the city and state your system is located in.",

"6",
"Enter the name of the system administrator (which is probably you).",

"7",
"You should create a user called 'bbs', 'guest', 'citadel',",
"or something similar, that will allow users a way into",
"your BBS.  Citadel doesn't require that you put all of",
"your users into /etc/passwd, although it will create",
"accounts automatically for those users and link them to",
"their /etc/passwd accounts, automatically logging them",
"into their Citadel account when they run Citadel.  For",
"everyone else, however, you can simply create one public",
"login in /etc/passwd, and Citadel will maintain its own",
"userlog for those people.  For this to work, you must set",
"the BBS User ID parameter to the UID of that account.",

"8",
"Citadel uses a (very) simple password encryption scheme",
"to thwart breakins that could occur if someone snatched",
"a copy of your userlog.  This parameter is part of the",
"algorithm, so that the code can be different on each",
"system.  Once it has been set, DO NOT change it --",
"otherwise no one will be able to log in!",

"9",
"This is a boolean value.  If you set it to 1, anyone who",
"creates a class 3 (passworded) or class 4 (invitation",
"only) room will automatically become the Room Aide for",
"that room, allowing them to edit it, delete/move messages,",
"etc.  This is an administrative decision: it works well on",
"some systems, and not so well on others.  Set this to 0 to",
"disable this function.",

"10",
"Citadel/UX can automatically log out users who sit idle,",
"not typing anything, for a given amount of time.  If you",
"wish to use this function, set this value to the number",
"of seconds to wait before logging someone out.  For",
"example, setting it to 180 (the recommended value) will",
"log a user off if he/she doesn't type anything for three",
"minutes.  To disable the watchdog timer, set it to 0.",

"11",
"This is the access level new users are assigned."
"",
"The most common settings for this will be either 1, for",
"systems which require new user validation by the system",
"administrator ('sysop' is a word for people who run DOS",
"boards!), or 4, for systems which give instant access.",
"The current access levels available are:",

"12",

"13",
"'Registration' refers to the boring part of logging into",
"a BBS for the first time: typing your name, address, and",
"telephone number.  Set this value to 1 to automatically",
"do registration for new users, or 0 to not auto-register.",
"Optionally, you could set it to, say, 2, to auto-register",
"on a user's second call, but since most sysadmins will use",
"registration info when validating users, this isn't really",
"desirable.  The recommended value is 1 if you've set your",
"initial access level to 1, or 0 if you've set your initial",
"access level to something higher.",

"14",
"Every BBS has its share of problem users.  This is one",
"good way to deal with them: if you enable this option,",
"anyone you flag as a 'problem user' (access level 2) can",
"post anywhere they want, but their messages will all be",
"automatically moved to a room of your choosing.  Set this",
"value to 1 to enable Twit Detect, or 0 to disable it.",

"15",
"This is the name of the room that problem user messages",
"get moved to if you have Twit Detect enabled.",
"(Note: don't forget to *create* this room!)",

"16",
"This is the command that gets executed when a user",
"presses the <E>nter message key.  The possible values are:",
"46 - .<E>nter message with <E>ditor",
" 4 - .<E>nter <M>essage",
"36 - .<E>nter message with <A>scii",
"",
"Normally, this value will be set to 4, to cause the <E>nter message",
"command to run Citadel's built-in editor.  However, if you have an external",
"editor installed, and you want to make it the default, set this to 46",
"to make it use your editor by default.  You can also set",
"it to 36 for raw input, but this is NOT recommended as",
"it tends to generate very messy messages. ",

"17",

"18",
"This is the prompt that appears after each screenful of",
"text - for users that have chosen that option.  Usually",
"a simple '<more>' will do, but some folks like to be",
"creative...",

"19",
"If you have a gateway set up to allow Citadel users to",
"send Internet mail, with UUCP, sendmail, or whatever, and",
"you wish to restrict this to only users to whom you have",
"given this privilege, set this flag to 1.  Otherwise, set",
"it to 0 to allow everyone to send Internet mail.",
"(Obviously, if your system doesn't have the ability to",
"send mail to the outside world, this is all irrelevant.)",

"20",
"This is the size of the file ALL messages are stored in.",
"The file is a fixed size, is created during setup, and",
"never grows or shrinks.  Once you have created the file,",
"you cannot change its size.",
"Two megabytes (2097152 bytes) is fine for most systems.",

"21",
"Select the name of a subdirectory (relative to the main",
"Citadel directory - do not type an absolute pathname!) in",
"which to place arriving file transfers that otherwise",
"don't have a home.",

"22",
"DO NOT re-create files that you wish to keep intact.",
"They will be ERASED if you do so!",
"If you are setting up Citadel/UX for the first time,",
"answer 'yes' to all of the prompts.",

"23",

"24",

"25",


};


long atol();
struct config config;
int direction;

#ifdef VISUAL_SETUP


void inverse(onoff)
int onoff; {
	if (onoff==1) {
#ifdef A_REVERSE
		attron(A_REVERSE);
#else
		standout();
#endif
		}
	else {
#ifdef A_REVERSE
		attroff(A_REVERSE);
#else
		standend();
#endif
		}
	}


getlin(yp,xp,string,lim)	/* Gets a line from the terminal */
int yp,xp;			/* Where on the screen to start */
char string[];	 		/* Pointer to string buffer */
int lim;			/* Maximum length - if negative, no-show */
{
	int a,b; char flag;

	flag=0;
	if (lim<0) { lim=(0-lim); flag=1; }
	move(yp,xp);
	inverse(1);
	for (a=0; a<lim; ++a) addch('-');
	refresh();
	move(yp,xp);
	for (a=0; a<lim; ++a) addch(' ');
	move(yp,xp);
	printw("%s",string);
GLA:	move(yp,xp+strlen(string));
	refresh();
	a=getch();
	if (a==127) a=8;
#ifdef KEY_LEFT
	if (a==KEY_LEFT) a=8;
#endif
#ifdef KEY_BACKSPACE
	if (a==KEY_BACKSPACE) a=8;
#endif
	if (a==10) a=13;
	if ((a==8)&&(strlen(string)==0)) goto GLA;
	if ((a!=13)&&(a!=8)&&(strlen(string)==lim)) goto GLA;
	if ((a==8)&&(string[0]!=0)) {
		string[strlen(string)-1]=0;
		move(yp,xp+strlen(string));
		addch(' ');
		goto GLA;
		}
	if ((a==13)||(a==10)||(a==KEY_UP)||(a==KEY_DOWN)) {
		inverse(0);
		move(yp,xp);
		for (b=0; b<lim; ++b) addch(' ');
		mvprintw(yp,xp,"%s",string);
		refresh();
		if (a==KEY_UP) direction = (-2);
		else direction = 0;
		return(0);
		}
	b=strlen(string);
	string[b]=a;
	string[b+1]=0;
	if (flag==0) addch(a);
	if (flag==1) addch('*');
	goto GLA;
}
#endif


void title(text)
char *text; {
#ifdef VISUAL_SETUP
	clear();
	move(0,10);
	inverse(1);
	printw("%s",text);
	inverse(0);
	refresh();
#else
	printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<%s>\n",text);
#endif
	}


void hit_any_key() {
	char junk[5];
#ifdef VISUAL_SETUP
	move(22,20);
	inverse(1);
	printw("Press any key to continue");
	inverse(0);
	refresh();
	getch();
#else
	printf("Press return to continue...\n");
	gets(junk);
#endif
	}

int yesno(question)
char *question; {
	int answer;
	char buf[10];

#ifdef VISUAL_SETUP
	mvprintw(10,0,"%s",question);
	mvprintw(11,0,"Yes/No --> ");
	refresh();
	do {
		answer=getch();
		answer=tolower(answer);
		if (answer=='y') answer=1;
		else if (answer=='n') answer=0;
		} while ((answer<0)||(answer>1));
	mvprintw(10,0,"%80s","");
	mvprintw(11,0,"%80s","");
	refresh();
	return(answer);
#else
	do {
		printf("%s\nYes/No --> ",question);
		gets(buf);
		answer=tolower(buf[0]);
		if (answer=='y') answer=1;
		else if (answer=='n') answer=0;
		} while ((answer<0)||(answer>1));
	return(answer);
#endif
	}


void display_error(text)
char *text; {
#ifdef VISUAL_SETUP
	move(22,0);
	inverse(1);
	printw("%s",text);
	inverse(0);
	refresh();
#else
	printf("\n%s\n",text);
#endif
	}

void dump_access_levels() {
	int a;
#ifdef VISUAL_SETUP
	for (a=0; a<=6; ++a) mvprintw(10+a,0,"%d %s",a,axdefs[a]);
#else
	for (a=0; a<=6; ++a) printf("%d %s\n",a,axdefs[a]);
#endif
	}

void print_setup(msgnum)
int msgnum; {
	int a,b;

	a=0;
	while (atol(setup_text[a]) != msgnum) ++a;
	++a;
#ifdef VISUAL_SETUP
	move(2,0);
	clrtobot();
	do {
		printw("%s\n",setup_text[a++]);
		} while(atol(setup_text[a])!=(msgnum+1));
#else
	printf("\n\n");
	do {
		printf("%s\n",setup_text[a++]);
		} while(atol(setup_text[a])!=(msgnum+1));
	printf("\n\n");
#endif
	}


void progress(text,curr,cmax)
char *text;
long curr;
long cmax; {
	static long dots_printed;
	long a;

#ifdef VISUAL_SETUP
	if (curr==0) {
		move(5,0);
		for (a=0; a<((80-strlen(text))/2); ++a) addch(' ');
		printw("%s\n",text);
		move(10,0);
	/*	addch(ACS_ULCORNER);
		for (a=0; a<78; ++a) addch(ACS_HLINE);
		addch(ACS_URCORNER);
		move(11,0);
		addch(ACS_VLINE);
		move(11,79);
		addch(ACS_VLINE);
		move(12,0);
		addch(ACS_LLCORNER);
		for (a=0; a<78; ++a) addch(ACS_HLINE);
		addch(ACS_LRCORNER); */
		refresh();
		dots_printed = 0;
		move(11,1);
		}
	else if (curr==cmax) {
		mvprintw(5,0,"%80s","");
		mvprintw(10,0,"%80s","");
		mvprintw(11,0,"%80s","");
		mvprintw(12,0,"%80s","");
		refresh();
		}
	else {
		a=(curr * 100) / cmax;
		a=a*78; a=a/100;
		while (dots_printed < a) {
		/*	addch(ACS_BLOCK); */
			++dots_printed;
			refresh();
			}
		}
	}
#else
	if (curr==0) {
		printf("%s\n",text);
		printf(".......................................");
		printf(".......................................\r");
		fflush(stdout);
		dots_printed = 0;
		}
	else if (curr==cmax) {
		printf("\r%79s\n","");
		}
	else {
		a=(curr * 100) / cmax;
		a=a*78; a=a/100;
		while (dots_printed < a) {
			printf("*");
			++dots_printed;
			fflush(stdout);
			}
		}
	}
#endif


cre8user() {
	int fd;
	long lbuf;

	/* write null files */
	close(creat("usersupp",0666));
	close(creat("hashtab",0666));

	fd=creat("eternal",0666);
	lbuf = 0L;
	write(fd,&lbuf,sizeof(long));
	close(fd);

	}

cre8msg() {
	struct msgmain msgmain;
	FILE *fp;
	long aa;

	fp=fopen("msgmain","wb");
	for (aa=0; aa<=(MM_FILELEN+100); ++aa) {
		putc(0,fp);
		if ((aa%10000L)==0L)
			progress("Creating message base file...",
				aa,
				(MM_FILELEN+100));
		}
	fclose(fp);

	msgmain.MMlowest=1L;
	msgmain.MMhighest=1L;
	msgmain.MMcurpos=0L;
	msgmain.MMflags=0;

	fp=fopen("MMstructure","wb");
	fwrite((char *)&msgmain,sizeof(struct msgmain),1,fp);
	fclose(fp);
}

cre8room() {
	int a;
	FILE *fp;
	char aaa[50];
	struct quickroom quickroom;
	struct fullroom fullroom;


	/* Load up a blank fullroom structure to be used for all rooms */
	for (a=0; a<MSGSPERRM; ++a) {
		fullroom.FRnum[a]=0L;
		fullroom.FRpos[a]=0L;
		}

	/* Open a new quickroom file */
	fp=fopen("quickroom","wb");
	strcpy(quickroom.QRpasswd,"");
	quickroom.QRroomaide=0L;
	quickroom.QRhighest=0L;
	quickroom.QRgen=1;
	quickroom.QRflags=QR_INUSE;

	/* Create Lobby> Mail> and Aide> */
	strcpy(quickroom.QRname,"Patio");
	fwrite((char *)&quickroom,sizeof(struct quickroom),1,fp);

	strcpy(quickroom.QRname,"Mail");
	fwrite((char *)&quickroom,sizeof(struct quickroom),1,fp);
	
	strcpy(quickroom.QRname,"Aide");
	fwrite((char *)&quickroom,sizeof(struct quickroom),1,fp);

	/* make the remaining rooms blanks */
	strcpy(quickroom.QRname,"");
	quickroom.QRflags=0;
	for (a=3; a<MAXROOMS; ++a) {
		progress("Creating room index file (quickroom)",
			(long)a,
			(long)MAXROOMS-1
			);
		fwrite((char *)&quickroom,sizeof(struct quickroom),1,fp);
		}
	fclose(fp);

	/* Create directories and fullroom files */
	system("mkdir rooms 2>/dev/null");
	for (a=0; a<MAXROOMS; ++a) {
		progress("Creating message pointer files (fullroom)",
			(long)a,
			(long)MAXROOMS-1
			);
		sprintf(aaa,"./rooms/fullrm%d",a);
		fp=fopen(aaa,"wb");
		fwrite((char *)&fullroom,sizeof(struct fullroom),1,fp);
		fclose(fp);
		}
}

cre8clog() {
	int file,a;
	struct calllog calllog;

	calllog.CLfullname[0]=0;
	calllog.CLtime=0L;
	calllog.CLflags=0;
	a=0;

	file=creat("calllog.pos",0666);
	chmod("calllog.pos",0666);
	write(file,&a,sizeof(int));
	close(file);

	file=creat("calllog",0666);
	chmod("calllog",0666);
	for (a=0; a<CALLLOG; ++a) {
		progress("Creating call log file",
			(long)a,
			(long)CALLLOG-1
			);
		write(file,&calllog,sizeof(struct calllog));
		}
	close(file);
	return(0);
}


int set_str_val(str)
char *str; {
	char buf[128];

#ifdef VISUAL_SETUP
	mvprintw(19,0,"Set this value to:");
	mvprintw(19,40,"(Up and down arrow keys are active)");
	getlin(20,0,str,80);
#else	
	printf("This is currently set to:\n%s\n",str);
	printf("Enter new value or press return to leave unchanged:\n");
	gets(buf);
	if (strlen(buf)!=0) strcpy(str,buf);
#endif
	}

set_int_val(ip)
int *ip; {
	int a;
	char buf[16];
	sprintf(buf,"%d",(int)*ip);
	set_str_val(buf);
	*ip = atoi(buf);
	}


set_char_val(ip)
char *ip; {
	char buf[16];
	sprintf(buf,"%d",(int)*ip);
	set_str_val(buf);
	*ip = (char)atoi(buf);
	}


set_long_val(ip)
long *ip; {
	char buf[16];
	sprintf(buf,"%ld",*ip);
	set_str_val(buf);
	*ip = atol(buf);
	}


int yesno_s(question) {
	int a;

	a=yesno(question);
	if (a==1) a=yesno("Are you SURE you want to reinitialize this file? ");
	return(a);
	}


/*
 * if we're upgrading from 3.xx to 3.23, we have to set up all of the users
 * to a default 80x24 screen.
 */
void setup_screen_dims() {
	FILE *fp;
	struct usersupp usbuf;
	long numusers,prog;

	fp=fopen("usersupp","r+");
	if (fp==NULL) return;

	fseek(fp,0L,2);
	numusers = ftell(fp) / (long)sizeof(struct usersupp);

	title("Updating user file");
	for (prog=0; prog<numusers; ++prog) {
		fseek(fp,(prog*((long)sizeof(struct usersupp))),0);
		fread((char *)&usbuf,sizeof(struct usersupp),1,fp);
		usbuf.USscreenwidth = 80;
		usbuf.USscreenheight = 24;
		fseek(fp,(prog*((long)sizeof(struct usersupp))),0);
		fwrite((char *)&usbuf,sizeof(struct usersupp),1,fp);
		progress("Updating user file",prog,(numusers-1));
		}

	fclose(fp);
	return;
	}

/*
 * if we're upgrading from 3.xx to 3.23, clear some bits...
 */
void setup_room_bits() {
	FILE *fp;
	struct quickroom qrbuf;
	long prog;

	fp=fopen("quickroom","r+");
	if (fp==NULL) return;

	fseek(fp,0L,2);

	title("Updating room file");
	for (prog=0; prog<MAXROOMS; ++prog) {
		fseek(fp,(prog*((long)sizeof(struct quickroom))),0);
		fread((char *)&qrbuf,sizeof(struct quickroom),1,fp);

		if (qrbuf.QRflags & QR_READONLY)
		   qrbuf.QRflags = (qrbuf.QRflags ^ QR_READONLY);

		fseek(fp,(prog*((long)sizeof(struct quickroom))),0);
		fwrite((char *)&qrbuf,sizeof(struct quickroom),1,fp);
		progress("Updating room file",prog,(MAXROOMS-1));
		}

	fclose(fp);
	return;
	}


main() {
	int a;
	int curr;
	char aaa[128];
	FILE *fp;
	int created_msgmain = 0;

	int old_setup_level = 0;
	int new_setup_level = 0;

	chdir(BBSDIR);
	printf("\n\n\n               *** Citadel/UX setup program ***\n\n");

	/*
 	 * what we're going to try to do here is append a whole bunch of
	 * nulls to the citadel.config file, so we can keep the old config
	 * values if they exist, but if the file is missing or from an
	 * earlier version with a shorter config structure, when setup tries
	 * to read the old config parameters, they'll all come up zero.
	 * The length of the config file will be set to what it's supposed
	 * to be when we rewrite it, because we replace the old file with a
	 * completely new copy.  (Neat, eh?)
	 */
	fp=fopen("citadel.config","a");
	if (fp==NULL) {
		fprintf(stderr,"setup: cannot open citadel.config\n");
		exit(1);
		}
	for (a=0; a<sizeof(struct config); ++a) putc(0,fp);
	fclose(fp);

	/* now we re-open it, and read the old or blank configuration */
	fp=fopen("citadel.config","r");
	if (fp==NULL) {
		fprintf(stderr,"setup: cannot open citadel.config\n");
		exit(1);
		}
	fread((char *)&config,sizeof(struct config),1,fp);
	fclose(fp);


	/* set some sample/default values in place of blanks... */
	if (strlen(config.c_nodename)==0)
		strcpy(config.c_nodename,"mysystem");
	if (strlen(config.c_fqdn)==0)
		sprintf(config.c_fqdn,"%s.UUCP",config.c_nodename);
	if (strlen(config.c_humannode)==0)
		strcpy(config.c_humannode,"My System");
	if (strlen(config.c_phonenum)==0)
		strcpy(config.c_phonenum,"US 800 555 1212");
	if (config.c_initax == 0)
		config.c_initax = 1;
	if (config.c_regiscall == 0)
		config.c_regiscall = 1;
	if (strlen(config.c_moreprompt)==0)
		strcpy(config.c_moreprompt,"<more>");
	if (strlen(config.c_twitroom)==0)
		strcpy(config.c_twitroom,"Trashcan");
	if (config.c_defent == 0)
		config.c_defent = 4;
	if (strlen(config.c_bucket_dir)==0)
		strcpy(config.c_bucket_dir,"bitbucket");
	if (config.c_msgbase == 0L)
		config.c_msgbase = 2000000;


#ifdef VISUAL_SETUP
	initscr();
	raw();
	noecho();
	keypad(stdscr,TRUE);
	clear();	
	refresh();
#endif

direction = 0;
for (curr = 1; curr <= 19; ++curr) {
curr = curr + direction;
if (curr < 1) curr = 1;
 switch(curr) {

case 1:
	title("Citadel and UUCP node name");
	print_setup(1);
	set_str_val(config.c_nodename);
	break;

case 2:
	title("Fully Qualified Domain Name (FQDN)");
	print_setup(2);
	set_str_val(config.c_fqdn);
	break;

case 3:
	title("Human-readable node name");
	print_setup(3);
	set_str_val(config.c_humannode);
	break;

case 4:
	title("Phone number");
	print_setup(4);
	set_str_val(config.c_phonenum);
	break;

case 5:
	title("BBS City and State");
	print_setup(5);
	set_str_val(config.c_bbs_city);
	break;

case 6:
	title("System Administrator");
	print_setup(6);
	set_str_val(config.c_sysadm);
	break;

case 7:
	title("BBS User ID");
	print_setup(7);
	set_int_val(&config.c_bbsuid);
	break;

case 8:
	title("Password encryption seed");
	print_setup(8);
	set_int_val(&config.c_pwcrypt);
	break;

case 9:
	title("'Room Creator = Room Aide' flag");
	print_setup(9);
	set_char_val(&config.c_creataide);
	break;

case 10:
	title("Watchdog timer setting");
	print_setup(10);
	set_int_val(&config.c_sleeping);
	break;

case 11:
	title("Initial access level");
	print_setup(11);
	dump_access_levels();
	set_char_val(&config.c_initax);
	break;

case 12:
	title("Registration requirements");
	print_setup(13);
	set_char_val(&config.c_regiscall);
	break;

case 13:
	title("Twit Detect!");
	print_setup(14);
	set_char_val(&config.c_twitdetect);
	break;

case 14:
	title("Twit Detect target room");
	print_setup(15);
	set_str_val(config.c_twitroom);
	break;

case 15:
	title("The <E>nter message command...");
	print_setup(16);
  do {
	set_int_val(&config.c_defent);
    	if ( (config.c_defent != 46) 
	   && (config.c_defent != 4)
	   && (config.c_defent != 36))
		display_error("ERROR: you must set this to 46, 4, or 36.");
    } while ( (config.c_defent != 46) 
		&& (config.c_defent != 4)
		&& (config.c_defent != 36) );
	break;

case 16:
	title("Paginator prompt");
	print_setup(18);
	set_str_val(config.c_moreprompt);
	break;

case 17:
	title("Restrict Internet mail flag");
	print_setup(19);
	set_char_val(&config.c_restrict);
	break;

case 18:
	title("Message base size");
	print_setup(20);
	set_long_val(&config.c_msgbase);
	break;

case 19:
	title("Name of bit bucket subdirectory");
	print_setup(21);
	set_str_val(config.c_bucket_dir);
	config.c_bucket_dir[14] = 0;
	for (a=0; a<strlen(config.c_bucket_dir); ++a)
		if (!isalpha(config.c_bucket_dir[a]))
			strcpy(&config.c_bucket_dir[a],
				&config.c_bucket_dir[a+1]);
	break;

 }
}


	sprintf(aaa,"mkdir %s 2>/dev/null",config.c_bucket_dir);
	system(aaa);

	fp=fopen("citadel.config","w");
	if (fp==NULL) {
		display_error("setup: cannot open citadel.config");
		exit(1);
		}

	/* take care of any updating that is necessary */
	old_setup_level = config.c_setup_level;
	
	if (old_setup_level < 323) {
		setup_screen_dims();
		setup_room_bits();
		config.c_setup_level = 323;
		}

	config.c_setup_level = REV_LEVEL;

	/* now (re-)write the config data to disk */
	fwrite((char *)&config,sizeof(struct config),1,fp);
	fclose(fp);

	title("Important Message");
	print_setup(22);
	hit_any_key();

	title("Message base file");
	created_msgmain = 0;
	fp=fopen("msgmain","r");
	if (fp==NULL) {
		cre8msg();
		created_msgmain = 1;
		}
	else {
		fclose(fp);
		if (yesno_s("Create message file?") == 1) {
			cre8msg();
			created_msgmain = 1;
			}
		}

	title("Room file");
	if (created_msgmain == 1) {
		cre8room();
		}
	else {
		fp=fopen("quickroom","r");
		if (fp==NULL) {
			cre8room();
			}
		else {
			fclose(fp);
			if (yesno_s("Create room files?")==1) cre8room();
			}
		}

	title("User file");
	fp=fopen("usersupp","r");
	if (fp==NULL) {
		cre8user();
		}
	else {
		fclose(fp);
		if (yesno_s("Create user file?")==1) cre8user();
		}

	title("Call log");
	a=0;
	fp=fopen("calllog","r");
	if (fp==NULL) {
		cre8clog();
		}
	else {
		fclose(fp);
		if (yesno_s("Create call log?")==1) cre8clog();
		}

	title("Setup finished.");
	hit_any_key();

#ifdef VISUAL_SETUP
	clear();
	refresh();
	endwin();
#endif
	exit(0);
}
