[alt.sources] cit301.part6

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 13:03:01 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 'aidepost.c'" '(4213 characters)'
if test -f 'aidepost.c'
then
	echo shar: "will not over-write existing file 'aidepost.c'"
else
cat << \SHAR_EOF > 'aidepost.c'
/* aidepost.c
 * v1.3
 * posts standard input to Aide> room
 * updated to include I (orig sys msg #) field and P (path) field
 */

#include <stdio.h>
#include <fcntl.h>
#include "citadel.h"
char temp[20];

long lseek();
long atol();

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;
	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);
	putc(255,fp);
	putc(MES_NORMAL,fp);
	putc(1,fp);
	fprintf(fp,"Psysop"); putc(0,fp);
	fprintf(fp,"T%ld",now); putc(0,fp);
	fprintf(fp,"ACitadel"); putc(0,fp);
	fprintf(fp,"OAide"); putc(0,fp);
	fprintf(fp,"N%s",NODENAME); putc(0,fp);
	putc('M',fp);
	bb=ftell(fp);
	while ((a=getc(stdin))>0) {
		if (a!=8) putc(a,fp);
		else {
			cc=ftell(fp);
			if (cc!=bb) fseek(fp,(-1L),1);
			}
		}
MEFIN:	putc(0,fp);
	fclose(fp);
	return(0);

}

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

	chdir(BBSDIR);
	sprintf(temp,"/tmp/ap%d",getpid());
	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 'netmailer.c'" '(5806 characters)'
if test -f 'netmailer.c'
then
	echo shar: "will not over-write existing file 'netmailer.c'"
else
cat << \SHAR_EOF > 'netmailer.c'
/*
 * netmailer for network release 1.4
 * by Art Cancro - March 1989
 * see copyright.doc for copyright information
 *
 * Not responsible for porting problems!!!
 * (although this one should be significantly easier than 1.1)
 *
 * This program allows Citadel/UX users to send network mail.
 * It is invoked by citadel with these arguments:
 * argv[1] = string pointer containing the temp file name of a binary message.
 * argv[2] = pointer to an integer containing the mailtype (see header file)
 *
 * The program may not be invoked from the shell.
 *
 * Place this program in your citadel directory, NOT /usr/lib/mail.
 */

#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include "citadel.h"

char temp[20];
long lseek();
long atol();
char *months[] = {	"Jan","Feb","Mar","Apr","May","Jun",
			"Jul","Aug","Sep","Oct","Nov","Dec" };

main(argc,argv)
int argc;
char *argv[];
{
	int a,mailtype;
	FILE *fp;
	char sbuf[200],rbuf[200],cstr[100];
	
	sprintf(temp,"/tmp/CMail.%d",getpid());	/* temp file name */
	mailtype=(*argv[2]);

switch(mailtype) {

   case M_UUCP: /* send message using uucp mail facility */
	fp=fopen(temp,"w");
	msgform(argv[1],fp,sbuf,rbuf); /* convert to ASCII & get sndr/recp */
	fclose(fp);

	/* replace spaces with underscores, to avoid mailer problems */
	for (a=0; a<strlen(sbuf); ++a) if (sbuf[a]==32) sbuf[a]='_';
	for (a=0; a<strlen(rbuf); ++a) if (rbuf[a]==32) rbuf[a]='_';

	/* this line is quite tricky, it pipes the message through rmail */
	sprintf(cstr,"(echo From %s remote from %s; cat %s) |rmail %s",
		sbuf,NODENAME,temp,rbuf);

	system(cstr);	/* execute the mailer command */
	break;
  
   case M_BINARY: /* send mail using Citadel network facility */
	citnetmail(argv[1]);
	break;

   }

unlink(temp);		/* get rid of the ASCII file */
unlink(argv[1]);	/* netmailer is responsible for removal of this */
exit(0);		/* go back to the main program */
}

/* This is NOT the same msgform() found in the main program. It has been
 * modified to format 80 columns into a temporary file, and extract the
 * sender and recipient names for use within the main() loop.
 */
msgform(msgfile,mfout,sbuf,rbuf)
char *msgfile;
FILE *mfout;
char *sbuf;
char *rbuf;
	{
	struct tm *tm;
	int a,b,c,d,e,real,old,mtype,aflag;
	char aaa[100],bbb[100],ttm[3];
	FILE *fp;
	long now;
	int width;
	long spos;
		
	width=80;
	spos=0L;
	fp=fopen(msgfile,"rb");
	if (fp==NULL) {
			fprintf(stderr,"netmailer: can't open message 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) {
		fprintf(stderr,"Can't find message! Start Byte=%ld\n",spos);
		goto END; }
	mtype=getc(fp); aflag=getc(fp);
	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))) {
						fprintf(mfout,"\n"); c=1; }

	if (a!=32) {
	if ( ((strlen(aaa)+c)>(width-5)) && (strlen(aaa)>(width-5)) )
		{ fprintf(mfout,"\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(mfout,"\n");
							c=1;
							}
			fprintf(mfout,"%s ",aaa); ++c; c=c+strlen(aaa);
			strcpy(aaa,""); goto A; }
	if ((a==13)||(a==10)) {
				fprintf(mfout,"%s\n",aaa); c=1;
				strcpy(aaa,""); goto A; }
	goto A;

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

END:	fclose(fp);
	return(0);

BONFGM:	b=getc(fp); if (b<0) goto END;
	if (b=='M') goto A;
	fpgetfield(fp,bbb);
	if (b=='A') strcpy(sbuf,bbb);
	if (b=='R') strcpy(rbuf,bbb);
	goto BONFGM;
}

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

citnetmail(flnm)	/* process and send binary mail */
char flnm[];	{	/* filename of temp file containing message */
	int file,a,b,c;
	long pos;
	FILE *fp;
	char name[100];
	char netcmd[256],netraw[256];

	file=open(flnm,O_RDWR); if (file<0) return(-1); b=c=(-1);
	do { 
		c=b; b=0; a=read(file,&b,1);
		if (a==0) {
			close(file); return(-1);
			}
		} while((b!='R')&&(c!=0));
	do {
		b=0; a=read(file,&b,1);
		if (a==0) {
			close(file); return(-1);
			}
		} while(b!='@');
	lseek(file,(-2L),1);
	write(file,"\000D",2);
	name[0]=0;
	do {
		b=0; a=read(file,&b,1);
		c=strlen(name);
		name[c]=b; name[c+1]=0;
		} while(b!=0);
	close(file);
	sysinfo(name);
	sprintf(netcmd,"network/systems/%s",name);
	fp=fopen(netcmd,"r"); if (fp==NULL) return(-1);
	fgets(netraw,256,fp);
	fclose(fp);
	sprintf(netcmd,netraw,flnm);
	system(netcmd);
	return(0);
	}

