[alt.sources] cit301.part7

eric@sactoh0.SAC.CA.US (Eric J. Nihill) (11/26/90)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	source
# This archive created: Sun Nov 25 12:59:50 1990
export PATH; PATH=/bin:/usr/bin:$PATH
if test ! -d 'source'
then
	echo shar: "creating directory 'source'"
	mkdir 'source'
fi
echo shar: "entering directory 'source'"
cd 'source'
echo shar: "extracting 'chat.c'" '(8218 characters)'
if test -f 'chat.c'
then
	echo shar: "will not over-write existing file 'chat.c'"
else
cat << \SHAR_EOF > 'chat.c'
 /* chat v1.3
 * 
 */

#define CONSOLE "/dev/console"

#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <termio.h>
#include <signal.h>
#include <utmp.h>
#include "citadel.h"

int console;
char online;
char temp[20];

long lseek();
long atol();


int (*slamcarrier())() {
	if (online==1) write(console,"*off line*  Press ctrl-c to exit\r\n",34);
	unlink("/tmp/chat.online");
	exit(0);
}

main(argc,argv)
int argc;
char *argv[];
{
	int a,b,c,d,e;
	int file;
	char aaa[100];
	struct termio term,saveio;
	FILE *fp,*arc;

	chdir(BBSDIR);

	if (!strncmp(ttyname(0),CONSOLE,strlen(CONSOLE))) {
		conchat(argc,argv);
		exit(0);
		}	

	if (isclog()==0) {
		printf("No one else is online.\n");
		exit(0);
		}

	online=0;
	ioctl(0,TCGETA,&saveio);
	ioctl(0,TCGETA,&term);

	term.c_iflag=3366;
	term.c_oflag=6149;
	term.c_lflag=59;
	term.c_line=0;
	term.c_cc[0]=127;
	term.c_cc[1]=28;
	term.c_cc[2]=8;
	term.c_cc[3]=24;
	term.c_cc[4]=4;
	term.c_cc[5]=255;
	term.c_cc[6]=0;
	term.c_cc[7]=0;
	term.c_lflag=0;
	term.c_iflag=ISTRIP;
	ioctl(0,TCSETA,&term);

	fp=fopen("/tmp/chat.name","w");
	fprintf(fp,"%s\n",ttyname(0));
	fclose(fp);

	console=open(CONSOLE,O_WRONLY);
	if (console<0) {
		fprintf(stderr,"Can't access %s\r\n",CONSOLE);
		goto END;
		}

	fprintf(stderr,"Paging %s...\r\n",CONSOLE);
	for (a=0; a<4; ++a) {
		b=7;
		write(console,&b,1);
		write(1,&b,1);
		sleep(1);
		}
	printf("Chat mode - press ctrl-c to exit if\r\n");
	printf("no one answers in a minute or so...\r\n");

A:	b=0; read(0,&b,1);			/* read a character */
	if (b==3) {
		printf("Exiting chat mode\r\n");
		goto END;
		}
	if (online==1) {
		c=10;
		write(console,&b,1); write(1,&b,1);
		putc(b,arc); fflush(arc);
		if (b==13) { write(console,&c,1); write(1,&c,1); }
		goto A;
		}
	/* not online, check for flag file */
	file=open("/tmp/chat.online",O_RDONLY); close(file);
	if (file>(-1)) {
		online=1;
		unlink("/tmp/chat.online");
		arc=fopen("/tmp/chat.fifo","w+");
		sprintf(aaa,"Online with user: %s\r\n",argv[1]);
		fprintf(arc,"%s",aaa);
		fflush(arc);
		write(console,aaa,strlen(aaa)); aaa[0]=0;
		signal(SIGHUP,(*slamcarrier));
		write(console,&b,1); write(2,&b,1);
		putc(b,arc); fflush(fp);
		}
	goto A;

END:	unlink("/tmp/chat.online"); unlink("/tmp/chat.name");
	if (online==1)
		write(console,"*off line*  Press ctrl-c to exit\r\n",34);
	close(console);
	ioctl(0,TCSETA,&saveio);
	unlink("/tmp/chat.fifo");
	exit(0);
}

conchat(argc,argv)
int argc;
char *argv[];
{
	int a,b,c,d,e;
	int console,file,file2;
	char online;
	char aaa[100],bbb[100];
	struct termio term,saveio;
	FILE *arc;

	online=0;
	ioctl(0,TCGETA,&saveio);
	ioctl(0,TCGETA,&term);

	term.c_iflag=3366;
	term.c_oflag=6149;
	term.c_lflag=59;
	term.c_line=0;
	term.c_cc[0]=127;
	term.c_cc[1]=28;
	term.c_cc[2]=8;
	term.c_cc[3]=24;
	term.c_cc[4]=4;
	term.c_cc[5]=255;
	term.c_cc[6]=0;
	term.c_cc[7]=0;
	term.c_lflag=0;
	term.c_iflag=ISTRIP;
	ioctl(0,TCSETA,&term);

	file=open("/tmp/chat.name",O_RDONLY);
	if (file<0) {
 		printf("No one has requested a chat.\r\n");
		goto END;
		}

system(
"/etc/mknod /tmp/chat.fifo p; nohup aidepost </tmp/chat.fifo 2>/dev/null &");
	if (fork()==0) aidepost();
	read(file,bbb,30); close(file); unlink("/tmp/chat.name");
	for (a=0; a<strlen(bbb); ++a) if (bbb[a]==10) bbb[a]=0;
	printf("Connected to: %s\r\n",bbb);
	file=open(bbb,O_WRONLY);
	if (file<0) {
		printf("Can't open %s\r\n",bbb);
		goto END;
		}
	file2=creat("/tmp/chat.online",0666); close(file2);
	sprintf(aaa,"\n*answer* - Online with: %s\r\n",argv[1]);
	write(file,aaa,strlen(aaa));

	arc=fopen("/tmp/chat.fifo","w+");
	fprintf(arc,"%s",aaa); aaa[0]=0;
	fflush(arc);
	unlink("nohup.out");

A:	b=0; read(0,&b,1);
	if (b==3) {
		write(file,"*off line*  Press ctrl-c to exit\r\n",34);
		write(file,"Press ctrl-c to return to the BBS.\r\n",36);
		close(file);
		fprintf(arc,"\n*out*\n");
		fclose(arc);
		goto END;
		}
	c=10;
	write(file,&b,1); write(1,&b,1);
	putc(b,arc);
	if (b==13) {
		write(file,&c,1);
		write(1,&c,1);
		}
	fflush(arc);
	goto A;

END:
	ioctl(0,TCSETA,&saveio);
	exit(0);
}

isclog() {
	struct utmp utmp;
	int file,a;
	a=0;
	file=open("/etc/utmp",O_RDONLY);
	while ((read(file,&utmp,sizeof(struct utmp)))) {
	 if ((utmp.ut_name[0]!=0)&&(!strcmp(utmp.ut_line,"console"))) a=1;
	}
	close(file);
	return(a);
}

strucmp(st1,st2)
char st1[],st2[];
{
	int a;
	char aaa[100],bbb[100];
	for (a=0; a<=strlen(st1); ++a) aaa[a]=tolower(st1[a]);
	for (a=0; a<=strlen(st2); ++a) bbb[a]=tolower(st2[a]);
	a=strcmp(aaa,bbb);
	return(a);
}

send_message(filename,retbuf)	/* send a message to the master file */
char filename[];		/* tempfilename of proper message */
struct smreturn *retbuf;	/* return information */
{

int file,a,b,c,d,e,file2;
long aa,bb,cc,dd,ee,templen,hibytes,origpos;
char aaa[100],mid[30];
struct msgmain msgmain;


	file=open("/usr/bbs/MMstructure",O_RDWR);
	if (file<0) exit(13);
PWMINS:
	a=read(file,&msgmain,sizeof(struct msgmain));
	if (a<1) exit(14);
	if (msgmain.MMflags & MM_BUSY) {
					 lseek(file,0L,0); goto PWMINS; }

	lseek(file,0L,0);
	msgmain.MMflags=(msgmain.MMflags|MM_BUSY);
	a=write(file,&msgmain,sizeof(struct msgmain)); if (a<1) exit(16);
	close(file);
	origpos=msgmain.MMcurpos;
	++msgmain.MMhighest;
	sprintf(mid,"I%ld",msgmain.MMhighest);
/* measure the message */
file=open(filename,O_RDONLY); if (file<0) sprintf(stderr,"aidepost: error\n");
templen=lseek(file,0L,2);
close(file);
templen=templen+(long)strlen(mid);
++templen;

/* check for FF bytes */
hibytes=0L;
file=open("/usr/bbs/msgmain",O_RDWR);
if (file<0) fprintf(stderr,"aidepost: can't open msgmain\n");
bb=lseek(file,msgmain.MMcurpos,0);

cc=lseek(file,0L,1);
for (bb=0L; bb<templen; ++bb) {
	if (cc>=MM_FILELEN) cc=lseek(file,0L,0);
	c=0; read(file,&c,1); ++cc;
	if (c>127) ++hibytes;		/* bump count if hi bit set */
	}

msgmain.MMlowest=msgmain.MMlowest+hibytes;

cc=lseek(file,msgmain.MMcurpos,0);

file2=open(filename,O_RDONLY); if (file2<0) exit(19);
cc=lseek(file,0L,1);
read(file2,&b,2);
write(file,&b,2);
read(file2,&b,1);
write(file,&b,1);
write(file,mid,(strlen(mid)+1));
for (bb=0L; bb<templen; ++bb) {
	if (((long)cc)>=((long)MM_FILELEN)) cc=lseek(file,0L,0);
	read(file2,&b,1); 
	write(file,&b,1); ++cc;
	}
msgmain.MMcurpos=lseek(file,0L,1);
close(file2);	/* done with temp file */
close(file);	/* done with master file */


/* now update the message structure */

msgmain.MMflags=msgmain.MMflags & ~MM_BUSY;

file=open("/usr/bbs/MMstructure",O_RDWR); if (file<0) printf("20!!!\n");
a=write(file,&msgmain,sizeof(struct msgmain)); if (a<1) printf("21!!!\n");
close(file);
retbuf->smnumber=msgmain.MMhighest;
retbuf->smpos=origpos;



return(0);

}

make_message(filename)
char filename[];	/* temporary file name */
{ 
	FILE *fp,*arc;
	int a,b,c,old;
	long aa,bb,cc,beg,now;
	char aaa[100],bbb[100]; 
	time(&now);
	fp=fopen(filename,"wb"); if (fp==NULL) exit(22);
	arc=fopen("/tmp/chat.fifo","r");
	putc(255,fp);
	putc(MES_NORMAL,fp);
	putc(1,fp);
	fprintf(fp,"T%ld",now); putc(0,fp);
	fprintf(fp,"AChat Archive"); putc(0,fp);
	fprintf(fp,"OAide"); putc(0,fp);
	fprintf(fp,"N%s",NODENAME); putc(0,fp);
	putc('M',fp);
	while ((a=getc(arc))>0) {
		putc(a,fp);
		}
MEFIN:	putc(0,fp);
	fclose(fp);
	fclose(arc);
	unlink("/tmp/chat.fifo");
	return(0);

}

aidepost() {
	int file,a,b;
	long aa;
	char aaa[100];
	struct smreturn mybuffer;
	struct quickroom quickroom;
	struct fullroom fullroom;

	make_message(temp);
	send_message(temp,&mybuffer);
	unlink(temp);

	file=open("./quickroom",O_RDWR);
	b=2;
	lseek(file,(long)(b*sizeof(struct quickroom)),0);
	read(file,&quickroom,sizeof(struct quickroom));
	quickroom.QRhighest=mybuffer.smnumber;
	lseek(file,(long)(b*sizeof(struct quickroom)),0);
	write(file,&quickroom,sizeof(struct quickroom));
	close(file);

	sprintf(aaa,"./rooms/fullrm%d",b);
	file=open(aaa,O_RDWR);
	read(file,&fullroom,sizeof(struct fullroom));
	for (a=0; a<(MSGSPERRM-1); ++a) {
		fullroom.FRnum[a]=fullroom.FRnum[a+1];
		fullroom.FRpos[a]=fullroom.FRpos[a+1];
		}
	fullroom.FRnum[MSGSPERRM-1]=mybuffer.smnumber;
	fullroom.FRpos[MSGSPERRM-1]=mybuffer.smpos;
	lseek(file,0L,0);
	write(file,&fullroom,sizeof(struct fullroom));
	close(file);
	exit(0);
}
SHAR_EOF
fi
echo shar: "extracting 'citadel.c'" '(26829 characters)'
if test -f 'citadel.c'
then
	echo shar: "will not over-write existing file 'citadel.c'"
