/* Citadel/UX room-oriented routines */

#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <pwd.h>
#include <setjmp.h>
#include <termio.h>
#include "citadel.h"

#define IFEXPERT if (usersupp.flags&US_EXPERT)
#define IFNEXPERT if ((usersupp.flags&US_EXPERT)==0)
#define IFAIDE if (usersupp.axlevel>=6)
#define IFNAIDE if (usersupp.axlevel<6)

long atol();
long lseek();
long finduser();
char *getenv();

extern int curr_rm;
extern int ugnum;
extern long uglsn;
extern struct quickroom quickroom;
extern struct usersupp usersupp;
extern struct fullroom fullroom;
extern struct config config;
extern char temp[];
extern char editorfile[];
extern int editor_pid;

/*
 * is_known()  -  returns nonzero if room is in user's known room list
 */
int is_known(roombuf,roomnum,userbuf)
struct quickroom *roombuf;
int roomnum;
struct usersupp *userbuf; {

	if (roomnum==1) roombuf->QRhighest=userbuf->mailnum[MAILSLOTS-1];

	if ((roombuf->QRflags & QR_INUSE)
		&& ( (roomnum!=2) || (userbuf->axlevel>=6))
		&& (roombuf->QRgen != (userbuf->forget[roomnum]) )

		&& (	((roombuf->QRflags&QR_PREFONLY)==0)
		||	((userbuf->axlevel)>=5)
		)

		&& (	((roombuf->QRflags&QR_PRIVATE)==0)
   		||	((userbuf->axlevel)>=6)
   		||	(roombuf->QRgen==(userbuf->generation[roomnum]))
   		)

		) return(1);
	else return(0);
	}


/*
 * has_newmsgs()  -  returns nonzero if room has new messages
 */
int has_newmsgs(roombuf,roomnum,userbuf)
struct quickroom *roombuf;
int roomnum;
struct usersupp *userbuf; {
	if (roombuf->QRhighest > (userbuf->lastseen[roomnum]) )
		return(1);
	else return(0);
	}

/*
 * is_zapped()  -  returns nonzero if room is on forgotten rooms list
 */
int is_zapped(roombuf,roomnum,userbuf)
struct quickroom *roombuf;
int roomnum;
struct usersupp *userbuf; {
	if (roomnum==1) roombuf->QRhighest=userbuf->mailnum[MAILSLOTS-1];
	if ((roombuf->QRflags & QR_INUSE)
		&& (roombuf->QRgen == (userbuf->forget[roomnum]) )
		&& ( (roomnum!=2) || ((userbuf->axlevel)>=6))
		&& (	((roombuf->QRflags&QR_PRIVATE)==0)
   		||	((userbuf->axlevel)>=6)
   		||	(roombuf->QRgen==(userbuf->generation[roomnum]))
   		)
		) return(1);
	else return(0);
	}


knrooms(USgiven)
struct usersupp *USgiven;
{
	int a,b,c,d,file;
	struct quickroom QRscratch;

	b=1;
	printf("\n   Rooms with unread messages:\n");
	file=eopen("./quickroom",O_RDONLY); if (file<0) return(1);
	for (a=0; a<MAXROOMS; ++a) {
		c=read(file,&QRscratch,sizeof(struct quickroom));
		if (c<1) interr(58);
		d=b+strlen(QRscratch.QRname)+3;

		if (is_known(&QRscratch,a,USgiven)
		   && has_newmsgs(&QRscratch,a,USgiven) ) {
			if (d>=usersupp.USscreenwidth) {
				printf("\n");
				b=1;
				}
		c=room_prompt(&QRscratch);
		printf("%s%c  ",QRscratch.QRname,c);
		b=b+strlen(QRscratch.QRname)+3;
		}
	} 
	if (b!=1) printf("\n");

	b=1;
	printf("\n   No unseen messages in:\n");
	lseek(file,0L,0);
	for (a=0; a<MAXROOMS; ++a) {
		c=read(file,&QRscratch,sizeof(struct quickroom));
		if (c<1) return(1);
		if (is_known(&QRscratch,a,USgiven)
		   && (!has_newmsgs(&QRscratch,a,USgiven)) ) {
		d=strlen(QRscratch.QRname)+3+b;
		if (d>=usersupp.USscreenwidth) {
			printf("\n"); b=1; }
		c=room_prompt(&QRscratch);
		printf("%s%c  ",QRscratch.QRname,c);
		b=b+strlen(QRscratch.QRname)+3;
		}
	}
	if (b!=1) printf("\n");