sysinfo(name)	/* determine routing from sysinfo file */
char name[]; {
	int file,a;
	char aaa[100];
	file=open("network/mail.sysinfo",O_RDONLY);
GETSN:	do {
		a=getstring(file,aaa);
		} while ((a>=0)&&(strucmp(aaa,name)));
	a=getstring(file,aaa);
	if (!strncmp(aaa,"use ",4)) {
		strcpy(name,&aaa[4]);
		goto GETSN;
		}
	close(file);
	if (!strncmp(aaa,"bin",3)) {
		return(0);
		}
	printf("Error in network/mail.sysinfo file\n");
	return(-1);
	}

getstring(file,string)		/* get a line of text from a file */
int file; char string[]; {	/* ignores lines beginning with # */
int a,b,c;
do {
	strcpy(string,"");
	a=0;
	do {
		c=0; b=read(file,&c,1);
		if (b<1) { string[a]=0; return(-1); }
		string[a]=c;
		++a;
		} while(c!=10);
		string[a-1]=0;
	} while(string[0]=='#');
return(strlen(string));
}

strucmp(st1,st2) /* Compares two strings without case sensitivity */
char st1[],st2[]; {
char aaa[100],bbb[100];
int a;
	for (a=0; a<=strlen(st1); ++a) aaa[a]=tolower(st1[a]);
	for (a=0; a<=strlen(st2); ++a) bbb[a]=tolower(st2[a]);
	return(strcmp(aaa,bbb));
	}
SHAR_EOF
fi
echo shar: "extracting 'netproc.c'" '(15863 characters)'
if test -f 'netproc.c'
then
	echo shar: "will not over-write existing file 'netproc.c'"
else
cat << \SHAR_EOF > 'netproc.c'
/*
 * Citadel/UX Network Processor v1.52
 * designed and written by Art Cancro @ Uncensored Communications Group
 * see copyright.doc for copyright information
 * 
 *
 * History:
 * 08/01/88 AJC - Wrote v1.0
 *   /  /88 AJC - Rewrote inbound processor
 *              - Added shell command to do the dirty work of looking in
 *                the spoolin directory for inbound network files
 *   /  /88 AJC - Moved use table check into a function call
 *              - Changed usetable code to use originating message ID ("I"
 *                field) in table rather than message time. Time is still used
 *                if no I field is present.
 *   /  /88 AJC - Modified outbound side to not send a system its own messages
 * 10/28/88 AJC - Fixed bug that would screw up the use table if the
 *                originating system's name exceeded 19 characters.
 *              - Increased size of minfo buffers to handle big Henge names.
 *              - Annoying error messages from empty spoolin diverted to null
 * 11/25/88 AJC - Added software to look at P (path) field and not send a
 *		  message to a system if it's already been there
 * 05/30/89 AJC - Added mail routing based on D (destination system) field
 *              - Added routines to accept binary mail
 * 06/11/89 AJC - Oops! Fixed bug that caused mail arriving in rooms other than
 *                mail to be posted publicly AND privately. (One Nasty Bug)
 * 08/15/89 AJC - Read entire use table into memory during inbound processing,
 *                which writes it back to disk when finished. NOTE! If you have
 *                multiple netproc processes running concurrently, you MUST add
 *                some sort of locking code!
 *
 */

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

long atol();
long lseek();

struct recentmsg usemsgs[PREVMSGS];
int usepos;

struct minfo {
	char A[30];
	long I;
	char N[30];
	char O[30];
	char R[30];
	long T;
	char D[30];
	};


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; }
}



main(argc,argv)
int argc;
char *argv[];
{
	if (argc==2) outprocess(argv[1]);
	inprocess();
	exit(0);
}

inprocess() {	/* Process incoming files in ./network/spoolin */
	FILE *fp,*message;
	struct minfo minfo;
	struct recentmsg recentmsg;
	struct smreturn smreturn;
	char tname[50],aaa[100],iname[50];
	int a;

	sprintf(tname,"/tmp/net.t%d",getpid());	/* temp file name */
	sprintf(iname,"/tmp/net.i%d",getpid());	/* temp file name */

	if (readusetable()==1) {
		fprintf(stderr,"netproc: no use table online\n");
		fprintf(stderr,
	"         inbound is already running or netsetup needs to be run\n");
		return(1);
		}

	/* Let the shell do the dirty work. Get ALL data from spoolin */
sprintf(aaa,"for x in network/spoolin/*; do cat <$x; rm $x; done 2>/dev/null");
	fp=(FILE *)popen(aaa,"r");

NXMSG:	/* Break out the next message */
	do {
		a=getc(fp);
		} while((a!=255)&&(a>=0));
	if (a<0) goto ENDSTR;
	message=fopen(tname,"w");
	putc(255,message);
ZFLD:	do {
		a=getc(fp);
		putc(a,message);
		} while(a!=0);
	a=getc(fp);
	putc(a,message);
	if (a!='M') goto ZFLD;
	do {
		a=getc(fp);
		putc(a,message);
		} while(a>0);
	fclose(message);

	/* process the individual mesage */
	minfo.D[0]=0;
	msgfind(tname,&minfo);
	strncpy(recentmsg.RMnodename,minfo.N,19);
	recentmsg.RMnodename[19]=0;
	recentmsg.RMnum=minfo.I;
	a=usetable(&recentmsg);
	if (a==0) printf("Accept: ");
	if (a==1) printf("Reject: ");
	if (a==2) printf("Garbge: ");
	if (a>=3) printf("UKretn: ");
	printf("#%ld fm %s in %s @ %s\n",
		minfo.I,minfo.A,minfo.O,minfo.N);
	if (a!=0) goto SKMSG;
	if ((strucmp(minfo.D,NODENAME))&&(minfo.D[0]!=0)) { 
		sysinfo(minfo.D);
		ship_to(tname,minfo.D);
		}
	else {
		send_message(tname,&smreturn);
		if (minfo.R[0]!=0) {
			a=mail_to(minfo.R,&smreturn);
			if (a<0) file_message("Aide",&smreturn);
			}
		else {
			file_message(minfo.O,&smreturn);
			}
		}

SKMSG:	unlink(tname);
	goto NXMSG;

ENDSTR:	fclose(fp);
	unlink(iname);
	writeusetable();
	return(0);
}

readusetable() {
	int file;
	file=open("./network/prevmsgs",O_RDONLY);
	if (file<0) return(1);
	read(file,&usemsgs[0],(PREVMSGS*sizeof(struct recentmsg)));
	close(file);
	file=open("./network/prevmsgs.pos",O_RDONLY);
	usepos=0; read(file,&usepos,sizeof(usepos));
	close(file);
	return(0);
	}