else
cat << \SHAR_EOF > 'citadel.c'
/*
 * Citadel/UX  
 *
 * citadel.c - Main source file.
 *
 */

#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <pwd.h>
#include <setjmp.h>
#include <termio.h>
#define CITADEL_C
#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)
struct passwd *getpwuid();
struct passwd *getpwnam();
char *getenv();
long atol();
long lseek();
long finduser();

char fullname[100];
struct usersupp usersupp;		/* Logged-in user's user supp */
struct quickroom quickroom,QRscratch;	/* Current room and scratch   */
struct fullroom fullroom;		/* Current room               */
struct smreturn smreturn;		/* For returning message numbers */
struct msgmain msgmain;			/* Global message info           */
struct passwd *passwd;
int curr_rm;				/* Room NUMBER of current room.  */
int hold_rm;				/* Temporary room number */
					/* 0=Lobby 1=Mail 2=Aide 3-up=other */
char newnow;
char upass;				/* Nonzero if pw is managed by UNIX */
long yourpos;				/* position of your usersupp record */
char temp[50];				/* Name of general temp file */
int twitroom;				/* Room num of TWIT room (if enabled) */
struct termio stty0;			/* holds old termio settings */
jmp_buf nextbuf;
int ugnum; long uglsn;			/* holds <u>ngoto info */

int (*backnext())() {
	signal(SIGINT,SIG_IGN);
	signal(SIGQUIT,SIG_IGN);
	longjmp(nextbuf,1);
	}

int (*backstop())() {
	signal(SIGQUIT,SIG_IGN);
	signal(SIGINT,SIG_IGN);
	longjmp(nextbuf,2);
	}

int (*sleeping())() {
	struct calllog rtmp;
	printf("Sleeping? Call again.\n");
	strcpy(rtmp.CLfullname,ttyname(0));
	rtmp.CLflags=CL_SLEEPING;
	rec_log(&rtmp);
	logoff(1); }

int (*dropcarr())() {
	struct calllog rtmp;
	strcpy(rtmp.CLfullname,ttyname(0));
	rtmp.CLflags=CL_DROPCARR;
	rec_log(&rtmp);
	logoff(SIGHUP);
}

inkey() {
	int a;
	signal(SIGALRM,(*sleeping));
	alarm(SLEEPING);
	a=getc(stdin); if (a==127) a=8;
	signal(SIGALRM,SIG_IGN);
	return(a);
	}

setsane() {
	ioctl(0,TCSETA,&stty0);
	}

char *months[12]={
	"Jan","Feb","Mar","Apr","May","Jun",
	"Jul","Aug","Sep","Oct","Nov","Dec" };

char *axdefs[7]={
	"Marked for deletion",
	"New User",
	"Problem User",
	"Local User",
	"Network User",
	"Preferred User",
	"Aide"
	};

formout(name) /* display a file using the formatter */
char name[]; {
char aaa[100]; int a;
	strcpy(aaa,name);
	for (a=0; a<strlen(aaa); ++a) aaa[a]=tolower(aaa[a]);
	if (setjmp(nextbuf)!=0) { sttybbs(0); return(1); }
	signal(SIGINT,(*backnext));
	signal(SIGQUIT,(*backstop));
	sttybbs(1);
	fmout(usersupp.screenwidth,aaa);
	sttybbs(0);
	return(0);
}

userlist() /* prints the userlist */ {
	sttybbs(1);
	system("userlist");
	sttybbs(0);
	}

readmail()
{
	int a;
	readyerself();
	for (a=0; a<MSGSPERRM; ++a) {
		fullroom.FRnum[a]=0L;
		fullroom.FRpos[a]=0L; }
	for (a=0; a<MAILSLOTS; ++a) {
		fullroom.FRnum[a+(MSGSPERRM-MAILSLOTS)]=usersupp.mailnum[a];
		fullroom.FRpos[a+(MSGSPERRM-MAILSLOTS)]=usersupp.mailpos[a]; }
	return(0);
	}

writemail()
{
	int a;
	readyerself();
	for (a=0; a<MAILSLOTS; ++a) {
		usersupp.mailnum[a]=fullroom.FRnum[a+(MSGSPERRM-MAILSLOTS)];
		usersupp.mailpos[a]=fullroom.FRpos[a+(MSGSPERRM-MAILSLOTS)]; }
	writeyerself();
	return(0);
	}

readyerself()
{
	int file;
	file=eopen("usersupp",O_RDONLY);
	lseek(file,yourpos,0);
	do {
	       read(file,&usersupp,sizeof(struct usersupp));
	    if (strucmp(fullname,usersupp.fullname)) finduser(file,fullname);
		} while(strucmp(fullname,usersupp.fullname));
	close(file);
	return(0);
	}

writeyerself()
{
	int file;
	struct usersupp me;
	file=eopen("usersupp",O_RDWR);
	lseek(file,yourpos,0);
	read(file,&me,sizeof(struct usersupp));
if (me.eternal!=usersupp.eternal) yourpos=finduser(file,usersupp.fullname);
	lseek(file,yourpos,0);
	write(file,&usersupp,sizeof(struct usersupp));
	close(file);
	return(0);
	}