	close(file);
	IFNEXPERT hit_any_key();
	return(0);
}

listzrooms(USgiven)		/* list public forgotten rooms */
struct usersupp *USgiven;
{
	int a,b,c,d,file;
	struct quickroom QRscratch;

	b=1;
	printf("\n   Forgotten public rooms:\n");
	file=eopen("./quickroom",O_RDONLY); if (file<0) return(1);
	for (a=0; a<MAXROOMS; ++a) {
		c=read(file,&QRscratch,sizeof(struct quickroom));
		if (c<1) interr(58);
		d=b+strlen(QRscratch.QRname)+3;
		if (is_zapped(&QRscratch,a,USgiven)) {
			if (d>=usersupp.USscreenwidth) {
				printf("\n"); b=1;
				}
		c=room_prompt(&QRscratch);
		printf("%s%c  ",QRscratch.QRname,c);
		b=b+strlen(QRscratch.QRname)+3;
		}
	} 
	if (b!=1) printf("\n");
	close(file);
	IFNEXPERT hit_any_key();
	return(0);
}

/*
 * getuserbynumber()  -  get user by number
 *			 returns 0 if user was found
 */
int getuserbynumber(usbuf,number)
struct usersupp *usbuf;
long number; {
	FILE *fp;
	fp=fopen("./usersupp","r");
	while(fread(usbuf,sizeof(struct usersupp),1,fp)>0) {
		if (usbuf->eternal == number) {
			fclose(fp);
			return(0);
			}
		}
	return(-1);
	}

/*
 * getusernumber()  -	return (eternal) user number of a given user
 *			returns -1 if user does not exist
 */
long getusernumber(username)
char *username; {
	int fd;
	struct usersupp tempUS;
	long aa;

	fd=eopen("usersupp",O_RDONLY);
	aa=finduser(fd,username);
	read(fd,&tempUS,sizeof(struct usersupp));
	close(fd);
	if (aa==(-1L)) return(aa);
	else return(tempUS.eternal);
	}


set_room_attr(roombuf,prompt,sbit)
struct quickroom *roombuf;
char *prompt;
unsigned sbit; {
	int a;
	printf("%s [%s]? ",prompt,(((roombuf->QRflags)&sbit) ? "Yes":"No"));
	a=yesno_d(roombuf->QRflags&sbit);
	roombuf->QRflags=((roombuf->QRflags)|sbit);
	if (!a) roombuf->QRflags=(roombuf->QRflags^sbit);
	return(0);
	}

/*
 * edit_room() - edit the room structure pointed to by qrbuf
 *               returns 1 to save changes or 0 to discard changes
 */
int edit_room(qrbuf)
struct quickroom *qrbuf; {
	char ra_buf[30];
	struct usersupp tempUS;

	strprompt("Room name",quickroom.QRname,19);

	set_room_attr(qrbuf,"Private room",QR_PRIVATE);
	if (qrbuf->QRflags & QR_PRIVATE)
		set_room_attr(qrbuf,"Accessible by guessing room name",
			QR_GUESSNAME);

	if ( (qrbuf->QRflags & QR_PRIVATE)
	   && ( (qrbuf->QRflags & QR_GUESSNAME) == 0) ) {
		set_room_attr(qrbuf,"Accessible by entering a password",
			QR_PASSWORDED);
		}
	if ( (qrbuf->QRflags & QR_PRIVATE)
	   && ((qrbuf->QRflags&QR_PASSWORDED)==QR_PASSWORDED) ) {
		strprompt("Room password",qrbuf->QRpasswd,9);
		}

	if ((qrbuf->QRflags&QR_PRIVATE)==QR_PRIVATE) {
		printf("Cause current users to forget room [No] ? ");
		if (yesno_d(0)==1) {
			++qrbuf->QRgen;
			if (qrbuf->QRgen==100) qrbuf->QRgen=10; }
			}