writeusetable() {
	int file;
	file=open("./network/prevmsgs",O_WRONLY);
	write(file,&usemsgs[0],(PREVMSGS*sizeof(struct recentmsg)));
	close(file);
	file=open("./network/prevmsgs.pos",O_WRONLY);
	write(file,&usepos,sizeof(usepos));
	close(file);
	return(0);
	}

usetable(msg)		/* check use table	   */
struct recentmsg *msg;	/* returns 0 if ok to post */
	{
	int file3,a;
	struct recentmsg recent2;

	if ((msg->RMnum)<=0L) return(2);	/* can't use garbage ID's */
	for (a=0; a<PREVMSGS; ++a) {
		if ((!strucmp(msg->RMnodename,usemsgs[a].RMnodename))
			&&(msg->RMnum==usemsgs[a].RMnum)) {
				return(1);
				}
		}
	++usepos; if (usepos==PREVMSGS) usepos=0;
	usemsgs[usepos].RMnum=(msg->RMnum);
	strcpy(usemsgs[usepos].RMnodename,(msg->RMnodename));
	return(0);
}

msgfind(msgfile,buffer)
char *msgfile;
struct minfo *buffer;
	{
	struct tm *tm;
	int a,b,c,d,e,real,old,mtype,aflag;
	char aaa[100],bbb[100],ttm[3];
	FILE *fp;
		
	fp=fopen(msgfile,"rb");
	if (fp==NULL) {
			fprintf(stderr,"Can't open message file\n");
			return(1); }
	e=getc(fp);
	if (e!=255) {
		fprintf(stderr,"Incorrect message format\n");
		goto END; }
	mtype=getc(fp); aflag=getc(fp);
	buffer->I=0L;
	buffer->R[0]=0;

BONFGM:	b=getc(fp); if (b<0) goto END;
	if (b=='M') goto END;
	fpgetfield(fp,bbb);
	if (b=='A') strcpy(buffer->A,bbb);
	if (b=='O') strcpy(buffer->O,bbb);
	if (b=='N') strcpy(buffer->N,bbb);
	if (b=='R') strcpy(buffer->R,bbb);
	if (b=='D') strcpy(buffer->D,bbb);
	if (b=='T') buffer->T=atol(bbb);
	if (b=='I') buffer->I=atol(bbb);
	goto BONFGM;

END:	if (buffer->I==0L) buffer->I=buffer->T;
	fclose(fp);
	return(0);
}

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;
}

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,ffsource;
char aaa[100];
struct msgmain msgmain;

do {
	file=open("./MMstructure",O_RDWR);
	a=read(file,&msgmain,sizeof(struct msgmain));
	close(file);
		} while ( (msgmain.MMflags & MM_BUSY) !=0 );

	
	file=open("./MMstructure",O_RDWR);
	msgmain.MMflags=(msgmain.MMflags|MM_BUSY);
	a=write(file,&msgmain,sizeof(struct msgmain));
	close(file);
	origpos=msgmain.MMcurpos;

/* measure the message and count FF bytes */
ffsource=0L;
file=open(filename,O_RDONLY);
templen=0L;
do {
	a=0; b=read(file,&a,1);
	if (a==255) ++ffsource;
	templen=templen+(long)b;
	} while (b!=0);
close(file);

/* check for FF bytes */
hibytes=0L;
file=open("./msgmain",O_RDWR);
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;
msgmain.MMhighest=msgmain.MMhighest+ffsource;

cc=lseek(file,msgmain.MMcurpos,0);
file2=open(filename,O_RDONLY);
cc=lseek(file,0L,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("./MMstructure",O_RDWR);
a=write(file,&msgmain,sizeof(struct msgmain));
close(file);

retbuf->smnumber=msgmain.MMhighest;
retbuf->smpos=origpos;
return(0);
}

strucmp(st1,st2)
char *st1;
char *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);
}

getline(buffer,file)
char buffer[];
int file; {
	int a,b,c;
	c=0; b=0;
	do {
		a=read(file,&b,1);
		if (b==10) b=0;
		if (a<1) b=0;
		buffer[c]=b; ++c; } while(b!=0);
	return(c-1);
}

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

	file=open("msgmain",O_RDONLY);
	lseek(file,spos,0);

A:	for (a=0; a<3; ++a) {
		read(file,&b,1);
		write(file2,&b,1);
		}
PI:	b=0; read(file,&b,1); write(file2,&b,1);
	if (b=='M') goto B;
	getline(field,file);
	fwork[0]=0;
	if (b=='P') {
		strcpy(fwork,NODENAME);
		strcat(fwork,"!");
		}
	strcat(fwork,field);
	write(file2,fwork,strlen(fwork)+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);
	return(0);
}
	
outprocess(sysname) /* send new room messages to sysname */
char *sysname;
{
	int a,b,c,roomnum,file,file2,file3,file4;
	long aa,bb,cc,lastseen;
	char aaa[300],bbb[300],spflname[100],tfname[50],sysflname[100];
	char roomname[50];
	char xroom[50],xsys[50],xpath[512];
	struct quickroom quickroom;
	struct fullroom fullroom;
	
	sprintf(sysflname,"network/systems/%s",sysname);
	file=open(sysflname,O_RDONLY);
	if (file<0) {
		fprintf("netproc: no system %s\n",sysname);
		return(1); }
	close(file);
	a=getpid();
	sprintf(spflname,"/tmp/%s.%d",NODENAME,a);
	file=creat(spflname,0666);
	chmod(spflname,0666);
	sprintf(tfname,"/tmp/nt%d",a);
	file2=creat(tfname,0666);
	chmod(tfname,0666);
	file3=open(sysflname,O_RDONLY);

	getline(aaa,file3);
	sprintf(bbb,"%s\n",aaa);	/* copy uucp command to temp file */
	write(file2,bbb,strlen(bbb));

NXRM:	/* get the next room off the list */
	a=getline(roomname,file3);
	if (a==0) goto FINISHED;
	sprintf(bbb,"%s\n",roomname);	/* copy it to the temp file */
	write(file2,bbb,strlen(bbb));
	getline(aaa,file3);
	lastseen=atol(aaa);

	/* look for the room in the local file */
	roomnum=(-1);
	file4=open("quickroom",O_RDONLY);
	for (a=0; a<MAXROOMS; ++a) {
		read(file4,&quickroom,sizeof(struct quickroom));
		if (!strucmp(quickroom.QRname,roomname)) roomnum=a;
		}
	close(file4);
	if (roomnum==(-1)) {
		fprintf(stderr,"netproc: no local room %s\n",roomname);
		goto NXRM;
		}
	sprintf(aaa,"./rooms/fullrm%d",roomnum);
	file4=open(aaa,O_RDONLY);
	read(file4,&fullroom,sizeof(struct fullroom));
	close(file4);
	
	/* go thru fullroom list, sending all new messages */
	for (a=0; a<MSGSPERRM; ++a) {
if (fullroom.FRnum[a]!=0L) b=check_message(fullroom.FRpos[a],xroom,xsys,xpath);
	if ((fullroom.FRnum[a]>lastseen)
		&& (strucmp(xsys,sysname))
		&& (checkpath(xpath,sysname)==1) 
			) {
			pull_message(fullroom.FRpos[a],file);
			lastseen=fullroom.FRnum[a];
			}
		}
	sprintf(aaa,"%ld\n",lastseen);
	write(file2,aaa,strlen(aaa));
	goto NXRM;

FINISHED:	/* finished spooling new messages */
	close(file);
	close(file2);
	close(file3);

	/* copy temporary sys file into permanent sys file */
	file2=open(tfname,O_RDONLY);
	file3=creat(sysflname,0666);
	chmod(sysflname,0666);
	do {
		b=0; a=read(file2,&b,1);
		if (a>0) write(file3,&b,1);
		} while(a>0);
	close(file2);
	close(file3);
	unlink(tfname);
	ship_to(spflname,sysname);		/* send the outbound file */
	unlink(spflname);			/* and then delete it     */
	return(0);
}

