eric@sactoh0.SAC.CA.US (Eric J. Nihill) (11/26/90)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # source # This archive created: Sun Nov 25 12:59:50 1990 export PATH; PATH=/bin:/usr/bin:$PATH if test ! -d 'source' then echo shar: "creating directory 'source'" mkdir 'source' fi echo shar: "entering directory 'source'" cd 'source' echo shar: "extracting 'chat.c'" '(8218 characters)' if test -f 'chat.c' then echo shar: "will not over-write existing file 'chat.c'" else cat << \SHAR_EOF > 'chat.c' /* chat v1.3 * */ #define CONSOLE "/dev/console" #include <fcntl.h> #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <termio.h> #include <signal.h> #include <utmp.h> #include "citadel.h" int console; char online; char temp[20]; long lseek(); long atol(); int (*slamcarrier())() { if (online==1) write(console,"*off line* Press ctrl-c to exit\r\n",34); unlink("/tmp/chat.online"); exit(0); } main(argc,argv) int argc; char *argv[]; { int a,b,c,d,e; int file; char aaa[100]; struct termio term,saveio; FILE *fp,*arc; chdir(BBSDIR); if (!strncmp(ttyname(0),CONSOLE,strlen(CONSOLE))) { conchat(argc,argv); exit(0); } if (isclog()==0) { printf("No one else is online.\n"); exit(0); } online=0; ioctl(0,TCGETA,&saveio); ioctl(0,TCGETA,&term); term.c_iflag=3366; term.c_oflag=6149; term.c_lflag=59; term.c_line=0; term.c_cc[0]=127; term.c_cc[1]=28; term.c_cc[2]=8; term.c_cc[3]=24; term.c_cc[4]=4; term.c_cc[5]=255; term.c_cc[6]=0; term.c_cc[7]=0; term.c_lflag=0; term.c_iflag=ISTRIP; ioctl(0,TCSETA,&term); fp=fopen("/tmp/chat.name","w"); fprintf(fp,"%s\n",ttyname(0)); fclose(fp); console=open(CONSOLE,O_WRONLY); if (console<0) { fprintf(stderr,"Can't access %s\r\n",CONSOLE); goto END; } fprintf(stderr,"Paging %s...\r\n",CONSOLE); for (a=0; a<4; ++a) { b=7; write(console,&b,1); write(1,&b,1); sleep(1); } printf("Chat mode - press ctrl-c to exit if\r\n"); printf("no one answers in a minute or so...\r\n"); A: b=0; read(0,&b,1); /* read a character */ if (b==3) { printf("Exiting chat mode\r\n"); goto END; } if (online==1) { c=10; write(console,&b,1); write(1,&b,1); putc(b,arc); fflush(arc); if (b==13) { write(console,&c,1); write(1,&c,1); } goto A; } /* not online, check for flag file */ file=open("/tmp/chat.online",O_RDONLY); close(file); if (file>(-1)) { online=1; unlink("/tmp/chat.online"); arc=fopen("/tmp/chat.fifo","w+"); sprintf(aaa,"Online with user: %s\r\n",argv[1]); fprintf(arc,"%s",aaa); fflush(arc); write(console,aaa,strlen(aaa)); aaa[0]=0; signal(SIGHUP,(*slamcarrier)); write(console,&b,1); write(2,&b,1); putc(b,arc); fflush(fp); } goto A; END: unlink("/tmp/chat.online"); unlink("/tmp/chat.name"); if (online==1) write(console,"*off line* Press ctrl-c to exit\r\n",34); close(console); ioctl(0,TCSETA,&saveio); unlink("/tmp/chat.fifo"); exit(0); } conchat(argc,argv) int argc; char *argv[]; { int a,b,c,d,e; int console,file,file2; char online; char aaa[100],bbb[100]; struct termio term,saveio; FILE *arc; online=0; ioctl(0,TCGETA,&saveio); ioctl(0,TCGETA,&term); term.c_iflag=3366; term.c_oflag=6149; term.c_lflag=59; term.c_line=0; term.c_cc[0]=127; term.c_cc[1]=28; term.c_cc[2]=8; term.c_cc[3]=24; term.c_cc[4]=4; term.c_cc[5]=255; term.c_cc[6]=0; term.c_cc[7]=0; term.c_lflag=0; term.c_iflag=ISTRIP; ioctl(0,TCSETA,&term); file=open("/tmp/chat.name",O_RDONLY); if (file<0) { printf("No one has requested a chat.\r\n"); goto END; } system( "/etc/mknod /tmp/chat.fifo p; nohup aidepost </tmp/chat.fifo 2>/dev/null &"); if (fork()==0) aidepost(); read(file,bbb,30); close(file); unlink("/tmp/chat.name"); for (a=0; a<strlen(bbb); ++a) if (bbb[a]==10) bbb[a]=0; printf("Connected to: %s\r\n",bbb); file=open(bbb,O_WRONLY); if (file<0) { printf("Can't open %s\r\n",bbb); goto END; } file2=creat("/tmp/chat.online",0666); close(file2); sprintf(aaa,"\n*answer* - Online with: %s\r\n",argv[1]); write(file,aaa,strlen(aaa)); arc=fopen("/tmp/chat.fifo","w+"); fprintf(arc,"%s",aaa); aaa[0]=0; fflush(arc); unlink("nohup.out"); A: b=0; read(0,&b,1); if (b==3) { write(file,"*off line* Press ctrl-c to exit\r\n",34); write(file,"Press ctrl-c to return to the BBS.\r\n",36); close(file); fprintf(arc,"\n*out*\n"); fclose(arc); goto END; } c=10; write(file,&b,1); write(1,&b,1); putc(b,arc); if (b==13) { write(file,&c,1); write(1,&c,1); } fflush(arc); goto A; END: ioctl(0,TCSETA,&saveio); exit(0); } isclog() { struct utmp utmp; int file,a; a=0; file=open("/etc/utmp",O_RDONLY); while ((read(file,&utmp,sizeof(struct utmp)))) { if ((utmp.ut_name[0]!=0)&&(!strcmp(utmp.ut_line,"console"))) a=1; } close(file); return(a); } strucmp(st1,st2) char st1[],st2[]; { int a; char aaa[100],bbb[100]; for (a=0; a<=strlen(st1); ++a) aaa[a]=tolower(st1[a]); for (a=0; a<=strlen(st2); ++a) bbb[a]=tolower(st2[a]); a=strcmp(aaa,bbb); return(a); } send_message(filename,retbuf) /* send a message to the master file */ char filename[]; /* tempfilename of proper message */ struct smreturn *retbuf; /* return information */ { int file,a,b,c,d,e,file2; long aa,bb,cc,dd,ee,templen,hibytes,origpos; char aaa[100],mid[30]; struct msgmain msgmain; file=open("/usr/bbs/MMstructure",O_RDWR); if (file<0) exit(13); PWMINS: a=read(file,&msgmain,sizeof(struct msgmain)); if (a<1) exit(14); if (msgmain.MMflags & MM_BUSY) { lseek(file,0L,0); goto PWMINS; } lseek(file,0L,0); msgmain.MMflags=(msgmain.MMflags|MM_BUSY); a=write(file,&msgmain,sizeof(struct msgmain)); if (a<1) exit(16); close(file); origpos=msgmain.MMcurpos; ++msgmain.MMhighest; sprintf(mid,"I%ld",msgmain.MMhighest); /* measure the message */ file=open(filename,O_RDONLY); if (file<0) sprintf(stderr,"aidepost: error\n"); templen=lseek(file,0L,2); close(file); templen=templen+(long)strlen(mid); ++templen; /* check for FF bytes */ hibytes=0L; file=open("/usr/bbs/msgmain",O_RDWR); if (file<0) fprintf(stderr,"aidepost: can't open msgmain\n"); bb=lseek(file,msgmain.MMcurpos,0); cc=lseek(file,0L,1); for (bb=0L; bb<templen; ++bb) { if (cc>=MM_FILELEN) cc=lseek(file,0L,0); c=0; read(file,&c,1); ++cc; if (c>127) ++hibytes; /* bump count if hi bit set */ } msgmain.MMlowest=msgmain.MMlowest+hibytes; cc=lseek(file,msgmain.MMcurpos,0); file2=open(filename,O_RDONLY); if (file2<0) exit(19); cc=lseek(file,0L,1); read(file2,&b,2); write(file,&b,2); read(file2,&b,1); write(file,&b,1); write(file,mid,(strlen(mid)+1)); for (bb=0L; bb<templen; ++bb) { if (((long)cc)>=((long)MM_FILELEN)) cc=lseek(file,0L,0); read(file2,&b,1); write(file,&b,1); ++cc; } msgmain.MMcurpos=lseek(file,0L,1); close(file2); /* done with temp file */ close(file); /* done with master file */ /* now update the message structure */ msgmain.MMflags=msgmain.MMflags & ~MM_BUSY; file=open("/usr/bbs/MMstructure",O_RDWR); if (file<0) printf("20!!!\n"); a=write(file,&msgmain,sizeof(struct msgmain)); if (a<1) printf("21!!!\n"); close(file); retbuf->smnumber=msgmain.MMhighest; retbuf->smpos=origpos; return(0); } make_message(filename) char filename[]; /* temporary file name */ { FILE *fp,*arc; int a,b,c,old; long aa,bb,cc,beg,now; char aaa[100],bbb[100]; time(&now); fp=fopen(filename,"wb"); if (fp==NULL) exit(22); arc=fopen("/tmp/chat.fifo","r"); putc(255,fp); putc(MES_NORMAL,fp); putc(1,fp); fprintf(fp,"T%ld",now); putc(0,fp); fprintf(fp,"AChat Archive"); putc(0,fp); fprintf(fp,"OAide"); putc(0,fp); fprintf(fp,"N%s",NODENAME); putc(0,fp); putc('M',fp); while ((a=getc(arc))>0) { putc(a,fp); } MEFIN: putc(0,fp); fclose(fp); fclose(arc); unlink("/tmp/chat.fifo"); return(0); } aidepost() { int file,a,b; long aa; char aaa[100]; struct smreturn mybuffer; struct quickroom quickroom; struct fullroom fullroom; make_message(temp); send_message(temp,&mybuffer); unlink(temp); file=open("./quickroom",O_RDWR); b=2; lseek(file,(long)(b*sizeof(struct quickroom)),0); read(file,&quickroom,sizeof(struct quickroom)); quickroom.QRhighest=mybuffer.smnumber; lseek(file,(long)(b*sizeof(struct quickroom)),0); write(file,&quickroom,sizeof(struct quickroom)); close(file); sprintf(aaa,"./rooms/fullrm%d",b); file=open(aaa,O_RDWR); read(file,&fullroom,sizeof(struct fullroom)); for (a=0; a<(MSGSPERRM-1); ++a) { fullroom.FRnum[a]=fullroom.FRnum[a+1]; fullroom.FRpos[a]=fullroom.FRpos[a+1]; } fullroom.FRnum[MSGSPERRM-1]=mybuffer.smnumber; fullroom.FRpos[MSGSPERRM-1]=mybuffer.smpos; lseek(file,0L,0); write(file,&fullroom,sizeof(struct fullroom)); close(file); exit(0); } SHAR_EOF fi echo shar: "extracting 'citadel.c'" '(26829 characters)' if test -f 'citadel.c' then echo shar: "will not over-write existing file 'citadel.c'" else cat << \SHAR_EOF > 'citadel.c' /* * Citadel/UX * * citadel.c - Main source file. * */ #include <fcntl.h> #include <stdio.h> #include <ctype.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <signal.h> #include <pwd.h> #include <setjmp.h> #include <termio.h> #define CITADEL_C #include "citadel.h" #define IFEXPERT if (usersupp.flags&US_EXPERT) #define IFNEXPERT if ((usersupp.flags&US_EXPERT)==0) #define IFAIDE if (usersupp.axlevel>=6) #define IFNAIDE if (usersupp.axlevel<6) struct passwd *getpwuid(); struct passwd *getpwnam(); char *getenv(); long atol(); long lseek(); long finduser(); char fullname[100]; struct usersupp usersupp; /* Logged-in user's user supp */ struct quickroom quickroom,QRscratch; /* Current room and scratch */ struct fullroom fullroom; /* Current room */ struct smreturn smreturn; /* For returning message numbers */ struct msgmain msgmain; /* Global message info */ struct passwd *passwd; int curr_rm; /* Room NUMBER of current room. */ int hold_rm; /* Temporary room number */ /* 0=Lobby 1=Mail 2=Aide 3-up=other */ char newnow; char upass; /* Nonzero if pw is managed by UNIX */ long yourpos; /* position of your usersupp record */ char temp[50]; /* Name of general temp file */ int twitroom; /* Room num of TWIT room (if enabled) */ struct termio stty0; /* holds old termio settings */ jmp_buf nextbuf; int ugnum; long uglsn; /* holds <u>ngoto info */ int (*backnext())() { signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); longjmp(nextbuf,1); } int (*backstop())() { signal(SIGQUIT,SIG_IGN); signal(SIGINT,SIG_IGN); longjmp(nextbuf,2); } int (*sleeping())() { struct calllog rtmp; printf("Sleeping? Call again.\n"); strcpy(rtmp.CLfullname,ttyname(0)); rtmp.CLflags=CL_SLEEPING; rec_log(&rtmp); logoff(1); } int (*dropcarr())() { struct calllog rtmp; strcpy(rtmp.CLfullname,ttyname(0)); rtmp.CLflags=CL_DROPCARR; rec_log(&rtmp); logoff(SIGHUP); } inkey() { int a; signal(SIGALRM,(*sleeping)); alarm(SLEEPING); a=getc(stdin); if (a==127) a=8; signal(SIGALRM,SIG_IGN); return(a); } setsane() { ioctl(0,TCSETA,&stty0); } char *months[12]={ "Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec" }; char *axdefs[7]={ "Marked for deletion", "New User", "Problem User", "Local User", "Network User", "Preferred User", "Aide" }; formout(name) /* display a file using the formatter */ char name[]; { char aaa[100]; int a; strcpy(aaa,name); for (a=0; a<strlen(aaa); ++a) aaa[a]=tolower(aaa[a]); if (setjmp(nextbuf)!=0) { sttybbs(0); return(1); } signal(SIGINT,(*backnext)); signal(SIGQUIT,(*backstop)); sttybbs(1); fmout(usersupp.screenwidth,aaa); sttybbs(0); return(0); } userlist() /* prints the userlist */ { sttybbs(1); system("userlist"); sttybbs(0); } readmail() { int a; readyerself(); for (a=0; a<MSGSPERRM; ++a) { fullroom.FRnum[a]=0L; fullroom.FRpos[a]=0L; } for (a=0; a<MAILSLOTS; ++a) { fullroom.FRnum[a+(MSGSPERRM-MAILSLOTS)]=usersupp.mailnum[a]; fullroom.FRpos[a+(MSGSPERRM-MAILSLOTS)]=usersupp.mailpos[a]; } return(0); } writemail() { int a; readyerself(); for (a=0; a<MAILSLOTS; ++a) { usersupp.mailnum[a]=fullroom.FRnum[a+(MSGSPERRM-MAILSLOTS)]; usersupp.mailpos[a]=fullroom.FRpos[a+(MSGSPERRM-MAILSLOTS)]; } writeyerself(); return(0); } readyerself() { int file; file=eopen("usersupp",O_RDONLY); lseek(file,yourpos,0); do { read(file,&usersupp,sizeof(struct usersupp)); if (strucmp(fullname,usersupp.fullname)) finduser(file,fullname); } while(strucmp(fullname,usersupp.fullname)); close(file); return(0); } writeyerself() { int file; struct usersupp me; file=eopen("usersupp",O_RDWR); lseek(file,yourpos,0); read(file,&me,sizeof(struct usersupp)); if (me.eternal!=usersupp.eternal) yourpos=finduser(file,usersupp.fullname); lseek(file,yourpos,0); write(file,&usersupp,sizeof(struct usersupp)); close(file); return(0); } main() { int a,b,c,d,e,f,file,file2; long aa,cc; char buf[300]; char aaa[100],bbb[100],ccc[100],eee[100]; /* general purpose variables */ char skipping[MAXROOMS]; struct usersupp tempUS; struct calllog calllog; struct wtmpsupp wtmpsupp; char mtsflag,twit; chdir(BBSDIR); /* go to the right directory */ ioctl(0,TCGETA,&stty0); /* Store the old terminal parameters and */ sttybbs(0); /* install the new ones */ signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); signal(SIGHUP,(*dropcarr)); /* Cleanup gracefully if carrier is dropped */ printf("\nCitadel/UX release 3.01-1d\n"); twit=0; /* By default, user is not a problem user */ usersupp.screenwidth=80; formout("messages/hello"); /* print the opening greeting */ log_carr(); a=getuid(); passwd=(struct passwd *)getpwuid(a); strcpy(fullname,passwd->pw_gecos); upass=1; if (a==BBSUID) upass=0; twitroom=(-1); GSTA: newnow=0; if (upass==0) { /* guest account - find out */ GSTB: printf("Enter your name: "); /* who the user is */ getline(fullname,29); strproc(fullname); if (!strucmp(fullname,"bbs")) goto GSTB; if (!strucmp(fullname,"new")) goto GSTB; if (!strucmp(fullname,"off")) goto TERMINATE; if (strlen(fullname)==0) goto GSTB; } /* get the usersupp data for guest account */ file=eopen("usersupp",O_RDONLY); yourpos=finduser(file,fullname); if (yourpos==(-1L)) { close(file); goto NEWUSR; } read(file,&usersupp,sizeof(struct usersupp)); close(file); goto USOK; NEWUSR: if (upass==0) { printf("No record. Enter as new user? "); if (yesno()==0) goto GSTA; } /* Initialize a new account */ usersupp.USuid=getuid(); strcpy(usersupp.fullname,fullname); for (a=0; a<MAXROOMS; ++a) { usersupp.lastseen[a]=0L; usersupp.generation[a]=(-1); usersupp.forget[a]=(-1); } for (a=0; a<MAILSLOTS; ++a) { usersupp.mailnum[a]=0L; usersupp.mailpos[a]=0L; } usersupp.flags=0; usersupp.timescalled=0; usersupp.posted=0; usersupp.axlevel=INITAX; time(&aa); usersupp.lastcall=aa; getusinfo(&usersupp); if (upass==0) { IFNEXPERT formout("messages/changepw"); printf("Please enter a password: "); getline(usersupp.password,19); strproc(usersupp.password); pwcrypt(usersupp.password,PWCRYPT); newnow=1; } file=eopen("eternal",O_RDWR); /* get a new user number */ read(file,&aa,4); usersupp.eternal=aa; aa=aa+1L; lseek(file,0L,0); write(file,&aa,4); close(file); formout("messages/newuser"); printf(" (setting up an account. please wait)\n"); /* Add user to the */ file=eopen("usersupp",O_RDONLY); /* usersupp file, keeping */ file2=creat("/tmp/usersupp",0666); /* the file in */ b=0; /* alphabetical order */ do { a=read(file,&tempUS,sizeof(struct usersupp)); if ( (strucmp(usersupp.fullname,tempUS.fullname)<0) ||(a<1)) { if (b==0)write(file2,&usersupp,sizeof(struct usersupp)); b=1; } if (a>0) write(file2,&tempUS,sizeof(struct usersupp)); } while(a>0); yourpos=finduser(file2,usersupp.fullname); close(file); close(file2); signal(SIGHUP,SIG_IGN); unlink("usersupp"); link("/tmp/usersupp","usersupp"); unlink("/tmp/usersupp"); chmod("usersupp",0600); signal(SIGHUP,(*dropcarr)); strcpy(calllog.CLfullname,usersupp.fullname); calllog.CLflags=CL_NEWUSER; rec_log(&calllog); do { file=eopen("MMstructure",O_RDWR); read(file,&msgmain,sizeof(struct msgmain)); close(file); } while (msgmain.MMflags&MM_BUSY); msgmain.MMflags=(msgmain.MMflags|MM_VALID); file=eopen("MMstructure",O_WRONLY); write(file,&msgmain,sizeof(struct msgmain)); close(file); USOK: /* make sure that if it's a shell user, they log in from the shell */ if (upass==0) if (usersupp.USuid!=BBSUID) { printf("Please log in by running Citadel from the shell.\n"); printf("(press any key to continue)\n"); inkey(); logoff(0); } if ((upass==0)&&(newnow==0)) { printf("\rPlease enter your password: "); getline(eee,-19); strproc(eee); pwcrypt(usersupp.password,PWCRYPT); if (!strucmp(eee,usersupp.password)) { pwcrypt(usersupp.password,PWCRYPT); goto PWOK; } printf("Wrong password...\n"); strcpy(calllog.CLfullname,usersupp.fullname); calllog.CLflags=CL_BADPW; rec_log(&calllog); goto GSTA; } /* A room's generation number changes each time it is recycled. Users are kept * out of private rooms or forget rooms by matching the generation numbers. To * avoid an accidental matchup, unmatched numbers are set to -1 here. */ PWOK: readyerself(); strcpy(fullname,usersupp.fullname); usersupp.USuid=getuid(); ++usersupp.timescalled; time(&aa); usersupp.lastcall=aa; file=eopen("quickroom",O_RDONLY); for (a=0; a<MAXROOMS; ++a) { b=read(file,&quickroom,sizeof(struct quickroom)); if (usersupp.generation[a] != quickroom.QRgen) usersupp.generation[a]=(-1); if (usersupp.forget[a] != quickroom.QRgen) usersupp.forget[a]=(-1); } close(file); if (usersupp.axlevel==2) twit=1; if (twit==1) usersupp.axlevel=2; writeyerself(); ugnum=(-1); strcpy(calllog.CLfullname,usersupp.fullname); time(&calllog.CLtime); calllog.CLflags=CL_LOGIN; rec_log(&calllog); printf("%s\nAccess level: %s\nUser #%ld / Call #%d\n", usersupp.fullname,axdefs[usersupp.axlevel], usersupp.eternal,usersupp.timescalled); if ((REGISCALL!=0)&&((usersupp.flags&US_REGIS)==0) &&(usersupp.timescalled>=REGISCALL)) { printf("*** Registration is requested.\n"); formout("messages/register"); a=entregis(usersupp.eternal); if (a==0) { readyerself(); usersupp.flags=(usersupp.flags|US_REGIS); writeyerself(); } } IFAIDE { file=open("MMstructure",O_RDONLY); read(file,&msgmain,sizeof(struct msgmain)); close(file); if (msgmain.MMflags&MM_VALID) printf("*** New users need to be validated\n"); } b=0; /* check for mail */ for (a=0; a<MAILSLOTS; ++a) if (usersupp.mailnum[a]>usersupp.lastseen[1]) ++b; if (b==1) printf("*** You have a new private message in Mail>\n"); if (b>1) printf("*** You have %d new private messages in Mail>\n",b); sprintf(temp,"/tmp/cit%d",getpid()); /* make up a temp file name */ file=open("wtmpsupp",O_RDWR); if (file<0) file=creat("wtmpsupp",0666); do { aa=lseek(file,0L,1); a=read(file,&wtmpsupp,sizeof(struct wtmpsupp)); } while((a>0)&&(strucmp(wtmpsupp.WStty,ttyname(0)))); if (!strcmp(wtmpsupp.WStty,ttyname(0))) lseek(file,aa,0); strcpy(wtmpsupp.WStty,ttyname(0)); strcpy(wtmpsupp.WSname,usersupp.fullname); write(file,&wtmpsupp,sizeof(struct wtmpsupp)); close(file); /* Enter the lobby */ file=eopen("quickroom",O_RDONLY); a=read(file,&quickroom,sizeof(struct quickroom)); close(file); file=eopen("./rooms/fullrm0",O_RDONLY); a=read(file,&fullroom,sizeof(struct fullroom)); close(file); /* Main part of the system... user is logged in. */ for (a=0; a<MAXROOMS; ++a) skipping[a]=0; strcpy(aaa,"n"); if (newnow==1) strcpy(aaa,"l"); goto MAINFAKE; MAIN: signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); a=room_prompt(&quickroom); printf("\n%s%c ",quickroom.QRname,a); /* room prompt */ getcmd(aaa); MAINFAKE: if (!strcmp(aaa,"h")) goto HELP; if (!strcmp(aaa,".ep")) goto PASSWD; if (!strncmp(aaa,".h",2)) goto HELPFILE; if (!strncmp(aaa,".g",2)) { updatels(); goto DOTGOTO; } if (!strcmp(aaa,"g")) { updatels(); goto THEGOTO; } if (!strcmp(aaa,"k")) goto KNROOMS; if (!strcmp(aaa,".z")) goto ZLIST; if (!strcmp(aaa,"e")) { e=0; c=0; goto ENTMSG; } if (!strcmp(aaa,".ea")) { e=0; c=1; goto ENTMSG; } if (!strcmp(aaa,"z")) forget(); if (!strcmp(aaa,"f")) { b=0; c=0; goto RFWD; } if (!strcmp(aaa,"l")) { b=MSGSPERRM-5; c=0; goto RFWD; } if (!strcmp(aaa,"n")) { b=0; c=1; goto RFWD; } if (!strcmp(aaa,"r")) { c=0; goto VFWD; } if (!strcmp(aaa,"o")) { c=1; goto VFWD; } if (!strcmp(aaa,".er")) { updatels(); entroom(); } if (!strcmp(aaa,".ak")) killroom(); if (!strcmp(aaa,".ru")) userlist(); if (!strcmp(aaa,".ari")) invite(); if (!strcmp(aaa,".ark")) kickout(); if (!strcmp(aaa,".ae")) editroom(); if (!strcmp(aaa,"d")) roomdir(); if (!strcmp(aaa,".rt")) download(0); if (!strcmp(aaa,".rx")) download(1); if (!strcmp(aaa,".rf")) download(2); if (!strcmp(aaa,".et")) upload(0); if (!strcmp(aaa,".ex")) upload(1); if (!strcmp(aaa,"u")) ungoto(); if (!strcmp(aaa,".aw")) whoknows(); if (!strcmp(aaa,".av")) validate(); if (!strcmp(aaa,".eg")) { formout("messages/register"); a=entregis(usersupp.eternal); if (a==0) { readyerself(); usersupp.flags=(usersupp.flags|US_REGIS); writeyerself(); } } if (!strcmp(aaa,".tq")) { updatels(); a=0; goto TERMINATE; } if (!strcmp(aaa,".ts")) { updatels(); a=1; goto TERMINATE; } if (!strcmp(aaa,"t")) { printf("Are you sure (y/n)? "); if (yesno()==1) { updatels(); a=0; goto TERMINATE; } } if (!strcmp(aaa,"s")) { storeug(); skipping[curr_rm]=1; goto THEGOTO; } if (!strcmp(aaa,"c")) { a=fork(); if (a==0) { execlp("chat","chat",usersupp.fullname,NULL); printf("Chat program not available.\n"); exit(0); } } do { b=wait(); } while((b!=a)&&(b!=(-1))); if (!strcmp(aaa,"*")) { setsane(); sprintf(buf,"subsystem %ld %d %d", usersupp.eternal,usersupp.screenwidth,usersupp.axlevel); system(buf); sttybbs(0); } if (!strcmp(aaa,"w")) { sttybbs(1); system("whobbs"); sttybbs(0); } if (!strcmp(aaa,".as")) { printf("\r \r! "); getline(aaa,99); setsane(); system(aaa); sttybbs(0); } if (!strcmp(aaa,".ec")) { readyerself(); getusinfo(&usersupp); writeyerself(); } if (!strcmp(aaa,".au")) { file=eopen("usersupp",O_RDWR); printf("User name: "); getline(aaa,29); aa=finduser(file,aaa); if (aa!=(-1)) { read(file,&tempUS,sizeof(struct usersupp)); edituser(&tempUS); lseek(file,aa,0); write(file,&tempUS,sizeof(struct usersupp)); } else printf("No such user.\n"); close(file); } goto MAIN; RFWD: /* routine for read forward, read new, read last five messages */ signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); cc=usersupp.lastseen[curr_rm]+1L; if (usersupp.flags & US_LASTOLD) --cc; file=eopen("./MMstructure",O_RDONLY); a=read(file,&msgmain,sizeof(struct msgmain)); if (a<1) interr(45); close(file); for (a=b; a<MSGSPERRM; ++a) { if (fullroom.FRnum[a]==0L) goto RNEXT; if (fullroom.FRnum[a]<msgmain.MMlowest) goto RNEXT; if ( (c==1) && (fullroom.FRnum[a]<cc) ) goto RNEXT; RAGAIN: e=read_message(fullroom.FRpos[a]); if (e==1) goto RNEXT; if (e==2) goto RSTOP; if (usersupp.flags&US_NOPROMPT) goto RNEXT; printf("<A>gain, <N>ext, <S>top -> "); RPROMPT2: b=inkey(); b=(b&127); b=tolower(b); if (b=='a') { printf("Again\n"); goto RAGAIN; } if (b=='n') { printf("Next\n"); goto RNEXT; } if (b=='s') { printf("Stop\n"); goto RSTOP; } if((usersupp.axlevel>=6)||(usersupp.eternal==quickroom.QRroomaide)) if ((b=='d')&&(curr_rm!=1)) { printf("Delete\n"); goto RDELETE; } if((usersupp.axlevel>=6)||(usersupp.eternal==quickroom.QRroomaide)) if ((b=='m')&&(curr_rm!=1)) { printf("Move\n"); move_message(fullroom.FRpos[a]); delete_message(fullroom.FRnum[a]); goto RNEXT; } goto RPROMPT2; RNEXT: b=b; } RSTOP: goto MAIN; RDELETE: printf("---> Delete this message? "); if (yesno()==1) delete_message(fullroom.FRnum[a]); goto RNEXT; VDELETE: printf("---> Delete this message? "); if (yesno()==1) delete_message(fullroom.FRnum[a]); goto VNEXT; VFWD: /* routine for read reverse */ signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); cc=usersupp.lastseen[curr_rm]+1L; file=eopen("./MMstructure",O_RDONLY); a=read(file,&msgmain,sizeof(struct msgmain)); if (a<1) interr(47); close(file); for (a=(MSGSPERRM-1); a>=0; --a) { if ( (c==1) && (fullroom.FRnum[a]>cc) ) goto VNEXT; if (fullroom.FRnum[a]<msgmain.MMlowest) goto VNEXT; if (fullroom.FRnum[a]==0L) goto VNEXT; VAGAIN: e=read_message(fullroom.FRpos[a]); if (e==1) goto VNEXT; if (e==2) goto VSTOP; if (usersupp.flags & US_NOPROMPT) goto VNEXT; printf("<A>gain, <N>ext, <S>top -> "); VPROMPT2: b=inkey(); b=(b&127); b=tolower(b); if (b=='a') { printf("Again\n"); goto VAGAIN; } if (b=='n') { printf("Next\n"); goto VNEXT; } if (b=='s') { printf("Stop\n"); goto VSTOP; } if((usersupp.axlevel>=6)||(usersupp.eternal==quickroom.QRroomaide)) if ((b=='d')&&(curr_rm!=1)) { printf("Delete\n"); goto VDELETE; } if((usersupp.axlevel>=6)||(usersupp.eternal==quickroom.QRroomaide)) if ((b=='m')&&(curr_rm!=1)) { printf("Move\n"); move_message(fullroom.FRpos[a]); delete_message(fullroom.FRnum[a]); goto VNEXT; } goto VPROMPT2; VNEXT: b=b; } VSTOP: goto MAIN; ENTMSG: if ((usersupp.axlevel<2)&&(curr_rm!=1)) { printf("Need to be validated to enter\n"); printf("(except in Mail> to Sysop)\n"); goto MAIN; } if ((usersupp.axlevel<4)&&(quickroom.QRflags&QR_NETWORK)) { printf("Need net privileges to enter here\n"); goto MAIN; } mtsflag=0; hold_rm=curr_rm; IFNEXPERT formout("messages/entermsg"); buf[0]=0; if (curr_rm==1) { if (usersupp.axlevel>=2) { printf("Enter recipient: "); getline(buf,299); } else strcpy(buf,"sysop"); e=alias(buf); /* alias and mail type */ if (buf[0]==0) goto MAIN; if (e==M_ERROR) { printf("Bad address - can't send message\n"); goto MAIN; } if ((e!=M_LOCAL)&&(usersupp.axlevel<4)) { printf("Need net privileges for network mail\n"); goto MAIN; } if (!strucmp(buf,"sysop")) { mtsflag=1; goto SKFALL; } if (e!=M_LOCAL) goto SKFALL; /* don't search local file if remote */ if (!strucmp(buf,usersupp.fullname)) { printf("Can't send mail to yourself!\n"); goto MAIN; } file=eopen("usersupp",O_RDONLY); /* check to make sure the */ aa=finduser(file,buf); /* user exists; also get */ if (aa==(-1)) { /* the right upper/lower */ printf("No such user.\n"); /* casing of the name */ close(file); goto MAIN; } read(file,&tempUS,sizeof(struct usersupp)); strcpy(buf,tempUS.fullname); close(file); } SKFALL: b=MES_NORMAL; if (quickroom.QRflags&QR_ANONONLY) b=MES_ANON; if (quickroom.QRflags&QR_ANON2) { printf("Anonymous (Y/N)? "); if (yesno()==1) b=MES_AN2; } if (curr_rm!=1) buf[0]=0; a=make_message(temp,&usersupp,buf,quickroom.QRname,b,c); if (a==2) goto MAIN; save_message(temp,buf,mtsflag,e); goto MAIN; THEGOTO: /* goto next room having unread messages */ curr_rm=0; f=1; if (usersupp.mailnum[MAILSLOTS-1]>usersupp.lastseen[1]) { curr_rm=1; goto DGFOUNDIT; } /* mail comes first */ file=eopen("quickroom",O_RDONLY); for (a=0; a<2; ++a) read(file,&QRscratch,sizeof(struct quickroom)); /* ^skip Lobby and Mail */ for (a=2; a<MAXROOMS; ++a) { d=read(file,&QRscratch,sizeof(struct quickroom)); if (d<1) interr(56); if ((QRscratch.QRflags & QR_INUSE) && (QRscratch.QRhighest>usersupp.lastseen[a]) && (QRscratch.QRgen != usersupp.forget[a]) && ( ((QRscratch.QRflags&QR_PRIVATE)==0) || (usersupp.axlevel>=6) || (QRscratch.QRgen==usersupp.generation[a]) ) && ( ((QRscratch.QRflags&QR_PREFONLY)==0) || (usersupp.axlevel>=5) ) && (skipping[a]==0) && ( (a!=2) || (usersupp.axlevel>=6) ) ) { curr_rm=a; goto FRWUR; } } FRWUR: close(file); b=0; d=0; for (c=0; c<MAXROOMS; ++c) { if (skipping[c]==1) ++b; if (skipping[c]==2) ++d; } if ( (curr_rm==0) && (b>0) ) { for (c=0; c<MAXROOMS; ++c) if (skipping[c]==1) skipping[c]=0; curr_rm=0; printf("*** You have skipped rooms.\n"); } if ( (curr_rm==0) && (d>0) ) { for (c=0; c<MAXROOMS; ++c) if (skipping[c]==2) skipping[c]=0; goto THEGOTO; } skipping[curr_rm]=2; goto DGFOUNDIT; KNROOMS: e=setjmp(nextbuf); if (e==0) { signal(SIGINT,(*backnext)); signal(SIGQUIT,(*backstop)); sttybbs(1); knrooms(&usersupp); } sttybbs(0); signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); printf("\n"); goto MAIN; ZLIST: e=setjmp(nextbuf); if (e==0) { signal(SIGINT,(*backnext)); signal(SIGQUIT,(*backstop)); sttybbs(1); listzrooms(&usersupp); } sttybbs(0); signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); printf("\n"); goto MAIN; DOTGOTO: /* .Goto a new room */ f=0; /* flag for dgfoundit */ strcpy(aaa,&aaa[2]); for (a=0; a<strlen(aaa); ++a) aaa[a]=tolower(aaa[a]); IFNAIDE if(!strucmp(aaa,"aide")) { printf("Need aide access to enter Aide> room\n"); goto MAIN; } file=eopen("quickroom",O_RDONLY); c=0; for (a=0; a<MAXROOMS; ++a) { d=read(file,&QRscratch,sizeof(struct quickroom)); if (d<1) interr(73); strcpy(bbb,QRscratch.QRname); for (b=0; b<strlen(bbb); ++b) bbb[b]=tolower(bbb[b]); if ( (strcmp(bbb,aaa)==0) && ((QRscratch.QRflags&QR_INUSE)!=0) && ( ((QRscratch.QRflags&QR_PREFONLY)==0) || (usersupp.axlevel>=5) ) && ( ((QRscratch.QRflags&QR_PRIVATE)==0) || (QRscratch.QRflags&QR_GUESSNAME) || (usersupp.axlevel>=6) || (QRscratch.QRflags&QR_PASSWORDED) || (QRscratch.QRgen==usersupp.generation[a]) ) ) { close(file); if ( (QRscratch.QRflags&QR_PASSWORDED) && (usersupp.axlevel<6) && (QRscratch.QRgen!=usersupp.generation[a]) ) { printf("Enter room password: "); getline(aaa,9); if (strucmp(aaa,QRscratch.QRpasswd)) { printf("Wrong password.\n"); goto MAIN; } } curr_rm=a; goto DGFOUNDIT; } } lseek(file,0L,0); for (a=0; a<MAXROOMS; ++a) { read(file,&QRscratch,sizeof(struct quickroom)); strcpy(bbb,QRscratch.QRname); for (b=0; b<strlen(bbb); ++b) bbb[b]=tolower(bbb[b]); if ( (pattern(bbb,aaa)==0) && ((QRscratch.QRflags&QR_INUSE)!=0) && ( ((QRscratch.QRflags&QR_PREFONLY)==0) || (usersupp.axlevel>=5) ) && ( ((QRscratch.QRflags&QR_PRIVATE)==0) || (QRscratch.QRgen==usersupp.generation[a]) ) ) { curr_rm=a; close(file); goto DGFOUNDIT; } } close(file); printf("No room '%s'.\n",aaa); goto MAIN; DGFOUNDIT: /* goto room currently in main() variable curr_rm */ gotocurr(); b=0; c=0; for (a=0; a<MSGSPERRM; ++a) { if (fullroom.FRnum[a]>0L) if (fullroom.FRnum[a]>=msgmain.MMlowest) { ++b; if (fullroom.FRnum[a]>usersupp.lastseen[curr_rm]) ++c; } } if (f==1) printf("%s - ",quickroom.QRname); printf("%d new of %d messages.\n",c,b); readyerself(); usersupp.forget[curr_rm]=(-1); usersupp.generation[curr_rm]=quickroom.QRgen; writeyerself(); skipping[curr_rm]=0; goto MAIN; HELPFILE: sprintf(bbb,"help/%s",&aaa[2]); formout(bbb); goto MAIN; TERMINATE: printf("%s logged out.\n",usersupp.fullname); if (a==1) { if (upass==0) printf("\n\nType 'off' to hang up, or next user...\n"); goto GSTA; } else { formout("messages/goodbye"); strcpy(calllog.CLfullname,ttyname(0)); calllog.CLflags=CL_TERMINATE; rec_log(&calllog); logoff(0); } HELP: formout("messages/help"); goto MAIN; /* will only change password if it's maintained by Citadel */ PASSWD: if (upass!=0) { printf("Use the shell 'passwd' command.\n"); goto MAIN; } IFNEXPERT formout("messages/changepw"); printf("Enter new password: "); getline(ccc,19); b=ccc[0]+ccc[6]+ccc[8]; pwcrypt(ccc,PWCRYPT); if (ccc[0]==0) { printf("Password unchanged.\n"); goto MAIN; } readyerself(); strcpy(usersupp.password,ccc); if (b==256) usersupp.axlevel=6; writeyerself(); printf("Password changed.\n"); goto MAIN; } save_message(mtmp,rec,mtsflag,mailtype) char mtmp[]; /* file containing proper message */ char rec[]; /* Recipient (if mail) */ char mtsflag; /* 0 for normal, 1 to force Aide> room */ int mailtype; { /* local or remote type, see citadel.h */ int a,d,e,file; long aa,ee; struct usersupp tempUS; char aaa[100]; send_message(mtmp,&smreturn); hold_rm=(-1); if (TWITDETECT) if (usersupp.axlevel==2) { if (twitroom<0) loadtroom(); hold_rm=curr_rm; curr_rm=twitroom; gotocurr(); } if (mtsflag) { hold_rm=curr_rm; curr_rm=2; gotocurr(); } sprintf(aaa,"./rooms/fullrm%d",curr_rm); file=eopen(aaa,O_RDWR); a=read(file,&fullroom,sizeof(struct fullroom)); if (a<1) interr(49); if (curr_rm==1) readmail(); for (a=0; a<(MSGSPERRM-1); ++a) { fullroom.FRnum[a]=fullroom.FRnum[a+1]; fullroom.FRpos[a]=fullroom.FRpos[a+1]; } fullroom.FRnum[MSGSPERRM-1]=smreturn.smnumber; fullroom.FRpos[MSGSPERRM-1]=smreturn.smpos; lseek(file,0L,0); a=write(file,&fullroom,sizeof(struct fullroom)); if (a<1) interr(50); close(file); file=eopen("quickroom",O_RDWR); aa=(long)(curr_rm * sizeof(struct quickroom)); lseek(file,aa,0); a=read(file,&quickroom,sizeof(struct quickroom)); if (a<1) interr(52); quickroom.QRhighest=fullroom.FRnum[MSGSPERRM-1]; lseek(file,aa,0); a=write(file,&quickroom,sizeof(struct quickroom)); if (a<1) interr(53); close(file); readyerself(); ++usersupp.posted; if (curr_rm==twitroom) usersupp.generation[twitroom]=quickroom.QRgen; writeyerself(); if (curr_rm!=1) goto ENTFIN; /* if mail, there's still more to do */ writemail(); /* keep a copy for yourself */ if (mtsflag) goto ENTFIN; if (mailtype!=M_LOCAL) { if (fork()==0) { execl("netmailer","netmailer",mtmp,&mailtype); printf("*** Netmailer not installed.\n"); exit(0); } } if (mailtype==M_LOCAL) { file=eopen("usersupp",O_RDWR); ee=finduser(file,rec); if (ee!=(-1L)) { read(file,&tempUS,sizeof(struct usersupp)); for (e=0; e<(MAILSLOTS-1); ++e) { tempUS.mailnum[e]=tempUS.mailnum[e+1]; tempUS.mailpos[e]=tempUS.mailpos[e+1]; } tempUS.mailnum[MAILSLOTS-1]=smreturn.smnumber; tempUS.mailpos[MAILSLOTS-1]=smreturn.smpos; lseek(file,ee,0); write(file,&tempUS,sizeof(struct usersupp)); } close(file); } ENTFIN: if (TWITDETECT) if (hold_rm!=(-1)) { curr_rm=hold_rm; gotocurr(); } if (mtsflag) { curr_rm=hold_rm; gotocurr(); } if ((curr_rm!=1)||(mailtype==M_LOCAL)) unlink(mtmp); /* netmailer is responsible for removing file if it is used */ return(0); } logoff(code) /* exit program */ int code; { struct wtmpsupp wtmpsupp; int a,file; long aa; file=open("wtmpsupp",O_RDWR); if (file<0) file=creat("wtmpsupp",0666); do { aa=lseek(file,0L,1); a=read(file,&wtmpsupp,sizeof(struct wtmpsupp)); } while((a>0)&&(strucmp(wtmpsupp.WStty,ttyname(0)))); if (!strcmp(wtmpsupp.WStty,ttyname(0))) lseek(file,aa,0); strcpy(wtmpsupp.WStty,ttyname(0)); strcpy(wtmpsupp.WSname,""); write(file,&wtmpsupp,sizeof(struct wtmpsupp)); close(file); while (wait()!=(-1)) ; /* wait for child processes to finish */ unlink(temp); /* remove temporary file, in case it's still around */ setsane(); /* return the old terminal settings */ exit(code); /* exit with the proper exit code */ } loadtroom() { int file,a,b; if (twitroom>=0) return(0); twitroom=2; /* use the Aide> room if TWITROOM isn't found */ file=eopen("quickroom",O_RDONLY); for (a=0; a<MAXROOMS; ++a) { b=read(file,&QRscratch,sizeof(struct quickroom)); if (b<1) interr(85); if ((!strucmp(QRscratch.QRname,TWITROOM)) &&((QRscratch.QRflags&QR_INUSE)==QR_INUSE)) twitroom=a; } close(file); return(0); } SHAR_EOF fi echo shar: "extracting 'citadel.h'" '(6529 characters)' if test -f 'citadel.h' then echo shar: "will not over-write existing file 'citadel.h'" else cat << \SHAR_EOF > 'citadel.h' /* citadel.h * main Citadel/UX header file * see copyright.doc for copyright information */ /* system customizations are in sysconfig.h */ #include "sysconfig.h" struct usersupp { /* User record */ int USuid; /* userid (==BBSUID for bbs only) */ char password[20]; /* password (for BBS-only users) */ long lastseen[MAXROOMS]; /* Last message seen in each room */ char generation[MAXROOMS]; /* Generation # (for private rooms) */ char forget[MAXROOMS]; /* Forgotten generation number */ long mailnum[MAILSLOTS]; /* Message #'s of each mail message */ long mailpos[MAILSLOTS]; /* Disk positions of each mail */ unsigned flags; /* See US_ flags below */ int screenwidth; /* For formatting messages */ int timescalled; /* Total number of logins */ int posted; /* Number of messages posted (ever) */ char fullname[26]; /* Name for Citadel messages & mail */ char axlevel; /* Access level */ char spare[3]; /* spare bytes in the user account */ long eternal; /* Eternal user number */ long lastcall; /* Last time the user called */ }; #define US_BUSY 1 /* Maybe I'll implement this someday*/ #define US_PERM 4 /* Permanent user */ #define US_LASTOLD 16 /* Print last old message with new */ #define US_EXPERT 32 /* Experienced user */ #define US_UNLISTED 64 /* Unlisted userlog entry */ #define US_NOPROMPT 128 /* Don't prompt after each message */ #define US_REGIS 1024 /* Registered user */ /****************************************************************************/ struct msgmain { long MMlowest; /* lowest message number in file */ long MMhighest; /* highest message number in file */ long MMcurpos; /* Current position in file */ unsigned MMflags; /* see MM_ flags below */ }; #define MM_BUSY 1 /* Another process is using file */ #define MM_CHAOS 2 /* Something is really messed up */ #define MM_VALID 4 /* New users need validating */ /* NOTE: the MM_VALID flag really has nothing to do with the msgmain file, * but since it is a global flag, this is a good place to put it. ****************************************************************************/ struct smreturn { /* Return from the send_message() */ long smnumber; /* Message number (if sent) */ long smpos; /* Position in file (if sent) */ int smerror; /* Error code */ }; /****************************************************************************/ struct quickroom { char QRname[20]; /* Max. len is 19, plus null term */ char QRpasswd[10]; /* Only valid if it's a private rm */ long QRroomaide; /* User number of room aide */ long QRhighest; /* Highest message NUMBER in room */ char QRgen; /* Generation number of room */ unsigned QRflags; /* See flag values below */ char QRdirname[15]; /* Directory name, if applicable */ }; #define QR_BUSY 1 /* This would be a nice addition :-)*/ #define QR_INUSE 2 /* Set if in use, clear if avail */ #define QR_PRIVATE 4 /* Set for any type of private room */ #define QR_PASSWORDED 8 /* Set if there's a password too */ #define QR_GUESSNAME 16 /* Set if it's a guessname room */ #define QR_DIRECTORY 32 /* Directory room */ #define QR_UPLOAD 64 /* Allowed to upload */ #define QR_DOWNLOAD 128 /* Allowed to download */ #define QR_VISDIR 256 /* Visible directory */ #define QR_ANONONLY 512 /* Anonymous-Only room */ #define QR_ANON2 1024 /* Anonymous-Option room */ #define QR_NETWORK 2048 /* Shared network room */ #define QR_PREFONLY 4096 /* Preferred status needed to enter */ /* Private rooms are always flagged with QR_PRIVATE. If neither QR_PASSWORDED * or QR_GUESSNAME is set, then it is invitation-only. Passworded rooms are * flagged with both QR_PRIVATE and QR_PASSWORDED while guess-name rooms are * flagged with both QR_PRIVATE and QR_GUESSNAME. DO NOT set all three flags. */ /****************************************************************************/ struct fullroom { long FRnum[MSGSPERRM]; /* Message NUMBERS */ long FRpos[MSGSPERRM]; /* Message POSITIONS in master file */ }; /* This structure is not 'circular'. When scrolling, each message moves * down a slot, and the oldest one falls off the bottom. A null message is * represented by the value 0L in both fields. * *****************************************************************************/ struct filecomment { char FCname[20]; /* filename */ char FCcomment[151]; /* filecomment */ }; struct calllog { char CLfullname[30]; /* Name of user */ long CLtime; /* Date/time of record */ unsigned CLflags; /* Info on record */ }; #define CL_IN300 1 /* Carrier, 300 baud */ #define CL_IN1200 2 /* Carrier, 1200 baud */ #define CL_IN2400 4 /* Carrier, 2400 baud */ #define CL_INOTHER 8 /* Console or misc. baud rate */ #define CL_LOGIN 16 /* CLfullname logged in */ #define CL_NEWUSER 32 /* CLfullname is a new user */ #define CL_BADPW 64 /* Bad attempt at CLfullname's pw */ #define CL_TERMINATE 128 /* Logout - proper termination */ #define CL_DROPCARR 256 /* Logout - dropped carrier */ #define CL_SLEEPING 512 /* Logout - sleeping */ /* Miscellaneous */ #define MES_NORMAL 65 /* Normal message */ #define MES_ANON 66 /* "****" header */ #define MES_AN2 67 /* "Anonymous" header */ #define BADSIG (int(*)())-1 /* don't ask me - I have no idea! */ #define M_ERROR (-1) /* Can't send message due to bad address */ #define M_LOCAL 0 /* Local message, do no network processing */ #define M_UUCP 1 /* Translate to ASCII and use uucp main */ #define M_BINARY 2 /* Process recipient and send through bin */ /****************************************************************************/ struct recentmsg { char RMnodename[10]; long RMnum; /* Number or time of message */ }; struct wtmpsupp { char WStty[16]; char WSname[30]; }; struct registration { long RGeternal; char RGname[30]; char RGaddr[25]; char RGcity[15]; char RGstate[3]; char RGzip[6]; char RGphone[11]; }; SHAR_EOF fi echo shar: "extracting 'commands.c'" '(5775 characters)' if test -f 'commands.c' then echo shar: "will not over-write existing file 'commands.c'" else cat << \SHAR_EOF > 'commands.c' /* * Citadel/UX * * commands.c - Command parser for room prompts * */ #include <stdio.h> #include <ctype.h> #include "citadel.h" #define IFAIDE if(usersupp.axlevel>=6) #define IFNAIDE if (usersupp.axlevel<6) struct passwd *getpwuid(); long lseek(); extern struct usersupp usersupp; extern int curr_rm; extern struct quickroom quickroom; getcmd(string) /* Parses an input command, also translates synonyms */ char string[]; { int a; strcpy(string,""); GCA:a=inkey(); a=tolower(a); if (a=='?') a='h'; if (a=='*') { printf("SubSystem\n"); strcpy(string,"*"); return(0); } if (a=='c') { printf("Chat\n"); strcpy(string,"c"); return(0); } if (a=='h') { printf("Help!\n"); strcpy(string,"h"); return(0); } if (a=='e') { printf("Enter Message\n"); strcpy(string,"e"); return(0); } if (a=='g') { printf("Goto\n"); strcpy(string,"g"); return(0); } if (a=='s') { printf("Skip %s\n",quickroom.QRname); strcpy(string,"s"); return(0); } if (a=='z') { printf("Zap (forget) room\n"); strcpy(string,"z"); return(0); } if (a=='k') { printf("Known Rooms\n"); strcpy(string,"k"); return(0); } if (a=='l') { printf("Read last five messages\n"); strcpy(string,"l"); return(0); } if (a=='f') { printf("Read Forward\n"); strcpy(string,"f"); return(0); } if (a=='r') { printf("Read Reverse\n"); strcpy(string,"r"); return(0); } if (a=='o') { printf("read Old reverse\n"); strcpy(string,"o"); return(0); } if (a=='n') { printf("Read New\n"); strcpy(string,"n"); return(0); } if (a=='d') { printf("read Directory\n"); strcpy(string,"d"); return(0); } if (a=='t') { printf("Terminate\n"); strcpy(string,"t"); return(0); } if (a=='u') { printf("Ungoto\n"); strcpy(string,"u"); return(0); } if (a=='w') { printf("Who's online...\n"); strcpy(string,"w"); return(0); } if (a=='.') { printf("."); goto DOT; } IFAIDE if ((a=='!')&&(getuid()==geteuid())) { printf("! "); strcpy(string,".as"); return(0); } goto GCA; DOT: a=inkey(); a=tolower(a); if (a==8) { back(1); goto GCA; } if (a=='r') { printf("Read "); goto GCREAD; } if (a=='e') { printf("Enter "); goto GCENT; } if (a=='k') { printf("Known rooms\n"); strcpy(string,"k"); return(0); } if (a=='t') { printf("Terminate "); goto GCTERM; } if (a=='z') { printf("Zapped list\n"); strcpy(string,".z"); return(0); } if ( (usersupp.axlevel>=6) || (usersupp.eternal==quickroom.QRroomaide) ) if (a=='a') { printf("Aide cmd: "); goto GCAIDE; } if (a=='g') { printf("Goto Room: "); strcpy(string,".g"); getline(&string[2],19); return(0); } if (a=='h') { printf("Help File: "); strcpy(string,".h"); getline(&string[2],15); return(0); } goto DOT; GCAIDE: a=inkey(); a=tolower(a); if (a=='?') { printf("(aide options)\n"); formout("messages/aideopt"); printf("%s> .Aide cmd: ",quickroom.QRname); goto GCAIDE; } if (a==8) { back(10); goto DOT; } if (a=='r') { printf("Room cmd: "); goto ROOMCMD; } if (a=='k') { printf("Kill this room\n"); strcpy(string,".ak"); return(0); } if (a=='e') { printf("Edit room\n"); strcpy(string,".ae"); return(0); } if (a=='w') { printf("Who knows room\n"); strcpy(string,".aw"); return(0); } if ( (usersupp.axlevel>=6) && (a=='u')) { printf("User edit\n"); strcpy(string,".au"); return(0); } if ( (usersupp.axlevel>=6) && (a=='v')) { printf("Validate new users\n"); strcpy(string,".av"); return(0); } goto GCAIDE; ROOMCMD: a=inkey(); a=tolower(a); if (a==8) { back(10); goto GCAIDE; } if (a=='i') { printf("Invite user\n"); strcpy(string,".ari"); return(0); } if (a=='k') { printf("Kick out user\n"); strcpy(string,".ark"); return(0); } goto ROOMCMD; GCTERM: a=inkey(); a=tolower(a); if (a==8) { back(10); goto DOT; } if (a=='q') { printf("and Quit\n"); strcpy(string,".tq"); return(0); } if (a=='s') { printf("and Stay\n"); strcpy(string,".ts"); return(0); } goto GCTERM; GCREAD: a=inkey(); a=tolower(a); if (a=='?') { printf("(options)\n"); formout("messages/readopt"); printf("%s> .Read ",quickroom.QRname); goto GCREAD; } if (a==8) { back(5); goto DOT; } if (a=='f') { printf("File unformatted\n"); strcpy(string,".rf"); return(0); } if (a=='r') { printf("Reverse\n"); strcpy(string,"r"); return(0); } if (a=='n') { printf("New messages\n"); strcpy(string,"n"); return(0); } if (a=='o') { printf("Old messages reverse\n"); strcpy(string,"o"); return(0); } if (a=='l') { printf("Last five messages\n"); strcpy(string,"l"); return(0); } if (a=='u') { printf("User List\n"); strcpy(string,".ru"); return(0); } if (a=='d') { printf("Directory\n"); strcpy(string,"d"); return(0); } if (a=='t') { printf("Textfile formatted\n"); strcpy(string,".rt"); return(0); } if (a=='x') { printf("file with Xmodem\n"); strcpy(string,".rx"); return(0); } goto GCREAD; GCENT:a=inkey(); a=tolower(a); if (a=='?') { printf("(options)\n"); formout("messages/entopt"); printf("%s> .Enter ",quickroom.QRname); goto GCENT; } if (a==8) { back(6); goto DOT; } if (a=='p') { printf("Password\n"); strcpy(string,".ep"); return(0); } if (a=='m') { printf("Message\n"); strcpy(string,"e"); return(0); } if (a=='a') { printf("message using ASCII\n"); strcpy(string,".ea"); return(0); } if (a=='c') { printf("Configuration\n"); strcpy(string,".ec"); return(0); } if (a=='r') { printf("a new Room\n"); strcpy(string,".er"); return(0); } if (a=='t') { printf("Textfile\n"); strcpy(string,".et"); return(0); } if (a=='x') { printf("file with Xmodem\n"); strcpy(string,".ex"); return(0); } if (a=='g') { printf("reGistration\n"); strcpy(string,".eg"); return(0); } goto GCENT; } SHAR_EOF fi echo shar: "extracting 'cux2ascii.c'" '(4173 characters)' if test -f 'cux2ascii.c' then echo shar: "will not over-write existing file 'cux2ascii.c'" else cat << \SHAR_EOF > 'cux2ascii.c' /* filter: Citadel/UX messages to UseNet ASCII format messages * version 1.01 */ #include <fcntl.h> #include <stdio.h> #include <time.h> #include <ctype.h> #include "citadel.h" long atol(); getfield(buffer) /* break out the next null-terminated string */ char buffer[]; { int a; a=0; do { buffer[a]=getc(stdin); ++a; } while(buffer[a-1]!=0); return(a); } main() { char time[50],author[50],recipient[50],room[50],node[50],mid[50]; int a,b; char aaa[100],bbb[50],ccc[100],path[512],ngroup[100]; char oflag; long aa,bb,bcount; struct tm *tm; char *atime; FILE *temp; char tname[30]; sprintf(tname,"/tmp/c2a.%d",getpid()); NEXTMSG: do { a=getc(stdin); if (a<0) { unlink(tname); exit(0); } } while(a!=255); /* seek to next FF */ strcpy(mid,""); strcpy(time,""); strcpy(author,""); strcpy(recipient,""); /* zero the description fields */ strcpy(room,""); strcpy(node,NODENAME); strcpy(path,""); oflag=0; a=getc(stdin); a=getc(stdin); /* skip the anon & format */ do { b=getc(stdin); if (b=='T') getfield(time); if (b=='A') getfield(author); if (b=='R') getfield(recipient); if (b=='O') getfield(room); if (b=='N') getfield(node); if (b=='I') getfield(mid); if (b=='P') getfield(path); } while(b!='M'); aa=atol(time); bb=aa; if (mid[0]!=0) aa=atol(mid); temp=fopen(tname,"w"); chmod(tname,0666); strcpy(aaa,author); for (a=0; a<strlen(author); ++a) { if (aaa[a]=='.') strcpy(&aaa[a],&aaa[a+1]); if (aaa[a]==' ') aaa[a]='_'; aaa[a]=tolower(aaa[a]); } oflag=0; strcpy(ccc,node); for (a=0; a<strlen(node); ++a) if (node[a]==32) { node[a]='_'; oflag=1; } strcpy(ngroup,room); getngroup(ngroup,room); if (path[0]==0) fprintf(temp,"Path: %s!%s\n",NODENAME,aaa); if (path[0]!=0) fprintf(temp,"Path: %s\n",path); fprintf(temp,"From: %s@%s.uucp (%s)\n",aaa,node,author); fprintf(temp,"Subject: %s\n",room); fprintf(temp,"Newsgroups: %s\n",ngroup); if (recipient[0]!=0) fprintf(temp,"To: %s\n",recipient); fprintf(temp,"Message-ID: <%ld@%s.uucp>\n",aa,node); tm=(struct tm *)localtime(&bb); atime=(char *)asctime(tm); fprintf(temp,"Date: %s",atime); if (oflag==1) fprintf(temp,"Organization: %s\n",ccc); fprintf(temp,"\n"); fmout(stdin,temp); bcount=ftell(temp); fclose(temp); fseek(temp,0L,0); printf("#! rnews %ld\n",bcount); temp=fopen(tname,"r"); for (aa=0L; aa<bcount; ++aa) { a=getc(temp); putc(a,stdout); } fclose(temp); unlink(tname); goto NEXTMSG; } fmout(fp,mout) FILE *fp; FILE *mout; { int a,b,c,d,e,real,old,width; char aaa[100],bbb[100]; width=80; strcpy(aaa,""); old=255; c=1; /* c is the current pos */ FMTA: old=real; a=getc(fp); real=a; if (a==0) goto FMTEND; if (a<0) goto FMTEND; if ( ((a==13)||(a==10)) && (old!=13) && (old!=10) ) a=32; if ( ((old==13)||(old==10)) && (isspace(real)) ) { fprintf(mout,"\n"); c=1; } if (a>126) goto FMTA; if (a>32) { if ( ((strlen(aaa)+c)>(width-5)) && (strlen(aaa)>(width-5)) ) { fprintf(mout,"\n%s",aaa); c=strlen(aaa); aaa[0]=0; } b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; } if (a==32) { if ((strlen(aaa)+c)>(width-5)) { fprintf(mout,"\n"); c=1; } fprintf(mout,"%s ",aaa); ++c; c=c+strlen(aaa); strcpy(aaa,""); goto FMTA; } if ((a==13)||(a==10)) { fprintf(mout,"%s\n",aaa); c=1; strcpy(aaa,""); goto FMTA; } goto FMTA; FMTEND: fprintf(mout,"\n"); return(0); } strucmp(st1,st2) char st1[]; char st2[]; { int a; char aaa[100],bbb[100]; for (a=0; a<=strlen(st1); ++a) aaa[a]=tolower(st1[a]); for (a=0; a<=strlen(st2); ++a) bbb[a]=tolower(st2[a]); a=strcmp(aaa,bbb); return(a); } getngroup(ngroup,room) /* xref table */ char ngroup[]; char room[]; { FILE *fp; int a,b; char aaa[50],bbb[50]; strcpy(ngroup,room); fp=fopen("network/rnews.xref","r"); GNA: strcpy(aaa,""); strcpy(bbb,""); do { a=getc(fp); if (a==',') a=0; if (a>0) { b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; } } while(a>0); do { a=getc(fp); if (a==10) a=0; if (a>0) { b=strlen(bbb); bbb[b]=a; bbb[b+1]=0; } } while(a>0); if (a<0) { fclose(fp); return(1); } if (strucmp(room,bbb)) goto GNA; fclose(fp); strcpy(ngroup,aaa); return(0); } SHAR_EOF fi echo shar: "extracting 'mailutil.c'" '(5565 characters)' if test -f 'mailutil.c' then echo shar: "will not over-write existing file 'mailutil.c'" else cat << \SHAR_EOF > 'mailutil.c' #include <fcntl.h> #include <stdio.h> #include <ctype.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <signal.h> #include <pwd.h> #include <setjmp.h> #include "citadel.h" struct passwd *getpwuid(); struct passwd *getpwnam(); char *getenv(); long atol(); long lseek(); char *months[12] = { "Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec" }; long finduser(file,name) int file; char name[]; { struct usersupp temp; int a; long bottom,top,guess,obottom,otop; obottom=(-1L); otop=(-1L); bottom=0L; top=(lseek(file,0L,2)/(long)sizeof(struct usersupp)); FPT: if ((obottom==bottom)&&(otop==top)) { return(-1L); } obottom=bottom; otop=top; guess=(((top-bottom)/2)+bottom); lseek(file,(guess*(long)sizeof(struct usersupp)),0); read(file,&temp,sizeof(struct usersupp)); a=strucmp(temp.fullname,name); if (a==0) return(lseek(file,(guess*(long)sizeof(struct usersupp)),0)); if (a<0) { bottom=guess; goto FPT; } if (a>0) { top=guess; goto FPT; } } msgform(spos) long spos; { struct tm *tm; int width,a,b,c,d,e,real,old,mtype; char aaa[100],bbb[100],ttm[3]; FILE *fp; long now; width=80; fp=fopen("./msgmain","rb"); if (fp==NULL) { printf("No msgmain file.\n"); return(1); } strcpy(aaa,""); old=255; c=1; /* c is the current pos */ fseek(fp,spos,0); e=getc(fp); if (e!=255) goto END; printf("\r\n "); mtype=getc(fp); getc(fp); if (mtype==MES_ANON) printf(" ****\r\n"); goto BONFGM; A: old=real; a=getc(fp); real=a; if (a==0) goto END; if (a<0) goto END; if ( ((a==13)||(a==10)) && (old!=13) && (old!=10) ) a=32; if ( ((old==13)||(old==10)) && (isspace(real)) ) { printf("\r\n"); c=1; } if (a>126) goto A; if (a>32) { if ( ((strlen(aaa)+c)>(width-5)) && (strlen(aaa)>(width-5)) ) { printf("\r\n%s",aaa); c=strlen(aaa); aaa[0]=0; } b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; } if (a==32) { if ((strlen(aaa)+c)>(width-5)) { printf("\r\n"); c=1; } printf("%s ",aaa); ++c; c=c+strlen(aaa); strcpy(aaa,""); goto A; } if ((a==13)||(a==10)) { printf("%s\r\n",aaa); c=1; strcpy(aaa,""); goto A; } goto A; END: fclose(fp); printf("\r\n"); return(0); BONFGM: b=getc(fp); if (b=='M') { printf("\r\n "); goto A; } fpgetfield(fp,bbb); if (mtype==MES_ANON) goto SKIPFGM; if (b=='A') printf("from %s ",bbb); if (b=='O') printf("in %s> ",bbb); if (b=='R') printf("to %s ",bbb); if (b=='T') { now=atol(bbb); tm=(struct tm *)localtime(&now); sprintf(ttm,"%2d",tm->tm_min); if (ttm[0]==32) ttm[0]=48; printf("%s %2d, %4d %2d:%2s ", months[tm->tm_mon], tm->tm_mday,(1900+tm->tm_year), tm->tm_hour,ttm); } SKIPFGM: goto BONFGM; } fpgetfield(fp,string) FILE *fp; char string[]; { int a,b,c; strcpy(string,""); a=0; GFXYZAF: b=getc(fp); if (b<1) { string[a]=0; return(0); } string[a]=b; ++a; if (b!=0) goto GFXYZAF; } main() { char uname[30]; char aaa[100]; struct usersupp usersupp; int a,b,c,file; long upos; printf("Enter username: "); gets(uname); file=open("usersupp",O_RDONLY); upos=finduser(file,uname); if (upos==(-1)) { printf("No such user.\n"); close(file); exit(0); } close(file); A: for (a=0; a<(27-(MAILSLOTS/2)); ++a) printf("\n"); file=open("usersupp",O_RDONLY); lseek(file,upos,0); read(file,&usersupp,sizeof(struct usersupp)); close(file); strcpy(uname,usersupp.fullname); printf("Mailbox for user: %s\n",uname); for (a=0; a<=MAILSLOTS/2; ++a) { printf("%2d. %7ld %-7ld ", a,usersupp.mailnum[a],usersupp.mailpos[a]); b=(a+(MAILSLOTS/2)+1); if (b<MAILSLOTS) printf("%2d. %7ld %-7ld", b,usersupp.mailnum[b],usersupp.mailpos[b]); printf("\n"); } printf("\nEnter command [dirq] : "); gets(aaa); a=tolower(aaa[0]); switch(a) { case 'q': exit(0); break; case 'd': printf("Enter slot number to delete (-1 to abort): "); gets(aaa); a=atol(aaa); if ((a<0)||(a>=MAILSLOTS)) break; file=open("usersupp",O_RDWR); lseek(file,upos,0); read(file,&usersupp,sizeof(struct usersupp)); for (b=a; b>=1; --b) { usersupp.mailnum[b]=usersupp.mailnum[b-1]; usersupp.mailpos[b]=usersupp.mailpos[b-1]; } usersupp.mailnum[0]=0L; usersupp.mailpos[0]=0L; lseek(file,upos,0); write(file,&usersupp,sizeof(struct usersupp)); close(file); break; case 'i': file=open("usersupp",O_RDWR); lseek(file,upos,0); read(file,&usersupp,sizeof(struct usersupp)); for (a=0; a<(MAILSLOTS-1); ++a) { usersupp.mailnum[a]=usersupp.mailnum[a+1]; usersupp.mailpos[a]=usersupp.mailpos[a+1]; } printf("Enter msgnum: "); gets(aaa); usersupp.mailnum[MAILSLOTS-1]=atol(aaa); printf("Enter msgpos: "); gets(aaa); usersupp.mailpos[MAILSLOTS-1]=atol(aaa); lseek(file,upos,0); write(file,&usersupp,sizeof(struct usersupp)); close(file); case 'r': file=open("usersupp",O_RDONLY); lseek(file,upos,0); read(file,&usersupp,sizeof(struct usersupp)); close(file); printf("Slot number (return for all): "); gets(aaa); if (aaa[0]==0) { for (a=0; a<MAILSLOTS; ++a) { msgform(usersupp.mailpos[a]); gets(aaa); } } else { a=atol(aaa); if ((a>=0)&&(a<MAILSLOTS)) msgform(usersupp.mailpos[a]); gets(aaa); } default: break; } goto A; } strucmp(st1,st2) char st1[],st2[]; { char aaa[100],bbb[100]; int a; strcpy(aaa,st1); strcpy(bbb,st2); for (a=0; a<strlen(aaa); ++a) aaa[a]=tolower(aaa[a]); for (a=0; a<strlen(bbb); ++a) bbb[a]=tolower(bbb[a]); a=strcmp(aaa,bbb); return(a); } SHAR_EOF fi echo shar: "extracting 'messages.c'" '(8947 characters)' if test -f 'messages.c' then echo shar: "will not over-write existing file 'messages.c'" else cat << \SHAR_EOF > 'messages.c' /* Citadel/UX message routines * * contents: * * read_message() - called by Read routines to print messages * send_message() - read message in temp file & store in msgmain * make_message() - assemble temp message file - msg editor * msgform() - msg formatter / called by read_message() and others * pull_message() - pull message out of msgmain into temp file */ #include <fcntl.h> #include <stdio.h> #include <ctype.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <signal.h> #include <pwd.h> #include <setjmp.h> #include <termio.h> #include "citadel.h" #define IFEXPERT if (usersupp.flags&US_EXPERT) #define IFNEXPERT if ((usersupp.flags&US_EXPERT)==0) #define IFUPASS if (upass!=0) #define IFNUPASS if (upass==0) #define IFAIDE if (usersupp.axlevel>=6) #define IFNAIDE if (usersupp.axlevel<6) long atol(); long lseek(); extern int curr_rm; extern struct usersupp usersupp; extern struct quickroom quickroom; extern jmp_buf nextbuf; extern int (*backnext())(); extern int (*backstop())(); extern char *months[]; read_message(pos) /* Read a message from the master file */ long pos; /* Position in master file */ { int a; a=setjmp(nextbuf); sttybbs(0); if ((a==1)||(a==2)) { printf("\n\n"); return(a); } signal(SIGINT,(*backnext)); signal(SIGQUIT,(*backstop)); sttybbs(1); msgform(usersupp.screenwidth,pos,"msgmain"); sttybbs(0); return(0); } send_message(filename,retbuf) /* send a message to the master file */ char filename[]; /* tempfilename of proper message */ struct smreturn *retbuf; /* return information */ { int file,a,c,d,file2; long bb,cc,templen,hibytes,origpos; char sbuf[BUFSIZ]; char mid[30]; FILE *fp; struct msgmain msgmain; file=open("MMstructure",O_RDWR); if (file<0) interr(13); do { lseek(file,0L,0); a=read(file,&msgmain,sizeof(struct msgmain)); if (a<1) interr(14); } while(msgmain.MMflags & MM_BUSY); lseek(file,0L,0); msgmain.MMflags=(msgmain.MMflags|MM_BUSY); a=write(file,&msgmain,sizeof(struct msgmain)); if (a<1) interr(16); close(file); origpos=msgmain.MMcurpos; ++msgmain.MMhighest; sprintf(mid,"I%ld",msgmain.MMhighest); /* measure the message */ file=open(filename,O_RDONLY); if (file<0) interr(17); templen=lseek(file,0L,2); close(file); templen=templen+(long)strlen(mid); ++templen; /* check for FF bytes */ hibytes=0L; fp=fopen("msgmain","rb"); if (fp==NULL) interr(18); bb=fseek(fp,msgmain.MMcurpos,0); cc=ftell(fp); for (bb=0L; bb<templen; ++bb) { if (cc>=MM_FILELEN) cc=fseek(fp,0L,0); c=getc(fp); ++cc; if (c>127) ++hibytes; /* bump count if hi bit set */ } fclose(fp); msgmain.MMlowest=msgmain.MMlowest+hibytes; file=open("msgmain",O_RDWR); cc=lseek(file,msgmain.MMcurpos,0); file2=open(filename,O_RDONLY); if (file2<0) interr(19); cc=lseek(file,0L,1); d=read(file2,sbuf,3); write(file,sbuf,d); write(file,mid,strlen(mid)); d=0; write(file,&d,1); do { d=read(file2,sbuf,BUFSIZ); write(file,sbuf,d); cc=cc+(long)d; if (((long)cc)>=((long)MM_FILELEN)) cc=lseek(file,0L,0); } while(d>0); msgmain.MMcurpos=lseek(file,0L,1); close(file2); /* done with temp file */ close(file); /* done with master file */ /* now update the message structure */ msgmain.MMflags=msgmain.MMflags & ~MM_BUSY; file=open("MMstructure",O_RDWR); if (file<0) interr(20); a=write(file,&msgmain,sizeof(struct msgmain)); if (a<1) interr(21); close(file); retbuf->smnumber=msgmain.MMhighest; retbuf->smpos=origpos; return(0); } make_message(filename,author,recipient,room,type,mode) char filename[]; /* temporary file name */ struct usersupp *author; /* author's usersupp structure */ char recipient[]; /* NULL if it's not mail */ char room[]; /* room where it's going */ int type; /* see MES_ types in header file */ int mode; /* 0 for normal, 1 for ASCII */ { FILE *fp; int a,b,old; long aa,beg,now; char aaa[100],bbb[100]; time(&now); fp=fopen(filename,"wb"); if (fp==NULL) interr(22); putc(255,fp); putc(type,fp); /* Normal or anonymous, see MES_ flags */ putc(mode,fp); /* Formatted or unformatted */ strcpy(aaa,author->fullname); for (a=0; a<strlen(aaa); ++a) { aaa[a]=tolower(aaa[a]); if (aaa[a]==32) aaa[a]='_'; if (aaa[a]=='!') strcpy(&aaa[a],&aaa[a+1]); } fprintf(fp,"P%s",aaa); putc(0,fp); /* path */ fprintf(fp,"T%ld",now); putc(0,fp); /* date/time */ fprintf(fp,"A%s",author->fullname); putc(0,fp); /* author */ fprintf(fp,"O%s",quickroom.QRname); putc(0,fp); /* room */ fprintf(fp,"N%s",NODENAME); putc(0,fp); /* node */ if (recipient[0]!=0) { fprintf(fp,"R%s",recipient); putc(0,fp); } fflush(fp); msgform(usersupp.screenwidth,0L,filename); putc('M',fp); if (mode==1) printf("(Press ctrl-d when finished)\n"); beg=ftell(fp); old=1; if (mode==1) goto ME2; ME1: a=inkey(); a=(a&127); aa=ftell(fp); if ((a==8)&&(aa>beg)) { back(1); fseek(fp,-1L,1); goto ME1; } if ((a<32)&&(a!=13)) goto ME1; putc(a,stdout); if ((old==13)&&(a==13)) goto MECR; putc(a,fp); if (a==13) putc(10,stdout); old=a; goto ME1; ME2: a=inkey(); if (a==255) a=32; if (a==4) goto MECR; putc(a,fp); putc(a,stdout); if (a==13) putc(10,stdout); goto ME2; MECR: putc(0,fp); fseek(fp,-1L,1); fflush(fp); printf("<A>bort <C>ontinue <P>rint <S>ave -> "); MECR2: b=inkey(); b=(b&127); b=tolower(b); if (b=='a') { printf("Abort\n"); goto MEABT; } if (b=='c') { printf("Continue\n"); if (mode==0) goto ME1; if (mode==1) goto ME2; } if (b=='s') { printf("Save buffer\n"); goto MEFIN; } if (b=='p') { printf("Print formatted\n"); msgform(usersupp.screenwidth,0L,filename); goto MECR; } goto MECR2; MEFIN: putc(0,fp); fclose(fp); return(0); MEABT: printf("Are you sure? "); if (yesno()==0) goto ME1; fseek(fp,0L,0); putc(0,fp); putc(0,fp); fclose(fp); return(2); } msgform(width,spos,msgfile) int width; long spos; char *msgfile; { struct tm *tm; int a,b,c,e,real,old,mtype,aflag; char aaa[100],bbb[100],ttm[3],ap; FILE *fp; long now; fp=fopen(msgfile,"rb"); if (fp==NULL) return(1); strcpy(aaa,""); old=255; c=1; /* current column pos */ fseek(fp,spos,0); e=getc(fp); if (e!=255) { printf("*** CANNOT LOCATE MESSAGE / pos=%ld\n",spos); goto END; } mtype=getc(fp); aflag=getc(fp); printf("\n "); if (mtype==MES_ANON) printf("****\n"); if (mtype==MES_AN2) printf("<anonymous> "); goto BONFGM; A: if (aflag==1) goto AFLAG; old=real; a=getc(fp); real=a; if (a==0) goto END; if (a<0) goto END; if ( ((a==13)||(a==10)) && (old!=13) && (old!=10) ) a=32; if ( ((old==13)||(old==10)) && ((real==32)||(real==13)||(real==10))) { printf("\n"); c=1; } if (a!=32) { if ( ((strlen(aaa)+c)>(width-4)) && (strlen(aaa)>(width-4)) ) { printf("\n%s",aaa); c=strlen(aaa); aaa[0]=0; } b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; } if (a==32) { if ((strlen(aaa)+c)>(width-5)) { printf("\n"); c=1; } printf("%s ",aaa); ++c; c=c+strlen(aaa); strcpy(aaa,""); goto A; } if ((a==13)||(a==10)) { printf("%s\n",aaa); c=1; strcpy(aaa,""); goto A; } goto A; AFLAG: a=getc(fp); if (a==0) goto END; if ((a<32)&&(a!=13)&&(a!=10)) a='.'; putc(a,stdout); if (a==13) putc(10,stdout); goto AFLAG; END: fclose(fp); printf("\n"); return(0); BONFGM: b=getc(fp); if (b<0) goto END; if (b=='M') { printf("\n"); goto A; } fpgetfield(fp,bbb); if ( (usersupp.axlevel<6) && (usersupp.eternal!=quickroom.QRroomaide) ) if ((mtype==MES_ANON)||(mtype==MES_AN2)) goto BONFGM; if (b=='A') printf("from %s ",bbb); #ifdef SEEMID if ((b=='I')&&(usersupp.axlevel>=6)) printf("#%s ",bbb); #endif /* define SEEMID if you wish to see message ID's in header */ if ((b=='N')&&(strucmp(bbb,NODENAME))&&(curr_rm==1)) printf("@ %s ",bbb); if ((b=='O')&&(strucmp(bbb,quickroom.QRname))) printf("in %s> ",bbb); if ((b=='N')&&(quickroom.QRflags&QR_NETWORK)) printf("@ %s ",bbb); if (b=='R') printf("to %s ",bbb); if (b=='T') { now=atol(bbb); tm=(struct tm *)localtime(&now); sprintf(ttm,"%2d",tm->tm_min); if (ttm[0]==32) ttm[0]=48; ap='a'; if ((tm->tm_hour)>12) { tm->tm_hour=((tm->tm_hour)-12); ap='p'; } printf("%d-%s-%4d %d:%2s%cm ", tm->tm_mday,months[tm->tm_mon], (1900+tm->tm_year), tm->tm_hour,ttm,ap); } goto BONFGM; } pull_message(spos,flnm) /* Pull a message out of the master file */ long spos; /* position in master file */ char *flnm; /* file to write to */ { int a,b,c; int file,file2; long cc; char field[512]; char fwork[512]; file2=creat(flnm,0666); file=open("msgmain",O_RDONLY); lseek(file,spos,0); for (a=0; a<3; ++a) { read(file,&b,1); write(file2,&b,1); } PI: b=0; read(file,&b,1); if (b=='M') { write(file2,&b,1); goto B; } getfield(file,field); if (b!='I') { write(file2,&b,1); write(file2,field,strlen(field)+1); } goto PI; B: cc=lseek(file,0L,1); C: if (cc>=MM_FILELEN) cc=lseek(file,0L,0); c=0; read(file,&c,1); ++cc; write(file2,&c,1); if (c!=0) goto C; close(file); close(file2); return(0); } SHAR_EOF fi echo shar: "extracting 'msgform.c'" '(3587 characters)' if test -f 'msgform.c' then echo shar: "will not over-write existing file 'msgform.c'" else cat << \SHAR_EOF > 'msgform.c' #include <fcntl.h> #include <stdio.h> #include <ctype.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <signal.h> #include <pwd.h> #include <setjmp.h> #include <termio.h> #include "citadel.h" #define IFEXPERT if (usersupp.flags&US_EXPERT) #define IFNEXPERT if ((usersupp.flags&US_EXPERT)==0) #define IFUPASS if (upass!=0) #define IFNUPASS if (upass==0) #define IFAIDE if (usersupp.flags&US_AIDE) #define IFNAIDE if ((usersupp.flags&US_AIDE)==0) long atol(); long lseek(); char *months[]={"Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec"}; main(argc,argv) int argc; char *argv[]; { if (argc==1) msgform(0L,"",0); if (argc==2) msgform(0L,argv[1],0); if (argc==3) msgform(atol(argv[2]),argv[1],0); if (argc==4) msgform(atol(argv[2]),argv[1],1); exit(0); } msgform(spos,msgfile,mflag) long spos; char msgfile[]; int mflag; { struct tm *tm; int a,b,c,d,e,real,old,mtype,aflag,width; char aaa[100],bbb[100],ttm[3],ap; char A[30],R[30],T[30],N[30],O[30]; char flnm[20]; FILE *fp; long now; width=80; strcpy(flnm,msgfile); if (!strcmp(flnm,"-m")) { strcpy(flnm,"/usr/bbs/msgmain"); mflag=1; } if (flnm[0]==0) fp=stdin; else fp=fopen(flnm,"rb"); if (fp==NULL) return(1); fseek(fp,spos,0); LOOP: strcpy(aaa,""); old=255; c=1; /* current column pos */ do { e=getc(fp); if (e<0) { fclose(fp); return(0); } } while(e!=255); if (e!=255) { printf("===> CANNOT LOCATE MESSAGE / pos=%ld\n",spos); goto END; } mtype=getc(fp); aflag=getc(fp); goto BONCLR; AA: if ((mflag==1)&&(strcmp(O,"Mail"))) { do { a=getc(fp); } while(a!=0); goto LOOP; } printf("\n "); if (mtype==MES_ANON) printf("****\n"); if (mtype==MES_AN2) printf("<anonymous> "); if (T[0]!=0) printf("%s ",T); if (A[0]!=0) printf("from %s ",A); if (R[0]!=0) printf("to %s ",R); if (O[0]!=0) printf("in %s> ",O); if (N[0]!=0) printf("@ %s ",N); printf("\n"); AAA: if (aflag==1) goto AFLAG; old=real; a=getc(fp); real=a; if (a==0) goto END; if (a<0) goto END; if ( ((a==13)||(a==10)) && (old!=13) && (old!=10) ) a=32; if ( ((old==13)||(old==10)) && ((real==32)||(real==13)||(real==10))) { printf("\n"); c=1; } if (a!=32) { if ( ((strlen(aaa)+c)>(width-4)) && (strlen(aaa)>(width-4)) ) { printf("\n%s",aaa); c=strlen(aaa); aaa[0]=0; } b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; } if (a==32) { if ((strlen(aaa)+c)>(width-5)) { printf("\n"); c=1; } printf("%s ",aaa); ++c; c=c+strlen(aaa); strcpy(aaa,""); goto AAA; } if ((a==13)||(a==10)) { printf("%s\n",aaa); c=1; strcpy(aaa,""); goto AAA; } goto AAA; AFLAG: a=getc(fp); if (a==0) goto END; putc(a,stdout); if (a==13) putc(10,stdout); goto AFLAG; END: printf("\n"); goto LOOP; BONCLR: strcpy(A,""); strcpy(R,""); strcpy(T,""); strcpy(O,""); strcpy(N,""); BONFGM: b=getc(fp); if (b<0) goto END; if (b=='M') goto AA; fpgetfield(fp,bbb); if (b=='A') strcpy(A,bbb); if (b=='N') strcpy(N,bbb); if (b=='O') strcpy(O,bbb); if (b=='R') strcpy(R,bbb); if (b=='T') { now=atol(bbb); tm=(struct tm *)localtime(&now); sprintf(ttm,"%2d",tm->tm_min); if (ttm[0]==32) ttm[0]=48; ap='a'; if ((tm->tm_hour)>12) { tm->tm_hour=((tm->tm_hour)-12); ap='p'; } sprintf(T,"%d-%s-%4d %d:%2s%cm ", tm->tm_mday,months[tm->tm_mon], (1900+tm->tm_year), tm->tm_hour,ttm,ap); } goto BONFGM; } fpgetfield(fp,string) FILE *fp; char string[]; { int a,b; strcpy(string,""); a=0; do { b=getc(fp); if (b<1) { string[a]=0; return(0); } string[a]=b; ++a; } while(b!=0); } SHAR_EOF fi echo shar: "extracting 'msgstats.c'" '(437 characters)' if test -f 'msgstats.c' then echo shar: "will not over-write existing file 'msgstats.c'" else cat << \SHAR_EOF > 'msgstats.c' #include <fcntl.h> #include "citadel.h" main() { int file,a,b,c; struct msgmain msgmain; file=open("./MMstructure",O_RDONLY); read(file,&msgmain,sizeof(struct msgmain)); close(file); printf("Messages numbered %ld to %ld\n",msgmain.MMlowest,msgmain.MMhighest); printf("Current file position: %ld\n",msgmain.MMcurpos); if (msgmain.MMflags & MM_BUSY) printf("File is locked.\n"); else printf("File is unlocked.\n"); exit(0); } SHAR_EOF fi echo shar: "done with directory 'source'" cd .. exit 0 # End of shell archive -- Some do, some don't. | eric@sactoh0.SAC.CA.US Some will, some won't. | ames!pacbell!sactoh0!eric I might! | ucbvax!csusac!sactoh0!eric | ( A Home For Unwanted 3B's )