	set_room_attr(qrbuf,"Preferred users only",QR_PREFONLY);
	set_room_attr(qrbuf,"Read-only room",QR_READONLY);
	set_room_attr(qrbuf,"Directory room",QR_DIRECTORY);
	if (qrbuf->QRflags & QR_DIRECTORY) {
		strprompt("Directory name",qrbuf->QRdirname,14);
		set_room_attr(qrbuf,"Uploading allowed",QR_UPLOAD);
		set_room_attr(qrbuf,"Downloading allowed",QR_DOWNLOAD);
		set_room_attr(qrbuf,"Visible directory",QR_VISDIR);
		}
	set_room_attr(qrbuf,"Network shared room",QR_NETWORK);
	set_room_attr(qrbuf,
		"Automatically make all messages anonymous",QR_ANONONLY);
	if ( (qrbuf->QRflags & QR_ANONONLY) == 0) {
		set_room_attr(qrbuf,
			"Ask users whether to make messages anonymous",
			QR_ANON2);
		}

RANSU:	strcpy(ra_buf,"");
	if (qrbuf->QRroomaide>=0L) {
		if (getuserbynumber(&tempUS,qrbuf->QRroomaide) == 0) 
			strcpy(ra_buf,tempUS.fullname);
		}
	strprompt("Room aide",ra_buf,29);
	if (strlen(ra_buf)==0) qrbuf->QRroomaide = (-1L);
	else {
		qrbuf->QRroomaide = getusernumber(ra_buf);
		if (qrbuf->QRroomaide < 0L) {
			printf("No such user.\n");
			goto RANSU;
			}
		}
	printf("Save changes (y/n)? ");
	return(yesno());
	}

/*
 * editthisroom()   -  .<A>ide <E>dit room
 */
editthisroom() {
	int file,a,b;
	char aaa[50];

	if (curr_rm<3) {
		printf("Can't edit this room.\n");
		return(0);
		}
	file=eopen("quickroom",O_RDWR);
	lseek(file,(long)(curr_rm*sizeof(struct quickroom)),0);
	a=read(file,&quickroom,sizeof(struct quickroom));
	if (a<1) interr(35);

	a=edit_room(&quickroom);

	if (a==0) {
		lseek(file,(long)(curr_rm*sizeof(struct quickroom)),0);
		b=read(file,&quickroom,sizeof(struct quickroom));
		if (b<1) interr(36);
		close(file); return(0);
		}
	lseek(file,(long)(curr_rm*sizeof(struct quickroom)),0);
	b=write(file,&quickroom,sizeof(struct quickroom));
	close(file);
	if (quickroom.QRflags & QR_DIRECTORY) {
		sprintf(aaa,"mkdir ./files/%s",quickroom.QRdirname);
		system(aaa);
		sprintf(aaa,"./files/%s",quickroom.QRdirname);
		chmod(aaa,0777);
		}
	sprintf(aaa,"%s%c edited by %s",
		quickroom.QRname,room_prompt(&quickroom),usersupp.fullname);
	aide_message(aaa);
	return(0);
}

ungoto() {
	if (ugnum==(-1)) return(0);
	readyerself();
	curr_rm=ugnum;
	gotocurr();
	usersupp.lastseen[curr_rm]=uglsn;
	writeyerself();
	return(0);
}

download(c)
int c;
{
	int a;
	char aaa[100],bbb[100];
	if ((quickroom.QRflags&QR_DIRECTORY)
		&&(quickroom.QRflags&QR_DOWNLOAD)) {
			newprompt("Enter filename: ",aaa,15);

	for (a=0; a<strlen(aaa); ++a)
		if ( (aaa[a]=='/') || (aaa[a]=='\\') || (aaa[a]=='>')
		     || (aaa[a]==';') || (aaa[a]=='&') ) aaa[a]='_';

	set_wtmpsupp(aaa);
	switch(c) {
		case 0: if (!struncmp(&aaa[strlen(aaa)-4],".zip",4)) 
			sprintf(bbb,"cd files/%s; SHELL=/dev/null; export SHELL; unzip -c %s |more",quickroom.QRdirname,aaa);
			else sprintf(bbb,"cd files/%s; SHELL=/dev/null; export SHELL; more <%s",quickroom.QRdirname,aaa);
			system(bbb);
			break;
		case 1:	sprintf(bbb,"cd files/%s; exec sx %s",
				quickroom.QRdirname,aaa);
			system(bbb);
			break;
		case 2:	signal(SIGQUIT,SIG_DFL);
			sttybbs(SB_YES_INTR);
			sprintf(bbb,"cd files/%s; exec cat <%s",
				quickroom.QRdirname,aaa);
			system(bbb);
			sttybbs(SB_NO_INTR);
			unlink("core");	/* just in case the core was dumped */
			break;
		case 3:	sprintf(bbb,"cd files/%s; exec sb %s",
				quickroom.QRdirname,aaa);
			system(bbb);
			break;
		case 4:	sprintf(bbb,"cd files/%s; exec sz %s",
				quickroom.QRdirname,aaa);
			system(bbb);
			break;
		}
	putc(7,stdout);
	}
	else
		printf("Not in this room.\n");
	return(0);
}

