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:00:34 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 'readlog.c'" '(2176 characters)' if test -f 'readlog.c' then echo shar: "will not over-write existing file 'readlog.c'" else cat << \SHAR_EOF > 'readlog.c' #include <fcntl.h> #include <time.h> #include "citadel.h" long lseek(); main(argc,argv) int argc; char *argv[]; { struct calllog calllog; int file,pos,a; char aaa[100]; struct tm *tm; char *tstring; file=open("calllog.pos",O_RDONLY); read(file,&pos,2); close(file); file=open("calllog",O_RDONLY); if (!strcmp(argv[1],"-t")) last20(file,(long)pos); else { lseek(file,(long)(pos*sizeof(struct calllog)),0); for (a=0; a<CALLLOG; ++a) { if ((a+pos)==CALLLOG) lseek(file,0L,0); read(file,&calllog,sizeof(struct calllog)); if (calllog.CLflags!=0) { strcpy(aaa,""); if (calllog.CLflags&CL_IN300) strcpy(aaa,"Connect 300"); if (calllog.CLflags&CL_IN1200) strcpy(aaa,"Connect 1200"); if (calllog.CLflags&CL_IN2400) strcpy(aaa,"Connect 2400"); if (calllog.CLflags&CL_INOTHER) strcpy(aaa,"Console/Other"); if (calllog.CLflags&CL_LOGIN) strcpy(aaa,"Login"); if (calllog.CLflags&CL_NEWUSER) strcpy(aaa,"New User"); if (calllog.CLflags&CL_BADPW) strcpy(aaa,"Bad PW Attempt"); if (calllog.CLflags&CL_TERMINATE) strcpy(aaa,"Terminate"); if (calllog.CLflags&CL_DROPCARR) strcpy(aaa,"Dropped Carrier"); if (calllog.CLflags&CL_SLEEPING) strcpy(aaa,"Sleeping"); tm=(struct tm *)localtime(&calllog.CLtime); tstring=(char *)asctime(tm); printf("%30s %20s %s",calllog.CLfullname,aaa,tstring); } } } close(file); exit(0); } last20(file,pos) int file; long pos; { int a,count; long aa; struct calllog calllog; struct calllog listing[20]; struct tm *tm; char *tstring; count=0; for (a=0; a<20; ++a) { listing[a].CLfullname[0]=0; listing[a].CLtime=0L; listing[a].CLflags=0; } aa=pos-1; while(count<20) { if (aa<0L) aa=CALLLOG; lseek(file,(aa*sizeof(struct calllog)),0); read(file,&calllog,sizeof(struct calllog)); if (calllog.CLflags==CL_LOGIN) { strcpy(listing[count].CLfullname,calllog.CLfullname); listing[count].CLtime=calllog.CLtime; listing[count].CLflags=calllog.CLflags; ++count; } if (aa==pos) break; aa=aa-1; } for (a=19; a>=0; --a) { tm=(struct tm *)localtime(&listing[a].CLtime); tstring=(char *)asctime(tm); printf("%30s %s",listing[a].CLfullname,tstring); } return(0); } SHAR_EOF fi echo shar: "extracting 'rmail.c'" '(7699 characters)' if test -f 'rmail.c' then echo shar: "will not over-write existing file 'rmail.c'" else cat << \SHAR_EOF > 'rmail.c' /* Citadel/UX uucp mail reciever Version 2.10, January 1989 This is just a quick hack I threw together to enable BBS users to recieve mail through the uucp mail facility. Move rmail to rmail.real and compile this program as rmail. New change: mail can now be recieved by user number, i.e. sysname!cit123 This program looks at the recipient to determine if he/she is a bbs user. It falls back on the old mailer if: 1. The program is called with less or more than one argument 2. The recipient is not someone in the BBS user file (so users who are in /etc/passwd can still recieve mail) 3. The recipient name contains ! or @ characters (so it doesn't try to mail something that really should be sent out of the system via uucp) Generally, this program will require a bit of hacking before it will run on your system. If you have any questions, call UNCENSORED! BBS at (914) 761-6877. Good luck... */ #include <fcntl.h> #include <stdio.h> #include <ctype.h> #include "/usr/bbs/citadel.h" long lseek(); long atol(); 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; } } 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]; 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; /* measure the message */ file=open(filename,O_RDONLY); if (file<0) exit(17); templen=lseek(file,0L,2); close(file); /* check for FF bytes */ hibytes=0L; file=open("/usr/bbs/msgmain",O_RDWR); if (file<0) exit(18); 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; cc=lseek(file,msgmain.MMcurpos,0); file2=open(filename,O_RDONLY); if (file2<0) exit(19); 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("/usr/bbs/MMstructure",O_RDWR); if (file<0) exit(20); a=write(file,&msgmain,sizeof(struct msgmain)); if (a<1) exit(21); close(file); retbuf->smnumber=msgmain.MMhighest; retbuf->smpos=origpos; return(0); } make_message(filename,recipient) char filename[]; /* temporary file name */ char recipient[]; /* NULL if it's not mail */ { char author[300]; FILE *fp; int a,b,c,old; long aa,bb,cc,beg,now; char aaa[300],bbb[300]; strcpy(author,"UUCP Mailer"); strcpy(aaa,""); gets(aaa); if (strncmp(aaa,"From ",5)) goto NOFRM; strcpy(aaa,&aaa[5]); strcpy(bbb,"somewhere"); for (a=0; a<strlen(aaa); ++a) if (!strncmp(&aaa[a],"remote from ",12)) { strcpy(bbb,&aaa[a+12]); aaa[a]=0; } for (a=0; a<strlen(aaa); ++a) if (aaa[a]==32) aaa[a]=0; strcat(bbb,"!"); strcat(bbb,aaa); strcpy(author,bbb); aaa[0]=0; NOFRM: time(&now); fp=fopen(filename,"wb"); if (fp==NULL) exit(22); putc(255,fp); putc(MES_NORMAL,fp); putc(1,fp); fprintf(fp,"T%ld",now); putc(0,fp); fprintf(fp,"A%s",author); putc(0,fp); if (recipient[0]!=0) { fprintf(fp,"R%s",recipient); putc(0,fp); } fprintf(fp,"OMail"); putc(0,fp); fprintf(fp,"N%s",NODENAME); putc(0,fp); putc('M',fp); if (aaa[0]!=0) fprintf(fp,"%s\n",aaa); do { a=getc(stdin); if (a>0) putc(a,fp); } while(a>0); MEFIN: putc(0,fp); fclose(fp); return(0); } 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); } main(argc,argv) int argc; char *argv[]; { int a,file; long aa; char aaa[100],temp[20]; struct usersupp usersupp; struct smreturn smreturn; struct quickroom quickroom; struct fullroom fullroom; sprintf(temp,"/tmp/rmail.%d",getpid()); goto TRY; GIVEUP: execv("/usr/bin/rmail.real",argv); exit(1); TRY: if (argc!=2) goto GIVEUP; strcpy(aaa,argv[1]); for (a=0; a<strlen(aaa); ++a) { if ((aaa[a]=='!')||(aaa[a]=='@')) goto GIVEUP; if (aaa[a]=='_') aaa[a]=32; } check4n(aaa); alias(aaa); if (strucmp(aaa,"sysop")) { file=open("/usr/bbs/usersupp",O_RDWR); if (file<0) goto GIVEUP; aa=finduser(file,aaa); if (aa==(-1L)) { close(file); goto GIVEUP; } } make_message(temp,aaa); send_message(temp,&smreturn); if (strucmp(aaa,"sysop")) { aa=finduser(file,aaa); 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]=smreturn.smnumber; usersupp.mailpos[MAILSLOTS-1]=smreturn.smpos; aa=finduser(file,aaa); write(file,&usersupp,sizeof(struct usersupp)); close(file); } else { /* file it in Aide> */ file=open("/usr/bbs/quickroom",O_RDWR); lseek(file,(long)(2*sizeof(struct quickroom)),0); read(file,&quickroom,sizeof(struct quickroom)); quickroom.QRhighest=smreturn.smnumber; lseek(file,(long)(2*sizeof(struct quickroom)),0); write(file,&quickroom,sizeof(struct quickroom)); close(file); file=open("/usr/bbs/rooms/fullrm2",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]=smreturn.smnumber; fullroom.FRpos[MSGSPERRM-1]=smreturn.smpos; lseek(file,0L,0); write(file,&fullroom,sizeof(struct fullroom)); close(file); } unlink(temp); exit(0); } alias(name) char name[]; { FILE *fp; int a,b; char aaa[50],bbb[50]; fp=fopen("/usr/bbs/network/mail.aliases","r"); if (fp==NULL) return(2); 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(name,aaa)) goto GNA; fclose(fp); strcpy(name,bbb); return(0); } check4n(name) char name[]; { struct usersupp usersupp; int a,file; if ((strncmp(name,"cit",2))||(atol(&name[3])==0L)) return(0); file=open("/usr/bbs/usersupp",O_RDONLY); while (read(file,&usersupp,sizeof(struct usersupp))>0) { if (usersupp.eternal==atol(&name[3])) { strcpy(name,usersupp.fullname); goto CLCN; } } CLCN: close(file); return(0); } SHAR_EOF fi echo shar: "extracting 'rnews.c'" '(4125 characters)' if test -f 'rnews.c' then echo shar: "will not over-write existing file 'rnews.c'" else cat << \SHAR_EOF > 'rnews.c' /* Citadel/UX rnews * version 1.02 * * This program functions the same as the standard rnews program for * UseNet. It accepts standard input, and looks for rooms to post messages * in that match the names of the newsgroups. network/rnews.xref is checked * in case the sysop wants to cross-reference room names to newsgroup names. * The netproc program is required for final processing. * * usage: * rnews <stdin is translated to Cit/UX format and posted> * rnews -c <assumes stdin is already in Cit/UX format and posts> */ #include <fcntl.h> #include <stdio.h> #include <ctype.h> #include <time.h> #include "citadel.h" long lseek(); long atol(); main(argc,argv) int argc; char *argv[]; { char aaa[100],bbb[100],ccc[100]; char author[50],recipient[50],room[50],node[50],path[300]; long mid,now,bcount,aa; int a; char flnm[100],tname[100]; FILE *mout,*mtemp; chdir(BBSDIR); sprintf(flnm,"./network/spoolin/rnews.%d",getpid()); sprintf(tname,"/tmp/rnews.%d",getpid()); mout=fopen(flnm,"w"); if ((argc==2)&&(!strcmp(argv[1],"-c"))) { while ((a=getc(stdin))>=0) putc(a,mout); goto END; } A: a=getline(aaa,stdin); if (a<0) goto END; if (strncmp(aaa,"#! rnews ",9)) goto A; bcount=atol(&aaa[9]); mtemp=fopen(tname,"w"); for (aa=0L; aa<bcount; ++aa) { a=getc(stdin); if (a<0) goto NMA; if (a>=0) putc(a,mtemp); } NMA: fclose(mtemp); if (a<0) goto END; mtemp=fopen(tname,"r"); strcpy(author,""); strcpy(recipient,""); strcpy(room,""); strcpy(node,""); strcpy(path,""); B: a=getline(aaa,mtemp); if (a==0) goto C; if (a<0) goto ABORT; if (!strncmp(aaa,"From: ",5)) { while((aaa[0]!='(')&&(aaa[0]!=0)) { strcpy(&aaa[0],&aaa[1]); } strcpy(&aaa[0],&aaa[1]); for (a=0; a<strlen(aaa); ++a) if (aaa[a]==')') aaa[a]=0; strcpy(author,aaa); goto B; } if (!strncmp(aaa,"Path: ",5)) strcpy(path,&aaa[6]); if (!strncmp(aaa,"Newsgroups: ",11)) { strcpy(room,&aaa[12]); for (a=0; a<strlen(aaa); ++a) if (aaa[a]==',') aaa[a]=0; goto B; } if (!strncmp(aaa,"Message-ID: ",11)) { strcpy(bbb,&aaa[13]); for (a=0; a<strlen(bbb); ++a) if (bbb[a]=='@') bbb[a]=0; mid=atol(bbb); while((aaa[0]!='@')&&(aaa[0]!=0)) { strcpy(&aaa[0],&aaa[1]); } strcpy(&aaa[0],&aaa[1]); for (a=0; a<strlen(aaa); ++a) if ((aaa[a]=='.')||(aaa[a]=='>')) aaa[a]=0; strcpy(node,aaa); goto B; } goto B; C: if ((author[0]==0)||(room[0]==0)||(node[0]==0)) goto ABORT; putc(255,mout); /* start of message */ putc(MES_NORMAL,mout); /* not anonymous */ putc(1,mout); /* not formatted */ time(&now); fprintf(mout,"I%ld",mid); putc(0,mout); fprintf(mout,"P%s",path); putc(0,mout); fprintf(mout,"T%ld",now); putc(0,mout); fprintf(mout,"A%s",author); putc(0,mout); strcpy(ccc,room); getroom(room,ccc); fprintf(mout,"O%s",room); putc(0,mout); fprintf(mout,"N%s",node); putc(0,mout); fprintf(mout,"M"); a=0; aaa[0]=0; D: do { a=getc(mtemp); if (a>0) putc(a,mout); } while (a>0); putc(0,mout); ABORT: pclose(mtemp); unlink(tname); goto A; END: putc(0,mout); fclose(mout); unlink(tname); execlp("netproc","netproc",NULL); exit(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); } getroom(room,ngroup) /* xref table */ char room[]; char ngroup[]; { FILE *fp; int a,b; char aaa[50],bbb[50]; strcpy(room,ngroup); 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(ngroup,aaa)) goto GNA; fclose(fp); strcpy(room,bbb); return(0); } getline(str,fp) char str[]; FILE *fp; { int a,b; a=0; str[0]=0; do { a=getc(fp); if (a>10) { b=strlen(str); str[b]=a; str[b+1]=0; } } while(a>10); if (a<0) return(a); return(strlen(str)); } SHAR_EOF fi echo shar: "extracting 'rooms.c'" '(15734 characters)' if test -f 'rooms.c' then echo shar: "will not over-write existing file 'rooms.c'" else cat << \SHAR_EOF > 'rooms.c' /* Citadel/UX room-oriented routines */ #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 IFAIDE if (usersupp.axlevel>=6) #define IFNAIDE if (usersupp.axlevel<6) long atol(); long lseek(); long finduser(); extern int curr_rm; extern int ugnum; extern long uglsn; extern struct quickroom quickroom; extern struct usersupp usersupp; extern struct fullroom fullroom; knrooms(USgiven) struct usersupp *USgiven; { int a,b,c,d,file; struct quickroom QRscratch; b=1; printf("\n Rooms with unread messages:\n"); file=open("./quickroom",O_RDONLY); if (file<0) return(1); for (a=0; a<MAXROOMS; ++a) { c=read(file,&QRscratch,sizeof(struct quickroom)); if (c<1) interr(58); if (a==1) QRscratch.QRhighest=USgiven->mailnum[MAILSLOTS-1]; d=b+strlen(QRscratch.QRname)+3; if ((QRscratch.QRflags & QR_INUSE) && (QRscratch.QRhighest> (USgiven->lastseen[a]) ) && ( (a!=2) || (USgiven->axlevel>=6)) && (QRscratch.QRgen != (USgiven->forget[a]) ) && ( ((QRscratch.QRflags&QR_PREFONLY)==0) || ((USgiven->axlevel)>=5) ) && ( ((QRscratch.QRflags&QR_PRIVATE)==0) || ((USgiven->axlevel)>=6) || (QRscratch.QRgen==(USgiven->generation[a])) ) ) { if (d>=(USgiven->screenwidth)) { printf("\n"); b=1; } c=room_prompt(&QRscratch); printf("%s%c ",QRscratch.QRname,c); b=b+strlen(QRscratch.QRname)+3; } } if (b!=1) printf("\n"); b=1; printf("\n No unseen messages in:\n"); lseek(file,0L,0); for (a=0; a<MAXROOMS; ++a) { c=read(file,&QRscratch,sizeof(struct quickroom)); if (c<1) return(1); if (a==1) QRscratch.QRhighest=USgiven->mailnum[MAILSLOTS-1]; if ((QRscratch.QRflags & QR_INUSE) && (QRscratch.QRhighest<=USgiven->lastseen[a]) && ( (a!=2) || ((USgiven->axlevel)>=6)) && (QRscratch.QRgen != USgiven->forget[a]) && ( ((QRscratch.QRflags&QR_PREFONLY)==0) || ((USgiven->axlevel)>=5) ) && ( ((QRscratch.QRflags&QR_PRIVATE)==0) || ((USgiven->axlevel)>=6) || (QRscratch.QRgen==USgiven->generation[a]) ) ) { d=strlen(QRscratch.QRname)+3+b; if (d>=(USgiven->screenwidth)) { printf("\n"); b=1; } c=room_prompt(&QRscratch); printf("%s%c ",QRscratch.QRname,c); b=b+strlen(QRscratch.QRname)+3; } } if (b!=1) printf("\n"); close(file); return(0); } listzrooms(USgiven) /* list public forgotten rooms */ struct usersupp *USgiven; { int a,b,c,d,file; struct quickroom QRscratch; b=1; printf("\n Forgotten public rooms:\n"); file=open("./quickroom",O_RDONLY); if (file<0) return(1); for (a=0; a<MAXROOMS; ++a) { c=read(file,&QRscratch,sizeof(struct quickroom)); if (c<1) interr(58); if (a==1) QRscratch.QRhighest=USgiven->mailnum[MAILSLOTS-1]; if ((QRscratch.QRflags & QR_INUSE) && (QRscratch.QRgen == (USgiven->forget[a]) ) && ( (a!=2) || ((USgiven->axlevel)>=6)) && ( ((QRscratch.QRflags&QR_PRIVATE)==0) || ((USgiven->axlevel)>=6) || (QRscratch.QRgen==(USgiven->generation[a])) ) ) { d=b+strlen(QRscratch.QRname)+3; if (d>=(USgiven->screenwidth)) { printf("\n"); b=1; } c=room_prompt(&QRscratch); printf("%s%c ",QRscratch.QRname,c); b=b+strlen(QRscratch.QRname)+3; } } if (b!=1) printf("\n"); close(file); return(0); } editroom() { /* .<A>ide <E>dit room */ int file,file2,a,b; char aaa[50]; long aa; struct usersupp tempUS; if (curr_rm<3) { printf("Can't edit this room.\n"); return(0); } file=open("quickroom",O_RDWR); if (file<0) interr(34); lseek(file,(long)(curr_rm*sizeof(struct quickroom)),0); a=read(file,&quickroom,sizeof(struct quickroom)); if (a<1) interr(35); printf("Room name is currently: %s\n",quickroom.QRname); printf("New name <return=same>? "); getline(aaa,19); if (aaa[0]!=0) strcpy(quickroom.QRname,aaa); printf("This is currently a"); if ((quickroom.QRflags&QR_PRIVATE)==0) printf(" public"); if (quickroom.QRflags&QR_PRIVATE) printf(" private"); if (quickroom.QRflags&QR_PASSWORDED) printf(", passworded"); if (quickroom.QRflags&QR_GUESSNAME) printf(", guessname"); printf(" room"); if ((quickroom.QRflags&QR_PASSWORDED)==QR_PASSWORDED) printf(", password: %s",quickroom.QRpasswd); printf(".\n"); if (quickroom.QRflags&QR_PREFONLY) printf("PREFERRED USERS ONLY.\n"); if (quickroom.QRflags&QR_DIRECTORY) { printf("Directory room"); if (quickroom.QRflags&QR_UPLOAD) printf(", uploading allowed"); if (quickroom.QRflags&QR_DOWNLOAD) printf(", downloading allowed"); if (quickroom.QRflags&QR_VISDIR) printf(", visible directory"); printf(".\nDirectory name: %s\n",quickroom.QRdirname); } if (quickroom.QRflags&QR_ANONONLY) printf("Anonymous-only room.\n"); quickroom.QRflags=(quickroom.QRflags|QR_PRIVATE|QR_PASSWORDED|QR_GUESSNAME); quickroom.QRflags=(quickroom.QRflags|QR_DIRECTORY|QR_UPLOAD|QR_DOWNLOAD); quickroom.QRflags=(quickroom.QRflags|QR_VISDIR|QR_ANONONLY); quickroom.QRflags=(quickroom.QRflags|QR_ANON2|QR_NETWORK|QR_PREFONLY); printf("New room type? <1>pub <2>guessname <3>passwd <4>inv-only : "); do { b=inkey()-48; } while ((b<1)||(b>4)); printf("%d\n",b); if (b!=2) quickroom.QRflags=(quickroom.QRflags-QR_GUESSNAME); if (b!=3) quickroom.QRflags=(quickroom.QRflags-QR_PASSWORDED); if (b==1) quickroom.QRflags=(quickroom.QRflags-QR_PRIVATE); if ((quickroom.QRflags&QR_PASSWORDED)==QR_PASSWORDED) { printf("<return> or new password: "); getline(aaa,9); if (aaa[0]!=0) strcpy(quickroom.QRpasswd,aaa); } if ((quickroom.QRflags&QR_PRIVATE)==QR_PRIVATE) { printf("Cause users to forget room? "); if (yesno()==1) { ++quickroom.QRgen; if (quickroom.QRgen==100) quickroom.QRgen=10; } } printf("Preferred users only? "); if (yesno()==0) quickroom.QRflags=(quickroom.QRflags-QR_PREFONLY); printf("Directory room? "); if (yesno()==0) quickroom.QRflags=(quickroom.QRflags-QR_DIRECTORY); else { printf(" Directory name? "); getline(quickroom.QRdirname,14); printf(" Uploading allowed? "); if (yesno()==0) quickroom.QRflags=(quickroom.QRflags-QR_UPLOAD); printf("Downloading allowed? "); if (yesno()==0) quickroom.QRflags=(quickroom.QRflags-QR_DOWNLOAD); printf(" Visible Directory? "); if (yesno()==0) quickroom.QRflags=(quickroom.QRflags-QR_VISDIR); } printf("Network Room? "); if (yesno()==0) quickroom.QRflags=(quickroom.QRflags-QR_NETWORK); printf("<1>Normal <2>Anon-only <3>Anon-option ? "); do { a=inkey()-48; } while((a<1)||(a>3)); printf("%d\n",a); if ((a==1)||(a==3)) quickroom.QRflags=(quickroom.QRflags-QR_ANONONLY); if ((a==1)||(a==2)) quickroom.QRflags=(quickroom.QRflags-QR_ANON2); RANSU: file2=open("usersupp",O_RDONLY); /* (gee, thanks a lot!) */ if (quickroom.QRroomaide>=0L) { do { a=read(file2,&tempUS,sizeof(struct usersupp)); } while((a>0)&&(quickroom.QRroomaide!=tempUS.eternal)); close(file2); if (a>0) printf("Room aide is currently: %s\nNew ", tempUS.fullname); } else printf("No room aide.\n"); printf("Room aide (RETURN to leave unchanged): "); getline(aaa,29); if (aaa[0]!=0) { file2=open("usersupp",O_RDONLY); aa=finduser(file2,aaa); read(file2,&tempUS,sizeof(struct usersupp)); close(file2); if (aa==(-1L)) { printf("No such user.\n"); goto RANSU; } quickroom.QRroomaide=tempUS.eternal; } printf("\n\nSave changes (y/n)? "); if (yesno()==0) { lseek(file,(long)(curr_rm*sizeof(struct quickroom)),0); b=read(file,&quickroom,sizeof(struct quickroom)); if (b<1) interr(36); close(file); return(0); } lseek(file,(long)(curr_rm*sizeof(struct quickroom)),0); b=write(file,&quickroom,sizeof(struct quickroom)); close(file); if (quickroom.QRflags & QR_DIRECTORY) { sprintf(aaa,"mkdir ./files/%s",quickroom.QRdirname); system(aaa); sprintf(aaa,"./files/%s",quickroom.QRdirname); chmod(aaa,0777); } sprintf(aaa,"%s%c edited by %s", quickroom.QRname,room_prompt(&quickroom),usersupp.fullname); aide_message(aaa); return(0); } ungoto() { if (ugnum==(-1)) return(0); readyerself(); curr_rm=ugnum; gotocurr(); usersupp.lastseen[curr_rm]=uglsn; writeyerself(); return(0); } download(c) int c; { int a; char aaa[100],bbb[100]; if ((quickroom.QRflags&QR_DIRECTORY) &&(quickroom.QRflags&QR_DOWNLOAD)) { printf("Enter filename: "); getline(aaa,15); for (a=0; a<strlen(aaa); ++a) { aaa[a]=tolower(aaa[a]); if (aaa[a]=='/') aaa[a]='_'; } sprintf(bbb,"files/%s/%s",quickroom.QRdirname,aaa); if (c==0) formout(bbb); if (c==1) { sprintf(aaa,"wcsend %s",bbb); system(aaa); } if (c==2) { signal(SIGQUIT,SIG_DFL); sttybbs(1); sprintf(aaa,"cat <%s",bbb); system(aaa); sttybbs(0); unlink("core"); /* just in case the core was dumped */ } } else printf("Not in this room.\n"); return(0); } roomdir() { char aaa[100]; if ((quickroom.QRflags&QR_DIRECTORY) &&(quickroom.QRflags&QR_VISDIR)) { sprintf(aaa,"./files/%s",quickroom.QRdirname); printf("Directory of %s!%s/%s\n",NODENAME,BBSDIR,&aaa[2]); directory(aaa); } else printf("Not in this room.\n"); return(0); } invite() { /* add a user to a private room */ char aaa[31]; int file; long aa; struct usersupp USscratch; if ((quickroom.QRflags&QR_PRIVATE)==0) { printf("Not a private room.\n"); return(0); } printf("Name of user? "); getline(aaa,30); if (aaa[0]==0) return(0); file=open("usersupp",O_RDWR); if (file<0) interr(38); aa=finduser(file,aaa); if (aa!=(-1L)) { read(file,&USscratch,sizeof(struct usersupp)); lseek(file,aa,0); USscratch.generation[curr_rm]=quickroom.QRgen; USscratch.forget[curr_rm]=(-1); write(file,&USscratch,sizeof(struct usersupp)); } else printf("No such user.\n"); close(file); return(0); } kickout() { /* kick a user out of a private room */ int file; char aaa[100]; long aa; struct usersupp USscratch; if ((quickroom.QRflags&QR_PRIVATE)==0) { printf("Not a private room.\n"); return(0); } printf("Name of user? "); getline(aaa,30); file=open("usersupp",O_RDWR); if (file<0) interr(40); aa=finduser(file,aaa); if (aa!=(-1L)) { read(file,&USscratch,sizeof(struct usersupp)); lseek(file,aa,0); USscratch.generation[curr_rm]=(-1); write(file,&USscratch,sizeof(struct usersupp)); } else printf("No such user.\n"); close(file); return(0); } killroom() { /* aide command: kill the current room */ int file; long aa; char aaa[100]; if (curr_rm<3) { printf("Can't kill this room.\n"); return(0); } printf("Are you sure you want to kill this room? "); if (yesno()==0) return(0); file=open("quickroom",O_RDWR); if (file<0) interr(42); aa=(long)curr_rm*sizeof(struct quickroom); lseek(file,aa,0); quickroom.QRflags=0; write(file,&quickroom,sizeof(struct quickroom)); close(file); sprintf(aaa,"%s%c killed by %s", quickroom.QRname,room_prompt(&quickroom),usersupp.fullname); aide_message(aaa); curr_rm=0; /* then goto the lobby */ gotocurr(); return(0); } forget() { /* forget the current room */ if (curr_rm<3) { printf("Cannot forget this room.\n"); return(0); } IFAIDE { printf("Aides cannot forget rooms.\n"); return(0); } printf("Are you sure you want to forget this room? "); if (yesno()==0) return(0); readyerself(); usersupp.forget[curr_rm]=quickroom.QRgen; usersupp.generation[curr_rm]=(-1); writeyerself(); curr_rm=0; /* then goto the lobby */ gotocurr(); return(0); } entroom() { int a,b,c,d,file; char aaa[100],bbb[100]; long bb,cc,dd; struct quickroom QRscratch; if (usersupp.axlevel<3) { printf("You need higher access to create rooms.\n"); return(0); } printf("Name for new room? "); getline(aaa,19); if (strlen(aaa)==0) return(0); aaa[19]=0; file=open("quickroom",O_RDONLY); if (file<0) interr(62); b=0; for (a=0; a<MAXROOMS; ++a) { c=read(file,&QRscratch,sizeof(struct quickroom)); if (c<1) interr(63); if ( (QRscratch.QRflags & QR_INUSE) && (!strucmp(QRscratch.QRname,aaa)) ) b=1; } close(file); if (b==1) { printf("'%s' already exists.\n",aaa); return(0); } bb=(-1L); file=open("quickroom",O_RDONLY); if (file<0) interr(64); for (a=0; a<MAXROOMS; ++a) { cc=lseek(file,0L,1); c=read(file,&QRscratch,sizeof(struct quickroom)); if (c<1) interr(65); if (((QRscratch.QRflags&QR_INUSE)==0)&&(bb==(-1L))) bb=cc; } close(file); if (bb==(-1L)) { printf("No room space available.\n"); return(0); } IFNEXPERT formout("messages/roomaccess"); ACSEL: printf("<?>Help\n<1>Public room\n<2>Guess-name room\n"); printf("<3>Passworded room\n<4>Invitation-only room\n"); printf("Enter room type: "); ACSE2: b=inkey(); b=tolower(b); if (b=='?') { printf("?\n"); formout("messages/roomaccess"); goto ACSEL; } b=b-48; if ((b<1)||(b>4)) goto ACSE2; if (b==3) { printf("Enter a room password: "); getline(bbb,9); } printf("%d\n\042%s\042, a",b,aaa); if (b==1) printf(" public room."); if (b==2) printf(" guess-name room."); if (b==3) printf(" passworded room, password: %s",bbb); if (b==4) printf("n invitation-only room."); printf("\nInstall it? (y/n) : "); a=yesno(); if (a==0) return(0); curr_rm=(int)(bb/sizeof(struct quickroom)); file=open("quickroom",O_RDWR); if (file<0) interr(66); dd=lseek(file,bb,0); d=read(file,&quickroom,sizeof(struct quickroom)); if (d<1) interr(67); strcpy(quickroom.QRname,aaa); strcpy(quickroom.QRpasswd,""); if (b==3) strcpy(quickroom.QRpasswd,bbb); quickroom.QRroomaide=(-1L); quickroom.QRhighest=0L; ++quickroom.QRgen; if (quickroom.QRgen==100) quickroom.QRgen=10; quickroom.QRflags=QR_INUSE; if (b>1) quickroom.QRflags=(quickroom.QRflags|QR_PRIVATE); if (b==2) quickroom.QRflags=(quickroom.QRflags|QR_GUESSNAME); if (b==3) quickroom.QRflags=(quickroom.QRflags|QR_PASSWORDED); if ((b>2)&&(CREATAIDE==1)) quickroom.QRroomaide=usersupp.eternal; lseek(file,bb,0); write(file,&quickroom,sizeof(struct quickroom)); close(file); /* Initialize a blank fullroom structure */ for (a=0; a<MSGSPERRM; ++a) { fullroom.FRnum[a]=0L; fullroom.FRpos[a]=0L; } sprintf(aaa,"./rooms/fullrm%d",curr_rm); file=open(aaa,O_RDWR); if (file<0) interr(70); write(file,&fullroom,sizeof(struct fullroom)); close(file); gotocurr(); strcpy(aaa,quickroom.QRname); strcat(aaa,"> created by "); strcat(aaa,usersupp.fullname); if (quickroom.QRflags&QR_PRIVATE) strcat(aaa," [private]"); if (quickroom.QRflags&QR_GUESSNAME) strcat(aaa,"[guessname] "); if (quickroom.QRflags&QR_PASSWORDED) { strcat(aaa,"\n Password: "); strcat(aaa,quickroom.QRpasswd); } aide_message(aaa); return(0); } gotocurr() /* goto room currently in global variable curr_rm */ { int file,d; char aaa[100]; file=open("quickroom",O_RDONLY); if (file<0) interr(74); lseek(file,(long)(curr_rm*sizeof(struct quickroom)),0); d=read(file,&quickroom,sizeof(struct quickroom)); if (d<1) interr(75); close(file); if (curr_rm==1) { readmail(); return(0); } sprintf(aaa,"./rooms/fullrm%d",curr_rm); file=open(aaa,O_RDONLY); if (file<0) interr(76); d=read(file,&fullroom,sizeof(struct fullroom)); if (d<1) interr(77); close(file); return(0); } whoknows() { struct usersupp temp; int file; file=open("usersupp",O_RDONLY); if (file<0) return(file); while(read(file,&temp,sizeof(struct usersupp))>0) if ((quickroom.QRflags & QR_INUSE) && ( (curr_rm!=2) || (temp.axlevel>=6) ) && (quickroom.QRgen != (temp.forget[curr_rm]) ) && ( ((quickroom.QRflags&QR_PREFONLY)==0) || (temp.axlevel>=5) ) && ( ((quickroom.QRflags&QR_PRIVATE)==0) || (temp.axlevel>=6) || (quickroom.QRgen==(temp.generation[curr_rm])) ) ) printf("%s\n",temp.fullname); close(file); return(0); } SHAR_EOF fi echo shar: "extracting 'routines.c'" '(10412 characters)' if test -f 'routines.c' then echo shar: "will not over-write existing file 'routines.c'" else cat << \SHAR_EOF > 'routines.c' /* Citadel/UX independent routines (i.e. no global variables are used) */ #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 ROUTINES_C #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) struct passwd *getpwuid(); struct passwd *getpwnam(); char *getenv(); long atol(); long lseek(); extern char *days[7]; extern char *months[12]; extern char *axdefs[7]; 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)); } back(spaces) /* Destructive backspace */ int spaces; { int a; for (a=1; a<=spaces; ++a) { putc(8,stdout); putc(32,stdout); putc(8,stdout); } } yesno() { /* Returns 1 for yes, 0 for no */ int a; while (1) { a=inkey(); a=tolower(a); if (a=='y') { printf("Yes\n"); return(1); } if (a=='n') { printf("No\n"); return(0); } } } edituser(structure) struct usersupp *structure; { int a,b; do { printf("Current access level: %d [%s]\n",structure->axlevel, axdefs[structure->axlevel]); printf("New level (? to list them): "); a=inkey(); if (a=='?') { printf("list\n"); for (b=0; b<7; ++b) printf("%d %s\n",b,axdefs[b]); } a=a-48; } while((a<0)||(a>6)); printf("%d\n",a); structure->axlevel=a; return(0); } getusinfo(structure) struct usersupp *structure; { int a; char aaa[100]; do { printf("Enter your screen width: "); getline(aaa,3); a=atoi(aaa); if ((a<20)||(a>132)) printf("...must be between 20 and 132.\n"); } while((a<20)||(a>132)); structure->screenwidth=a; printf("Are you an experienced Citadel user? "); structure->flags=((structure->flags)|US_EXPERT); if (yesno()==0) structure->flags=((structure->flags)^US_EXPERT); printf("Print last old message on New message request? "); structure->flags=((structure->flags)|US_LASTOLD); if (yesno()==0) structure->flags=((structure->flags)^US_LASTOLD); if ((structure->flags&US_EXPERT)==0) formout("messages/unlisted"); printf("List in userlog? "); structure->flags=((structure->flags)|US_UNLISTED); if (yesno()==1) structure->flags=((structure->flags)^US_UNLISTED); printf("Prompt after each message? "); structure->flags=((structure->flags)|US_NOPROMPT); if (yesno()==1) structure->flags=((structure->flags)^US_NOPROMPT); } getfield(file,string) /* Break out next null-terminated string */ int file; char string[]; { int a,b,c; strcpy(string,""); a=0; do { c=0; b=read(file,&c,1); if (b<1) { string[a]=0; return(0); } string[a]=c; ++a; } while(c!=0); return(0); } 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)); } pattern(search,patn) /* Searches for patn in search string */ char search[]; char patn[]; { int a,b; for (a=0; a<strlen(search); ++a) { b=strncmp(&search[a],patn,strlen(patn)); if (b==0) return(b); } return(1); } interr(errnum) /* display internal error as defined in errmsgs */ int errnum; { printf("INTERNAL ERROR %d\n",errnum); printf("(Press any key to continue)\n"); inkey(); logoff(errnum); } directory(path) char *path; { struct directx { int d_ino; char d_name[15]; } dlink; char comment[151]; int fd,nread,a; char tname[100]; struct stat statbuf; long aa; FILE *fp; if ((fd=open(path,0))==(-1)) return(1); dlink.d_name[14]=0; printf("-----------------------\n"); read(fd,&dlink,16); read(fd,&dlink,16); while ((nread=read(fd,&dlink,16)) > 0) { if ((strucmp(dlink.d_name,"filedir"))&&(dlink.d_ino!=0)) { sprintf(tname,"%s/%s",path,dlink.d_name); stat(tname,&statbuf); aa=(long)statbuf.st_size; sprintf(tname,"%s/filedir",path); fp=fopen(tname,"r"); comment[0]=0; if (fp!=NULL) { do { for (a=0; a<17; ++a) comment[a]=0; fgets(comment,151,fp); comment[strlen(comment)-1]=0; if (!strncmp(comment,dlink.d_name,strlen(dlink.d_name))) goto FND; } while(!feof(fp)); FND: fclose(fp); } printf("%-14s %8ld %s\n",dlink.d_name,aa,&comment[strlen(dlink.d_name)+1]); } } close(fd); return(0); } fpgetfield(fp,string) /* level-2 break out next null-terminated 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); return(0); } fmout(width,flname) int width; char flname[]; { int a,b,c,real,old; char aaa[140]; FILE *fp; fp=fopen(flname,"rb"); if (fp==NULL) { printf("No file %s.\n",flname); return(1); } 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)) ) { printf("\n"); c=1; } if (a>126) goto FMTA; if (a>32) { if ( ((strlen(aaa)+c)>(width-5)) && (strlen(aaa)>(width-5)) ) { 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 FMTA; } if ((a==13)||(a==10)) { printf("%s\n",aaa); c=1; strcpy(aaa,""); goto FMTA; } goto FMTA; FMTEND: fclose(fp); printf("\n"); return(0); } strproc(string) char string[]; { int a; char aaa[100]; char bbb[5]; strcpy(aaa,string); if (string[0]==0) return(0); /* Convert non-printable characters to blanks */ for (a=0; a<strlen(aaa); ++a) { if (aaa[a]<32) aaa[a]=32; if (aaa[a]>126) aaa[a]=32; } /* Remove leading and trailing blanks */ while(aaa[0]<33) strcpy(aaa,&aaa[1]); while(aaa[strlen(aaa)-1]<33) aaa[strlen(aaa)-1]=0; /* Remove double blanks */ bbb[1]=0; strcpy(string,""); for (a=0; a<strlen(aaa); ++a) { if ((aaa[a]==32)&&(aaa[a+1]==32)) goto PSSKP; bbb[0]=aaa[a]; strcat(string,bbb); PSSKP: bbb[1]=0; } /* remove characters which would interfere with the network */ for (a=0; a<strlen(aaa); ++a) { if (aaa[a]=='!') strcpy(&aaa[a],&aaa[a+1]); if (aaa[a]=='@') strcpy(&aaa[a],&aaa[a+1]); if (aaa[a]=='_') strcpy(&aaa[a],&aaa[a+1]); if (aaa[a]==',') strcpy(&aaa[a],&aaa[a+1]); } return(0); } sttybbs(sflag) int sflag;{ struct termio live; ioctl(0,TCGETA,&live); live.c_iflag=ISTRIP|IXON|IXANY; live.c_oflag=OPOST|ONLCR; live.c_lflag=NOFLSH; if (sflag==1) live.c_lflag=ISIG|NOFLSH; live.c_line=0; live.c_cc[0]=15; live.c_cc[1]=3; live.c_cc[2]=8; live.c_cc[3]=24; live.c_cc[4]=1; live.c_cc[5]=255; live.c_cc[6]=0; live.c_cc[7]=0; ioctl(0,TCSETA,&live); return(0); } long finduser(file,name) /* binary search for a user */ 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)); while(1) { 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; if (a>0) top=guess; } } rec_log(record) /* record an entry in the call log */ struct calllog *record; { int file,a,b; time(&record->CLtime); file=open("calllog.pos",O_RDWR); read(file,&a,2); b=a; ++a; if (a==CALLLOG) a=0; lseek(file,0L,0); write(file,&a,2); close(file); file=open("calllog",O_RDWR); lseek(file,(long)(b*sizeof(struct calllog)),0); write(file,record,sizeof(struct calllog)); close(file); return(0); } log_carr() /* use rec_log to record the connection */ { struct calllog temp; struct termio stty; strcpy(temp.CLfullname,ttyname(0)); temp.CLflags=CL_INOTHER; ioctl(0,TCGETA,&stty); if ((stty.c_cflag&B300)==B300) temp.CLflags=CL_IN300; if ((stty.c_cflag&B1200)==B1200) temp.CLflags=CL_IN1200; if ((stty.c_cflag&B2400)==B2400) temp.CLflags=CL_IN2400; if ((stty.c_cflag&B9600)==B9600) temp.CLflags=CL_INOTHER; rec_log(&temp); return(0); } alias(name) /* process alias and routing info for mail */ char name[]; { FILE *fp; int a,b,file; char aaa[300],bbb[300]; fp=fopen("network/mail.aliases","r"); if (fp==NULL) return(2); 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); goto DETYPE; } if (strucmp(name,aaa)) goto GNA; fclose(fp); strcpy(name,bbb); printf("*** Mail is being forwarded to %s\n",name); DETYPE: /* determine local or remote type, see citadel.h */ for (a=0; a<strlen(name); ++a) if (name[a]=='!') return(M_UUCP); b=0; for (a=0; a<strlen(name); ++a) if (name[a]=='@') ++b; if (b>1) { printf("Too many @'s in address\n"); return(M_ERROR); } if (b==1) { for (a=0; a<strlen(name); ++a) if (name[a]=='@') strcpy(bbb,&name[a+1]); while (bbb[0]==32) strcpy(bbb,&bbb[1]); file=open("network/mail.sysinfo",O_RDONLY); GETSN: do { a=getstring(file,aaa); } while ((a>=0)&&(strucmp(aaa,bbb))); a=getstring(file,aaa); if (!strncmp(aaa,"use ",4)) { strcpy(bbb,&aaa[4]); goto GETSN; } close(file); if (!strncmp(aaa,"bin",3)) { strcpy(aaa,name); strcpy(bbb,name); while (aaa[strlen(aaa)-1]!='@') aaa[strlen(aaa)-1]=0; aaa[strlen(aaa)-1]=0; while (aaa[strlen(aaa)-1]==' ') aaa[strlen(aaa)-1]=0; while (bbb[0]!='@') strcpy(bbb,&bbb[1]); strcpy(bbb,&bbb[1]); while (bbb[0]==' ') strcpy(bbb,&bbb[1]); sprintf(name,"%s @%s",aaa,bbb); return(M_BINARY); } printf("Error in network/mail.sysinfo file\n"); return(M_ERROR); } return(M_LOCAL); } SHAR_EOF fi echo shar: "extracting 'routines2.c'" '(10078 characters)' if test -f 'routines2.c' then echo shar: "will not over-write existing file 'routines2.c'" else cat << \SHAR_EOF > 'routines2.c' /* More Citadel/UX routines... * unlike routines.c, some of these DO use global variables. */ #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" long atol(); long lseek(); long finduser(); extern int curr_rm; extern int ugnum; extern long uglsn; extern struct quickroom quickroom; extern struct usersupp usersupp; extern struct fullroom fullroom; extern char temp[]; extern char *axdefs[7]; eopen(name,mode) char *name; int mode; { int ret; ret=open(name,mode); if (ret<0) { fprintf(stderr,"-------------------------\n"); fprintf(stderr,"Cannot open file '%s', mode=%d\n",name,mode); interr(1); } return(ret); } 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); } int room_prompt(qrptr) /* return proper room prompt character */ struct quickroom *qrptr; { int a; a='>'; if ((qrptr->QRflags)&QR_DIRECTORY) a=']'; if ((a==']')&&((qrptr->QRflags)&QR_NETWORK)) a='}'; if ((a=='>')&&((qrptr->QRflags)&QR_NETWORK)) a=')'; return(a); } entregis(who) /* register a user with name and address */ long who; { int f,file,a,b; char pbuf[15]; struct registration regis,rtemp; regis.RGeternal=who; printf("REAL name: "); getline(regis.RGname,29); printf(" Address: "); getline(regis.RGaddr,24); printf("City/town: "); getline(regis.RGcity,14); printf(" State: "); getline(regis.RGstate,2); printf(" ZIP code: "); getline(regis.RGzip,5); printf("Phone num: "); getline(pbuf,14); 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; } printf("\n"); f=fork(); /* register in the background */ if (f<0) { fprintf(stderr,"citadel: cannot fork-registration not filed\n"); return(-1); } if (f>0) return(0); /* remainder of this routine happens in a separate task! */ file=open("registration",O_RDWR); if (file<0) file=creat("registration",0644); while(read(file,&rtemp,sizeof(struct registration))>0) { if (rtemp.RGeternal==who) { lseek(file,(0L-sizeof(struct registration)),1); goto WRT; } } WRT: write(file,®is,sizeof(struct registration)); close(file); exit(0); /* no, not return() - we're a child process */ } updatels() { /* make all messages old in current room */ int a; readyerself(); storeug(); for (a=0; a<MSGSPERRM; ++a) if (fullroom.FRnum[a]>usersupp.lastseen[curr_rm]) usersupp.lastseen[curr_rm]=fullroom.FRnum[a]; if (curr_rm==1) /* if mail room, do it a little differently... */ usersupp.lastseen[1]=usersupp.mailnum[MAILSLOTS-1]; writeyerself(); } storeug() { /* store <u>ngoto information */ ugnum=curr_rm; uglsn=usersupp.lastseen[curr_rm]; return(0); } getline(string,lim) /* Gets a line from the terminal */ char string[]; /* Pointer to string buffer */ int lim; /* Maximum length - if negative, no-show */ { int a,b; char flag; flag=0; if (lim<0) { lim=(0-lim); flag=1; } strcpy(string,""); GLA: a=inkey(); a=(a&127); if ((a==8)&&(strlen(string)==0)) goto GLA; if ((a!=13)&&(a!=8)&&(strlen(string)==lim)) goto GLA; if ((a==8)&&(string[0]!=0)) { string[strlen(string)-1]=0; putc(8,stdout); putc(32,stdout); putc(8,stdout); goto GLA; } if ((a==13)||(a==10)) { putc(13,stdout); putc(10,stdout); return(0); } b=strlen(string); string[b]=a; string[b+1]=0; if (flag==0) putc(a,stdout); if (flag==1) putc('*',stdout); goto GLA; } delete_message(delnum) /* Delete message from current room */ long delnum; { int file,a,b; char aaa[100]; if (curr_rm==1) { printf("Can't delete mail.\n"); return(1); } sprintf(aaa,"./rooms/fullrm%d",curr_rm); file=eopen(aaa,O_RDWR); a=read(file,&fullroom,sizeof(struct fullroom)); if (a<1) interr(79); for (a=0; a<MSGSPERRM; ++a) if (fullroom.FRnum[a]==delnum) { fullroom.FRnum[a]=0L; fullroom.FRpos[a]=0L; } lseek(file,0L,0); a=write(file,&fullroom,sizeof(struct fullroom)); if (a<1) interr(80); close(file); file=eopen("./quickroom",O_RDWR); lseek(file,(long)(curr_rm*sizeof(struct quickroom)),0); b=read(file,&quickroom,sizeof(struct quickroom)); if (b<1) interr(82); quickroom.QRhighest=0L; for (a=0; a<MSGSPERRM; ++a) if (fullroom.FRnum[a]>quickroom.QRhighest) quickroom.QRhighest=fullroom.FRnum[a]; lseek(file,(long)(curr_rm*sizeof(struct quickroom)),0); b=write(file,&quickroom,sizeof(struct quickroom)); if (b<1) interr(83); close(file); printf("Message deleted.\n"); return(0); } upload(c) /* c = upload mode */ int c; { char buf[151],aaa[100],bbb[60],ccc[60]; int a,b,file; long cc; FILE *fp; if ( ((quickroom.QRflags&QR_DIRECTORY)==0) || ((quickroom.QRflags&QR_UPLOAD)==0) ) { printf("Not in this room.\n"); return(1); } printf("Enter filename: "); getline(aaa,15); for (a=0; a<strlen(aaa); ++a) aaa[a]=tolower(aaa[a]); sprintf(bbb,"./files/%s/%s",quickroom.QRdirname,aaa); file=open(bbb,O_RDONLY); if (file>(-1)) { printf("There already is a file by that name.\n"); close(file); return(1); } printf("Enter a short description of the file:\n: "); getline(buf,150); sprintf(ccc,"./files/%s/filedir",quickroom.QRdirname); fp=fopen(ccc,"r+"); if (fp==NULL) fp=fopen(ccc,"w"); fseek(fp,0L,2); fprintf(fp,"%s %s\n",aaa,buf); fclose(fp); file=creat(bbb,0666); if (file<0) { printf("Can't create that file?\n"); return(1); } if (c>0) { close(file); goto ETUX; } a=0; printf("Now recieving. ESC to end.\n"); do { b=inkey(); if (b==13) { b=10; printf("\r"); } if (b!=27) { printf("%c",b); write(file,&b,1); } } while(b!=27); close(file); ETPRF: printf("File recieved.\n"); time(&cc); /* put together an upload notice */ fp=fopen(temp,"wb"); if (fp==NULL) interr(22); putc(255,fp); putc(MES_NORMAL,fp); putc(0,fp); fprintf(fp,"Psysop"); putc(0,fp); fprintf(fp,"T%ld",cc); putc(0,fp); fprintf(fp,"A%s",usersupp.fullname); putc(0,fp); fprintf(fp,"O%s",quickroom.QRname); putc(0,fp); fprintf(fp,"N%s",NODENAME); putc(0,fp); putc('M',fp); fprintf(fp,"*New Upload*\nFilename: %s\r %s\n",aaa,buf); putc(0,fp); fclose(fp); save_message(temp,buf,0,M_LOCAL); return(0); ETUX: if (c==1) { sprintf(ccc,"wcreceive %s",bbb); system(ccc); } goto ETPRF; } move_message(pos) long pos; { char targ[20]; int file,a,h; struct quickroom qtemp; h=curr_rm; pull_message(pos,temp); do { curr_rm=(-1); printf("Enter target room: "); getline(targ,19); if (targ[0]==0) strcpy(targ,quickroom.QRname); file=open("quickroom",O_RDONLY); for (a=0; a<MAXROOMS; ++a) { read(file,&qtemp,sizeof(struct quickroom)); if ((!strucmp(qtemp.QRname,targ))&&(qtemp.QRflags&QR_INUSE)) curr_rm=a; } close(file); } while(curr_rm<0); gotocurr(); save_message(temp,"",0,M_LOCAL); curr_rm=h; gotocurr(); return(0); } aide_message(text) /* post a message in Aide> */ char *text; { long now; FILE *fp; time(&now); fp=fopen(temp,"wb"); if (fp==NULL) interr(92); putc(255,fp); putc(MES_NORMAL,fp); putc(0,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); fprintf(fp,"%s\n",text); putc(0,fp); fclose(fp); save_message(temp,"",1,M_LOCAL); return(0); } validate() { /* validate new users */ struct msgmain MMtemp; struct usersupp UStemp; int file,a,b; file=eopen("MMstructure",O_RDONLY); read(file,&MMtemp,sizeof(struct msgmain)); close(file); if ((MMtemp.MMflags&MM_VALID)==0) { printf("There are no unvalidated users.\n"); return(0); } do { file=eopen("MMstructure",O_RDONLY); read(file,&MMtemp,sizeof(struct msgmain)); close(file); } while(MMtemp.MMflags&MM_BUSY); file=eopen("MMstructure",O_WRONLY); MMtemp.MMflags=MMtemp.MMflags&(~MM_VALID); write(file,&MMtemp,sizeof(struct msgmain)); close(file); file=eopen("usersupp",O_RDWR); while(read(file,&UStemp,sizeof(struct usersupp))>0) { if (UStemp.axlevel==1) { printf("\n\n\nUser #%-5ld %s ", UStemp.eternal,UStemp.fullname); if (usersupp.screenwidth<=40) printf("\n"); pwcrypt(UStemp.password,PWCRYPT); printf("PW: %s\n",UStemp.password); dis_regis(&UStemp); printf("Access level (? for list): "); do { a=inkey(); if (a=='?') { printf("list\n"); for (b=0; b<7; ++b) printf("%d %s\n",b,axdefs[b]); } a=a-48; } while((a<0)||(a>6)); printf("%d\n",a); UStemp.axlevel=a; pwcrypt(UStemp.password,PWCRYPT); lseek(file,(0L-sizeof(struct usersupp)),1); write(file,&UStemp,sizeof(struct usersupp)); } } close(file); printf("\n*** End of registration.\n"); return(0); } dis_regis(userdata) struct usersupp *userdata; { struct registration regis; int a,b,file; char pbuf[20]; if (!((userdata->flags)&US_REGIS)) { printf("No registration online.\n"); return(1); } file=open("registration",O_RDONLY); if (file<0) return(2); while(read(file,®is,sizeof(struct registration))>0) { if (userdata->eternal==regis.RGeternal) { printf("%-29s\n",regis.RGname); printf("%-29s\n",regis.RGaddr); printf("%-14s %2s %6s\n", 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); } printf("(%c%c%c) %c%c%c-%c%c%c%c\n", 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]); } if (userdata->eternal==regis.RGeternal) break; } close(file); return(0); } SHAR_EOF fi echo shar: "extracting 's.h'" '(2401 characters)' if test -f 's.h' then echo shar: "will not over-write existing file 's.h'" else cat << \SHAR_EOF > 's.h' /****************************************************************************/ /* YOUR SYSTEM CONFIGURATION!!! */ /* Edit these values to your particular system, then recompile all programs */ /* which use Citadel.h, so they all use your new values. Customize your */ /* system BEFORE running setup for the first time to avoid UNIXmadness!! */ /****************************************************************************/ /****************************************************************************/ /* Networking stuff * set NODENAME to your UUCP node name. Set PREVMSGS to the number of * records you want in the prevmsgs file, which keeps a record of recently * seen messages on all systems. This prevents messages from cycling * endlessly through the network. If you are not in a network, set PREVMSGS * to 2. If messages seem to be cycling endlessly through the network, * increase the value of PREVMSGS. */ #define NODENAME "cavevax" /* Your system's uucp nodename */ #define PREVMSGS 2 /* Number of recs in prevmsgs file */ /****************************************************************************/ #define BBSUID 999 /* make an account called "bbs", "guest", or something to that effect which * shells directly to citadel. Place the userid of the account here. */ #define CREATAIDE 0 /* If CREATAIDE is set to 1, anyone who creates a class 3 (passworded) or * class 4 (invitation-only) room automatically becomes the room-aide for * that room. */ #define SLEEPING 1800 /* If the program is waiting for input more than SLEEPING number of seconds, * Citadel will print "Sleeping? Call again." and hang up. To disable the * feature, set SLEEPING to 0. */ /* You may NOT change these six values once you set up your system. */ #define MAXROOMS 100 /* Number of rooms in system */ #define NVOTES 10 /* Number of votes sys can handle */ #define MAILSLOTS 35 /* Number of mail slots */ #define MSGSPERRM 150 /* Messages per room */ #define MM_FILELEN (2000000L) /* Number of bytes in message file */ #define CALLLOG 1000 /* Number of entries in call log */ /* Do not set MAILSLOTS higher than MSGSPERRM */ /* problem user stuff. */ #define IAADETECT 1 /* 1=on, 0=off */ #define IAAROOM "IAA etc." /* Name of room to send problems to */ SHAR_EOF fi echo shar: "extracting 'setup.c'" '(3913 characters)' if test -f 'setup.c' then echo shar: "will not over-write existing file 'setup.c'" else cat << \SHAR_EOF > 'setup.c' /* * Citadel/UX setup program * v1.1 / by Art Cancro 05/25/89 * see copyright.doc for copyright information * * *** YOU MUST EDIT sysconfig.h >BEFORE< COMPILING SETUP *** */ #include <stdio.h> #include <ctype.h> #include <fcntl.h> #include "citadel.h" main() { int a; char aaa[20]; printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); printf("Citadel/UX setup program\n\n"); printf("DO NOT re-create files that you wish to keep intact.\n"); printf("They will be ERASED if you do so!\n"); printf("If you are setting up Citadel/UX for the first time,\n"); printf("answer 'yes' to all of the prompts.\n\n"); a=0; printf("\nCreate message file? "); gets(aaa); aaa[0]=tolower(aaa[0]); a=aaa[0]; if (aaa[0]=='y') cre8msg(); printf("\n Create user file? "); gets(aaa); aaa[0]=tolower(aaa[0]); if (aaa[0]=='y') cre8user(); printf("\n Create room files? "); if (a!='y') gets(aaa); aaa[0]=tolower(aaa[0]); if (aaa[0]=='y') cre8room(); printf("\n Create call log? "); gets(aaa); aaa[0]=tolower(aaa[0]); if (aaa[0]=='y') cre8clog(); printf("\nSetup finished.\n"); exit(0); } cre8msg() { struct msgmain msgmain; FILE *fp; long aa; fp=fopen("msgmain","wb"); for (aa=0; aa<=(MM_FILELEN+100); ++aa) { putc(0,fp); if ((aa%10000L)==0L) printf("setup: writing msgmain byte %15ld\r",aa); } fclose(fp); printf("setup: writing control structure and unlocking file\n"); msgmain.MMlowest=1L; msgmain.MMhighest=1L; msgmain.MMcurpos=0L; msgmain.MMflags=0; fp=fopen("MMstructure","wb"); fwrite(&msgmain,sizeof(struct msgmain),1,fp); fclose(fp); } cre8user() { int file; struct usersupp usersupp; long aa; printf("setup: creating a blank user file\n"); unlink("usersupp"); file=creat("usersupp",0666); usersupp.screenwidth=0; usersupp.eternal=0L; usersupp.timescalled=0; usersupp.posted=0; usersupp.flags=US_UNLISTED; usersupp.USuid=(-1); strcpy(usersupp.fullname,"!"); strcpy(usersupp.password,""); usersupp.axlevel=4; write(file,&usersupp,sizeof(struct usersupp)); close(file); file=creat("eternal",0666); chmod("eternal",0666); aa=1L; write(file,&aa,4); close(file); } cre8room() { int a; FILE *fp; char aaa[50]; struct quickroom quickroom; struct fullroom fullroom; printf("setup: creating and initializing room files\n"); /* Load up a blank fullroom structure to be used for all rooms */ for (a=0; a<MSGSPERRM; ++a) { fullroom.FRnum[a]=0L; fullroom.FRpos[a]=0L; } /* Open a new quickroom file */ fp=fopen("quickroom","wb"); strcpy(quickroom.QRpasswd,""); quickroom.QRroomaide=0L; quickroom.QRhighest=0L; quickroom.QRgen=1; quickroom.QRflags=QR_INUSE; /* Create Lobby> Mail> and Aide> */ strcpy(quickroom.QRname,"Lobby"); fwrite(&quickroom,sizeof(struct quickroom),1,fp); strcpy(quickroom.QRname,"Mail"); fwrite(&quickroom,sizeof(struct quickroom),1,fp); strcpy(quickroom.QRname,"Aide"); fwrite(&quickroom,sizeof(struct quickroom),1,fp); /* make the remaining rooms blanks */ strcpy(quickroom.QRname,""); quickroom.QRflags=0; for (a=3; a<MAXROOMS; ++a) { printf("setup: creating quickroom %-3d\r",a); fwrite(&quickroom,sizeof(struct quickroom),1,fp); } fclose(fp); /* Create directories and fullroom files */ system("mkdir rooms"); for (a=0; a<MAXROOMS; ++a) { printf("setup: creating fullroom %-4d\n",a); sprintf(aaa,"./rooms/fullrm%d",a); fp=fopen(aaa,"wb"); fwrite(&fullroom,sizeof(struct fullroom),1,fp); fclose(fp); } } cre8clog() { int file,a; struct calllog calllog; calllog.CLfullname[0]=0; calllog.CLtime=0L; calllog.CLflags=0; a=0; file=creat("calllog.pos",0666); chmod("calllog.pos",0666); write(file,&a,2); close(file); file=creat("calllog",0666); chmod("calllog",0666); for (a=0; a<CALLLOG; ++a) { printf("setup: creating call log #%-4d\r",a); write(file,&calllog,sizeof(struct calllog)); } close(file); return(0); } SHAR_EOF fi echo shar: "extracting 'stats.c'" '(6446 characters)' if test -f 'stats.c' then echo shar: "will not over-write existing file 'stats.c'" else cat << \SHAR_EOF > 'stats.c' /* Citadel/UX call log stats program * version 1.01 */ #include <fcntl.h> #include <time.h> #include <curses.h> #include "citadel.h" long lseek(); halfhour(time) /* Returns half-hour time period of time */ long time; { int a; struct tm *tm; tm=(struct tm *)localtime(&time); a=(tm->tm_hour)*2; if ((tm->tm_min)>29) ++a; return(a); } main() { struct calllog calllog; int file,pos,a,b; float p,q; long timeon[48]; long timeup[48]; char dname[30]; long cftime,cttime,aa; int calls,calls300,calls1200,calls2400,console,logins,newusers,noncon; int badpws,terms,drops,sleeps; long from,to,tottime; int days,hours,minutes; char aaa[100]; struct tm *tm; char *tstring; initscr(); clear(); move(10,20); standout(); addstr("Scanning call log, please wait..."); standend(); refresh(); file=open("calllog.pos",O_RDONLY); read(file,&pos,2); close(file); from=0L; to=0L; for (a=0; a<48; ++a) { timeon[a]=0L; timeup[a]=0L; } cftime=0L; cttime=0L; calls=0; calls300=0; calls1200=0; console=0; logins=0; newusers=0; badpws=0; terms=0; drops=0; sleeps=0; noncon=0; file=open("calllog",O_RDONLY); lseek(file,(long)(pos*sizeof(struct calllog)),0); for (a=0; a<CALLLOG; ++a) { if ((a+pos)==CALLLOG) lseek(file,0L,0); read(file,&calllog,sizeof(struct calllog)); if (calllog.CLflags!=0) { if ((calllog.CLtime<from)||(from==0L)) from=calllog.CLtime; if ((calllog.CLtime>to)||(to==0L)) to=calllog.CLtime; strcpy(aaa,""); if (calllog.CLflags&CL_IN300) { ++calls; ++calls300; cftime=calllog.CLtime; ++noncon; strcpy(dname,calllog.CLfullname); } if (calllog.CLflags&CL_IN1200) { ++calls; ++calls1200; cftime=calllog.CLtime; ++noncon; strcpy(dname,calllog.CLfullname); } if (calllog.CLflags&CL_IN2400) { ++calls; ++calls2400; cftime=calllog.CLtime; ++noncon; strcpy(dname,calllog.CLfullname); } if (calllog.CLflags&CL_INOTHER) { ++calls; ++console; } if (calllog.CLflags&CL_LOGIN) ++logins; if (calllog.CLflags&CL_NEWUSER) ++newusers; if (calllog.CLflags&CL_BADPW) ++badpws; if (calllog.CLflags&CL_TERMINATE) { ++terms; cttime=calllog.CLtime; if ((cftime!=0L)&&(cttime!=0L)&&(!strcmp(dname,calllog.CLfullname))) for (aa=cftime; aa<=cttime; aa=aa+300L) timeon[halfhour(aa)]=timeon[halfhour(aa)]+5L; cftime=0L; cttime=0L; } if (calllog.CLflags&CL_DROPCARR) { ++drops; cttime=calllog.CLtime; if ((cftime!=0L)&&(cttime!=0L)&&(!strcmp(dname,calllog.CLfullname))) for (aa=cftime; aa<=cttime; aa=aa+300L) timeon[halfhour(aa)]=timeon[halfhour(aa)]+5L; cftime=0L; cttime=0L; } if (calllog.CLflags&CL_SLEEPING) { ++sleeps; cttime=calllog.CLtime; if ((cftime!=0L)&&(cttime!=0L)&&(!strcmp(dname,calllog.CLfullname))) for (aa=cftime; aa<=cttime; aa=aa+300L) timeon[halfhour(aa)]=timeon[halfhour(aa)]+5L; cftime=0L; cttime=0L; } } } close(file); tottime=to-from; days=(int)(tottime/86400L); hours=(int)((tottime%86400L)/3600L); minutes=(int)((tottime%3600L)/60L); clear(); move(3,3); addstr("300 bps calls:"); move(4,2); addstr("1200 bps calls:"); move(5,2); addstr("2400 bps calls:"); move(6,3); addstr("Console calls:"); move(7,10); addstr("Logins:"); move(8,7); addstr("New users:"); move(9,1); addstr("Bad pw attempts:"); move(10,2); addstr("Proper logoffs:"); move(11,3); addstr("Carrier drops:"); move(12,2); addstr("Sleeping drops:"); move(13,5); addstr("TOTAL CALLS:"); move(14,1); addstr("Non-Console Calls:"); refresh(); move(2,43); addstr("Total"); move(2,33); addstr("Avg/Day"); move(2,23); addstr("Avg/Call"); move(18,19); addstr("From:"); move(19,21); addstr("To:"); move(20,6); addstr("Total report time:"); move(21,12); addstr("Total calls:"); refresh(); move(21,25); printw("%d",calls); move(3,41); printw("%9d",calls300); move(4,41); printw("%9d",calls1200); move(5,41); printw("%9d",calls2400); move(6,41); printw("%9d",console); move(7,41); printw("%9d",logins); move(8,41); printw("%9d",newusers); move(9,41); printw("%9d",badpws); move(10,41); printw("%9d",terms); move(11,41); printw("%9d",drops); move(12,41); printw("%9d",sleeps); move(13,41); printw("%9d",calls); move(14,41); printw("%9d",noncon); refresh(); move(3,31); printw("%9.1f",(float)calls300/days); move(4,31); printw("%9.1f",(float)calls1200/days); move(5,31); printw("%9.1f",(float)calls2400/days); move(6,31); printw("%9.1f",(float)console/days); move(7,31); printw("%9.1f",(float)logins/days); move(8,31); printw("%9.1f",(float)newusers/days); move(9,31); printw("%9.1f",(float)badpws/days); move(10,31); printw("%9.1f",(float)terms/days); move(11,31); printw("%9.1f",(float)drops/days); move(12,31); printw("%9.1f",(float)sleeps/days); move(13,31); printw("%9.1f",(float)calls/days); move(14,31); printw("%9.1f",(float)noncon/days); refresh(); move(3,21); printw("%9.1f",(float)calls300/calls); move(4,21); printw("%9.1f",(float)calls1200/calls); move(5,21); printw("%9.1f",(float)calls2400/calls); move(6,21); printw("%9.1f",(float)console/calls); move(7,21); printw("%9.1f",(float)logins/calls); move(8,21); printw("%9.1f",(float)newusers/calls); move(9,21); printw("%9.1f",(float)badpws/calls); move(10,21); printw("%9.1f",(float)terms/calls); move(11,21); printw("%9.1f",(float)drops/calls); move(12,21); printw("%9.1f",(float)sleeps/calls); move(13,21); printw("%9.1f",(float)calls/calls); move(14,21); printw("%9.1f",(float)noncon/calls); refresh(); tm=(struct tm *)localtime(&from); tstring=(char *)asctime(tm); move(18,25); addstr(tstring); tm=(struct tm *)localtime(&to); tstring=(char *)asctime(tm); move(19,25); addstr(tstring); move(20,25); printw("%d days, %d hours, %d minutes", days,hours,minutes); refresh(); move(23,0); addstr("(please wait)"); refresh(); for (aa=from; aa<=to; aa=aa+1800L) timeup[halfhour(aa)]=timeup[halfhour(aa)]+30L; move(23,0); addstr("Press RETURN for system usage graph"); move(0,0); refresh(); gets(aaa); clear(); move(21,6); addstr("0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2"); move(22,6); addstr("0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3"); for (a=0; a<21; ++a) { move(a,4); addch('%'); } for (a=0; a<=20; ++a) { move(20-a,1); printw("%3d",a*5); } refresh(); for (b=0; b<48; ++b) { for (a=0; a<=20; ++a) { p=((float)timeon[b])/((float)timeup[b])*20; q=(float)a; if (p>=q) { move(20-a,6+b); addch('*'); } } refresh(); } move(23,0); refresh(); endwin(); exit(0); } SHAR_EOF fi echo shar: "extracting 'sysconfig.h'" '(3506 characters)' if test -f 'sysconfig.h' then echo shar: "will not over-write existing file 'sysconfig.h'" else cat << \SHAR_EOF > 'sysconfig.h' /****************************************************************************/ /* YOUR SYSTEM CONFIGURATION */ /* Set all the values in this file appropriately BEFORE compiling any of the*/ /* C programs. If you are upgrading from an older version of Citadel/UX, it */ /* is vitally important that the #defines which are labelled "structure size*/ /* variables" are EXACTLY the same as they were in your old system, */ /* otherwise your files will be munged beyond repair. */ /****************************************************************************/ /****************************************************************************/ /* Networking stuff * set NODENAME to your UUCP node name. Set PREVMSGS to the number of * records you want in the prevmsgs file, which keeps a record of recently * seen messages on all systems. This prevents messages from cycling * endlessly through the network. If you are not in a network, set PREVMSGS * to 2. If messages seem to be cycling endlessly through the network, * increase the value of PREVMSGS. */ #define NODENAME "sysname" /* Your system's uucp nodename */ #define PREVMSGS 1000 /* Number of recs in prevmsgs file */ /****************************************************************************/ #define BBSDIR "/usr/bbs" /* This is the directory Citadel will reside in. */ #define BBSUID 7 /* make an account called "bbs", "guest", or something to that effect which * shells directly to citadel. Place the userid of the account here. */ #define PWCRYPT 123 /* Set PWCRYPT to any value between 0 and 255 for password encryption. DO * NOT CHANGE IT ONCE IT IS SET or your users will all be locked out. */ #define CREATAIDE 0 /* If CREATAIDE is set to 1, anyone who creates a class 3 (passworded) or * class 4 (invitation-only) room automatically becomes the room-aide for * that room. */ #define SLEEPING 180 /* If the program is waiting for input more than SLEEPING number of seconds, * Citadel will print "Sleeping? Call again." and hang up. To disable the * feature, set SLEEPING to 0. */ #define INITAX 1 /* New users are assigned the access level of INITAX: * 0 = Marked for deletion * 1 = New User * 2 = Problem User * 3 = Local User * 4 = Network User * 5 = Preferred User * 6 = Aide * set this value to 4 for instant validation or 1 for validation required. */ #define REGISCALL 1 /* If a user has called REGISCALL times, he/she will be required to register. * Set this value to 0 to disable required registration. * NOTE: Citadel/UX still does not require user validation by the sysop. */ /*** STRUCTURE SIZE VARIABLES ***/ /* You may NOT change these six values once you set up your system. */ #define MAXROOMS 64 /* Number of rooms in system */ #define MAILSLOTS 35 /* Number of mail slots */ #define MSGSPERRM 150 /* Messages per room */ #define MM_FILELEN (2000000L) /* Number of bytes in message file */ #define CALLLOG 1000 /* Number of entries in call log */ /* Do not set MAILSLOTS higher than MSGSPERRM */ /*** END OF STRUCTURE SIZE VARIABLES ***/ #define TWITDETECT 1 /* 1=on, 0=off */ #define TWITROOM "Trashcan" /* Name of room to send problems to */ /* If TWITDETECT is set to 1, messages posted by those designated as * "problem users" will automatically be moved to TWITROOM regardless of * what room they were posted in. */ SHAR_EOF fi echo shar: "extracting 'sysoputil.c'" '(10343 characters)' if test -f 'sysoputil.c' then echo shar: "will not over-write existing file 'sysoputil.c'" else cat << \SHAR_EOF > 'sysoputil.c' #include <fcntl.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include "citadel.h" #define ILIST 5000 #define CLN (5184000L) #define RLN (1209600L) #define BROWSE /* define BROWSE if the browse system is installed. */ /* Citadel/UX sysop utilities for release 3.01 * The software assumes that if any user who has access to this program is * allowed to use the sysop utilities. Make sure that the permissions * are correct for this. */ 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; } return(0); } cls() { return(system("clear")); } main(argc,argv) int argc; char *argv[]; { int a; char aaa[100]; chdir(BBSDIR); if (!strcmp(argv[1],"-u")) { userpurge(); exit(0); } if (!strcmp(argv[1],"-r")) { roompurge(); exit(0); } if (!strcmp(argv[1],"-g")) { readregis(1); exit(0); } MAINMENU: cls(); printf("\n\n"); printf(" *** Citadel/UX Sysop Utilities ***\n"); printf( "(aide access and /etc/passwd attachments are now in useradmin)\n\n"); printf(" 1. Purge old rooms\n"); printf(" 2. Read registration file (user num, street, city, phone)\n"); printf(" 3. Delete a user\n"); printf(" 4. Unlock message file\n"); printf(" 5. \n"); printf(" 6. Sort the userlog\n"); printf(" 7. Purge old users\n"); printf(" 8. Change casing of a user's name\n"); printf(" 9. Quit\n"); printf(" Please enter your selection: "); gets(aaa); a=atoi(aaa); switch(a) { case 1: roompurge(); break; case 2: readregis(0); break; case 3: deluser(); break; case 4: unlock(); break; case 6: sortlog("usersupp"); break; case 7: userpurge(); break; case 8: renameuser(); break; case 9: exit(0); default: goto MAINMENU; } goto MAINMENU; } deluser(argc,argv) int argc; char *argv[]; { int a,b,file,file2; char dme[100]; struct usersupp usersupp; printf("Name of user to delete? "); gets(dme); file=open("usersupp",O_RDONLY); if (file<0) { printf("No usersupp file available.\n"); return(1); } file2=creat("usersupp.new",0666); if (file<0) { printf("Can't open the new file.\n"); close(file); return(2); } A: a=read(file,&usersupp,sizeof(struct usersupp)); if (a<1) goto END; if (!strucmp(dme,usersupp.fullname)) goto B; b=write(file2,&usersupp,sizeof(struct usersupp)); if (b<1) printf("Can't rewrite!!!\n"); goto A; B: printf("%s removed\n", usersupp.fullname); goto A; END: close(file); close(file2); printf(" "); printf(" \n"); system("mv usersupp.new usersupp"); system("chmod 666 usersupp"); return(0); } /* The msgmain file is locked through the MMstructure file during writes, * to avoid two processes writing in the same place. If the program crashes * while the file is locked, run this program to unlock it. */ unlock() { struct msgmain msgmain; FILE *fp; fp=fopen("MMstructure","rb"); fread(&msgmain,sizeof(struct msgmain),1,fp); msgmain.MMflags = msgmain.MMflags & ~MM_BUSY; fclose(fp); fp=fopen("MMstructure","wb"); fwrite(&msgmain,sizeof(struct msgmain),1,fp); fclose(fp); return(0); } sortlog(filename) char *filename; { char aaa[100]; struct usersupp rec1; struct usersupp rec2; int file; long aa,cc,dd,nrecs; system("clear"); printf("6. Sort the userlog\n"); printf("--- this will take a long time, and if it is stopped\n"); printf("before it is finished, the userlog will be screwed up!\n"); printf("Enter password, or <return> to abort: "); gets(aaa); if (strucmp(aaa,"ledatic")) return(1); sprintf(aaa,"cp %s usersupp.bak",filename); system(aaa); file=open(filename,O_RDWR); if (file<0) return(file); aa=lseek(file,0L,2); nrecs=(aa/sizeof(struct usersupp)); for (cc=0; cc<nrecs; ++cc) { printf("Sorted %5d of %5d records.\n",cc,nrecs); for (dd=(nrecs-1L); dd>cc; --dd) { aa=((dd-1L)*sizeof(struct usersupp)); lseek(file,aa,0); read(file,&rec1,sizeof(struct usersupp)); read(file,&rec2,sizeof(struct usersupp)); if (strucmp(rec1.fullname,rec2.fullname)>0) { lseek(file,aa,0); write(file,&rec2,sizeof(struct usersupp)); write(file,&rec1,sizeof(struct usersupp)); } } } close(file); 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); } userpurge() { /* removes anyone who hasn't called in 2 months */ int a,b,c,d,file,file2; char aaa[100],bbb[100]; char dme[100]; long inlist[ILIST]; struct usersupp usersupp; struct registration regis; long now,call; FILE *post; for (a=0; a<ILIST; ++a) inlist[a]=0L; c=0; post=(FILE *)popen("aidepost","w"); fprintf(post,"Program: sysoputil userpurge() / Shell user = %s\n",logname()); fprintf(post,"The following users have not called in the past %ld seconds\n", CLN); fprintf(post,"or have been marked for deletion, and have been purged:\n"); time(&now); file=open("usersupp",O_RDONLY); if (file<0) { printf("No usersupp file available.\n"); return(1); } file2=creat("usersupp.new",0666); if (file<0) { printf("Can't open the new file.\n"); close(file); return(2); } read(file,&usersupp,sizeof(struct usersupp)); write(file2,&usersupp,sizeof(struct usersupp)); while (read(file,&usersupp,sizeof(struct usersupp))>0) { call=now-(usersupp.lastcall); strcpy(aaa,usersupp.password); pwcrypt(aaa,PWCRYPT); if (!strucmp(aaa,"deleteme")) call=CLN+1L; if (usersupp.axlevel==0) call=CLN+2L; printf("\r%20ld ",call); if ((call<=CLN)||(usersupp.flags&US_PERM)) { b=write(file2,&usersupp,sizeof(struct usersupp)); if (b<1) fprintf(stderr,"userpurge: cannot rewrite\n"); inlist[c]=usersupp.eternal; ++c; } else { printf("%s removed\n",usersupp.fullname); fprintf(post,"#%-5ld %-30s\n",usersupp.eternal, usersupp.fullname); } } END: close(file); close(file2); pclose(post); system("mv usersupp.new usersupp"); chmod("usersupp",0666); printf("Purging registration...\n"); file=open("registration",O_RDONLY); file2=creat("regis.new",0666); while(read(file,®is,sizeof(struct registration))>0) { for (a=0; a<c; ++a) if (inlist[a]==regis.RGeternal) write(file2,®is,sizeof(struct registration)); printf("\n"); } close(file); close(file2); system("mv regis.new registration"); #ifdef BROWSE printf("Purging browse files...\n"); system("mkdir /tmp/browse"); for (a=0; a<c; ++a) { sprintf(aaa,"subsysdir/browsedir/%ld",inlist[a]); sprintf(bbb,"/tmp/browse/%ld",inlist[a]); link(aaa,bbb); } system("rm subsysdir/browsedir/*"); system("mv /tmp/browse/* subsysdir/browsedir"); system("rm -r /tmp/browse"); #endif return(0); } roompurge() { /* remove any rooms which have not been accessed in 2 weeks */ int file,a,b; char fname[50]; long act,now; FILE *post; struct stat sbuf; struct quickroom quickroom; post=(FILE *)popen("aidepost","w"); fprintf(post, "Program: sysoputil roompurge() / Shell user = %s\n",logname()); fprintf(post, "The following rooms have not been used for %ld seconds\n",RLN); fprintf(post,"and have been deleted from the room files:\n"); time(&now); file=open("quickroom",O_RDWR); for (a=0; a<MAXROOMS; ++a) { sprintf(fname,"./rooms/fullrm%d",a); b=stat(fname,&sbuf); act=now-(long)sbuf.st_mtime; read(file,&quickroom,sizeof(struct quickroom)); if ((a>2)&&(quickroom.QRflags&QR_INUSE)&&(act>RLN)&&(b>=0) &&((quickroom.QRflags&QR_NETWORK)==0) &&((quickroom.QRflags&QR_DIRECTORY)==0)) { quickroom.QRflags=quickroom.QRflags-QR_INUSE; lseek(file,(long)a*sizeof(struct quickroom),0); write(file,&quickroom,sizeof(struct quickroom)); printf("%20s deleted\n",quickroom.QRname,act); fprintf(post,"%s\n",quickroom.QRname); } } close(file); pclose(post); return(0); } renameuser() { long aa; int file; struct usersupp user; char aaa[100]; long finduser(); printf("Enter old name: "); gets(aaa); file=open("usersupp",O_RDWR); aa=finduser(file,aaa); if (aa==(-1L)) { printf("No such user.\n"); close(file); return(0); } read(file,&user,sizeof(struct usersupp)); printf("Enter new name EXACTLY as it should appear: "); gets(user.fullname); if (strucmp(aaa,user.fullname)) { printf("You may only change casing. Rename not allowed\n"); close(file); return(1); } finduser(file,aaa); write(file,&user,sizeof(struct usersupp)); close(file); return(0); } readregis(mode) int mode; { struct registration regis; int file,a,b; char pbuf[11]; file=open("registration",O_RDONLY); if (file<0) { fprintf(stderr,"sysoputil: cannot open registration file\n"); return(1); } if (mode==0) cls(); while(read(file,®is,sizeof(struct registration))>0) { 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); } printf("#%4ld %-29s %14s, %-2s %6s ", regis.RGeternal,regis.RGname, regis.RGcity,regis.RGstate,regis.RGzip); printf("(%c%c%c) %c%c%c-%c%c%c%c\n", 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]); } close(file); if (mode==0) { printf("<press return to continue>\n"); gets(pbuf); } 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: "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 )