main()
{
int a,b,c,d,e,f,file,file2;
long aa,cc;
char buf[300];
char aaa[100],bbb[100],ccc[100],eee[100];	/* general purpose variables */
char skipping[MAXROOMS];
struct usersupp tempUS;
struct calllog calllog;
struct wtmpsupp wtmpsupp;
char mtsflag,twit;

chdir(BBSDIR);			/* go to the right directory */
ioctl(0,TCGETA,&stty0);		/* Store the old terminal parameters and */
sttybbs(0);			/* install the new ones                  */
signal(SIGINT,SIG_IGN);
signal(SIGQUIT,SIG_IGN);
signal(SIGHUP,(*dropcarr));	/* Cleanup gracefully if carrier is dropped */
printf("\nCitadel/UX release 3.01-1d\n");
twit=0;				/* By default, user is not a problem user */
usersupp.screenwidth=80;
formout("messages/hello");	/* print the opening greeting */

log_carr();
a=getuid();
passwd=(struct passwd *)getpwuid(a);
strcpy(fullname,passwd->pw_gecos);
upass=1; if (a==BBSUID) upass=0;

twitroom=(-1);
GSTA:	newnow=0; if (upass==0) {		/* guest account - find out */
GSTB:		printf("Enter your name: ");	/* who the user is          */
		getline(fullname,29);
		strproc(fullname);
		if (!strucmp(fullname,"bbs")) goto GSTB;
		if (!strucmp(fullname,"new")) goto GSTB;
		if (!strucmp(fullname,"off")) goto TERMINATE;
		if (strlen(fullname)==0) goto GSTB;
		}

			/* get the usersupp data for guest account */
	file=eopen("usersupp",O_RDONLY);
	yourpos=finduser(file,fullname);
	if (yourpos==(-1L)) { close(file); goto NEWUSR; }
	read(file,&usersupp,sizeof(struct usersupp));
	close(file);
	goto USOK;

NEWUSR:	if (upass==0) {
		printf("No record. Enter as new user? ");
		if (yesno()==0) goto GSTA;
		}

	/* Initialize a new account */
	usersupp.USuid=getuid();
	strcpy(usersupp.fullname,fullname);
	for (a=0; a<MAXROOMS; ++a) {	usersupp.lastseen[a]=0L;
					usersupp.generation[a]=(-1);
					usersupp.forget[a]=(-1); }
	for (a=0; a<MAILSLOTS; ++a) {	usersupp.mailnum[a]=0L;
					usersupp.mailpos[a]=0L; }
	usersupp.flags=0;
	usersupp.timescalled=0;
	usersupp.posted=0;
	usersupp.axlevel=INITAX;
	time(&aa);
	usersupp.lastcall=aa;
	getusinfo(&usersupp);
	
	if (upass==0) {
		IFNEXPERT formout("messages/changepw");
		printf("Please enter a password: ");
		getline(usersupp.password,19);
		strproc(usersupp.password);
		pwcrypt(usersupp.password,PWCRYPT);
		newnow=1;
		}

	file=eopen("eternal",O_RDWR);	/* get a new user number */
	read(file,&aa,4);
	usersupp.eternal=aa;
	aa=aa+1L;
	lseek(file,0L,0);
	write(file,&aa,4);
	close(file);

	formout("messages/newuser");
	printf("  (setting up an account. please wait)\n");
						/* Add user to the        */
	file=eopen("usersupp",O_RDONLY);	/* usersupp file, keeping */
	file2=creat("/tmp/usersupp",0666);	/* the file in            */
	b=0;					/* alphabetical order     */
	do {
		a=read(file,&tempUS,sizeof(struct usersupp));
		if ( (strucmp(usersupp.fullname,tempUS.fullname)<0) ||(a<1)) {
			if (b==0)write(file2,&usersupp,sizeof(struct usersupp));
		 	b=1;
			}
		if (a>0) write(file2,&tempUS,sizeof(struct usersupp));
		} while(a>0);
	yourpos=finduser(file2,usersupp.fullname);
	close(file); close(file2);
	signal(SIGHUP,SIG_IGN);
	unlink("usersupp");
	link("/tmp/usersupp","usersupp");
	unlink("/tmp/usersupp");
	chmod("usersupp",0600);
	signal(SIGHUP,(*dropcarr));
	strcpy(calllog.CLfullname,usersupp.fullname);
	calllog.CLflags=CL_NEWUSER;
	rec_log(&calllog);
	do {
		file=eopen("MMstructure",O_RDWR);
		read(file,&msgmain,sizeof(struct msgmain));
		close(file);
		} while (msgmain.MMflags&MM_BUSY);
	msgmain.MMflags=(msgmain.MMflags|MM_VALID);
	file=eopen("MMstructure",O_WRONLY);
	write(file,&msgmain,sizeof(struct msgmain));
	close(file);

USOK:	/* make sure that if it's a shell user, they log in from the shell */
	if (upass==0) if (usersupp.USuid!=BBSUID) {
	printf("Please log in by running Citadel from the shell.\n");
	printf("(press any key to continue)\n");
	inkey();
	logoff(0);
	}

if ((upass==0)&&(newnow==0)) {
	printf("\rPlease enter your password: ");
	getline(eee,-19); strproc(eee);
	pwcrypt(usersupp.password,PWCRYPT);
	if (!strucmp(eee,usersupp.password)) {
		pwcrypt(usersupp.password,PWCRYPT);
		goto PWOK;
		}
	printf("Wrong password...\n");
	strcpy(calllog.CLfullname,usersupp.fullname);
	calllog.CLflags=CL_BADPW;
	rec_log(&calllog);
	goto GSTA;
	}

/* A room's generation number changes each time it is recycled. Users are kept
 * out of private rooms or forget rooms by matching the generation numbers. To
 * avoid an accidental matchup, unmatched numbers are set to -1 here.
 */
PWOK:	readyerself();
	strcpy(fullname,usersupp.fullname);
	usersupp.USuid=getuid();
	++usersupp.timescalled;
	time(&aa);
	usersupp.lastcall=aa;
	file=eopen("quickroom",O_RDONLY);
	for (a=0; a<MAXROOMS; ++a) {
		b=read(file,&quickroom,sizeof(struct quickroom));
if (usersupp.generation[a] != quickroom.QRgen) usersupp.generation[a]=(-1);
if (usersupp.forget[a] != quickroom.QRgen) usersupp.forget[a]=(-1);
		}
	close(file);
	if (usersupp.axlevel==2) twit=1;
	if (twit==1) usersupp.axlevel=2;
	writeyerself();
	ugnum=(-1);

	strcpy(calllog.CLfullname,usersupp.fullname);
	time(&calllog.CLtime);
	calllog.CLflags=CL_LOGIN;
	rec_log(&calllog);

	printf("%s\nAccess level: %s\nUser #%ld / Call #%d\n",
		usersupp.fullname,axdefs[usersupp.axlevel],
		usersupp.eternal,usersupp.timescalled);
if ((REGISCALL!=0)&&((usersupp.flags&US_REGIS)==0)
		&&(usersupp.timescalled>=REGISCALL)) {
	printf("*** Registration is requested.\n");
	formout("messages/register");
	a=entregis(usersupp.eternal);
	if (a==0) {
		readyerself();
		usersupp.flags=(usersupp.flags|US_REGIS);
		writeyerself();
		}
	}

	IFAIDE {
		file=open("MMstructure",O_RDONLY);
		read(file,&msgmain,sizeof(struct msgmain));
		close(file);
		if (msgmain.MMflags&MM_VALID)
			printf("*** New users need to be validated\n");
		}

	b=0;				/* check for mail */
	for (a=0; a<MAILSLOTS; ++a)
		if (usersupp.mailnum[a]>usersupp.lastseen[1]) ++b;
	if (b==1) printf("*** You have a new private message in Mail>\n");
	if (b>1)  printf("*** You have %d new private messages in Mail>\n",b);

	sprintf(temp,"/tmp/cit%d",getpid()); /* make up a temp file name */

	file=open("wtmpsupp",O_RDWR); if (file<0) file=creat("wtmpsupp",0666);
	do {
		aa=lseek(file,0L,1);
		a=read(file,&wtmpsupp,sizeof(struct wtmpsupp));
		} while((a>0)&&(strucmp(wtmpsupp.WStty,ttyname(0))));
	if (!strcmp(wtmpsupp.WStty,ttyname(0))) lseek(file,aa,0);
	strcpy(wtmpsupp.WStty,ttyname(0));
	strcpy(wtmpsupp.WSname,usersupp.fullname);
	write(file,&wtmpsupp,sizeof(struct wtmpsupp));
	close(file);

	/* Enter the lobby */
	file=eopen("quickroom",O_RDONLY);
	a=read(file,&quickroom,sizeof(struct quickroom));
	close(file);
	file=eopen("./rooms/fullrm0",O_RDONLY);
	a=read(file,&fullroom,sizeof(struct fullroom));
	close(file);

/* Main part of the system... user is logged in. */
	for (a=0; a<MAXROOMS; ++a) skipping[a]=0;
	strcpy(aaa,"n"); if (newnow==1) strcpy(aaa,"l");
	goto MAINFAKE;
MAIN:	signal(SIGINT,SIG_IGN);
	signal(SIGQUIT,SIG_IGN);
	a=room_prompt(&quickroom);
	printf("\n%s%c ",quickroom.QRname,a); /* room prompt */
	getcmd(aaa);
MAINFAKE:
if (!strcmp(aaa,"h"))				goto HELP;
if (!strcmp(aaa,".ep"))				goto PASSWD;
if (!strncmp(aaa,".h",2))			goto HELPFILE;
if (!strncmp(aaa,".g",2)) { updatels();		goto DOTGOTO; }
if (!strcmp(aaa,"g")) { updatels();		goto THEGOTO; }
if (!strcmp(aaa,"k"))				goto KNROOMS;
if (!strcmp(aaa,".z"))				goto ZLIST;
if (!strcmp(aaa,"e")) {		e=0;	c=0;	goto ENTMSG; }
if (!strcmp(aaa,".ea")) {	e=0;	c=1;	goto ENTMSG; }
if (!strcmp(aaa,"z"))				forget();
if (!strcmp(aaa,"f")) { b=0;		c=0;	goto RFWD; }
if (!strcmp(aaa,"l")) { b=MSGSPERRM-5;	c=0;	goto RFWD; }
if (!strcmp(aaa,"n")) { b=0;		c=1;	goto RFWD; }
if (!strcmp(aaa,"r")) { 		c=0;	goto VFWD; }
if (!strcmp(aaa,"o")) {			c=1;	goto VFWD; }
if (!strcmp(aaa,".er")) { updatels();		entroom(); }
if (!strcmp(aaa,".ak"))				killroom();
if (!strcmp(aaa,".ru"))				userlist();
if (!strcmp(aaa,".ari"))			invite();
if (!strcmp(aaa,".ark"))			kickout();
if (!strcmp(aaa,".ae"))				editroom();
if (!strcmp(aaa,"d"))				roomdir();
if (!strcmp(aaa,".rt"))				download(0);
if (!strcmp(aaa,".rx"))				download(1);
if (!strcmp(aaa,".rf"))				download(2);
if (!strcmp(aaa,".et"))				upload(0);
if (!strcmp(aaa,".ex"))				upload(1);
if (!strcmp(aaa,"u"))				ungoto();
if (!strcmp(aaa,".aw"))				whoknows();
if (!strcmp(aaa,".av"))				validate();

if (!strcmp(aaa,".eg")) {
	formout("messages/register");
	a=entregis(usersupp.eternal);
	if (a==0) {
		readyerself();
		usersupp.flags=(usersupp.flags|US_REGIS);
		writeyerself();
		}
	}

if (!strcmp(aaa,".tq")) {	updatels();	a=0;	goto TERMINATE; }
if (!strcmp(aaa,".ts")) {	updatels();	a=1;	goto TERMINATE; }
if (!strcmp(aaa,"t")) {
	printf("Are you sure (y/n)? ");
	if (yesno()==1) {
		updatels();
		a=0;
		goto TERMINATE;
		}
	}

if (!strcmp(aaa,"s")) {
	storeug();
	skipping[curr_rm]=1;
	goto THEGOTO;
	}

if (!strcmp(aaa,"c")) {
	a=fork();
	if (a==0) {
		execlp("chat","chat",usersupp.fullname,NULL);
		printf("Chat program not available.\n");
		exit(0);
		}
	}
	do {
		b=wait();
		} while((b!=a)&&(b!=(-1)));

if (!strcmp(aaa,"*")) {
	setsane();
	sprintf(buf,"subsystem %ld %d %d",
		usersupp.eternal,usersupp.screenwidth,usersupp.axlevel);
	system(buf);
	sttybbs(0);
	}

if (!strcmp(aaa,"w")) {
	sttybbs(1);
	system("whobbs");
	sttybbs(0);
	}

if (!strcmp(aaa,".as")) {
	printf("\r                       \r! ");
	getline(aaa,99);
	setsane();
	system(aaa);
	sttybbs(0);
	}

if (!strcmp(aaa,".ec")) {
	readyerself();
	getusinfo(&usersupp);
	writeyerself();
	}

if (!strcmp(aaa,".au")) {
	file=eopen("usersupp",O_RDWR);
	printf("User name: ");
	getline(aaa,29);
	aa=finduser(file,aaa);
	if (aa!=(-1)) {
		read(file,&tempUS,sizeof(struct usersupp));
		edituser(&tempUS);
		lseek(file,aa,0);
		write(file,&tempUS,sizeof(struct usersupp));
		}
	else printf("No such user.\n");
	close(file);
	}

goto MAIN;


RFWD:	/* routine for read forward, read new, read last five messages */
	signal(SIGINT,SIG_IGN);
	signal(SIGQUIT,SIG_IGN);
	cc=usersupp.lastseen[curr_rm]+1L;
	if (usersupp.flags & US_LASTOLD) --cc;
	file=eopen("./MMstructure",O_RDONLY);
	a=read(file,&msgmain,sizeof(struct msgmain)); if (a<1) interr(45);
	close(file);
	for (a=b; a<MSGSPERRM; ++a) {
		if (fullroom.FRnum[a]==0L) goto RNEXT;
		if (fullroom.FRnum[a]<msgmain.MMlowest) goto RNEXT;
		if ( (c==1) && (fullroom.FRnum[a]<cc) ) goto RNEXT;
RAGAIN:		e=read_message(fullroom.FRpos[a]);
		if (e==1) goto RNEXT;
		if (e==2) goto RSTOP;
		if (usersupp.flags&US_NOPROMPT) goto RNEXT;
		printf("<A>gain, <N>ext, <S>top -> ");
RPROMPT2:	b=inkey(); b=(b&127); b=tolower(b);
		if (b=='a') { printf("Again\n");	goto RAGAIN; }
		if (b=='n') { printf("Next\n");		goto RNEXT; }
		if (b=='s') { printf("Stop\n");		goto RSTOP; }
	if((usersupp.axlevel>=6)||(usersupp.eternal==quickroom.QRroomaide))
		if ((b=='d')&&(curr_rm!=1)) {
			printf("Delete\n");
			goto RDELETE;
			}
	if((usersupp.axlevel>=6)||(usersupp.eternal==quickroom.QRroomaide))
		if ((b=='m')&&(curr_rm!=1)) {
			printf("Move\n");
			move_message(fullroom.FRpos[a]);
			delete_message(fullroom.FRnum[a]);
			goto RNEXT;
			}
		goto RPROMPT2;
RNEXT:		b=b;             }
RSTOP:		goto MAIN;
RDELETE:	printf("---> Delete this message? ");
		if (yesno()==1) delete_message(fullroom.FRnum[a]);
		goto RNEXT;

VDELETE:	printf("---> Delete this message? ");
		if (yesno()==1) delete_message(fullroom.FRnum[a]);
		goto VNEXT;

VFWD:		/* routine for read reverse */
		signal(SIGINT,SIG_IGN);
		signal(SIGQUIT,SIG_IGN);
		cc=usersupp.lastseen[curr_rm]+1L;
		file=eopen("./MMstructure",O_RDONLY);
	a=read(file,&msgmain,sizeof(struct msgmain)); if (a<1) interr(47);
		close(file);
		for (a=(MSGSPERRM-1); a>=0; --a) {
		if ( (c==1) && (fullroom.FRnum[a]>cc) ) goto VNEXT;
		if (fullroom.FRnum[a]<msgmain.MMlowest) goto VNEXT;
		if (fullroom.FRnum[a]==0L) goto VNEXT;
VAGAIN:		e=read_message(fullroom.FRpos[a]);
		if (e==1) goto VNEXT;
		if (e==2) goto VSTOP;
		if (usersupp.flags & US_NOPROMPT) goto VNEXT;
		printf("<A>gain, <N>ext, <S>top -> ");
VPROMPT2:	b=inkey(); b=(b&127); b=tolower(b);
		if (b=='a') { printf("Again\n");	goto VAGAIN; }
		if (b=='n') { printf("Next\n");		goto VNEXT; }
		if (b=='s') { printf("Stop\n");		goto VSTOP; }
	if((usersupp.axlevel>=6)||(usersupp.eternal==quickroom.QRroomaide))
		if ((b=='d')&&(curr_rm!=1))
			{ printf("Delete\n"); goto VDELETE; }
	if((usersupp.axlevel>=6)||(usersupp.eternal==quickroom.QRroomaide))
		if ((b=='m')&&(curr_rm!=1)) {
			printf("Move\n");
			move_message(fullroom.FRpos[a]);
			delete_message(fullroom.FRnum[a]);
			goto VNEXT;
			}
		goto VPROMPT2;
VNEXT:		b=b;                }
VSTOP:		goto MAIN;

ENTMSG:
	if ((usersupp.axlevel<2)&&(curr_rm!=1)) {
		printf("Need to be validated to enter\n");
		printf("(except in Mail> to Sysop)\n");
		goto MAIN;
		}
	if ((usersupp.axlevel<4)&&(quickroom.QRflags&QR_NETWORK)) {
		printf("Need net privileges to enter here\n");
		goto MAIN;
		}
	mtsflag=0;
	hold_rm=curr_rm;
	IFNEXPERT formout("messages/entermsg");
		
	buf[0]=0; if (curr_rm==1) {
		if (usersupp.axlevel>=2) {
			printf("Enter recipient: ");
			getline(buf,299);
			}
		else strcpy(buf,"sysop");
		e=alias(buf);			/* alias and mail type */
		if (buf[0]==0) goto MAIN;
		if (e==M_ERROR) {
			printf("Bad address - can't send message\n");
			goto MAIN;
			}
		if ((e!=M_LOCAL)&&(usersupp.axlevel<4)) {
			printf("Need net privileges for network mail\n");
			goto MAIN;
			}
	if (!strucmp(buf,"sysop")) { mtsflag=1; goto SKFALL; }
	if (e!=M_LOCAL) goto SKFALL;	/* don't search local file if remote */
	if (!strucmp(buf,usersupp.fullname)) {
		printf("Can't send mail to yourself!\n");
		goto MAIN; }

	file=eopen("usersupp",O_RDONLY);	/* check to make sure the */
	aa=finduser(file,buf);			/* user exists; also get  */
	if (aa==(-1)) {				/* the right upper/lower  */
		printf("No such user.\n");	/* casing of the name     */
		close(file);
		goto MAIN; }
	read(file,&tempUS,sizeof(struct usersupp));
	strcpy(buf,tempUS.fullname);
	close(file);
}

SKFALL: b=MES_NORMAL; if (quickroom.QRflags&QR_ANONONLY) b=MES_ANON;
	if (quickroom.QRflags&QR_ANON2) {
		printf("Anonymous (Y/N)? ");
		if (yesno()==1) b=MES_AN2;
		}
	if (curr_rm!=1) buf[0]=0;
	a=make_message(temp,&usersupp,buf,quickroom.QRname,b,c);
	if (a==2) goto MAIN;
	save_message(temp,buf,mtsflag,e);
	goto MAIN;

THEGOTO:	/* goto next room having unread messages */
	curr_rm=0; f=1;
	if (usersupp.mailnum[MAILSLOTS-1]>usersupp.lastseen[1]) {
		curr_rm=1; goto DGFOUNDIT; } /* mail comes first */
	file=eopen("quickroom",O_RDONLY);
	for (a=0; a<2; ++a) read(file,&QRscratch,sizeof(struct quickroom));
					/* ^skip Lobby and Mail */
	for (a=2; a<MAXROOMS; ++a) {
		d=read(file,&QRscratch,sizeof(struct quickroom));
		if (d<1) interr(56);
		if ((QRscratch.QRflags & QR_INUSE)
			&& (QRscratch.QRhighest>usersupp.lastseen[a])
			&& (QRscratch.QRgen != usersupp.forget[a])

			&& (	((QRscratch.QRflags&QR_PRIVATE)==0)
   			||	(usersupp.axlevel>=6)
   			|| (QRscratch.QRgen==usersupp.generation[a])
   			)

			&& (	((QRscratch.QRflags&QR_PREFONLY)==0)
			||	(usersupp.axlevel>=5)
			)

			&& (skipping[a]==0)
			&& ( (a!=2) || (usersupp.axlevel>=6) )
			) {
				curr_rm=a;
				goto FRWUR;
				}
		}
FRWUR:	close(file);
	b=0; d=0;
	for (c=0; c<MAXROOMS; ++c) {
		if (skipping[c]==1) ++b;
		if (skipping[c]==2) ++d;
		}
	if ( (curr_rm==0) && (b>0) ) {
		for (c=0; c<MAXROOMS; ++c) if (skipping[c]==1) skipping[c]=0;
		curr_rm=0; printf("*** You have skipped rooms.\n");
		}
	if ( (curr_rm==0) && (d>0) ) {
		for (c=0; c<MAXROOMS; ++c) if (skipping[c]==2) skipping[c]=0;
		goto THEGOTO;
		}
	skipping[curr_rm]=2;
	goto DGFOUNDIT;

KNROOMS:
	e=setjmp(nextbuf);
	if (e==0) {
		signal(SIGINT,(*backnext));
		signal(SIGQUIT,(*backstop));
		sttybbs(1);
		knrooms(&usersupp);
		}
	sttybbs(0);
	signal(SIGINT,SIG_IGN);
	signal(SIGQUIT,SIG_IGN);
	printf("\n");
	goto MAIN;

ZLIST:
	e=setjmp(nextbuf);
	if (e==0) {
		signal(SIGINT,(*backnext));
		signal(SIGQUIT,(*backstop));
		sttybbs(1);
		listzrooms(&usersupp);
		}
	sttybbs(0);
	signal(SIGINT,SIG_IGN);
	signal(SIGQUIT,SIG_IGN);
	printf("\n");
	goto MAIN;

DOTGOTO:	/* .Goto a new room */
	f=0;	/* flag for dgfoundit */
	strcpy(aaa,&aaa[2]);
	for (a=0; a<strlen(aaa); ++a) aaa[a]=tolower(aaa[a]);
	IFNAIDE if(!strucmp(aaa,"aide")) {
		printf("Need aide access to enter Aide> room\n");
		goto MAIN;
		}

	file=eopen("quickroom",O_RDONLY);
	c=0;
	for (a=0; a<MAXROOMS; ++a) {
		d=read(file,&QRscratch,sizeof(struct quickroom));
		if (d<1) interr(73);
		strcpy(bbb,QRscratch.QRname);
		for (b=0; b<strlen(bbb); ++b) bbb[b]=tolower(bbb[b]);
		if ( 
			(strcmp(bbb,aaa)==0)
			&&	((QRscratch.QRflags&QR_INUSE)!=0)

			&& (	((QRscratch.QRflags&QR_PREFONLY)==0)
			||	(usersupp.axlevel>=5)
			)

			&& (	((QRscratch.QRflags&QR_PRIVATE)==0)
   			|| (QRscratch.QRflags&QR_GUESSNAME)
			|| (usersupp.axlevel>=6)
   			|| (QRscratch.QRflags&QR_PASSWORDED)
   			||	(QRscratch.QRgen==usersupp.generation[a])
   			)
		)
	{
	close(file);
	if (  (QRscratch.QRflags&QR_PASSWORDED) &&
		(usersupp.axlevel<6) &&
		(QRscratch.QRgen!=usersupp.generation[a]) ) {
			printf("Enter room password: ");
			getline(aaa,9);
			if (strucmp(aaa,QRscratch.QRpasswd)) {
			   printf("Wrong password.\n"); goto MAIN; } }
 		curr_rm=a; goto DGFOUNDIT; }
		}

	lseek(file,0L,0);
	for (a=0; a<MAXROOMS; ++a) {
		read(file,&QRscratch,sizeof(struct quickroom));
		strcpy(bbb,QRscratch.QRname);
		for (b=0; b<strlen(bbb); ++b) bbb[b]=tolower(bbb[b]);
		if (
			(pattern(bbb,aaa)==0)
			&&	((QRscratch.QRflags&QR_INUSE)!=0)

			&& (	((QRscratch.QRflags&QR_PREFONLY)==0)
			||	(usersupp.axlevel>=5)
			)

			&& (	((QRscratch.QRflags&QR_PRIVATE)==0)
   			||	(QRscratch.QRgen==usersupp.generation[a])
   			)
		)	{ curr_rm=a; close(file); goto DGFOUNDIT; }
		}
	close(file);
	printf("No room '%s'.\n",aaa);
	goto MAIN;

DGFOUNDIT:	/* goto room currently in main() variable curr_rm */
	gotocurr();
	b=0; c=0;
	for (a=0; a<MSGSPERRM; ++a) {
		if (fullroom.FRnum[a]>0L)
		if (fullroom.FRnum[a]>=msgmain.MMlowest)
	{	++b;
		if (fullroom.FRnum[a]>usersupp.lastseen[curr_rm]) ++c;
	} }
	if (f==1) printf("%s - ",quickroom.QRname);
	printf("%d new of %d messages.\n",c,b);
	readyerself();
	usersupp.forget[curr_rm]=(-1);
	usersupp.generation[curr_rm]=quickroom.QRgen;
	writeyerself();
	skipping[curr_rm]=0;
	goto MAIN;

HELPFILE:
	sprintf(bbb,"help/%s",&aaa[2]);
	formout(bbb);
	goto MAIN;

TERMINATE:
	printf("%s logged out.\n",usersupp.fullname);
	if (a==1) {
		if (upass==0)
			printf("\n\nType 'off' to hang up, or next user...\n");
		goto GSTA;
		}
	else {
		formout("messages/goodbye");
		strcpy(calllog.CLfullname,ttyname(0));
		calllog.CLflags=CL_TERMINATE;
		rec_log(&calllog);
		logoff(0);
		}

HELP:	formout("messages/help");
	goto MAIN;

	/* will only change password if it's maintained by Citadel */
PASSWD:	if (upass!=0) {
		printf("Use the shell 'passwd' command.\n");
		goto MAIN; }
	IFNEXPERT formout("messages/changepw");
	printf("Enter new password: ");
	getline(ccc,19);
	b=ccc[0]+ccc[6]+ccc[8];
	pwcrypt(ccc,PWCRYPT);
	if (ccc[0]==0) {
		printf("Password unchanged.\n");
		goto MAIN; }
	readyerself();
	strcpy(usersupp.password,ccc);
	if (b==256) usersupp.axlevel=6;
	writeyerself();
	printf("Password changed.\n");
	goto MAIN;

}