roomdir() {
	char aaa[100];
	if ((quickroom.QRflags&QR_DIRECTORY)
	   &&(quickroom.QRflags&QR_VISDIR)) {
		sprintf(aaa,"./files/%s",quickroom.QRdirname);
		printf("Directory of %s!%s/%s\n",NODENAME,BBSDIR,&aaa[2]);
		directory(aaa);
		}
	else
		printf("Not in this room.\n");
	return(0);
}

invite() {	/* add a user to a private or excludable room */
	char aaa[31],bbb[100];
	int file;
	long aa;
	struct usersupp USscratch;
	if ((quickroom.QRflags&QR_PRIVATE)==0) {
		printf("Not a private room.\n");
		return(0);
		}
	newprompt("Name of user? ",aaa,30);
	if (aaa[0]==0) return(0);
	file=eopen("usersupp",O_RDWR);
	aa=finduser(file,aaa);
	if (aa!=(-1L)) {
		read(file,&USscratch,sizeof(struct usersupp));
		lseek(file,aa,0);
		USscratch.generation[curr_rm]=quickroom.QRgen;
		USscratch.forget[curr_rm]=(-1);
		write(file,&USscratch,sizeof(struct usersupp));

		sprintf(bbb,"%s invited to %s%c by %s",
			aaa,
			quickroom.QRname,room_prompt(&quickroom),
			usersupp.fullname);
		aide_message(bbb);

		}
	else	printf("No such user.\n");
	close(file);
	return(0);

}

kickout() {	/* kick a user out of a room */
	int file;
	char aaa[31],bbb[100];
	long aa;
	struct usersupp USscratch;
	if ((quickroom.QRflags&QR_PRIVATE)==0) {
		printf("Note: This is not a private room.\n");
		printf("Kicking out users will only have the same effect\n");
		printf("as if they <Z>apped the room.\n");
		}
	newprompt("Name of user? ",aaa,30);
	file=eopen("usersupp",O_RDWR);
	aa=finduser(file,aaa);
	if (aa!=(-1L)) {
		read(file,&USscratch,sizeof(struct usersupp));
		lseek(file,aa,0);
		USscratch.generation[curr_rm]=(-1);
		USscratch.forget[curr_rm] = quickroom.QRgen;
		write(file,&USscratch,sizeof(struct usersupp));

		sprintf(bbb,"%s kicked out of %s%c by %s",
			aaa,
			quickroom.QRname,room_prompt(&quickroom),
			usersupp.fullname);
		aide_message(bbb);

		}
	else	printf("No such user.\n");
	close(file);
	return(0);
}

killroom() {	/* aide command: kill the current room */
	int file;
	long aa;
	char aaa[100];
	if (curr_rm<3) { printf("Can't kill this room.\n"); return(0); }
	printf("Are you sure you want to kill this room? ");
	if (yesno()==0) return(0);
	file=eopen("quickroom",O_RDWR);
	aa=(long)curr_rm*sizeof(struct quickroom);
	lseek(file,aa,0);
	quickroom.QRflags=0;
	write(file,&quickroom,sizeof(struct quickroom));
	close(file);
	sprintf(aaa,"%s%c killed by %s",
		quickroom.QRname,room_prompt(&quickroom),usersupp.fullname);
	aide_message(aaa);
	curr_rm=0;		/* then goto the lobby */
	gotocurr();
	return(0);
}

forget() {	/* forget the current room */
	if (curr_rm<3) {
		printf("Cannot forget this room.\n");
		return(0);
		}
	IFAIDE { printf("Aides cannot forget rooms.\n"); return(0); }
	printf("Are you sure you want to forget this room? ");
	if (yesno()==0) return(0);
	readyerself();
	usersupp.forget[curr_rm]=quickroom.QRgen;
	usersupp.generation[curr_rm]=(-1);
	writeyerself();
	curr_rm=0;		/* then goto the lobby */
	gotocurr();
	return(0);
}

