simpsong@ncoast.UUCP (01/17/87)
*** Line-eater foo-d. *** Greetings Fellow Neter's... There was a lot of talk about UUCP for MS-DOS a week or two ago, and one thing that was mentioned was a program called uuslave.c from a BBS in NJ. Well, even though I am in Cleveland, I went ahead and registered just so I could get this program... Unfortunately, it contains very few comments, and appears to be originally targeted for CPM, as well as having lots of stuff hard-wired into the code... I really don't know if it will be of any use, but it may be a building block from which the readers of net-land can produce a usable uucp for msdos. (Does Minix have uucp?) There was absolutely no documentation, and after looking at it briefly, I really don't know where to start... So, I ask... can anyone out there make heads or tails of this? I will be trying to, but it really isn't my cup of tea. If anyone can make this work, please repost your enhanced version with some documentation. Thanks, and Enjoy. Gregory R. Simpson UUCP: {ihnp4, seismo, decwrl, philabs, ucbvax}!decvax!cwruecmp!ncoast!simpsong CSNET: ncoast!simpsong@case.CSNET ARPA: ncoast!simpsong%case.CSNET@Csnet-Relay.ARPA ------- This is NOT a shar, or an arc, or anything... just straight code ---- /* @[$]uuslave.c 1.7 08/12/85 14:04:20 */ #include <stdio.h> #include <fcntl.h> #ifndef CPM #include <termio.h> #include <signal.h> #endif #define MAGIC 0125252 #define EOT 4 #define CTRL 0 #define ALTCHN 1 #define LNGDAT 2 #define SHTDAT 3 #define CLOSE 1 #define RJ 2 #define SRJ 3 #define RR 4 #define INITC 5 #define INITB 6 #define INITA 7 extern errno; char msgi[256],msgo[256],ttynam[32],cmnd[8],srcnam[32],dstnam[32],dskbuf[256],msgbld[256]; int fdtty,fddsk,tt,xxx,yyy,rseq,wseq; #ifndef CPM struct termio atermio,btermio; #endif #ifdef ERRLOG FILE *file; #endif int wndsiz = 1; int segsiz = 1; char msgo0[] = "9800rcs login: "; char msgo1[] = "Password:"; char msgo2[] = "\20Shere\0"; char msgo3[] = "\20ROK\0\20Pg\0"; char msgo4[] = "\20OOOOOO\0"; char msgo5[] = "...abort..."; char msgi0[] = "uucp\n"; char msgi1[] = "s8000\n"; char msgi2[] = "\20S*\0"; char msgi3[] = "\20Ug\0"; #ifdef CPM extern xgetc(),xwrite(); #else sigint() { ioctl(fdtty,TCSETA,&atermio); close(fdtty); exit(0); } sigalrm() { } xgetc() { char data; signal(SIGALRM,sigalrm); alarm(10); if (read(fdtty,&data,1) > 0) { alarm(0); return(data & 0xFF); } return(EOF); } xwrite(fd,buf,ctr) int fd; char *buf; int ctr; { write(fd,buf,ctr); } #endif zero(p,c) char *p; int c; { while (c--) *p++ = 0; } ackmsg() { int cksm,index; msgo[0] = 020; msgo[1] = 9; msgo[4] = (CTRL << 6) | (RR << 3) | rseq; cksm = MAGIC - msgo[4]; msgo[2] = cksm; msgo[3] = cksm >> 8; msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4]; #ifdef DEBUG printf("T "); for (index = 0; index < 6; index++) printf("%03o ",msgo[index] & 0xFF); putchar('\n'); #endif xwrite(fdtty,msgo,6); rseq = (rseq + 1) & 7; } ctlmsg(byte) char byte; { int cksm,index; msgo[0] = 020; msgo[1] = 9; msgo[4] = (CTRL << 6) | byte; cksm = MAGIC - msgo[4]; msgo[2] = cksm; msgo[3] = cksm >> 8; msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4]; #ifdef DEBUG printf("T "); for (index = 0; index < 6; index++) printf("%03o ",msgo[index] & 0xFF); putchar('\n'); #endif xwrite(fdtty,msgo,6); } lngput(s,n) char *s; int n; { int cksm,index; zero(msgo,256); msgo[0] = 020; msgo[1] = segsiz + 1; msgo[4] = (LNGDAT << 6) + (wseq << 3) + rseq; for (index = 0; index < (segsiz + 1) * 32; index++) msgo[6+index] = 0; for (index = 0; index < n; index++) msgo[6+index] = *(s+index); cksm = MAGIC - (chksum(&msgo[6],(segsiz + 1) * 32) ^ (0377 & msgo[4])); msgo[2] = cksm; msgo[3] = cksm >> 8; msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4]; #ifdef DEBUG printf("T "); for (index = 0; index < (segsiz + 1) * 32 + 6; index++) printf("%03o ",msgo[index] & 0xFF); putchar('\n'); #endif do { xwrite(fdtty,msgo,(segsiz + 1) * 32 + 6); if (inpkt()) return(1); } while (tt != CTRL || xxx != RR || yyy != wseq); wseq = (wseq + 1) & 7; return(0); } shtput(s,n) char *s; int n; { int cksm,index; zero(msgo,256); msgo[0] = 020; msgo[1] = segsiz + 1; msgo[4] = (SHTDAT << 6) + (wseq << 3) + rseq; for (index = 0; index < (segsiz + 1) * 32; index++) msgo[6+index] = 0; msgo[6] = (segsiz + 1) * 32 - n; for (index = 0; index < n; index++) msgo[7+index] = *(s+index); cksm = MAGIC - (chksum(&msgo[6],(segsiz + 1) * 32) ^ (0377 & msgo[4])); msgo[2] = cksm; msgo[3] = cksm >> 8; msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4]; #ifdef DEBUG printf("T "); for (index = 0; index < (segsiz + 1) * 32 + 6; index++) printf("%03o ",msgo[index] & 0xFF); putchar('\n'); #endif do { xwrite(fdtty,msgo,(segsiz + 1) * 32 + 6); if (inpkt()) return(1); } while (tt != CTRL || xxx != RR || yyy != wseq); wseq = (wseq + 1) & 7; return(0); } instr(s,n) char *s; int n; { int data,count,i,j; count = 0; #ifdef DEBUG printf("Expecting "); for (i = 0; i < n; i++) printf("%03o ",*(s+i)); printf("\nR "); #endif while ((data = xgetc()) != EOF) { msgi[count++] = data & 0x7F; #ifdef DEBUG printf("%03o ",msgi[count-1]); #endif if (count >= n) { for (i = n - 1, j = count - 1; i >= 0; i--, j--) if (*(s+i) == '*' || *(s+i) != msgi[j]) break; if (i < 0 || *(s+i) == '*') { #ifdef DEBUG putchar('\n'); #endif return(0); } } } #ifdef DEBUG putchar('\n'); #endif msgi[count] = 0; return(1); } inpkt() { int data,count,need; count = 0; #ifdef DEBUG printf("R "); #endif while ((data = xgetc()) != EOF) { #ifdef DEBUG printf("%03o ",data & 0xFF); #endif switch (count) { case 0 : if (data == 020) msgi[count++] = 020; break; case 1 : msgi[count++] = data; if (data == 9) need = 4; else need = 32 * data + 4; break; case 4 : tt = (data >> 6) & 3; xxx = (data >> 3) & 7; yyy = data & 7; default : msgi[count++] = data; if (!--need) { #ifdef DEBUG putchar('\n'); #endif return(0); } break; } } #ifdef DEBUG putchar('\n'); #endif return(1); } chksum(s,n) register char *s; register n; { register short sum; register unsigned short t; register short x; sum = -1; x = 0; do { if (sum < 0) { sum <<= 1; sum++; } else sum <<= 1; t = sum; sum += *s++ & 0377; x += sum ^ n; if ((unsigned) sum <= t) sum ^= x; } while (--n > 0); return(sum); } main(argc,argv) int argc; char *argv[]; { char *p; int data,count; #ifdef CPM sioinit(); #else if (argc > 1) strcpy(ttynam,argv[1]); else strcpy(ttynam,"/dev/tty12"); if ((fdtty = open(ttynam,O_RDWR)) < 0) { printf("Cannot open %s for read/write %d\n",ttynam,errno); exit(1); } ioctl(fdtty,TCGETA,&atermio); btermio = atermio; btermio.c_iflag = btermio.c_oflag = btermio.c_lflag = 0; btermio.c_cc[VMIN] = 1; btermio.c_cc[VTIME] = 0; btermio.c_cflag = (btermio.c_cflag & ~CBAUD) | B1200; ioctl(fdtty,TCSETA,&btermio); signal(SIGINT,sigint); #endif while (1) { #ifdef DEBUG puts("restarting"); #endif rseq = 0; wseq = 1; /* wait for EOT */ while ((data = xgetc()) == EOF || (data &= 0x7F) != EOT); /* output login request, verify uucp */ xwrite(fdtty,msgo0,sizeof(msgo0)-1); if (instr(msgi0,sizeof(msgi0)-1)) goto abort; /* output password request, verify s8000 */ xwrite(fdtty,msgo1,sizeof(msgo1)-1); if (instr(msgi1,sizeof(msgi1)-1)) goto abort; /* output here message, wait for response */ xwrite(fdtty,msgo2,sizeof(msgo2)-1); if (instr(msgi2,sizeof(msgi2)-1)) goto abort; /* output ok message, output protocol request, wait for response */ xwrite(fdtty,msgo3,sizeof(msgo3)-1); if (instr(msgi3,sizeof(msgi3)-1)) goto abort; /* output inita message, wait for response */ ctlmsg((INITA << 3) | wndsiz); if (inpkt() || tt != CTRL || xxx != INITA) goto abort; /* output initb message, wait for response */ ctlmsg((INITB << 3) | segsiz); if (inpkt() || tt != CTRL || xxx != INITB) goto abort; /* output initc message, wait for response */ ctlmsg((INITC << 3) | wndsiz); if (inpkt() || tt != CTRL || xxx != INITC) goto abort; /* output initial acknowledge, wait for command */ ackmsg(); while (1) { if (inpkt() || tt != LNGDAT) { intf("OVER EIGHT"); goto abort; } strcpy(msgbld,&msgi[6]); while (strlen(&msgi[6]) == (segsiz + 1) * 32) { ackmsg(); if (inpkt() || tt != LNGDAT) { intf("OVER ABORT SEVEN"); goto abort; } strcat(msgbld,&msgi[6]); } switch (msgbld[0]) { case 'S' : sscanf(msgbld,"%s %s %s",cmnd,srcnam,dstnam); #ifdef CPM for (p = dstnam + strlen(dstnam); p != dstnam && *(p-1) != '/'; p--); #else p = dstnam; #endif if ((fddsk = creat(p,0644)) >= 0) { ackmsg(); if (lngput("SY",2)) { intf("OVER NINE"); goto abort; } do if (inpkt()) { intf("OVER TEN"); goto abort; } else switch (tt) { case LNGDAT : write(fddsk,&msgi[6],(segsiz + 1) * 32); ackmsg(); break; case SHTDAT : if (msgi[6] & 0x80) { intf("OVER ELEVEN"); #ifdef DEBUG puts("short packet error"); #endif goto abort; } else { if (msgi[6] != (segsiz + 1) * 32) write(fddsk,&msgi[7],(segsiz + 1) * 32 - msgi[6]); ackmsg(); } break; default : intf("OVER TWELVE"); goto abort; } while (tt != SHTDAT || msgi[6] != (segsiz + 1) * 32); close(fddsk); if (lngput("CY",2)) goto abort; } else { ackmsg(); #ifdef ERRLOG if (file = fopen("uuslave.log","a+")) { fprintf(file,"Cannot open file=%s for writing errno=%d\n",p,errno); fclose(file); } #endif sprintf(dskbuf,"SN%d",errno); if (lngput(dskbuf,strlen(dskbuf))) goto abort; } break; case 'R' : sscanf(msgbld,"%s %s %s",cmnd,srcnam,dstnam); #ifdef CPM for (p = srcnam + strlen(srcnam); p != srcnam && *(p-1) != '/'; p--); #else p = srcnam; #endif if ((fddsk = open(p,O_RDONLY)) >= 0) { ackmsg(); if (lngput("RY",2)) goto abort; do if ((count = read(fddsk,dskbuf,(segsiz + 1) * 32)) == (segsiz + 1) * 32) if (lngput(dskbuf,(segsiz + 1) * 32)) goto abort; else; else if (shtput(dskbuf,count)) goto abort; while (count); close(fddsk); do if (inpkt()) goto abort; while (tt != LNGDAT); ackmsg(); } else { ackmsg(); #ifdef ERRLOG if (file = fopen("uuslave.log","a+")) { fprintf(file,"Cannot open file=%s for reading errno=%d\n",p,errno); fclose(file); } #endif sprintf(dskbuf,"RN%d",errno); if (lngput(dskbuf,strlen(dskbuf))) goto abort; } break; case 'H' : intf("IN H CASE"); if (lngput("HY",2)) { intf("OVER ABORT ONE"); goto abort; } if (inpkt() || tt != LNGDAT) { intf("OVER ABORT TWO"); goto abort; } if (!strcmp(&msgi[6],"HY")) { ctlmsg(CLOSE << 3); do if (inpkt()) { intf("OVER ABORT THREE"); goto abort; } while (tt != CTRL && xxx != CLOSE); xwrite(fdtty,msgo4,sizeof(msgo4)-1); instr(msgo4,sizeof(msgo4)-1); } intf("OVER ABORT FIVE"); break; /*goto abort;*/ } } abort:; xwrite(fdtty,msgo5,sizeof(msgo5)-1); } } intf(buffer) register char *buffer; { int fd; fd = open("UUCP.DAT",O_RDWR + O_CREAT); lseek(fd,0L,2); write(fd,buffer,strlen(buffer)); close(fd); } -- Gregory R. Simpson UUCP: {ihnp4, seismo, decwrl, philabs, ucbvax}!decvax!cwruecmp!ncoast!simpsong CSNET: ncoast!simpsong@case.CSNET ARPA: ncoast!simpsong%case.CSNET@Csnet-Relay.ARPA
pozar@hoptoad.UUCP (01/24/87)
Sorry to post this, my mailer upchucked on ncoast.UUCP. I picked off the uuslave code. Could you point me the direction of where you got it from? There seems to be some header files that I'm unfamiler with and weren't included with the code. Mucho functions I don't fully know what they need, etc... Thanks -- Tim Pozar UUCP pozar@hoptoad.UUCP Fido 125/406 USNail KLOK-FM 77 Maiden Lane San Francisco CA 94108 terrorist cryptography DES drugs cipher secret decode NSA CIA NRO IRS coke crack pot LSD russian missile atom nuclear assassinate libyan RSA (Thanks to Robert Bickford for the suggestion for the NSA line eater)
allbery@ncoast.UUCP (01/26/87)
As quoted from <1683@hoptoad.uucp> by pozar@hoptoad.uucp (Tim Pozar): +--------------- | Sorry to post this, my mailer upchucked on ncoast.UUCP. | | I picked off the uuslave code. Could you point me the direction of where | you got it from? There seems to be some header files that I'm unfamiler | with and weren't included with the code. Mucho functions I don't fully | know what they need, etc... +--------------- I can't tell you what BBS it came from, but I'm pretty sure it's legit; I was given a copy somewhat earlier on another machine (tdi2.uucp). The posting mentioned the fact that we're all pretty well stumped by it. (I don't have a C compiler, so I can't translate it to C on my PC; and while I could conceivably translate to Turbo Pascal (I have done so in the past with C programs), pointer problems usually result and reasonable COMn: I/O seems to choke at anything over 1200 baud (and is somewhat flaky at 1200).) It *does* seem to be written for CP/M, as opposed to MS-DOS. This might mean Aztec or BDS C, the two most common for CP/M. ++Brandon -- ____ ______________ / \ / __ __ __ \ Brandon S. Allbery <backbone>!ncoast!allbery ___ | /__> / \ / \ aXcess Co., Consulting ncoast!allbery@Case.CSNET / \ | | `--, `--, 6615 Center St. #A1-105 (...@relay.CS.NET) | | \__/ \__/ \__/ Mentor, OH 44060-4101 \____/ \______________/ +1 216 781 6201
turner@imagen.UUCP (01/28/87)
in article <1943@ncoast.UUCP>, allbery@ncoast.UUCP (Brandon Allbery) says: > As quoted from <1683@hoptoad.uucp> by pozar@hoptoad.uucp (Tim Pozar): ......where does uuslave.c come from > I can't tell you what BBS it came from, but I'm pretty sure it's legit; I > was given a copy somewhat earlier on another machine (tdi2.uucp). > it came from the acg BBS in new jersey, they're number is 201 753-9758 -- --------------- C'est la vie, C'est le guerre, C'est la pomme de terre Mail: Imagen Corp. 2650 San Tomas Expressway Santa Clara, CA 95052-8101 UUCP: ...{decvax,ucbvax}!decwrl!imagen!turner AT&T: (408) 986-9400
shapiro@oucs.UUCP (01/28/87)
What is uuslave.c? What is it supposed to do? Thanks. Brian Shapiro Ohio University Computing and Learning Services Athens Ohio 45710 UUCP: !inhp4!cbatt!oucs!shapiro Fido: 126/110 BITNET: SHAPIROB@OUACCVMA
bruceb@telesoft.UUCP (01/28/87)
> As quoted from <1683@hoptoad.uucp> by pozar@hoptoad.uucp (Tim Pozar): > | > | I picked off the uuslave code. Could you point me the direction of ... > +--------------- > > The posting mentioned the fact that we're all pretty well stumped by it. (I > don't have a C compiler, so I can't translate it to C on my PC ... > > ++Brandon Hmmm. I also got a copy of uuslave.c and have had time to investigate it in depth. If you have not bothered to find out the guts of uucp, no, you probably will not make sense of it at all. Fortunately, in past, I did try to recreate uucp (similar to what lauren weinstien did), however the protocol level of uucp is not documented. Those who know the info aren't willing to share it, so if you want to rewrite uucp, you are on your own. Anyhow, with the advent of uuslave.c, the gaps have filled in. With about 3 exceptions, I think I have what I need to do what I want. In any case, I am already engaged in creating a Modula-2 version of uuslave.c. If this is successful (no reason why it shouldn't be), I will take the time to redo uuslave.c for MS-DOS. The Modula-2 version (for MS-DOS) should be available in a short while. If anyone is interested in the Modula-2 or C versions of uuslave.c for MS-DOS, please send me a note. I'll be porting it as we speak, in any case. Source code will be included, of course. Also, if you are interested in a discussion of how uucp communicates (including the information in uuslave.c), please send me a note also. If I get sufficient response, I may consider posting what I have. bruce -- bang!- allegra!\ \ gould9! \ crash!--\ ihnp4! \ \ >--sdcsvax!---->--telesoft!bruceb (Bruce Bergman N7HAW) noscvax! / / scgvaxd! / sdencore!--/ ucbvax! / / talaris!-
allbery@ncoast.UUCP (02/01/87)
As quoted from <378@telesoft.UUCP> by bruceb@telesoft.UUCP (Bruce Bergman @spot): +--------------- | > As quoted from <1683@hoptoad.uucp> by pozar@hoptoad.uucp (Tim Pozar): | > | | > | I picked off the uuslave code. Could you point me the direction of ... | > +--------------- | > | > The posting mentioned the fact that we're all pretty well stumped by it. (I | > don't have a C compiler, so I can't translate it to C on my PC ... | > | > ++Brandon | | Hmmm. I also got a copy of uuslave.c and have had time to investigate it in | depth. If you have not bothered to find out the guts of uucp, no, you | probably will not make sense of it at all. Fortunately, in past, I did try to +--------------- Actually, I meant the I/O code; specifically, how to duplicate it using UNIX system calls or the I/O routines of MSC 4.0, etc. I don't grok CP/M-80 C I/O calls. ++Brandon -- ++Brandon (Resident Elf @ ncoast.UUCP) ____ ______________ / \ / __ __ __ \ Brandon S. Allbery <backbone>!ncoast!allbery ___ | /__> / \ / \ aXcess Co., Consulting ncoast!allbery@Case.CSNET / \ | | `--, `--, 6615 Center St. #A1-105 (...@relay.CS.NET) | | \__/ \__/ \__/ Mentor, OH 44060-4101 \____/ \______________/ +1 216 781 6201
mjranum@osiris.UUCP (02/06/87)
This is the mangled version of uuslave. I've fixed some parts, and done my best to provide machine independence. The job is probably not complete, but it will compile OK on a PC with Lattice C, as well as a SUN workstation. (from the ridiculous to the sublime, eh ?) Anyhow, this is code "as is". It may need some work. If I was a dummy anywhere, flame me personally, don't E-mail to the net. --mjr; -------------fold here------------- /* uuslave.c - client uucp(R) connection */ /* (uucp is copyright AT&T) */ /* this is designed to run on IBM PCs w/ */ /* a modem or direct connection to UNIX */ /* no guarantees of functionality... */ /* original author ? */ /* very extensive and brutal hacks by Marcus J Ranum */ /* I take no responsibility for the working code here. */ /* all the comments (for what they're worth) are mine) */ /* I added all the incremental debug information stuff */ #include "stdio.h" #include "signal.h" /* if your system does not support signal, comment all */ /* references to signal out and it may still work. */ #define O_RDONLY 000 /* open for reading */ #define O_WRONLY 001 /* open for writing */ #define O_RDWR 002 /* open for read & write */ /* mysterious numbers that are possibly CP/M specific. */ /* they are used as masks for file I/O */ #define CLOSE 1 #define CTRL 0 #define LNGDAT 2 #define SHTDAT 3 #define MAGIC 0125252 #define EOT 4 #define RR 4 #define INITC 5 #define INITB 6 #define INITA 7 int sigint (); int abort (); char *strcat (); char *strcpy (); long lseek (); extern errno; int wndsiz = 1; int segsiz = 1; /* these are used later as buffers for ttynames, etc, etc, etc. */ char msgi[256], msgo[256], cmnd[8], srcnam[32]; char dstnam[32], dskbuf[256], msgbld[256]; /* fdtty is terminal file descriptor */ /* fddsk is disk file descriptor */ int fdtty, fddsk; /* I believe these are the message sequence numbers */ int tt, xxx, yyy, rseq, wseq; /* this is the communications device/port/whatever */ char *ttynam; /* error log file name, debug flags, etc.*/ FILE * errfile; char *errlog; int errflg; int debugmode = 0; /* these next few strings are strings uucp expects to see. */ /* they shouldn't need changing */ /* messages that get sent out */ char *msgo0; char msgo1[] = "Password:"; char msgo2[] = "\20Shere\0"; char msgo3[] = "\20ROK\0\20Pg\0"; char msgo4[] = "\20OOOOOO\0"; char msgo5[] = "...abort..."; /* messages that are read in */ char msgi0[] = "uucp\n"; char msgi1[] = "s8000\n"; char msgi2[] = "\20S*\0"; char *msgi3; main (argc, argv) int argc; char *argv[]; { char *p; int data, ttisflg, unamflg, themflg, count; errflg = ttisflg = 0; unamflg = themflg = 0; errlog = "uuerr.log"; /* mjr - this part completely mine. original version did not */ /* give a damn about arguments */ /* we try to remove compiled-in dependencies (ugh) */ for (count = 1; count <= argc; count++) { if (argv[count][0] == '-') { switch (argv[count][1]) { /* line name */ case 'l': case 'L': if (strlen (argv[count]) > 2) { ttynam = &argv[count][2]; ttisflg++; } break; /* error log file (default is uuerr.log) */ case 'e': case 'E': if (strlen (argv[count]) > 2) { errlog = &argv[count][2]; } break; /* this system's name */ case 'h': case 'H': if (strlen (argv[count]) > 2) { unamflg++; msgo0 = &argv[count][2]; } break; /* the other systems name */ case 's': case 'S': if (strlen (argv[count]) > 2) { themflg++; msgi3 = &argv[count][2]; } break; /* turn on debug */ case 'x': case 'X': debugmode = atoi (&argv[count][2]); if (!debugmode) debugmode++; break; /* options */ case 'o': case 'O': fprintf (stderr, "uuslave options: \n"); fprintf (stderr, "(mandatory) -ldevicename\n"); fprintf (stderr, "(mandatory) -hhostname\n"); fprintf (stderr, "(mandatory) -stheirname\n"); fprintf (stderr, "errlog -efilename\n"); fprintf (stderr, "debug -x#\n"); fprintf (stderr, "options -o\n"); exit (-9); default: fprintf (stderr, "uuslave:invalid option %s\n", &argv[count][1]); exit (-1); } } } if (!ttisflg) { fprintf (stderr, "uuslave: "); fprintf (stderr, "MUST specify line with -l<line> flag\n"); exit (-1); } if (!themflg) { fprintf (stderr, "uuslave: "); fprintf (stderr, "MUST name other system with -s<name> flag\n"); fprintf (stderr, "(use the name they will try to login as)\n"); exit (-1); } if (!unamflg) { fprintf (stderr, "uuslave: "); fprintf (stderr, "MUST specify this system name with -h<name> flag\n"); fprintf (stderr, "(use the name they are trying to log in to)\n"); exit (-1); } if (debugmode) { fprintf (stderr, "using line %s to communicate.\n", ttynam); fprintf (stderr, "expecting them to log in as %s.\n", msgi3); fprintf (stderr, "this system name is expected to be %s.\n", msgo0); fprintf (stderr, "error log file is %s.\n", errlog); } /* open the communications device/tty for read/write */ if ((fdtty = open (ttynam, O_RDWR)) < 0) { printf ("Cannot open %s for read/write %d\n", ttynam, errno); exit (1); } if (debugmode > 3) { printf ("opened %s read/write\n", ttynam); } /* trap interrupt to close communications line */ signal (SIGINT, sigint); while (1) { if (debugmode) { puts ("restarting\n"); } rseq = 0; wseq = 1; /* wait for EOT */ while ((data = xgetc ()) == EOF || (data &= 0x7F) != EOT); if (debugmode > 6) { puts ("got EOT\n"); } /* output login request, verify uucp */ write (fdtty, msgo0, sizeof (msgo0) - 1); if (instr (msgi0, sizeof (msgi0) - 1)) abort (); if (debugmode > 3) { puts ("requested and got login\n"); } /* output password request */ write (fdtty, msgo1, sizeof (msgo1) - 1); if (instr (msgi1, sizeof (msgi1) - 1)) abort (); if (debugmode > 4) { puts ("requested and got password\n"); } /* output system here message, wait for response */ write (fdtty, msgo2, sizeof (msgo2) - 1); if (instr (msgi2, sizeof (msgi2) - 1)) abort (); if (debugmode > 6) { puts ("sent and got system here name\n"); } /* output ok message, protocol request, wait for response */ write (fdtty, msgo3, sizeof (msgo3) - 1); if (instr (msgi3, sizeof (msgi3) - 1)) abort (); if (debugmode > 6) { puts ("sent OK\n"); } /* output inital message, wait for response */ ctlmsg ((INITA << 3) | wndsiz); if (inpkt () || tt != CTRL || xxx != INITA) abort (); if (debugmode > 6) { puts ("sent initial message\n"); } /* output initb message, wait for response */ ctlmsg ((INITB << 3) | segsiz); if (inpkt () || tt != CTRL || xxx != INITB) abort (); if (debugmode > 6) { puts ("sent initb message\n"); } /* output initc message, wait for response */ ctlmsg ((INITC << 3) | wndsiz); if (inpkt () || tt != CTRL || xxx != INITC) abort (); if (debugmode > 6) { puts ("sent initc message\n"); } /* output initial acknowledge, wait for command */ ackmsg (); while (1) { if (inpkt () || tt != LNGDAT) { intf ("OVER EIGHT"); abort (); } strcpy (msgbld, &msgi[6]); while (strlen (&msgi[6]) == (segsiz + 1) * 32) { ackmsg (); if (inpkt () || tt != LNGDAT) { intf ("OVER ABORT SEVEN"); abort (); } strcat (msgbld, &msgi[6]); } switch (msgbld[0]) { case 'S': sscanf (msgbld, "%s %s %s", cmnd, srcnam, dstnam); p = dstnam; if ((fddsk = creat (p, 0644)) >= 0) { ackmsg (); if (lngput ("SY", 2)) { intf ("OVER NINE"); abort (); } do if (inpkt ()) { intf ("OVER TEN"); abort (); } else switch (tt) { case LNGDAT: write (fddsk, &msgi[6], ((segsiz + 1) * 32)); ackmsg (); break; case SHTDAT: if (msgi[6] & 0x80) { intf ("OVER ELEVEN"); if (debugmode) { puts ("short packet error"); } abort (); } else { if (msgi[6] != (segsiz + 1) * 32) write (fddsk, &msgi[7], (segsiz + 1) * 32 - msgi[6]); ackmsg (); } break; default: intf ("OVER TWELVE"); abort (); } while (tt != SHTDAT || msgi[6] != (segsiz + 1) * 32); close (fddsk); if (lngput ("CY", 2)) abort (); } else { ackmsg (); if (errflg) { if (errfile = fopen (errlog, "a+")) { fprintf (errfile, "Cannot write %s errno%d\n", p, errno); fclose (errfile); } } sprintf (dskbuf, "SN%d", errno); if (lngput (dskbuf, strlen (dskbuf))) abort (); } break; case 'R': sscanf (msgbld, "%s %s %s", cmnd, srcnam, dstnam); p = srcnam; if ((fddsk = open (p, O_RDONLY)) >= 0) { ackmsg (); if (lngput ("RY", 2)) abort (); do if ((count = read (fddsk, dskbuf, ((segsiz + 1) * 32))) == (segsiz + 1) * 32) if (lngput (dskbuf, (segsiz + 1) * 32)) abort (); else; else if (shtput (dskbuf, count)) abort (); while (count); close (fddsk); do if (inpkt ()) abort (); while (tt != LNGDAT); ackmsg (); } else { ackmsg (); if (errflg) { if (errfile = fopen (errlog, "a+")) { fprintf (errfile, "Cannot read file %s errno:%d\n", p, errno); fclose (errfile); } } sprintf (dskbuf, "RN%d", errno); if (lngput (dskbuf, strlen (dskbuf))) abort (); } break; case 'H': intf ("IN H CASE"); if (lngput ("HY", 2)) { intf ("OVER ABORT ONE"); abort (); } if (inpkt () || tt != LNGDAT) { intf ("OVER ABORT TWO"); abort (); } if (!strcmp (&msgi[6], "HY")) { ctlmsg (CLOSE << 3); do if (inpkt ()) { intf ("OVER ABORT THREE"); abort (); } while (tt != CTRL && xxx != CLOSE); write (fdtty, msgo4, sizeof (msgo4) - 1); instr (msgo4, sizeof (msgo4) - 1); } intf ("OVER ABORT FIVE"); break; } } } } intf (buffer) register char *buffer; { int fd; /* make entry in UUCP.DAT file */ fd = open ("UUCP.DAT", O_RDWR); lseek (fd, (long) 0, 2); write (fd, buffer, strlen (buffer)); close (fd); } xgetc () { char data; /* get some stuff from acu/tty line */ if (read (fdtty, &data, 1) > 0) return (data & 0xFF); return (EOF); } sigint () { /* interrupt - close acu/tty line */ if (debugmode) { fprintf (stderr, "...interrupt...\n"); } close (fdtty); exit (0); } zero (p, c) char *p; int c; { /* zero a string */ while (c--) *p++ = 0; } ackmsg () { int cksm, index; /* looks like this writes a UUCp format ack message */ msgo[0] = 020; msgo[1] = 9; msgo[4] = (CTRL << 6) | (RR << 3) | rseq; cksm = MAGIC - msgo[4]; msgo[2] = cksm; msgo[3] = cksm >> 8; msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4]; if (debugmode > 6) { printf ("T "); for (index = 0; index < 6; index++) printf ("%03o ", msgo[index] & 0xFF); putchar ('\n'); } write (fdtty, msgo, 6); rseq = (rseq + 1) & 7; } ctlmsg (byte) char byte; { int cksm, index; msgo[0] = 020; msgo[1] = 9; msgo[4] = (CTRL << 6) | byte; cksm = MAGIC - msgo[4]; msgo[2] = cksm; msgo[3] = cksm >> 8; msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4]; if (debugmode > 6) { printf ("T "); for (index = 0; index < 6; index++) printf ("%03o ", msgo[index] & 0xFF); putchar ('\n'); } write (fdtty, msgo, 6); } lngput (s, n) char *s; int n; { int cksm, index; zero (msgo, 256); msgo[0] = 020; msgo[1] = segsiz + 1; msgo[4] = (LNGDAT << 6) + (wseq << 3) + rseq; for (index = 0; index < (segsiz + 1) * 32; index++) msgo[6 + index] = 0; for (index = 0; index < n; index++) msgo[6 + index] = *(s + index); cksm = MAGIC - (chksum (&msgo[6], (segsiz + 1) * 32) ^ (0377 & msgo[4])); msgo[2] = cksm; msgo[3] = cksm >> 8; msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4]; if (debugmode > 6) { printf ("T "); for (index = 0; index < (segsiz + 1) * 32 + 6; index++) printf ("%03o ", msgo[index] & 0xFF); putchar ('\n'); } do { write (fdtty, msgo, (segsiz + 1) * 32 + 6); if (inpkt ()) return (1); } while (tt != CTRL || xxx != RR || yyy != wseq); wseq = (wseq + 1) & 7; return (0); } shtput (s, n) char *s; int n; { int cksm, index; zero (msgo, 256); msgo[0] = 020; msgo[1] = segsiz + 1; msgo[4] = (SHTDAT << 6) + (wseq << 3) + rseq; for (index = 0; index < (segsiz + 1) * 32; index++) msgo[6 + index] = 0; msgo[6] = (segsiz + 1) * 32 - n; for (index = 0; index < n; index++) msgo[7 + index] = *(s + index); cksm = MAGIC - (chksum (&msgo[6], (segsiz + 1) * 32) ^ (0377 & msgo[4])); msgo[2] = cksm; msgo[3] = cksm >> 8; msgo[5] = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4]; if (debugmode > 4) { printf ("T "); for (index = 0; index < (segsiz + 1) * 32 + 6; index++) printf ("%03o ", msgo[index] & 0xFF); putchar ('\n'); } do { write (fdtty, msgo, (segsiz + 1) * 32 + 6); if (inpkt ()) return (1); } while (tt != CTRL || xxx != RR || yyy != wseq); wseq = (wseq + 1) & 7; return (0); } instr (s, n) char *s; int n; { int data, count, i, j; count = 0; if (debugmode > 4) { printf ("Expecting "); for (i = 0; i < n; i++) printf ("%03o ", *(s + i)); printf ("\nR "); } while ((data = xgetc ()) != EOF) { msgi[count++] = data & 0x7F; if (debugmode > 4) { printf ("%03o ", msgi[count - 1]); } if (count >= n) { for (i = n - 1, j = count - 1; i >= 0; i--, j--) if (*(s + i) == '*' || *(s + i) != msgi[j]) break; if (i < 0 || *(s + i) == '*') { if (debugmode > 4) { putchar ('\n'); } return (0); } } } if (debugmode > 4) { putchar ('\n'); } msgi[count] = 0; return (1); } inpkt () { int data, count, need; count = 0; if (debugmode > 4) { printf ("R "); } while ((data = xgetc ()) != EOF) { if (debugmode > 4) { printf ("%03o ", data & 0xFF); } switch (count) { case 0: if (data == 020) msgi[count++] = 020; break; case 1: msgi[count++] = data; if (data == 9) need = 4; else need = 32 * data + 4; break; case 4: tt = (data >> 6) & 3; xxx = (data >> 3) & 7; yyy = data & 7; default: msgi[count++] = data; if (!--need) { if (debugmode > 4) { putchar ('\n'); } return (0); } break; } } if (debugmode > 4) { putchar ('\n'); } return (1); } chksum (s, n) register char *s; register int n; { register short sum; register unsigned short t; register short x; sum = -1; x = 0; do { if (sum < 0) { sum <<= 1; sum++; } else sum <<= 1; t = sum; sum += *s++ & 0377; x += sum ^ n; if ((unsigned) sum <= t) sum ^= x; } while (--n > 0); return (sum); } int abort () { write (fdtty, msgo5, sizeof (msgo5) - 1); if (debugmode) { fprintf (stderr, "%s\n", msgo5); } exit (-1); } -- {decuac}!gouldsd!mjranum || {decuac}!osiris!mjranum "It is better to shred the bugger than to bugger the shredder." -ancient doltic proverb.