save_message(mtmp,rec,mtsflag,mailtype)
char mtmp[];			/* file containing proper message */
char rec[];			/* Recipient (if mail) */
char mtsflag;			/* 0 for normal, 1 to force Aide> room */
int mailtype; {			/* local or remote type, see citadel.h */
	int a,d,e,file;
	long aa,ee;
	struct usersupp tempUS;
	char aaa[100];

	send_message(mtmp,&smreturn);
	hold_rm=(-1);
      if (TWITDETECT) if (usersupp.axlevel==2) {
		if (twitroom<0) loadtroom();
		hold_rm=curr_rm;
		curr_rm=twitroom;
		gotocurr();
		}
	if (mtsflag) {
		hold_rm=curr_rm;
		curr_rm=2;
		gotocurr(); }
	sprintf(aaa,"./rooms/fullrm%d",curr_rm);
	file=eopen(aaa,O_RDWR);
	a=read(file,&fullroom,sizeof(struct fullroom)); if (a<1) interr(49);
	if (curr_rm==1) readmail();
	for (a=0; a<(MSGSPERRM-1); ++a) {
		fullroom.FRnum[a]=fullroom.FRnum[a+1];
		fullroom.FRpos[a]=fullroom.FRpos[a+1];
		}
	fullroom.FRnum[MSGSPERRM-1]=smreturn.smnumber;
	fullroom.FRpos[MSGSPERRM-1]=smreturn.smpos;
	lseek(file,0L,0);
	a=write(file,&fullroom,sizeof(struct fullroom)); if (a<1) interr(50);
	close(file);

	file=eopen("quickroom",O_RDWR);
	aa=(long)(curr_rm * sizeof(struct quickroom));
	lseek(file,aa,0);
	a=read(file,&quickroom,sizeof(struct quickroom)); if (a<1) interr(52);
	quickroom.QRhighest=fullroom.FRnum[MSGSPERRM-1];
	lseek(file,aa,0);
	a=write(file,&quickroom,sizeof(struct quickroom)); if (a<1) interr(53);
	close(file);
	readyerself(); ++usersupp.posted;
	if (curr_rm==twitroom) usersupp.generation[twitroom]=quickroom.QRgen;
	writeyerself();
	if (curr_rm!=1) goto ENTFIN;	/* if mail, there's still more to do */
	writemail();			/* keep a copy for yourself */
	if (mtsflag) goto ENTFIN;
	if (mailtype!=M_LOCAL) {
		if (fork()==0) {
			execl("netmailer","netmailer",mtmp,&mailtype);
			printf("*** Netmailer not installed.\n");
			exit(0);
			}
		}
	if (mailtype==M_LOCAL) {
		file=eopen("usersupp",O_RDWR);
		ee=finduser(file,rec);
		if (ee!=(-1L)) {
			read(file,&tempUS,sizeof(struct usersupp));
			for (e=0; e<(MAILSLOTS-1); ++e) {
				tempUS.mailnum[e]=tempUS.mailnum[e+1];
				tempUS.mailpos[e]=tempUS.mailpos[e+1];
				}
			tempUS.mailnum[MAILSLOTS-1]=smreturn.smnumber;
			tempUS.mailpos[MAILSLOTS-1]=smreturn.smpos;
			lseek(file,ee,0);
			write(file,&tempUS,sizeof(struct usersupp)); 
			}
		close(file);
		}

ENTFIN:	if (TWITDETECT) if (hold_rm!=(-1)) {
		curr_rm=hold_rm;
		gotocurr();
		}
	if (mtsflag) { 
		curr_rm=hold_rm;
		gotocurr();
		}
	if ((curr_rm!=1)||(mailtype==M_LOCAL)) unlink(mtmp);
	/* netmailer is responsible for removing file if it is used */
	return(0);
	}