ship_to(filenm,sysnm)	/* send spool file filenm to system sysnm */
char *filenm;
char *sysnm; {
	char sysflnm[100];
	char commbuf1[100];
	char commbuf2[100];
	int sysflfd;

	sprintf(sysflnm,"./network/systems/%s",sysnm);
	sysflfd=open(sysflnm,O_RDONLY);
	getline(commbuf1,sysflfd);
	close(sysflfd);
	sprintf(commbuf2,commbuf1,filenm);
	return(system(commbuf2));
	}

check_message(pos,xroom,xsys,xpath) /* get room, system, path */
long pos;
char xroom[];
char xsys[];
char xpath[]; {
	FILE *fp;
	int a;

	strcpy(xroom,"");
	strcpy(xsys,"");
	strcpy(xpath,"");
	fp=fopen("msgmain","r");
	if (fp==NULL) return(1);
	fseek(fp,pos,0);

CMCZ:	do {
		a=getc(fp);
		if (a<0) {
			fclose(fp);
			return(2);
			}
		} while(a!=0);
CMCN:	a=getc(fp);
	if (a=='M') {
			fclose(fp);
			return(0);
			}
	if (a=='O') fpgetfield(fp,xroom);
	if (a=='N') fpgetfield(fp,xsys);
	if (a=='P') fpgetfield(fp,xpath);
	if ((a=='O')||(a=='N')||(a=='P')) goto CMCN;
	goto CMCZ;
}

int mail_to(user,where)
char user[];
struct smreturn *where; {
	struct usersupp usersupp;
	long uspos;
	int file,a;

	file=open("usersupp",O_RDWR);
	if (file<0) return(-1);
	uspos=finduser(file,user);
	if (uspos<0L) {
		close(file);
		return(-1);
		}
	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];
		}
	usersupp.mailnum[MAILSLOTS-1]=where->smnumber;
	usersupp.mailpos[MAILSLOTS-1]=where->smpos;
	lseek(file,uspos,0);
	write(file,&usersupp,sizeof(struct usersupp));
	close(file);
	return(0);
	}

file_message(room,where)
char room[];
struct smreturn *where; {
	struct quickroom quickroom;
	struct fullroom fullroom;
	int rmnum,a,file;
	char frname[50];

	rmnum=2;
	file=open("quickroom",O_RDWR);
	for (a=0; a<MAXROOMS; ++a) {
		read(file,&quickroom,sizeof(struct quickroom));
		if (!strucmp(quickroom.QRname,room)) rmnum=a;
		}
	lseek(file,(long)(rmnum*sizeof(struct quickroom)),0);
	read(file,&quickroom,sizeof(struct quickroom));
	quickroom.QRhighest=where->smnumber;
	lseek(file,(long)(rmnum*sizeof(struct quickroom)),0);
	write(file,&quickroom,sizeof(struct quickroom));
	close(file);
	sprintf(frname,"./rooms/fullrm%d",rmnum);
	file=open(frname,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]=where->smnumber;
	fullroom.FRpos[MSGSPERRM-1]=where->smpos;
	lseek(file,0L,0);
	write(file,&fullroom,sizeof(struct fullroom));
	close(file);
	return(0);
}






checkpath(path,sys)	/* Checks to see whether its ok to send */
char path[];		/* Returns 1 for ok, send message	*/
char sys[]; {		/* Returns 0 if message already there	*/
	int a;
	char sys2[30];
	strcpy(sys2,sys);
	strcat(sys2,"!");

	for (a=0; a<strlen(path); ++a) 
		if (!strncmp(&path[a],sys2,strlen(sys2))) return(0);
	return(1);
}

sysinfo(name)	/* determine routing from sysinfo file */
char name[]; {
	int file,a;
	char aaa[100];
	file=open("network/mail.sysinfo",O_RDONLY);
GETSN:	do {
		a=getstring(file,aaa);
		} while ((a>=0)&&(strucmp(aaa,name)));
	a=getstring(file,aaa);
	if (!strncmp(aaa,"use ",4)) {
		strcpy(name,&aaa[4]);
		goto GETSN;
		}
	close(file);
	if (!strncmp(aaa,"bin",3)) {
		return(0);
		}
	printf("Error in network/mail.sysinfo file\n");
	return(-1);
	}

getstring(file,string)		/* get a line of text from a file */
int file; char string[]; {	/* ignores lines beginning with # */
int a,b,c;
do {
	strcpy(string,"");
	a=0;
	do {
		c=0; b=read(file,&c,1);
		if (b<1) { string[a]=0; return(-1); }
		string[a]=c;
		++a;
		} while(c!=10);
		string[a-1]=0;
	} while(string[0]=='#');
return(strlen(string));
}

SHAR_EOF
fi
echo shar: "extracting 'netsetup.c'" '(818 characters)'
if test -f 'netsetup.c'
then
	echo shar: "will not over-write existing file 'netsetup.c'"
else
cat << \SHAR_EOF > 'netsetup.c'
/* 
 * Citadel/UX Network Setup Program
 * see copyright.doc for copyright information
 */

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

long lseek();
long atol();