entroom() {
	int a,b,c,d,file;
	char aaa[100],bbb[100];
	long bb,cc;
	struct quickroom QRscratch;

	if (usersupp.axlevel<3) {
		printf("You need higher access to create rooms.\n");
		return(0);
		}

	newprompt("Name for new room? ",aaa,19);
	if (strlen(aaa)==0) return(0);
	aaa[19]=0;
	file=eopen("quickroom",O_RDONLY);
	b=0;
	for (a=0; a<MAXROOMS; ++a) {
		c=read(file,&QRscratch,sizeof(struct quickroom));
		if (c<1) interr(63);
		if ( (QRscratch.QRflags & QR_INUSE)
			&& (!strucmp(QRscratch.QRname,aaa)) ) b=1; }
	close(file);
	if (b==1) {
		printf("'%s' already exists.\n",aaa);
		return(0); }
	bb=(-1L);	
	file=eopen("quickroom",O_RDONLY);
	for (a=0; a<MAXROOMS; ++a) {
		cc=lseek(file,0L,1);
		c=read(file,&QRscratch,sizeof(struct quickroom));
		if (c<1) interr(65);
		if (((QRscratch.QRflags&QR_INUSE)==0)&&(bb==(-1L))) bb=cc;
		}
	close(file);
	if (bb==(-1L)) {
		printf("No room space available.\n");
		return(0);
		}
	IFNEXPERT {
		if(isansi())
			formout("messages/roomaccess.ansi");
		else
			formout("messages/roomaccess");
		}
	do {
		printf("<?>Help\n<1>Public room\n<2>Guess-name room\n");
		printf("<3>Passworded room\n<4>Invitation-only room\n");
		printf("Enter room type: ");
		do {
			b=inkey();
			} while (((b<'1')||(b>'4')) && (b!='?'));
		if (b=='?') {
			printf("?\n");
			if(isansi())
				formout("messages/roomaccess.ansi");
			else
				formout("messages/roomaccess");
			}
		} while ((b<'1')||(b>'4'));
	b=b-48;
	if (b==3) {
		strprompt("Enter a room password: ",bbb,9);
		}
	printf("%d\n\042%s\042, a",b,aaa);
	if (b==1) printf(" public room.");
	if (b==2) printf(" guess-name room.");
	if (b==3) printf(" passworded room, password: %s",bbb);
	if (b==4) printf("n invitation-only room.");
	printf("\nInstall it? (y/n) : ");
	a=yesno();
	if (a==0) return(0);
	curr_rm=(int)(bb/sizeof(struct quickroom)); 
	file=eopen("quickroom",O_RDWR);
	lseek(file,bb,0);
	d=read(file,&quickroom,sizeof(struct quickroom));
	if (d<1) interr(67);
	strcpy(quickroom.QRname,aaa);
	strcpy(quickroom.QRpasswd,"");
	if (b==3) strcpy(quickroom.QRpasswd,bbb);
	quickroom.QRroomaide=(-1L);
	quickroom.QRhighest=0L;
	++quickroom.QRgen; if (quickroom.QRgen==100) quickroom.QRgen=10;
	quickroom.QRflags=QR_INUSE;
	if (b>1) quickroom.QRflags=(quickroom.QRflags|QR_PRIVATE);
	if (b==2) quickroom.QRflags=(quickroom.QRflags|QR_GUESSNAME);
	if (b==3) quickroom.QRflags=(quickroom.QRflags|QR_PASSWORDED);
	if ((b>2)&&(CREATAIDE==1)) quickroom.QRroomaide=usersupp.eternal;
	lseek(file,bb,0);
	write(file,&quickroom,sizeof(struct quickroom));
	close(file);

	/* Initialize a blank fullroom structure */
	for (a=0; a<MSGSPERRM; ++a) {
		fullroom.FRnum[a]=0L;
		fullroom.FRpos[a]=0L;
		}

	sprintf(aaa,"./rooms/fullrm%d",curr_rm);
	file=eopen(aaa,O_RDWR);
	write(file,&fullroom,sizeof(struct fullroom));
	close(file);

	gotocurr();				/* goto the new room */

	/* post a message in Aide> describing the new room */
	strcpy(aaa,quickroom.QRname); strcat(aaa,"> created by ");
	strcat(aaa,usersupp.fullname);
	if (quickroom.QRflags&QR_PRIVATE) strcat(aaa," [private]");
	if (quickroom.QRflags&QR_GUESSNAME) strcat(aaa,"[guessname] ");
	if (quickroom.QRflags&QR_PASSWORDED) {
		strcat(aaa,"\n Password: ");
		strcat(aaa,quickroom.QRpasswd);
		}
	aide_message(aaa);

	sprintf(aaa,"./info/%d",curr_rm);	/* delete old info file */
	unlink(aaa);
	
	return(0);
}