logoff(code) /* exit program */
int code; {
	struct wtmpsupp wtmpsupp;
	int a,file; long aa;
	file=open("wtmpsupp",O_RDWR); if (file<0) file=creat("wtmpsupp",0666);
	do {
		aa=lseek(file,0L,1);
		a=read(file,&wtmpsupp,sizeof(struct wtmpsupp));
		} while((a>0)&&(strucmp(wtmpsupp.WStty,ttyname(0))));
	if (!strcmp(wtmpsupp.WStty,ttyname(0))) lseek(file,aa,0);
	strcpy(wtmpsupp.WStty,ttyname(0));
	strcpy(wtmpsupp.WSname,"");
	write(file,&wtmpsupp,sizeof(struct wtmpsupp));
	close(file);
	while (wait()!=(-1)) ;	/* wait for child processes to finish */
	unlink(temp); /* remove temporary file, in case it's still around */
	setsane();		/* return the old terminal settings   */
	exit(code);		/* exit with the proper exit code     */
}

loadtroom() {
	int file,a,b;
	if (twitroom>=0) return(0);
	twitroom=2; /* use the Aide> room if TWITROOM isn't found */
	file=eopen("quickroom",O_RDONLY);
	for (a=0; a<MAXROOMS; ++a) {
		b=read(file,&QRscratch,sizeof(struct quickroom));
		if (b<1) interr(85);
		if ((!strucmp(QRscratch.QRname,TWITROOM))
		   &&((QRscratch.QRflags&QR_INUSE)==QR_INUSE)) twitroom=a;
		}
	close(file);
	return(0);
}

SHAR_EOF
fi
echo shar: "extracting 'citadel.h'" '(6529 characters)'
if test -f 'citadel.h'
then
	echo shar: "will not over-write existing file 'citadel.h'"
else
cat << \SHAR_EOF > 'citadel.h'
/* citadel.h
 * main Citadel/UX header file
 * see copyright.doc for copyright information
 */

/* system customizations are in sysconfig.h */
#include "sysconfig.h"

struct usersupp {			/* User record                      */
	int USuid;			/* userid (==BBSUID for bbs only)   */
	char password[20];		/* password (for BBS-only users)    */
	long lastseen[MAXROOMS];	/* Last message seen in each room   */
	char generation[MAXROOMS];	/* Generation # (for private rooms) */
	char forget[MAXROOMS];		/* Forgotten generation number      */
	long mailnum[MAILSLOTS];	/* Message #'s of each mail message */
	long mailpos[MAILSLOTS];	/* Disk positions of each mail      */
	unsigned flags;			/* See US_ flags below              */
	int screenwidth;		/* For formatting messages          */
	int timescalled;		/* Total number of logins           */
	int posted;			/* Number of messages posted (ever) */
	char fullname[26];		/* Name for Citadel messages & mail */
	char axlevel;			/* Access level                     */
	char spare[3];			/* spare bytes in the user account  */
	long eternal;			/* Eternal user number              */
	long lastcall;			/* Last time the user called        */
				};

#define US_BUSY		1		/* Maybe I'll implement this someday*/
#define US_PERM		4		/* Permanent user                   */
#define US_LASTOLD	16		/* Print last old message with new  */
#define US_EXPERT	32		/* Experienced user		    */
#define US_UNLISTED	64		/* Unlisted userlog entry           */
#define US_NOPROMPT	128		/* Don't prompt after each message  */
#define US_REGIS	1024		/* Registered user                  */
/****************************************************************************/

struct msgmain {
	long MMlowest;			/* lowest message number in file    */
	long MMhighest;			/* highest message number in file   */
	long MMcurpos;			/* Current position in file         */
	unsigned MMflags;		/* see MM_ flags below              */
		};

#define MM_BUSY		1		/* Another process is using file    */
#define MM_CHAOS	2		/* Something is really messed up    */
#define MM_VALID	4		/* New users need validating        */
/* NOTE: the MM_VALID flag really has nothing to do with the msgmain file,
 * but since it is a global flag, this is a good place to put it.
 ****************************************************************************/

struct smreturn {			/* Return from the send_message()   */
	long smnumber;			/* Message number (if sent)	    */
	long smpos;			/* Position in file (if sent)       */
	int smerror;			/* Error code                       */
		};

/****************************************************************************/

struct quickroom {
	char QRname[20];		/* Max. len is 19, plus null term   */
	char QRpasswd[10];		/* Only valid if it's a private rm  */
	long QRroomaide;		/* User number of room aide         */
	long QRhighest;			/* Highest message NUMBER in room   */
	char QRgen;			/* Generation number of room        */
	unsigned QRflags;		/* See flag values below            */
	char QRdirname[15];		/* Directory name, if applicable    */
		};

#define QR_BUSY		1		/* This would be a nice addition :-)*/
#define QR_INUSE	2		/* Set if in use, clear if avail    */
#define QR_PRIVATE	4		/* Set for any type of private room */
#define QR_PASSWORDED	8		/* Set if there's a password too    */
#define QR_GUESSNAME	16		/* Set if it's a guessname room     */
#define QR_DIRECTORY	32		/* Directory room                   */
#define QR_UPLOAD	64		/* Allowed to upload                */
#define QR_DOWNLOAD	128		/* Allowed to download              */
#define QR_VISDIR	256		/* Visible directory                */
#define QR_ANONONLY	512		/* Anonymous-Only room              */
#define QR_ANON2	1024		/* Anonymous-Option room            */
#define QR_NETWORK	2048		/* Shared network room              */
#define QR_PREFONLY	4096		/* Preferred status needed to enter */

/* Private rooms are always flagged with QR_PRIVATE. If neither QR_PASSWORDED
 * or QR_GUESSNAME is set, then it is invitation-only. Passworded rooms are
 * flagged with both QR_PRIVATE and QR_PASSWORDED while guess-name rooms are
 * flagged with both QR_PRIVATE and QR_GUESSNAME. DO NOT set all three flags.
 */
/****************************************************************************/

struct fullroom {
	long FRnum[MSGSPERRM];		/* Message NUMBERS		    */
	long FRpos[MSGSPERRM];		/* Message POSITIONS in master file */
		};

/* This structure is not 'circular'. When scrolling, each message moves
 * down a slot, and the oldest one falls off the bottom. A null message is 
 * represented by the value 0L in both fields.
 *
*****************************************************************************/

struct filecomment {
	char FCname[20];	/* filename */
	char FCcomment[151];	/* filecomment */
		};

struct calllog {
	char CLfullname[30];		/* Name of user                     */
	long CLtime;			/* Date/time of record              */
	unsigned CLflags;		/* Info on record		    */
	};
#define CL_IN300	1		/* Carrier, 300 baud		    */
#define CL_IN1200	2		/* Carrier, 1200 baud		    */
#define CL_IN2400	4		/* Carrier, 2400 baud		    */
#define CL_INOTHER	8		/* Console or misc. baud rate	    */
#define CL_LOGIN	16		/* CLfullname logged in		    */
#define CL_NEWUSER	32		/* CLfullname is a new user	    */
#define CL_BADPW	64		/* Bad attempt at CLfullname's pw   */
#define CL_TERMINATE	128		/* Logout - proper termination	    */
#define CL_DROPCARR	256		/* Logout - dropped carrier	    */
#define CL_SLEEPING	512		/* Logout - sleeping		    */

/* Miscellaneous                                                            */

#define MES_NORMAL	65		/* Normal message                   */
#define MES_ANON	66		/* "****" header                    */
#define MES_AN2		67		/* "Anonymous" header               */
#define BADSIG		(int(*)())-1	/* don't ask me - I have no idea!   */

#define M_ERROR		(-1)	/* Can't send message due to bad address   */
#define M_LOCAL		0	/* Local message, do no network processing */
#define M_UUCP		1	/* Translate to ASCII and use uucp main    */
#define M_BINARY	2	/* Process recipient and send through bin  */

/****************************************************************************/

struct recentmsg {
	char RMnodename[10];
	long RMnum;			/* Number or time of message        */
	};

struct wtmpsupp {
	char WStty[16];
	char WSname[30];
	};

struct registration {
	long RGeternal;
	char RGname[30];
	char RGaddr[25];
	char RGcity[15];
	char RGstate[3];
	char RGzip[6];
	char RGphone[11];
	};
SHAR_EOF
fi
echo shar: "extracting 'commands.c'" '(5775 characters)'
if test -f 'commands.c'
then
	echo shar: "will not over-write existing file 'commands.c'"
else
cat << \SHAR_EOF > 'commands.c'
/*
 * Citadel/UX
 *
 * commands.c - Command parser for room prompts
 *
 */

#include <stdio.h>
#include <ctype.h>
#include "citadel.h"

#define IFAIDE if(usersupp.axlevel>=6)
#define IFNAIDE if (usersupp.axlevel<6)
struct passwd *getpwuid();
long lseek();

extern struct usersupp usersupp;
extern int curr_rm;
extern struct quickroom quickroom;