main() {

	int file,a,b,c,d;
	char aaa[100];
	struct recentmsg recentmsg;

	strcpy(recentmsg.RMnodename,"\000\000\000\000\000\000\000\000\000");
	recentmsg.RMnum=0L;

	printf("Do you want to initialize the use table (prevmsgs)? ");
	gets(aaa);
	a=tolower(aaa[0]);
	if (a!='y') exit(0);

	file=creat("./network/prevmsgs",0666);
	chmod("./network/prevmsgs",0666);
	for (a=0; a<PREVMSGS; ++a) {
		printf("%d\r",a);
		write(file,&recentmsg,sizeof(struct recentmsg));
		}
	close(file);
	file=creat("./network/prevmsgs.pos",0666);
	chmod("./network/prevmsgs.pos",0666);
	a=0;
	write(file,&a,2);
	close(file);
	printf("        \r");
	exit(0);
}
SHAR_EOF
fi
echo shar: "extracting 'useradmin.c'" '(7092 characters)'
if test -f 'useradmin.c'
then
	echo shar: "will not over-write existing file 'useradmin.c'"
else
cat << \SHAR_EOF > 'useradmin.c'
/*
 * useradmin.c - Full-screen user administration program
 * see copyright.doc for copyright information
 * v1.1
 */

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

long atol();
long lseek();

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; }
}

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);
}

main() {
	char user[100];
	long aa;
	int file,a;
	struct usersupp usersupp;
	
	chdir(BBSDIR);
	initscr();
	clear();
	printw("User Administration\n\nEnter user name: ");
	refresh();
	gets(user);

	file=open("usersupp",O_RDONLY);
	aa=finduser(file,user);
	if (aa<0L) {
		standout();
		printw("No such user.\n");
		standend(); refresh(); close(file); endwin();
		exit(1);
		}
	read(file,&usersupp,sizeof(struct usersupp));
	pwcrypt(usersupp.password,PWCRYPT);
	close(file);

	/* display user information */
	clear();
	move(1,0);
	printw("1. User name\n");
	printw("2. User number\n");
	printw("3. Uid attachment\n");
	printw("4. Password\n");
	printw("5. Screen width\n");
	printw("6. Times called\n");
	printw("7. Messages posted\n");
	printw("8. Last call\n");
	printw("9. Access level\n");
	for (a=10; a<=15; ++a) {
		move(a,0);
		printw("%d.\n",a);
		}
	for (a=1; a<=20; ++a) display_field(&usersupp,a);
	refresh();

	/* editing loop */
	while(1) {
		move(10,50); addstr("Enter field number to change");
		move(11,50); addstr("0 to exit");
		move(12,50); addstr("-1 to display registration");
		move(13,50); addstr("--> _____");
		refresh(); move(13,54); refresh();
		gets(user);
		refresh();
		a=atoi(user);
		if (a==0) break;
		if (a>0) edit_field(&usersupp,a);
		if (a<0) dis_regis(&usersupp);
		}

		move(22,0); addstr("Save changes (y/n)? ");
		refresh();
		gets(user);
		if (tolower(user[0])=='y') {
			file=open("usersupp",O_RDWR);
			aa=finduser(file,usersupp.fullname);
			pwcrypt(usersupp.password,PWCRYPT);
		      if (aa>=0L) write(file,&usersupp,sizeof(struct usersupp));
			close(file);
			}
	clear(); refresh();
	endwin();
	exit(0);
}

dis_regis(userdata)
struct usersupp *userdata; {
	struct registration regis;
	int a,b,file;
	char pbuf[20];
	if (!((userdata->flags)&US_REGIS)) {
		move(1,50); standout();
		addstr("No registration online");
		standend(); refresh();
		return(1);
		}
	file=open("registration",O_RDONLY);
	if (file<0) return(2);
	while(read(file,&regis,sizeof(struct registration))>0) {
		if (userdata->eternal==regis.RGeternal) {
			standout();
			move(1,50); printw("%-29s",regis.RGname);
			move(2,50); printw("%-29s",regis.RGaddr);
			move(3,50); printw("%-14s %2s %6s     ",
				regis.RGcity,regis.RGstate,regis.RGzip);
			strcpy(pbuf,regis.RGphone);
			regis.RGphone[0]=0;
			for (a=0; a<strlen(pbuf); ++a) {
				if ((pbuf[a]>='0')&&(pbuf[a]<='9')) {
					b=strlen(regis.RGphone);
					regis.RGphone[b]=pbuf[a];
					regis.RGphone[b+1]=0;
					}
				}
			while(strlen(regis.RGphone)<10) {
				strcpy(pbuf,regis.RGphone);
				strcpy(regis.RGphone," ");
				strcat(regis.RGphone,pbuf);
				}

			move(4,50);
			printw("(%c%c%c) %c%c%c-%c%c%c%c               ",
				regis.RGphone[0],regis.RGphone[1],
				regis.RGphone[2],regis.RGphone[3],
				regis.RGphone[4],regis.RGphone[5],
				regis.RGphone[6],regis.RGphone[7],
				regis.RGphone[8],regis.RGphone[9]);
			standend(); refresh();
			}
		if (userdata->eternal==regis.RGeternal) break;
		}
	close(file);
	return(0);
	}


display_field(userdata,fieldnum)
struct usersupp *userdata;
int fieldnum; {
	move(0,0); refresh();
	if (fieldnum<10) move(fieldnum,20);
		else move(fieldnum,5);
	refresh();
	switch(fieldnum) {
	case 1:		printw("%-30s",userdata->fullname);
			break;
	case 2:		printw("%-10ld",userdata->eternal);
			break;
	case 3:		printw("%-5d",userdata->USuid);
			break;
	case 4:		printw("%-20s",userdata->password);
			break;
	case 5:		printw("%-5d",userdata->screenwidth);
			break;
	case 6:		printw("%-5d",userdata->timescalled);
			break;
	case 7:		printw("%-5d",userdata->posted);
			break;
	case 8:		printw("%-20ld",userdata->lastcall);
			break;
	case 9:		printw("%1d",userdata->axlevel);
			break;
	case 10:	if (userdata->flags & US_PERM)
				addstr("Do not scroll off          ");
			else	addstr("Scroll off after two months");
			break;
	case 11:	if (userdata->flags & US_LASTOLD)
				addstr("Print last old message with new");
			else	addstr("Do not print last old message  ");
			break;
	case 12:	if (userdata->flags & US_EXPERT)
				addstr("Experienced user: suppress hints");
			else	addstr("Print help blurbs and hints     ");
			break;
	case 13:	if (userdata->flags & US_UNLISTED)
				addstr("Do not list in userlog");
			else	addstr("List in userlog       ");
			break;
	case 14:	if (userdata->flags & US_NOPROMPT)
				addstr("Do not prompt after each message");
			else	addstr("Prompt after each message       ");
			break;
	case 15:	if (userdata->flags & US_REGIS)
				addstr("Registered with name and address ");
			else	addstr("Not registered                   ");
			break;
	default:	break;
	}
	refresh();
	return(0);
	}