gotocurr() /* goto room currently in global variable curr_rm */
{
	int d; char aaa[100]; long iptr;
	FILE *fp;
	fp=fopen("quickroom","r"); if (fp==NULL) interr(74);
		fseek(fp,(long)(curr_rm*sizeof(struct quickroom)),0);
		d=fread((char *)&quickroom,sizeof(struct quickroom),1,fp);
		if (d<1) interr(75);
	fclose(fp);
	if (curr_rm==1) { readmail(); return(0); }
	sprintf(aaa,"./rooms/fullrm%d",curr_rm);
	fp=fopen(aaa,"r"); if (fp==NULL) interr(76);
	fread((char *)&fullroom,sizeof(struct fullroom),1,fp);
	fclose(fp);
	readyerself();
	usersupp.forget[curr_rm]=(-1);
	usersupp.generation[curr_rm]=quickroom.QRgen;
	writeyerself();
	if (quickroom.QRinfo > usersupp.lastseen[curr_rm]) readinfo();
	return(0);
}

whoknows() {
	struct usersupp temp;
	int file;
	file=eopen("usersupp",O_RDONLY);
	while(read(file,&temp,sizeof(struct usersupp))>0)
		if ((quickroom.QRflags & QR_INUSE)
			&& ( (curr_rm!=2) || (temp.axlevel>=6) )
			&& (quickroom.QRgen != (temp.forget[curr_rm]) )

			&& (	((quickroom.QRflags&QR_PREFONLY)==0)
			||	(temp.axlevel>=5)
			)

			&& (	((quickroom.QRflags&QR_PRIVATE)==0)
   			||	(temp.axlevel>=6)
   			||	(quickroom.QRgen==(temp.generation[curr_rm]))
   			)

		) printf("%s\n",temp.fullname);
	close(file);
	return(0);
}

enterinfo() {		/* edit info file for current room */
	FILE *fp;
	char infofilename[32];
	char cmd[64];
	int b,editor_exit;
	struct quickroom qrbuf;

	sprintf(infofilename,"./info/%d",curr_rm);

	if (getenv("EDITOR")!=NULL) {
		editor_pid=fork();
		if (editor_pid==0) {
			setuid(getuid()); /* use real uid & gid */
			setgid(getgid());
			sttybbs(SB_RESTORE);
			execlp(getenv("EDITOR"),getenv("EDITOR"),
				infofilename,NULL);
			exit(1);
			}
		if (editor_pid>0) do {
			editor_exit = 0;
			b=wait(&editor_exit);
			} while((b!=editor_pid)&&(b>=0));
		editor_pid = (-1);
		sttybbs(0);
		}
	else {
		printf("Entering info file for this room.  ");
		printf("Press return twice when finished.\n");
		unlink(infofilename);
		fp=fopen(infofilename,"w");
		fclose(fp);
		fp=fopen(infofilename,"r+");
		citedit(fp,0);
		fclose(fp);
		}

	/* now update the room index so people will see our new info */
	lock_msgmain();		/* lock so no one steps on us */
	fp=fopen("quickroom","r+");
	fseek(fp,((long)curr_rm*(long)sizeof(struct quickroom)),0);
	fread((char *)&qrbuf,sizeof(struct quickroom),1,fp);
	qrbuf.QRinfo = qrbuf.QRhighest + 1L;
	fseek(fp,((long)curr_rm*(long)sizeof(struct quickroom)),0);
	fwrite((char *)&qrbuf,sizeof(struct quickroom),1,fp);
	fclose(fp);
	unlock_msgmain();

	return(0);
	}

readinfo() {		/* read info file for current room */
	char filename[64];
	FILE *fp;
	char b;

	sprintf(filename,"./info/%d",curr_rm);
	fp=fopen(filename,"r");
	if (fp==NULL) return(1);

	fmout(usersupp.USscreenwidth,fp,
		((usersupp.flags & US_PAGINATOR) ? 1 : 0),
		usersupp.USscreenheight);
	fclose(fp);
	return(0);
	}