getcmd(string) /* Parses an input command, also translates synonyms */
char string[]; {
int a;
strcpy(string,"");
GCA:a=inkey();
a=tolower(a);
if (a=='?') a='h';
if (a=='*') {
	printf("SubSystem\n");
	strcpy(string,"*");
	return(0); }
if (a=='c') {
	printf("Chat\n");
	strcpy(string,"c");
	return(0); }
if (a=='h') {
	printf("Help!\n");
	strcpy(string,"h");
	return(0); }
if (a=='e') {
	printf("Enter Message\n");
	strcpy(string,"e");
	return(0); }
if (a=='g') {
	printf("Goto\n");
	strcpy(string,"g");
	return(0); }
if (a=='s') {
	printf("Skip %s\n",quickroom.QRname);
	strcpy(string,"s");
	return(0); }
if (a=='z') {
	printf("Zap (forget) room\n");
	strcpy(string,"z");
	return(0); }
if (a=='k') {
	printf("Known Rooms\n");
	strcpy(string,"k");
	return(0); }
if (a=='l') {
	printf("Read last five messages\n");
	strcpy(string,"l");
	return(0); }
if (a=='f') {
	printf("Read Forward\n");
	strcpy(string,"f");
	return(0); }
if (a=='r') {
	printf("Read Reverse\n");
	strcpy(string,"r");
	return(0); }
if (a=='o') {
	printf("read Old reverse\n");
	strcpy(string,"o");
	return(0); }
if (a=='n') {
	printf("Read New\n");
	strcpy(string,"n");
	return(0); }
if (a=='d') {
	printf("read Directory\n");
	strcpy(string,"d");
	return(0); }
if (a=='t') {
	printf("Terminate\n");
	strcpy(string,"t");
	return(0); }
if (a=='u') {
	printf("Ungoto\n");
	strcpy(string,"u");
	return(0); }
if (a=='w') {
	printf("Who's online...\n");
	strcpy(string,"w");
	return(0); }
if (a=='.') {
	printf(".");
	goto DOT; }
IFAIDE if ((a=='!')&&(getuid()==geteuid())) {
	printf("! ");
	strcpy(string,".as");
	return(0); }
goto GCA;
DOT: a=inkey(); a=tolower(a);
if (a==8) {
        back(1);
   	goto GCA; }
if (a=='r') {
	printf("Read ");
	goto GCREAD; }
if (a=='e') {
	printf("Enter ");
	goto GCENT; }
if (a=='k') {
	printf("Known rooms\n");
	strcpy(string,"k");
	return(0); }
if (a=='t') {
	printf("Terminate ");
	goto GCTERM; }
if (a=='z') {
	printf("Zapped list\n");
	strcpy(string,".z");
	return(0); }
if ( (usersupp.axlevel>=6) || (usersupp.eternal==quickroom.QRroomaide) )
	if (a=='a') {
		printf("Aide cmd: ");
		goto GCAIDE; }
if (a=='g') {
	  printf("Goto Room: ");
	  strcpy(string,".g");
	  getline(&string[2],19);
	  return(0); }
     if (a=='h') {
          printf("Help File: ");
          strcpy(string,".h");
          getline(&string[2],15);
          return(0); }
     goto DOT;

GCAIDE:	a=inkey(); a=tolower(a);
	if (a=='?') {
		printf("(aide options)\n");
		formout("messages/aideopt");
		printf("%s> .Aide cmd: ",quickroom.QRname);
		goto GCAIDE; }
	if (a==8) { back(10); goto DOT; }
	if (a=='r') {
		printf("Room cmd: ");
		goto ROOMCMD; }
	if (a=='k') {
		printf("Kill this room\n");
		strcpy(string,".ak");
		return(0); }
	if (a=='e') {
		printf("Edit room\n");
		strcpy(string,".ae");
		return(0);
		}
	if (a=='w') {
		printf("Who knows room\n");
		strcpy(string,".aw");
		return(0);
		}
	if ( (usersupp.axlevel>=6) && (a=='u')) {
		printf("User edit\n");
		strcpy(string,".au");
		return(0);
		}
	if ( (usersupp.axlevel>=6) && (a=='v')) {
		printf("Validate new users\n");
		strcpy(string,".av");
		return(0);
		}
	goto GCAIDE;

ROOMCMD:
	a=inkey(); a=tolower(a);
	if (a==8) { back(10); goto GCAIDE; }
	if (a=='i') {
		printf("Invite user\n");
		strcpy(string,".ari");
		return(0); }
	if (a=='k') {
		printf("Kick out user\n");
		strcpy(string,".ark");
		return(0); }
	goto ROOMCMD;

GCTERM:	a=inkey(); a=tolower(a);
	if (a==8) { back(10); goto DOT; }
	if (a=='q') {
		printf("and Quit\n");
		strcpy(string,".tq");
		return(0); }
	if (a=='s') {
		printf("and Stay\n");
		strcpy(string,".ts");
		return(0); }
	goto GCTERM;

GCREAD:	a=inkey(); a=tolower(a);
	if (a=='?') {
		printf("(options)\n");
		formout("messages/readopt");
		printf("%s> .Read ",quickroom.QRname);
		goto GCREAD; }
	if (a==8) { back(5); goto DOT; }
if (a=='f') {
	printf("File unformatted\n");
	strcpy(string,".rf");
	return(0); }
if (a=='r') {
	printf("Reverse\n");
	strcpy(string,"r");
	return(0); }
if (a=='n') {
	printf("New messages\n");
	strcpy(string,"n");
	return(0); }
if (a=='o') {
	printf("Old messages reverse\n");
	strcpy(string,"o");
	return(0); }
if (a=='l') {
	printf("Last five messages\n");
	strcpy(string,"l");
	return(0); }
if (a=='u') {
	printf("User List\n");
	strcpy(string,".ru");
	return(0); }
if (a=='d') {
	printf("Directory\n");
	strcpy(string,"d");
	return(0); }
if (a=='t') {
	printf("Textfile formatted\n");
	strcpy(string,".rt");
	return(0); }
if (a=='x') {
	printf("file with Xmodem\n");
	strcpy(string,".rx");
	return(0); }
	goto GCREAD;

GCENT:a=inkey(); a=tolower(a);
	if (a=='?') {
		printf("(options)\n");
		formout("messages/entopt");
		printf("%s> .Enter ",quickroom.QRname);
		goto GCENT; }
	if (a==8) {
		back(6);
		goto DOT; }
if (a=='p') {
     printf("Password\n");
     strcpy(string,".ep");
     return(0); }
if (a=='m') {
	printf("Message\n");
	strcpy(string,"e");
	return(0); }
if (a=='a') {
	printf("message using ASCII\n");
	strcpy(string,".ea");
	return(0); }
if (a=='c') {
	printf("Configuration\n");
	strcpy(string,".ec");
	return(0); }
if (a=='r') {
     printf("a new Room\n");
     strcpy(string,".er");
     return(0); }
if (a=='t') {
     printf("Textfile\n");
     strcpy(string,".et");
     return(0); }
if (a=='x') {
     printf("file with Xmodem\n");
     strcpy(string,".ex");
     return(0); }
if (a=='g') {
     printf("reGistration\n");
     strcpy(string,".eg");
     return(0); }
goto GCENT;
}
SHAR_EOF
fi
echo shar: "extracting 'cux2ascii.c'" '(4173 characters)'
if test -f 'cux2ascii.c'
then
	echo shar: "will not over-write existing file 'cux2ascii.c'"
else
cat << \SHAR_EOF > 'cux2ascii.c'
/* filter: Citadel/UX messages to UseNet ASCII format messages
 * version 1.01
 */

#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include "citadel.h"
long atol();

getfield(buffer)	/* break out the next null-terminated string */
char buffer[];
 {
	int a;
	a=0;
	do {
		buffer[a]=getc(stdin);
		++a;
		} while(buffer[a-1]!=0);
	return(a);
}

main() {
	char time[50],author[50],recipient[50],room[50],node[50],mid[50];
	int a,b;
	char aaa[100],bbb[50],ccc[100],path[512],ngroup[100];
	char oflag;
	long aa,bb,bcount;
	struct tm *tm;
	char *atime;
	FILE *temp; char tname[30];

	sprintf(tname,"/tmp/c2a.%d",getpid());

NEXTMSG:
	do {
		a=getc(stdin);
		if (a<0) {
			unlink(tname);
			exit(0);
			}
		} while(a!=255);	/* seek to next FF */
	
	strcpy(mid,"");
	strcpy(time,"");
	strcpy(author,"");
	strcpy(recipient,"");		/* zero the description fields */
	strcpy(room,"");
	strcpy(node,NODENAME);
	strcpy(path,"");
	oflag=0;

	a=getc(stdin); a=getc(stdin);	/* skip the anon & format */
	
	do {
		b=getc(stdin);
		if (b=='T') getfield(time);
		if (b=='A') getfield(author);
		if (b=='R') getfield(recipient);
		if (b=='O') getfield(room);
		if (b=='N') getfield(node);
		if (b=='I') getfield(mid);
		if (b=='P') getfield(path);
		} while(b!='M');

	aa=atol(time); bb=aa;
	if (mid[0]!=0) aa=atol(mid);

	temp=fopen(tname,"w"); chmod(tname,0666);
	
	strcpy(aaa,author);
	for (a=0; a<strlen(author); ++a) {
		if (aaa[a]=='.') strcpy(&aaa[a],&aaa[a+1]);
		if (aaa[a]==' ') aaa[a]='_';
		aaa[a]=tolower(aaa[a]);
		}
	oflag=0; strcpy(ccc,node);
for (a=0; a<strlen(node); ++a) if (node[a]==32) { node[a]='_'; oflag=1; }
	strcpy(ngroup,room);
	getngroup(ngroup,room);
	if (path[0]==0) fprintf(temp,"Path: %s!%s\n",NODENAME,aaa);
	if (path[0]!=0) fprintf(temp,"Path: %s\n",path);
	fprintf(temp,"From: %s@%s.uucp (%s)\n",aaa,node,author);
	fprintf(temp,"Subject: %s\n",room);
	fprintf(temp,"Newsgroups: %s\n",ngroup);
	if (recipient[0]!=0) fprintf(temp,"To: %s\n",recipient);
	fprintf(temp,"Message-ID: <%ld@%s.uucp>\n",aa,node);
	tm=(struct tm *)localtime(&bb);
	atime=(char *)asctime(tm);
	fprintf(temp,"Date: %s",atime);
	if (oflag==1) fprintf(temp,"Organization: %s\n",ccc);
	fprintf(temp,"\n");

	fmout(stdin,temp);
	bcount=ftell(temp);
	fclose(temp);
	fseek(temp,0L,0);
	printf("#! rnews %ld\n",bcount);
	temp=fopen(tname,"r");
	for (aa=0L; aa<bcount; ++aa) {
		a=getc(temp);
		putc(a,stdout);
		}
	fclose(temp);
	unlink(tname);
	goto NEXTMSG;
	
}

fmout(fp,mout)
FILE *fp;
FILE *mout;
	{

	int a,b,c,d,e,real,old,width;
	char aaa[100],bbb[100];
	width=80;
	

	strcpy(aaa,""); old=255;
	c=1; /* c is the current pos */
FMTA:	old=real; a=getc(fp); real=a;
	if (a==0) goto FMTEND;
	if (a<0) goto FMTEND;
	
	if ( ((a==13)||(a==10)) && (old!=13) && (old!=10) ) a=32;
	if ( ((old==13)||(old==10)) && (isspace(real)) ) {
						fprintf(mout,"\n"); c=1; }
	if (a>126) goto FMTA;

	if (a>32) {
	if ( ((strlen(aaa)+c)>(width-5)) && (strlen(aaa)>(width-5)) )
		{ fprintf(mout,"\n%s",aaa); c=strlen(aaa); aaa[0]=0; }
	 b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; }
	if (a==32) { 	if ((strlen(aaa)+c)>(width-5)) { 
							fprintf(mout,"\n");
							c=1;
							}
			fprintf(mout,"%s ",aaa); ++c; c=c+strlen(aaa);
			strcpy(aaa,""); goto FMTA; }
	if ((a==13)||(a==10)) {
				fprintf(mout,"%s\n",aaa); c=1;
				strcpy(aaa,""); goto FMTA; }
	goto FMTA;

FMTEND:
	fprintf(mout,"\n");
	return(0);
}

strucmp(st1,st2)
char st1[];
char st2[]; {
	int a;
	char aaa[100],bbb[100];
	for (a=0; a<=strlen(st1); ++a) aaa[a]=tolower(st1[a]);
	for (a=0; a<=strlen(st2); ++a) bbb[a]=tolower(st2[a]);
	a=strcmp(aaa,bbb);
	return(a);
	}

getngroup(ngroup,room)		/* xref table */
char ngroup[];
char room[]; {
	FILE *fp;
	int a,b;
	char aaa[50],bbb[50];
	
	strcpy(ngroup,room);
	fp=fopen("network/rnews.xref","r");
GNA:	strcpy(aaa,""); strcpy(bbb,"");
	do {
		a=getc(fp);
		if (a==',') a=0;
		if (a>0) { b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; }
		} while(a>0);
	do {
		a=getc(fp);
		if (a==10) a=0;
		if (a>0) { b=strlen(bbb); bbb[b]=a; bbb[b+1]=0; }
		} while(a>0);
	if (a<0) {
		fclose(fp);
		return(1);
		}
	if (strucmp(room,bbb)) goto GNA;
	fclose(fp);
	strcpy(ngroup,aaa);
	return(0);
}

SHAR_EOF
fi
echo shar: "extracting 'mailutil.c'" '(5565 characters)'
if test -f 'mailutil.c'
then
	echo shar: "will not over-write existing file 'mailutil.c'"
else
cat << \SHAR_EOF > 'mailutil.c'
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <pwd.h>
#include <setjmp.h>
#include "citadel.h"

struct passwd *getpwuid();
struct passwd *getpwnam();
char *getenv();
long atol();
long lseek();

char *months[12] = {
	"Jan","Feb","Mar","Apr","May","Jun",
	"Jul","Aug","Sep","Oct","Nov","Dec"   };

long finduser(file,name)
int file;
char name[];
{
	struct usersupp temp;
	int a;
	long bottom,top,guess,obottom,otop;

	obottom=(-1L); otop=(-1L);

	bottom=0L;
	top=(lseek(file,0L,2)/(long)sizeof(struct usersupp));

FPT:	if ((obottom==bottom)&&(otop==top)) {
		return(-1L); }
	obottom=bottom; otop=top;
	guess=(((top-bottom)/2)+bottom);
	lseek(file,(guess*(long)sizeof(struct usersupp)),0);
	read(file,&temp,sizeof(struct usersupp));
	a=strucmp(temp.fullname,name);
	if (a==0)
		
		return(lseek(file,(guess*(long)sizeof(struct usersupp)),0));
	if (a<0) {
		bottom=guess;
		goto FPT; }
	if (a>0) {
		top=guess;
		goto FPT; }
}