edit_field(userdata,fieldnum)
struct usersupp *userdata;
int fieldnum; {
	char new[100];
	if (fieldnum<10) { 
		move(fieldnum,20);
		addstr("                                               ");
		move(fieldnum,20);
		refresh();
		}
	switch(fieldnum) {
	case 2:		gets(new);
			userdata->eternal=atol(new);
			break;
	case 3:		gets(new);
			userdata->USuid=atol(new);
			break;
	case 4:		gets(userdata->password);
			break;
	case 5:		gets(new);
			userdata->screenwidth=atoi(new);
			break;
	case 6:		gets(new);
			userdata->timescalled=atoi(new);
			break;
	case 7:		gets(new);
			userdata->posted=atoi(new);
			break;
	case 8:		time(&userdata->lastcall);
			break;
	case 9:		gets(new);
			userdata->axlevel=atoi(new);
			break;
	case 10:	userdata->flags=(userdata->flags^US_PERM);
			break;
	case 11:	userdata->flags=(userdata->flags^US_LASTOLD);
			break;
	case 12:	userdata->flags=(userdata->flags^US_EXPERT);
			break;
	case 13:	userdata->flags=(userdata->flags^US_UNLISTED);
			break;
	case 14:	userdata->flags=(userdata->flags^US_NOPROMPT);
			break;
	case 15:	userdata->flags=(userdata->flags^US_REGIS);
			break;
	default:	break;
		}
	display_field(userdata,fieldnum);
	return(0);
}


pwcrypt(text,code)
char text[];
int code; {
	int a;
	for (a=0; a<strlen(text); ++a) text[a]=(text[a]^(((code|128)^a)&0xFF));
	return(0);
	}
SHAR_EOF
fi
echo shar: "extracting 'userlist.c'" '(2073 characters)'
if test -f 'userlist.c'
then
	echo shar: "will not over-write existing file 'userlist.c'"
else
cat << \SHAR_EOF > 'userlist.c'
/*
 * userlist.c v1.2
 * for use with Citadel/UX
 * see copyright.doc for copyright information
 */

#include <stdio.h>
#include <fcntl.h>
#include <pwd.h>
#include <ctype.h>
#include <time.h>
#include "citadel.h"

struct passwd *getpwnam();
struct tm *localtime();
long atol();

main(argc,argv)
int argc;
char *argv[];
 {
int a,b,c,file,pass;
char aaa[100];
long aa,snum;
struct usersupp usersupp;
struct tm *tmstruct;
pass=0; snum=(-1L);
for (a=1; a<argc; ++a) if (!strcmp(argv[a],"-p")) pass=1;
for (a=1; a<argc; ++a) if (!strcmp(argv[a],"-n")) snum=atol(argv[a+1]);

a=getuid();
if ((a!=0)&&(a!=9)) pass=0;
/* remove these two lines or change to user id's of people allowed
 * to read the users' passwords.
 */

file=open("usersupp",O_RDONLY);
if (file<0) {
	printf("No usersupp file available.\n");
	exit(1); }

printf("    User Name        Number LastCall Col #Calls Posted ");
if (pass) printf("Password");
printf("\n");
printf("-------------------- ------ -------- --- ------ ------ ");
if (pass) printf("-------------------");
printf("\n");
A:	a=read(file,&usersupp,sizeof(struct usersupp));
	if (a<1) goto END;
	for (b=0; b<strlen(usersupp.fullname); ++b) {
		if (usersupp.fullname[b]<32) usersupp.fullname[b]='.';
		if (usersupp.fullname[b]>126) usersupp.fullname[b]='.'; }
	if (snum!=(-1L)) {
		if ((pass==0)&&(((usersupp.flags&US_UNLISTED)==US_UNLISTED)))
			goto A;
		}
	if ((snum!=(-1L))&&(snum!=usersupp.eternal)) goto A;
		
	aa=usersupp.lastcall;
	tmstruct=localtime(&aa);
	sprintf(aaa,"%2d/%2d/%2d",
		(tmstruct->tm_mon+1),
		tmstruct->tm_mday,
		tmstruct->tm_year);
	usersupp.fullname[20]=0;

	a=48+usersupp.axlevel;
	printf("%-20s%c%6ld %6s %3d %6d %6d ",
		usersupp.fullname,a,
		usersupp.eternal,
		aaa,
		usersupp.screenwidth,
		usersupp.timescalled,
		usersupp.posted
		);
	pwcrypt(usersupp.password,PWCRYPT);
	if (pass) printf("%s",usersupp.password);
	printf("\n");
	goto A;

END:	close(file);
	exit(0);
}

pwcrypt(text,code)
char text[];
int code; {
	int a;
	for (a=0; a<strlen(text); ++a) text[a]=(text[a]^(((code|128)^a)&0xFF));
	return(0);
	}
SHAR_EOF
fi
echo shar: "extracting 'wcreceive.c'" '(2853 characters)'
if test -f 'wcreceive.c'
then
	echo shar: "will not over-write existing file 'wcreceive.c'"
else
cat << \SHAR_EOF > 'wcreceive.c'
#include <stdio.h>
#include <fcntl.h>
#include <sgtty.h>
#include <signal.h>
#include <setjmp.h>

struct sgttyb tty,ttysav;
int ttyfd;
jmp_buf tobuf;

#define SOH             1       /* Start of sector char */
#define EOT             4       /* end of transmission char */
#define ACK             6       /* acknowledge sector transmission */
#define NAK             21      /* error in transmission detected */
#define CAN		24	/* cancel session */
int (*timeout())() {
	longjmp(tobuf,1);
	}

fixterm()
{
    if ((ttyfd = open("/dev/tty",2)) < 0) {   /* Open terminal */
	fprintf(stderr,"wcrecieve: cannot open tty\n");
	exit(0);
    }

    ioctl(ttyfd,TIOCGETP,&tty);   /* Get terminal flags */
    ioctl(ttyfd,TIOCGETP,&ttysav);   /* save a copy */
#ifndef unix
    tty.sg_flags = RAW | TANDEM;
#else
    tty.sg_flags = RAW;
#endif
    ioctl(ttyfd,TIOCSETP,&tty);   /* Save as new characteristics */

}

restoreterm()
{
    ioctl(ttyfd,TIOCSETP,&ttysav);   /* Restore terminal */
    close(ttyfd);   /* Close terminal */
}

getbytes(buffer,nbytes)
char buffer[];
int nbytes; {
	int a,b;
	signal(SIGALRM,(*timeout));
	alarm(10);
	a=setjmp(tobuf);
	if (a!=0) return(-1);
	for (a=0; a<nbytes; ++a) read(ttyfd,&buffer[a],1);
	alarm(0);
	return(nbytes);
	}