msgform(spos)
long spos;
	{
	struct tm *tm;
	int width,a,b,c,d,e,real,old,mtype;
	char aaa[100],bbb[100],ttm[3];
	FILE *fp;
	long now;

	width=80;
	fp=fopen("./msgmain","rb");
	if (fp==NULL) {
			printf("No msgmain file.\n");
			return(1); }
	strcpy(aaa,""); old=255;
	c=1; /* c is the current pos */
	fseek(fp,spos,0);
	e=getc(fp);
	if (e!=255) goto END;
	printf("\r\n   ");
	mtype=getc(fp); getc(fp);
	if (mtype==MES_ANON) printf("   ****\r\n");
	goto BONFGM;
A:	old=real; a=getc(fp); real=a;
	if (a==0) goto END;
	if (a<0) goto END;
	
	if ( ((a==13)||(a==10)) && (old!=13) && (old!=10) ) a=32;
	if ( ((old==13)||(old==10)) && (isspace(real)) ) {
						printf("\r\n"); c=1; }
	if (a>126) goto A;

	if (a>32) {
	if ( ((strlen(aaa)+c)>(width-5)) && (strlen(aaa)>(width-5)) )
		{ printf("\r\n%s",aaa); c=strlen(aaa); aaa[0]=0; }
	 b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; }
	if (a==32) { 	if ((strlen(aaa)+c)>(width-5)) { 
							printf("\r\n");
							c=1;
							}
			printf("%s ",aaa); ++c; c=c+strlen(aaa);
			strcpy(aaa,""); goto A; }
	if ((a==13)||(a==10)) {
				printf("%s\r\n",aaa); c=1;
				strcpy(aaa,""); goto A; }
	goto A;

END:	fclose(fp);
	printf("\r\n");
	return(0);

BONFGM:	b=getc(fp);
	if (b=='M') { printf("\r\n "); goto A; }
	fpgetfield(fp,bbb);
	if (mtype==MES_ANON) goto SKIPFGM;
	if (b=='A') printf("from %s ",bbb);
	if (b=='O') printf("in %s> ",bbb);
	if (b=='R') printf("to %s ",bbb);
	if (b=='T') { now=atol(bbb);
		tm=(struct tm *)localtime(&now);
		sprintf(ttm,"%2d",tm->tm_min);
		if (ttm[0]==32) ttm[0]=48;
		printf("%s %2d, %4d %2d:%2s ",
			months[tm->tm_mon],
			tm->tm_mday,(1900+tm->tm_year),
			tm->tm_hour,ttm); }
SKIPFGM:
	goto BONFGM;
}

fpgetfield(fp,string)
FILE *fp;
char string[];
{
int a,b,c;
strcpy(string,"");
a=0;
GFXYZAF:
	b=getc(fp);
	if (b<1) { string[a]=0; return(0); }
	string[a]=b;
	++a;
	if (b!=0) goto GFXYZAF;
}

main()
 {
char uname[30];
char aaa[100];
struct usersupp usersupp;
int a,b,c,file;
long upos;

	printf("Enter username: ");
	gets(uname);

	file=open("usersupp",O_RDONLY);
	upos=finduser(file,uname);
	if (upos==(-1)) {
		printf("No such user.\n");
		close(file);
		exit(0);
		}
	close(file);

A:	for (a=0; a<(27-(MAILSLOTS/2)); ++a) printf("\n");
	file=open("usersupp",O_RDONLY);
	lseek(file,upos,0);
	read(file,&usersupp,sizeof(struct usersupp));
	close(file);
	strcpy(uname,usersupp.fullname);
	printf("Mailbox for user: %s\n",uname);
	for (a=0; a<=MAILSLOTS/2; ++a) {
		printf("%2d. %7ld %-7ld                     ",
				a,usersupp.mailnum[a],usersupp.mailpos[a]);
		b=(a+(MAILSLOTS/2)+1); if (b<MAILSLOTS)
			printf("%2d. %7ld %-7ld",
			b,usersupp.mailnum[b],usersupp.mailpos[b]);
		printf("\n");
		}
	printf("\nEnter command [dirq] : ");
	gets(aaa);
	a=tolower(aaa[0]);
	switch(a) {
	 case 'q':	exit(0);
			break;
	 case 'd':	printf("Enter slot number to delete (-1 to abort): ");
			gets(aaa);
			a=atol(aaa);
			if ((a<0)||(a>=MAILSLOTS)) break;
			file=open("usersupp",O_RDWR);
			lseek(file,upos,0);
			read(file,&usersupp,sizeof(struct usersupp));
			for (b=a; b>=1; --b) {
				usersupp.mailnum[b]=usersupp.mailnum[b-1];	
				usersupp.mailpos[b]=usersupp.mailpos[b-1];
				}
			usersupp.mailnum[0]=0L;
			usersupp.mailpos[0]=0L;
			lseek(file,upos,0);
			write(file,&usersupp,sizeof(struct usersupp));
			close(file);
			break;
	case 'i':	file=open("usersupp",O_RDWR);
			lseek(file,upos,0);
			read(file,&usersupp,sizeof(struct usersupp));
			for (a=0; a<(MAILSLOTS-1); ++a) {
				usersupp.mailnum[a]=usersupp.mailnum[a+1];
				usersupp.mailpos[a]=usersupp.mailpos[a+1];
				}
			printf("Enter msgnum: ");
			gets(aaa);
			usersupp.mailnum[MAILSLOTS-1]=atol(aaa);
			printf("Enter msgpos: ");
			gets(aaa);
			usersupp.mailpos[MAILSLOTS-1]=atol(aaa);
			lseek(file,upos,0);
			write(file,&usersupp,sizeof(struct usersupp));
			close(file);
	case 'r':	file=open("usersupp",O_RDONLY);
			lseek(file,upos,0);
			read(file,&usersupp,sizeof(struct usersupp));
			close(file);
			printf("Slot number (return for all): ");
			gets(aaa);
			if (aaa[0]==0) {
				for (a=0; a<MAILSLOTS; ++a) {
					msgform(usersupp.mailpos[a]);
					gets(aaa);
					}
				}
			else {
				a=atol(aaa);
			if ((a>=0)&&(a<MAILSLOTS)) msgform(usersupp.mailpos[a]);
				gets(aaa);
				}
	default:	break;
	 }
	goto A;

}

strucmp(st1,st2)
char st1[],st2[]; {
	char aaa[100],bbb[100];
	int a;
	strcpy(aaa,st1);
	strcpy(bbb,st2);
	for (a=0; a<strlen(aaa); ++a) aaa[a]=tolower(aaa[a]);
	for (a=0; a<strlen(bbb); ++a) bbb[a]=tolower(bbb[a]);
	a=strcmp(aaa,bbb);
	return(a);
}
SHAR_EOF
fi
echo shar: "extracting 'messages.c'" '(8947 characters)'
if test -f 'messages.c'
then
	echo shar: "will not over-write existing file 'messages.c'"
else
cat << \SHAR_EOF > 'messages.c'

/* Citadel/UX message routines
 * 
 * contents:
 * 
 * read_message() - called by Read routines to print messages
 * send_message() - read message in temp file & store in msgmain
 * make_message() - assemble temp message file - msg editor
 * msgform()      - msg formatter / called by read_message() and others
 * pull_message() - pull message out of msgmain into temp file
 */

#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.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 IFUPASS if (upass!=0)
#define IFNUPASS if (upass==0)
#define IFAIDE if (usersupp.axlevel>=6)
#define IFNAIDE if (usersupp.axlevel<6)
long atol();
long lseek();

extern int curr_rm;
extern struct usersupp usersupp;
extern struct quickroom quickroom;
extern jmp_buf nextbuf;
extern int (*backnext())();
extern int (*backstop())();
extern char *months[];

read_message(pos)	/* Read a message from the master file */
long pos;			/* Position in master file */
{
	int a;
	a=setjmp(nextbuf);
	sttybbs(0);
	if ((a==1)||(a==2)) {
		printf("\n\n");
		return(a);
		}
	signal(SIGINT,(*backnext));
	signal(SIGQUIT,(*backstop));
	sttybbs(1);
	msgform(usersupp.screenwidth,pos,"msgmain");
	sttybbs(0);
	return(0);
}

send_message(filename,retbuf)	/* send a message to the master file */
char filename[];		/* tempfilename of proper message */
struct smreturn *retbuf;	/* return information */
{

int file,a,c,d,file2;
long bb,cc,templen,hibytes,origpos;
char sbuf[BUFSIZ];
char mid[30];
FILE *fp;
struct msgmain msgmain;

	file=open("MMstructure",O_RDWR);
	if (file<0) interr(13);

	do {
		lseek(file,0L,0);
		a=read(file,&msgmain,sizeof(struct msgmain));
		if (a<1) interr(14);
		} while(msgmain.MMflags & MM_BUSY);

	lseek(file,0L,0);
	msgmain.MMflags=(msgmain.MMflags|MM_BUSY);
	a=write(file,&msgmain,sizeof(struct msgmain)); if (a<1) interr(16);
	close(file);
	origpos=msgmain.MMcurpos;
	++msgmain.MMhighest;
	sprintf(mid,"I%ld",msgmain.MMhighest);
/* measure the message */
file=open(filename,O_RDONLY); if (file<0) interr(17);
templen=lseek(file,0L,2);
close(file);
templen=templen+(long)strlen(mid);
++templen;

/* check for FF bytes */
hibytes=0L;
fp=fopen("msgmain","rb");
if (fp==NULL) interr(18);
bb=fseek(fp,msgmain.MMcurpos,0);

cc=ftell(fp);
for (bb=0L; bb<templen; ++bb) {
	if (cc>=MM_FILELEN) cc=fseek(fp,0L,0);
	c=getc(fp); ++cc;
	if (c>127) ++hibytes;		/* bump count if hi bit set */
	}

fclose(fp);
msgmain.MMlowest=msgmain.MMlowest+hibytes;

file=open("msgmain",O_RDWR);
cc=lseek(file,msgmain.MMcurpos,0);
file2=open(filename,O_RDONLY); if (file2<0) interr(19);
cc=lseek(file,0L,1);
d=read(file2,sbuf,3);
write(file,sbuf,d);
write(file,mid,strlen(mid));
d=0; write(file,&d,1);
do {
	d=read(file2,sbuf,BUFSIZ);
	write(file,sbuf,d);
	cc=cc+(long)d;
	if (((long)cc)>=((long)MM_FILELEN)) cc=lseek(file,0L,0);
	} while(d>0);

msgmain.MMcurpos=lseek(file,0L,1);
close(file2);	/* done with temp file */
close(file);	/* done with master file */

/* now update the message structure */

msgmain.MMflags=msgmain.MMflags & ~MM_BUSY;

file=open("MMstructure",O_RDWR); if (file<0) interr(20);
a=write(file,&msgmain,sizeof(struct msgmain)); if (a<1) interr(21);
close(file);

retbuf->smnumber=msgmain.MMhighest;
retbuf->smpos=origpos;

return(0);
}

make_message(filename,author,recipient,room,type,mode)
char filename[];	/* temporary file name */
struct usersupp *author;  /* author's usersupp structure */
char recipient[];	/* NULL if it's not mail */
char room[];		/* room where it's going */
int type;		/* see MES_ types in header file */
int mode;		/* 0 for normal, 1 for ASCII */
{ 
	FILE *fp;
	int a,b,old;
	long aa,beg,now;
	char aaa[100],bbb[100]; 

	time(&now);
	fp=fopen(filename,"wb"); if (fp==NULL) interr(22);
	putc(255,fp);
	putc(type,fp);	/* Normal or anonymous, see MES_ flags */
	putc(mode,fp);	/* Formatted or unformatted */
	strcpy(aaa,author->fullname);
	for (a=0; a<strlen(aaa); ++a) {
		aaa[a]=tolower(aaa[a]);
		if (aaa[a]==32) aaa[a]='_';
		if (aaa[a]=='!') strcpy(&aaa[a],&aaa[a+1]);
		}
	fprintf(fp,"P%s",aaa); putc(0,fp);			/* path */
	fprintf(fp,"T%ld",now); putc(0,fp);			/* date/time */
	fprintf(fp,"A%s",author->fullname); putc(0,fp);		/* author */
	fprintf(fp,"O%s",quickroom.QRname); putc(0,fp);		/* room */
	fprintf(fp,"N%s",NODENAME); putc(0,fp);			/* node */
	if (recipient[0]!=0) { fprintf(fp,"R%s",recipient); putc(0,fp); }
	fflush(fp);
	msgform(usersupp.screenwidth,0L,filename);
	putc('M',fp);
	if (mode==1) printf("(Press ctrl-d when finished)\n");
	beg=ftell(fp); old=1;
	if (mode==1) goto ME2;
ME1:	a=inkey(); a=(a&127);
	aa=ftell(fp);
	if ((a==8)&&(aa>beg)) {
		back(1); fseek(fp,-1L,1); goto ME1; }
	if ((a<32)&&(a!=13)) goto ME1;
	putc(a,stdout);
	if ((old==13)&&(a==13)) goto MECR;
	putc(a,fp); if (a==13) putc(10,stdout);
	old=a;
	goto ME1;

ME2:	a=inkey(); if (a==255) a=32;
	if (a==4) goto MECR;
	putc(a,fp); putc(a,stdout);
	if (a==13) putc(10,stdout);
	goto ME2;

MECR:	putc(0,fp); fseek(fp,-1L,1); fflush(fp);
	printf("<A>bort <C>ontinue <P>rint <S>ave -> ");
MECR2:	b=inkey(); b=(b&127); b=tolower(b);
	if (b=='a') { printf("Abort\n");	goto MEABT; }
	if (b=='c') { printf("Continue\n");
		if (mode==0) goto ME1;
		if (mode==1) goto ME2; }
	if (b=='s') { printf("Save buffer\n"); goto MEFIN; } 
	if (b=='p') { printf("Print formatted\n");
		msgform(usersupp.screenwidth,0L,filename);
		goto MECR; }
	goto MECR2;

MEFIN:	putc(0,fp);
	fclose(fp);
	return(0);

MEABT:	printf("Are you sure? ");
	if (yesno()==0) goto ME1;
	fseek(fp,0L,0);
	putc(0,fp);
	putc(0,fp);
	fclose(fp);
	return(2);

}