main(argc,argv)
int argc;
char *argv[]; {
	int a,b,c,d,file,retries,block;
	char buffer[150];

	if (argc!=2) {
		fprintf(stderr,"wcrecieve: usage: wcrecieve filanme\n");
		exit(1);
		}

	file=creat(argv[1],0666);
	if (file<0) {
		fprintf(stderr,"wcrecieve: cannot create %s\n",argv[1]);
		exit(2);
		}

	fprintf(stderr,"wcrecieve: begin uploading now\n");
	fixterm();

	block=1;
	retries=0;
SHAKE:	a=NAK;
	write(ttyfd,&a,1);
	++retries;

NBLOCK:	a=getbytes(buffer,1);
	if (a==1) goto RHOK;
	if (retries<10) goto SHAKE;
	restoreterm();
	fprintf(stderr,"wcrecieve: transfer timed out\n");
	exit(3);

RHOK:	retries=0;
	if (buffer[0]==EOT) {
		a=ACK;
		write(ttyfd,&a,1);
		close(file);
		restoreterm();
		fprintf(stderr,"wcrecieve: transfer complete\n");
		exit(0);
		}
	if (buffer[0]==CAN) {
		a=ACK;
		write(ttyfd,&a,1);
		close(file);
		restoreterm();
		fprintf(stderr,"wcrecieve: transfer aborted\n");
		exit(4);
		}
	if (buffer[0]!=SOH) goto SHAKE;

GETN:	b=0; c=0; d=0; a=getbytes(&b,1);
	if (a==1) a=a+getbytes(&c,1);
	if (a==2) a=a+getbytes(buffer,128);
	if (a==130) a=a+getbytes(&d,1);
	if (a==131) goto GBOK;
	++retries;
	if (retries<10) goto SHAKE;
	close(file);
	restoreterm();
	fprintf(stderr,"wcrecieve: transfer timed out\n");
	exit(5);

GBOK:	if (b!=(255-c)) goto SHAKE;
	if (b==(block-1)) {
		a=ACK;	
		write(ttyfd,&a,1);
		goto NBLOCK;
		}
	if (b!=block) goto SHAKE;
	b=0;
	for (a=0; a<128; ++a) b=b+buffer[a];
	c=b&0xFF;
	if (c!=d) goto SHAKE;
	write(file,buffer,128);
	a=ACK;
	write(ttyfd,&a,1);
	++block;
	if (block==256) block=0;
	retries=0;
	goto NBLOCK;
	} /* end of main() */
SHAR_EOF
fi
echo shar: "extracting 'wcsend.c'" '(4457 characters)'
if test -f 'wcsend.c'
then
	echo shar: "will not over-write existing file 'wcsend.c'"
else
cat << \SHAR_EOF > 'wcsend.c'
#include <stdio.h>
#include <fcntl.h>
#include <sgtty.h>
#include <signal.h>

struct sgttyb tty,ttysav;
int ttyfd;
char usage[] = {"usage: wcsend filename\n"};

#define FALSE 0
#define TRUE 1

#define DOTS            50      /* Sector counting dots per line */
#define SECSIZ          0x80
#define BufSize         0x1000  /* Text buffer */
#define ERRORMAX        20      /* Max errors before abort */
#define RETRYMAX        15      /* Maximum retrys before abort */
#define TIMEOUT		60     /* Maximum time between xfers */
#define XFERDELAY	30	/* THIS MUST BE < TIMEOUT (time to first try) */

#define SOH             1       /* Start of sector char */
#define EOT             4       /* end of transmission char */
#define ACK             6       /* acknowledge sector transmission */
#define NAK             21      /* error in transmission detected */

static char
    bufr[BufSize];

static int
    fd,
    mtimeout;

static long
    bytes_xferred;

quit()
{
    restoreterm();   /* Restore terminal */
    close(ttyfd);   /* Close terminal */
    fprintf(stderr,"Transfer timed out.\n");
    exit(0);
}


fixterm()
{
    if ((ttyfd = open("/dev/tty",2)) < 0) {   /* Open terminal */
	fprintf(stderr,"\nCouldn't open tty\n");
	exit(0);
    }

    ioctl(ttyfd,TIOCGETP,&tty);   /* Get terminal flags */
    ioctl(ttyfd,TIOCGETP,&ttysav);   /* save a copy */
#ifndef unix
    tty.sg_flags = RAW | TANDEM;
#else
    tty.sg_flags = RAW;
#endif
    ioctl(ttyfd,TIOCSETP,&tty);   /* Save as new characteristics */

    signal(SIGALRM,quit);   /* Catch alarm clock */
    signal(SIGHUP,quit);   /* and hang-up */
    alarm(TIMEOUT);   /* Start the alarm clock */
}

pch(ch)
char ch;
{
    putchar(ch);
    fflush(stdout);
}

int gch()
{
    int cc;

    alarm(TIMEOUT);
    return(getchar());
}

#ifdef FIONREAD
numwait()
{
    int t;

    ioctl(ttyfd,FIONREAD,&t);   /* See if any chars. waiting */
    return(t);
}
#endif

flushinput()
{
#ifdef FIONREAD
    int t;

    do {
	t = numwait();
	if (t > 0)
	    getchar();   /* Yes, toss 'em */
    } while (t > 0);
#else
#define TCFLSH (('T'<<8)|7)
    ioctl(ttyfd, TCFLSH, 0);
#endif
}

restoreterm()
{
    ioctl(ttyfd,TIOCSETP,&ttysav);   /* Restore terminal */
    close(ttyfd);   /* Close terminal */
}

XSend_File(file)
    char *file;
{
    int sectnum, bytes_to_send, size, attempts;
    unsigned checksum, j, bufptr;
    char c;


    if ((fd = open(file, O_RDONLY)) < 0)
        {
        fprintf(stderr,"wcsend: cannot open %s\r\n", file);
        return FALSE;
        }
    else
        fprintf(stderr,"wcsend: sending %s\r\n", file);

    attempts = 0;
    sectnum = 1;
    j = 0;

    flushinput ();

    while (((c = gch ()) != NAK) && (j++ < (ERRORMAX*2)));

    if (j >= (ERRORMAX*2))
        {
        return FALSE;
        };

    while ((bytes_to_send = read(fd, bufr, BufSize)) && attempts != RETRYMAX)
        {
        if (bytes_to_send == EOF)
            {
            close(fd);
            return FALSE;
            };

        bufptr = 0;

        while (bytes_to_send > 0 && attempts != RETRYMAX)
            {
            attempts = 0;

            do
                {
                pch(SOH);
                pch(sectnum);
                pch(~sectnum);
                checksum = 0;
                size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
                bytes_to_send -= size;

                for (j = bufptr; j < (bufptr + SECSIZ); j++)
                    if (j < (bufptr + size))
                        {
                        pch(bufr[j]);
                        checksum += bufr[j];
                        }
                    else
                        pch(0);

		fflush(stdout);
                pch(checksum);
                attempts++;
                c = gch();
                }
            while ((c != ACK) && (attempts != RETRYMAX));

            bufptr += size;
            bytes_xferred += size;
            sectnum++;
            }
        }

    close(fd);

    if (attempts == RETRYMAX)
        {
            return FALSE;
        }
    else
        {
        attempts = 0;

        do
            {
            pch(EOT);
            attempts++;
            }
        while ((getchar() != ACK) && (attempts != RETRYMAX));
        };

    return TRUE;
}

main(argc,argv)
int argc;
char *argv[];
{
if (argc != 2) {
	fprintf(stderr,usage);
	exit(1);
	}

	fixterm();
	XSend_File(argv[1]);
	alarm(0);
	restoreterm();
	exit(1);
    }

SHAR_EOF
fi
echo shar: "extracting 'whobbs.c'" '(1057 characters)'
if test -f 'whobbs.c'
then
	echo shar: "will not over-write existing file 'whobbs.c'"
else
cat << \SHAR_EOF > 'whobbs.c'
/*
 * Citadel/UX "who is logged in" report
 * see copyright.doc for copyright information
 * v1.0
 */

#include <fcntl.h>
#include <pwd.h>
#include "citadel.h"

struct passwd *getpwnam();

struct utmp {
	char	ut_line[8];		/* tty name */
	char	ut_name[8];		/* user id */
	long	ut_time;		/* time on */
};

main() {
	struct utmp utmp;
	int file,wfile,a;
	struct passwd *pwbuf;
	char name[30];
	struct wtmpsupp wtmpsupp;

	chdir(BBSDIR);
	printf(" Port   Name\n");
	printf("------- ----\n");
	file=open("/etc/utmp",O_RDONLY);
	while ((read(file,&utmp,sizeof(struct utmp)))) {
		if (utmp.ut_name[0]!=0) {
			pwbuf=getpwnam(utmp.ut_name);
			strcpy(name,pwbuf->pw_gecos);

if ((pwbuf->pw_uid)==BBSUID) {
	strcpy(name,"<not logged in>");
	wfile=open("wtmpsupp",O_RDONLY);
	do {
		a=read(wfile,&wtmpsupp,sizeof(struct wtmpsupp));
		if (!strcmp(&wtmpsupp.WStty[5],utmp.ut_line))
			strcpy(name,wtmpsupp.WSname);
		} while((a>0)&&(strcmp(&wtmpsupp.WStty[5],utmp.ut_line)));
		close(wfile);
	}

	printf("%-7s %s\n",utmp.ut_line,name);
		}
	}
	close(file);
	exit(0);
}
SHAR_EOF
fi
echo shar: "extracting 'backupsrc'" '(119 characters)'
if test -f 'backupsrc'
then
	echo shar: "will not over-write existing file 'backupsrc'"
else
cat << \SHAR_EOF > 'backupsrc'
clear
echo "Backing up source code - tar format"
tar cv *.c *.h *.doc */*.c */*.h Makefile *menu backup*
echo finished
SHAR_EOF
fi
echo shar: "extracting 'Makefile'" '(2468 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
MODEL=-Mm

todate: citadel aidepost chat netmailer netsetup netproc rmail setup userlist \
wcreceive wcsend whobbs useradmin msgform msgstats mailutil readlog rnews \
stats sysoputil cux2ascii
	echo "Last Make update: " `date` >todate

citadel: citadel.o rooms.o messages.o commands.o routines.o \
routines2.o citadel.h
	cc $(MODEL) -O citadel.o rooms.o messages.o commands.o routines.o \
routines2.o -o citadel
	chmod 4755 citadel

citadel.o: citadel.c citadel.h
	cc $(MODEL) -c citadel.c

rooms.o: rooms.c citadel.h
	cc -O $(MODEL) -c rooms.c

messages.o: messages.c citadel.h
	cc -O $(MODEL) -c messages.c

commands.o: commands.c citadel.h
	cc -O $(MODEL) -c commands.c

routines.o: routines.c citadel.h
	cc -O $(MODEL) -c routines.c

routines2.o: routines2.c citadel.h
	cc -O $(MODEL) -c routines2.c

aidepost: aidepost.c citadel.h
	cc -O aidepost.c -o aidepost
	chmod 4755 aidepost

chat: chat.c
	cc -O chat.c -o chat
	chmod 4755 chat

netmailer: netmailer.c citadel.h
	cc -O netmailer.c -o netmailer
	chmod 4755 netmailer

netproc: netproc.c citadel.h
	cc -O netproc.c -o netproc
	chmod 4755 netproc

netsetup.c: netsetup.c citadel.h
	cc -O netsetup.c -o netsetup
	chmod 4750 netsetup

rmail.c: rmail.c citadel.h
	cc -O rmail.c -o rmail
	chmod 4755 rmail
	echo "Move your old rmail to rmail.real and put this rmail where it was"

setup: setup.c citadel.h
	cc -O setup.c -o setup
	chmod 4755 setup

userlist: userlist.c citadel.h
	cc -O userlist.c -o userlist
	chmod 4755 userlist

wcreceive: wcreceive.c
	cc -O wcreceive.c -o wcreceive

wcsend: wcsend.c
	cc -O wcsend.c -o wcsend

whobbs.c: whobbs.c citadel.h
	cc -O whobbs.c -o whobbs
	chmod 4755 whobbs

useradmin: useradmin.c citadel.h
	cc -O useradmin.c -lcurses -ltermcap -o useradmin
	chmod 4750 useradmin

msgform: msgform.c citadel.h
	cc -O msgform.c -o msgform

msgstats: msgstats.c citadel.h
	cc -O msgstats.c -o msgstats
	chmod 4755 msgstats

mailutil: mailutil.c citadel.h
	cc -O mailutil.c -o mailutil
	chmod 4750 mailutil

readlog: readlog.c citadel.h
	cc -O readlog.c -o readlog
	chmod 4750 readlog

rnews: rnews.c citadel.h
	cc -O rnews.c -o rnews
	chmod 4755 rnews
	rm -f /usr/bin/rnews /bin/rnews
	ln rnews /usr/bin/rnews

stats: stats.c citadel.h
	cc -O stats.c -lcurses -ltermcap -o stats
	chmod 4755 stats

sysoputil: sysoputil.c citadel.h
	cc -O sysoputil.c -o sysoputil
	chmod 4750 sysoputil

citadel.h: sysconfig.h
	touch citadel.h

cux2ascii: cux2ascii.c
	cc -O cux2ascii.c -o cux2ascii
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 )