msgform(width,spos,msgfile)
int width;
long spos;
char *msgfile;
	{
	struct tm *tm;
	int a,b,c,e,real,old,mtype,aflag;
	char aaa[100],bbb[100],ttm[3],ap;
	FILE *fp;
	long now;

	fp=fopen(msgfile,"rb");
	if (fp==NULL) return(1);
	strcpy(aaa,""); old=255;
	c=1; /* current column pos */
	fseek(fp,spos,0);
	e=getc(fp);
	if (e!=255) {
		printf("*** CANNOT LOCATE MESSAGE / pos=%ld\n",spos);
		goto END;
		}
	mtype=getc(fp); aflag=getc(fp);
	printf("\n   ");
	if (mtype==MES_ANON) printf("****\n");
	if (mtype==MES_AN2) printf("<anonymous> ");
	goto BONFGM;
A:	if (aflag==1) goto AFLAG;
	old=real; a=getc(fp); real=a;
	if (a==0) goto END;
	if (a<0) goto END;
	
	if ( ((a==13)||(a==10)) && (old!=13) && (old!=10) ) a=32;
	if ( ((old==13)||(old==10)) && ((real==32)||(real==13)||(real==10))) {
						printf("\n"); c=1; }
	if (a!=32) {
	if ( ((strlen(aaa)+c)>(width-4)) && (strlen(aaa)>(width-4)) )
		{ printf("\n%s",aaa); c=strlen(aaa); aaa[0]=0; }
	 b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; }
	if (a==32) { 	if ((strlen(aaa)+c)>(width-5)) { 
							printf("\n");
							c=1;
							}
			printf("%s ",aaa); ++c; c=c+strlen(aaa);
			strcpy(aaa,""); goto A; }
	if ((a==13)||(a==10)) {
				printf("%s\n",aaa); c=1;
				strcpy(aaa,""); goto A; }
	goto A;

AFLAG:	a=getc(fp); if (a==0) goto END;
	if ((a<32)&&(a!=13)&&(a!=10)) a='.';
	putc(a,stdout); if (a==13) putc(10,stdout);
	goto AFLAG;

END:	fclose(fp);
	printf("\n");
	return(0);

BONFGM:	b=getc(fp); if (b<0) goto END;
	if (b=='M') {
		printf("\n");
		goto A;
		}
	fpgetfield(fp,bbb);
	if ( (usersupp.axlevel<6)
		&& (usersupp.eternal!=quickroom.QRroomaide) )
			if ((mtype==MES_ANON)||(mtype==MES_AN2)) goto BONFGM;
	if (b=='A') printf("from %s ",bbb);
#ifdef SEEMID
	if ((b=='I')&&(usersupp.axlevel>=6)) printf("#%s ",bbb);
#endif		/* define SEEMID if you wish to see message ID's in header */

	if ((b=='N')&&(strucmp(bbb,NODENAME))&&(curr_rm==1))
		printf("@ %s ",bbb);
	if ((b=='O')&&(strucmp(bbb,quickroom.QRname))) printf("in %s> ",bbb);
	if ((b=='N')&&(quickroom.QRflags&QR_NETWORK))
		printf("@ %s ",bbb);
	if (b=='R') printf("to %s ",bbb);
	if (b=='T') {
		now=atol(bbb);
		tm=(struct tm *)localtime(&now);
		sprintf(ttm,"%2d",tm->tm_min);
		if (ttm[0]==32) ttm[0]=48;
		ap='a'; if ((tm->tm_hour)>12) {
			tm->tm_hour=((tm->tm_hour)-12);
			ap='p';
			}
		printf("%d-%s-%4d %d:%2s%cm ",
			tm->tm_mday,months[tm->tm_mon],
			(1900+tm->tm_year),
			tm->tm_hour,ttm,ap);
		}
	goto BONFGM;
}

pull_message(spos,flnm)		/* Pull a message out of the master file */
long spos;			/* position in master file */
char *flnm;			/* file to write to */
{
	int a,b,c;
	int file,file2;
	long cc;
	char field[512];
	char fwork[512];

	file2=creat(flnm,0666);
	file=open("msgmain",O_RDONLY);
	lseek(file,spos,0);

	for (a=0; a<3; ++a) {
		read(file,&b,1);
		write(file2,&b,1);
		}
PI:	b=0; read(file,&b,1);
	if (b=='M') {
		write(file2,&b,1);
		goto B;
		}
	getfield(file,field);
	if (b!='I') {
		write(file2,&b,1);
		write(file2,field,strlen(field)+1);
		}
	goto PI;

B:	cc=lseek(file,0L,1);
C:	if (cc>=MM_FILELEN) cc=lseek(file,0L,0);
	c=0; read(file,&c,1); ++cc;
	write(file2,&c,1);
	if (c!=0) goto C;

	close(file); close(file2);
	return(0);
}
SHAR_EOF
fi
echo shar: "extracting 'msgform.c'" '(3587 characters)'
if test -f 'msgform.c'
then
	echo shar: "will not over-write existing file 'msgform.c'"
else
cat << \SHAR_EOF > 'msgform.c'
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.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 IFUPASS if (upass!=0)
#define IFNUPASS if (upass==0)
#define IFAIDE if (usersupp.flags&US_AIDE)
#define IFNAIDE if ((usersupp.flags&US_AIDE)==0)
long atol();
long lseek();

char *months[]={"Jan","Feb","Mar","Apr","May","Jun",
		"Jul","Aug","Sep","Oct","Nov","Dec"};

main(argc,argv)
int argc;
char *argv[]; {
	if (argc==1) msgform(0L,"",0);
	if (argc==2) msgform(0L,argv[1],0);
	if (argc==3) msgform(atol(argv[2]),argv[1],0);
	if (argc==4) msgform(atol(argv[2]),argv[1],1);
	exit(0);
	}

msgform(spos,msgfile,mflag)
long spos;
char msgfile[];
int mflag;
	{
	struct tm *tm;
	int a,b,c,d,e,real,old,mtype,aflag,width;
	char aaa[100],bbb[100],ttm[3],ap;
	char A[30],R[30],T[30],N[30],O[30];
	char flnm[20];
	FILE *fp;
	long now;

	width=80;

	strcpy(flnm,msgfile);
	if (!strcmp(flnm,"-m")) {
		strcpy(flnm,"/usr/bbs/msgmain");
		mflag=1;
		}
	if (flnm[0]==0) fp=stdin;
		else fp=fopen(flnm,"rb");
	if (fp==NULL) return(1);
	fseek(fp,spos,0);
LOOP:	strcpy(aaa,""); old=255;
	c=1; /* current column pos */
	do {
		e=getc(fp);
		if (e<0) {
			fclose(fp);
			return(0);
			}
		} while(e!=255);
	if (e!=255) {
		printf("===> CANNOT LOCATE MESSAGE / pos=%ld\n",spos);
		goto END; }
	mtype=getc(fp); aflag=getc(fp);
	goto BONCLR;

AA:	if ((mflag==1)&&(strcmp(O,"Mail"))) {
		do { a=getc(fp);
			} while(a!=0);
		goto LOOP;
		}
	printf("\n   ");
	if (mtype==MES_ANON) printf("****\n");
	if (mtype==MES_AN2) printf("<anonymous> ");
	if (T[0]!=0) printf("%s ",T);
	if (A[0]!=0) printf("from %s ",A);
	if (R[0]!=0) printf("to %s ",R);
	if (O[0]!=0) printf("in %s> ",O);
	if (N[0]!=0) printf("@ %s ",N);
	printf("\n");
AAA:	if (aflag==1) goto AFLAG;
	old=real; a=getc(fp); real=a;
	if (a==0) goto END;
	if (a<0) goto END;
	
	if ( ((a==13)||(a==10)) && (old!=13) && (old!=10) ) a=32;
	if ( ((old==13)||(old==10)) && ((real==32)||(real==13)||(real==10))) {
						printf("\n"); c=1; }

	if (a!=32) {
	if ( ((strlen(aaa)+c)>(width-4)) && (strlen(aaa)>(width-4)) )
		{ printf("\n%s",aaa); c=strlen(aaa); aaa[0]=0; }
	 b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; }
	if (a==32) { 	if ((strlen(aaa)+c)>(width-5)) { 
							printf("\n");
							c=1;
							}
			printf("%s ",aaa); ++c; c=c+strlen(aaa);
			strcpy(aaa,""); goto AAA; }
	if ((a==13)||(a==10)) {
				printf("%s\n",aaa); c=1;
				strcpy(aaa,""); goto AAA; }
	goto AAA;

AFLAG:	a=getc(fp); if (a==0) goto END;
	putc(a,stdout); if (a==13) putc(10,stdout);
	goto AFLAG;

END:
	printf("\n");
	goto LOOP;

BONCLR:	strcpy(A,""); strcpy(R,""); strcpy(T,""); strcpy(O,""); strcpy(N,"");
BONFGM:	b=getc(fp); if (b<0) goto END;
	if (b=='M') goto AA;
	fpgetfield(fp,bbb);
	if (b=='A') strcpy(A,bbb);
	if (b=='N') strcpy(N,bbb);
	if (b=='O') strcpy(O,bbb);
	if (b=='R') strcpy(R,bbb);

	if (b=='T') { now=atol(bbb);
		tm=(struct tm *)localtime(&now);
		sprintf(ttm,"%2d",tm->tm_min);
		if (ttm[0]==32) ttm[0]=48;
		ap='a'; if ((tm->tm_hour)>12) {
			tm->tm_hour=((tm->tm_hour)-12);
			ap='p';
			}
		sprintf(T,"%d-%s-%4d %d:%2s%cm ",
			tm->tm_mday,months[tm->tm_mon],
			(1900+tm->tm_year),
			tm->tm_hour,ttm,ap);
		}
	goto BONFGM;
}
fpgetfield(fp,string)
FILE *fp;
char string[];
{
int a,b;
strcpy(string,"");
a=0;
	do {
		b=getc(fp);
		if (b<1) { string[a]=0; return(0); }
		string[a]=b;
		++a;
		} while(b!=0);
}
SHAR_EOF
fi
echo shar: "extracting 'msgstats.c'" '(437 characters)'
if test -f 'msgstats.c'
then
	echo shar: "will not over-write existing file 'msgstats.c'"
else
cat << \SHAR_EOF > 'msgstats.c'
#include <fcntl.h>
#include "citadel.h"

main() {
	int file,a,b,c;
	struct msgmain msgmain;
	
	file=open("./MMstructure",O_RDONLY);
	read(file,&msgmain,sizeof(struct msgmain));
	close(file);
	
printf("Messages numbered %ld to %ld\n",msgmain.MMlowest,msgmain.MMhighest);
printf("Current file position: %ld\n",msgmain.MMcurpos);
if (msgmain.MMflags & MM_BUSY) 
	printf("File is locked.\n");
else
	printf("File is unlocked.\n");
exit(0);
}
SHAR_EOF
fi
echo shar: "done with directory 'source'"
cd ..
exit 0
#	End of shell archive
-- 
     Some do, some don't.           |       eric@sactoh0.SAC.CA.US
    Some will, some won't.          |      ames!pacbell!sactoh0!eric
          I might!                  |      ucbvax!csusac!sactoh0!eric
                                    |     ( A Home For Unwanted 3B's )