Path: utzoo!mnetor!uunet!husc6!cmcl2!brl-adm!brl-smoke!w8sdz From: w8sdz@brl-smoke.ARPA (Keith B. Petersen ) Newsgroups: comp.binaries.ibm.pc Subject: Zmodem for Unix and VAX/VMS (repost) part 3of3 Message-ID: <7816@brl-smoke.ARPA> Date: 3 May 88 04:18:51 GMT Reply-To: w8sdz@brl-smoke.UUCP (Keith B. Petersen (WSMR|towson) ) Followup-To: comp.binaries.ibm.pc.d Organization: Ballistic Research Lab (BRL), APG, MD. Lines: 2315 Keywords: xmodem,ymodem,zmodem,unix,vax/vms Summary: Chuck Forsberg's Zmodem now supports VAX/VMS as well as Unix This is a repost of Zmodem for Unix and VAX/VMS, by Chuck Forsberg. Sorry for the problems with the previous posting. To extract the files, use the unshar script or unshar.c program previously posted to this newsgroup. ---- Cut Here and unpack ---- #!/bin/sh # this is part 3 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file sz.c continued # CurArch=3 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file sz.c" sed 's/^X//' << 'SHAR_EOF' >> sz.c X#ifdef ONEREAD X c=read(iofd, byt, 1); /* regulus raw read is unique */ X#else X c=read(iofd, byt, count); X#endif X alarm(0); X if (Verbose>5) X fprintf(stderr, "ret cnt=%d %x %x\n", c, byt[0], byt[1]); X if (c<1) X return TIMEOUT; X if (c==1) X return (byt[0]&0377); X else X while (c) X if (byt[--c] != CAN) X return ERROR; X return CAN; X} Xreadline(n) X{ X return (readock(n, 1)); X} X Xflushmo() X{ X fflush(stdout); X} X X Xpurgeline() X{ X#ifdef USG X ioctl(iofd, TCFLSH, 0); X#else X lseek(iofd, 0L, 2); X#endif X} X#endif X X/* send cancel string to get the other end to shut up */ Xcanit() X{ X static char canistr[] = { X 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 X }; X X#ifdef vax11c X raw_wbuf(strlen(canistr), canistr); X purgeline(); X#else X printf(canistr); X fflush(stdout); X#endif X} X X X/* X * Log an error X */ X/*VARARGS1*/ Xzperr(s,p,u) Xchar *s, *p, *u; X{ X if (Verbose <= 0) X return; X fprintf(stderr, "Retry %d: ", errors); X fprintf(stderr, s, p, u); X fprintf(stderr, "\n"); X} X X/* X * substr(string, token) searches for token in string s X * returns pointer to token within string if found, NULL otherwise X */ Xchar * Xsubstr(s, t) Xregister char *s,*t; X{ X register char *ss,*tt; X /* search for first char of token */ X for (ss=s; *s; s++) X if (*s == *t) X /* compare token with substring */ X for (ss=s,tt=t; ;) { X if (*tt == 0) X return s; X if (*ss++ != *tt++) X break; X } X return NULL; X} X Xchar *babble[] = { X#ifdef vax11c X " Send file(s) with ZMODEM Protocol", X "Usage: sz [-2+abdefkLlNnquvwYy] [-] file ...", X " sz [-2Ceqv] -c COMMAND", X " \\ Force next option letter to upper case", X#else X "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol", X " (Y) = Option applies to YMODEM only", X " (Z) = Option applies to ZMODEM only", X "Usage: sz [-2+abdefkLlNnquvwYy] [-] file ...", X " sz [-2Ceqv] -c COMMAND", X " sb [-2adfkquv] [-] file ...", X " sx [-2akquv] [-] file", X#endif X#ifdef CSTOPB X " 2 Use 2 stop bits", X#endif X " + Append to existing destination file (Z)", X " a (ASCII) change NL to CR/LF", X " b Binary file transfer override", X " c send COMMAND (Z)", X#ifndef vax11c X " d Change '.' to '/' in pathnames (Y/Z)", X#endif X " e Escape all control characters (Z)", X " f send Full pathname (Y/Z)", X " i send COMMAND, ack Immediately (Z)", X " k Send 1024 byte packets (Y)", X " L N Limit subpacket length to N bytes (Z)", X " l N Limit frame length to N bytes (l>=L) (Z)", X " n send file if source newer (Z)", X " N send file if source newer or longer (Z)", X " o Use 16 bit CRC instead of 32 bit CRC (Z)", X " p Protect existing destination file (Z)", X " r Resume/Recover interrupted file transfer (Z)", X " q Quiet (no progress reports)", X#ifndef vax11c X " u Unlink file after transmission", X#endif X " v Verbose - provide debugging information", X " w N Window is N bytes (Z)", X " Y Yes, overwrite existing file, skip if not present at rx (Z)", X " y Yes, overwrite existing file (Z)", X "- as pathname sends standard input as sPID.sz or environment ONAME", X "" X}; X Xusage() X{ X char **pp; X X for (pp=babble; **pp; ++pp) X fprintf(stderr, "%s\n", *pp); X fprintf(stderr, "%s for %s by Chuck Forsberg, Omen Technology INC\n", X VERSION, OS); X fprintf(stderr, "\t\t\042The High Reliability Software\042\n"); X cucheck(); X exit(SS_NORMAL); X} X X/* X * Get the receiver's init parameters X */ Xgetzrxinit() X{ X register n; X struct stat f; X X for (n=10; --n>=0; ) { X X switch (zgethdr(Rxhdr, 1)) { X case ZCHALLENGE: /* Echo receiver's challenge numbr */ X stohdr(Rxpos); X zshhdr(ZACK, Txhdr); X continue; X case ZCOMMAND: /* They didn't see out ZRQINIT */ X stohdr(0L); X zshhdr(ZRQINIT, Txhdr); X continue; X case ZRINIT: X Rxflags = 0377 & Rxhdr[ZF0]; X Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32)); X Zctlesc |= Rxflags & TESCCTL; X Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8); X if ( !(Rxflags & CANFDX)) X Txwindow = 0; X vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen); X if ( !Fromcu) X signal(SIGINT, SIG_IGN); X#ifdef MODE2OK X mode(2); /* Set cbreak, XON/XOFF, etc. */ X#endif X#ifndef READCHECK X#ifndef USG X /* Use 1024 byte frames if no sample/interrupt */ X if (Rxbuflen < 32 || Rxbuflen > 1024) { X Rxbuflen = 1024; X vfile("Rxbuflen=%d", Rxbuflen); X } X#endif X#endif X /* Override to force shorter frame length */ X if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32)) X Rxbuflen = Tframlen; X if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024)) X Rxbuflen = Tframlen; X vfile("Rxbuflen=%d", Rxbuflen); X X#ifndef vax11c X /* If using a pipe for testing set lower buf len */ X fstat(iofd, &f); X if ((f.st_mode & S_IFMT) != S_IFCHR X && (Rxbuflen == 0 || Rxbuflen > 4096)) X Rxbuflen = 4096; X#endif X /* X * If input is not a regular file, force ACK's each 1024 X * (A smarter strategey could be used here ...) X */ X if ( !Command) { X fstat(fileno(in), &f); X if (((f.st_mode & S_IFMT) != S_IFREG) X && (Rxbuflen == 0 || Rxbuflen > 1024)) X Rxbuflen = 1024; X } X /* Set initial subpacket length */ X if (blklen < 1024) { /* Command line override? */ X if (Baudrate > 300) X blklen = 256; X if (Baudrate > 1200) X blklen = 512; X if (Baudrate > 2400) X blklen = 1024; X } X if (Rxbuflen && blklen>Rxbuflen) X blklen = Rxbuflen; X if (blkopt && blklen > blkopt) X blklen = blkopt; X vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen); X vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac); X X return (sendzsinit()); X case ZCAN: X case TIMEOUT: X return ERROR; X case ZRQINIT: X if (Rxhdr[ZF0] == ZCOMMAND) X continue; X default: X zshhdr(ZNAK, Txhdr); X continue; X } X } X return ERROR; X} X X/* Send send-init information */ Xsendzsinit() X{ X register c; X X if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL))) X return OK; X errors = 0; X for (;;) { X stohdr(0L); X if (Zctlesc) { X Txhdr[ZF0] |= TESCCTL; zshhdr(ZSINIT, Txhdr); X } X else X zsbhdr(ZSINIT, Txhdr); X zsdata(Myattn, 1+strlen(Myattn), ZCRCW); X c = zgethdr(Rxhdr, 1); X switch (c) { X case ZCAN: X return ERROR; X case ZACK: X return OK; X default: X if (++errors > 19) X return ERROR; X continue; X } X } X} X X/* Send file name and related info */ Xzsendfile(buf, blen) Xchar *buf; X{ X register c; X X for (;;) { X Txhdr[ZF0] = Lzconv; /* file conversion request */ X Txhdr[ZF1] = Lzmanag; /* file management request */ X if (Lskipnocor) X Txhdr[ZF1] |= ZMSKNOLOC; X Txhdr[ZF2] = Lztrans; /* file transport request */ X Txhdr[ZF3] = 0; X zsbhdr(ZFILE, Txhdr); X zsdata(buf, blen, ZCRCW); Xagain: X c = zgethdr(Rxhdr, 1); X switch (c) { X case ZRINIT: X while ((c = readline(50)) > 0) X if (c == ZPAD) { X goto again; X } X /* **** FALL THRU TO **** */ X default: X continue; X case ZCAN: X case TIMEOUT: X case ZABORT: X case ZFIN: X return ERROR; X case ZSKIP: X fclose(in); return c; X case ZRPOS: X /* X * Suppress zcrcw request otherwise triggered by X * lastyunc==bytcnt X */ X Lastsync = (bytcnt = Txpos = Rxpos) -1; X fseek(in, Rxpos, 0); X Dontread = FALSE; X return zsendfdata(); X } X } X} X X/* Send the data in the file */ Xzsendfdata() X{ X register c, e, n; X register newcnt; X register long tcount = 0; X int junkcount; /* Counts garbage chars received by TX */ X static int tleft = 6; /* Counter for test mode */ X X Lrxpos = 0; X junkcount = 0; X Beenhereb4 = FALSE; Xsomemore: X if (setjmp(intrjmp)) { Xwaitack: X junkcount = 0; X c = getinsync(0); Xgotack: X switch (c) { X default: X case ZCAN: X fclose(in); X return ERROR; X case ZSKIP: X fclose(in); X return c; X case ZACK: X case ZRPOS: X break; X case ZRINIT: X return OK; X } X#ifdef READCHECK X /* X * If the reverse channel can be tested for data, X * this logic may be used to detect error packets X * sent by the receiver, in place of setjmp/longjmp X * rdchk(fdes) returns non 0 if a character is available X */ X while (rdchk(iofd)) { X#ifdef SV X switch (checked) X#else X switch (readline(1)) X#endif X { X case CAN: X case ZPAD: X c = getinsync(1); X goto gotack; X case XOFF: /* Wait a while for an XON */ X case XOFF|0200: X readline(100); X } X } X#endif X } X X if ( !Fromcu) X signal(SIGINT, onintr); X newcnt = Rxbuflen; X Txwcnt = 0; X stohdr(Txpos); X zsbhdr(ZDATA, Txhdr); X X /* X * Special testing mode. This should force receiver to Attn,ZRPOS X * many times. Each time the signal should be caught, causing the X * file to be started over from the beginning. X */ X if (Test) { X if ( --tleft) X while (tcount < 20000) { X printf(qbf); fflush(stdout); X tcount += strlen(qbf); X#ifdef READCHECK X while (rdchk(iofd)) { X#ifdef SV X switch (checked) X#else X switch (readline(1)) X#endif X { X case CAN: X case ZPAD: X#ifdef TCFLSH X ioctl(iofd, TCFLSH, 1); X#endif X goto waitack; X case XOFF: /* Wait for XON */ X case XOFF|0200: X readline(100); X } X } X#endif X } X signal(SIGINT, SIG_IGN); canit(); X sleep(3); purgeline(); mode(0); X printf("\nsz: Tcount = %ld\n", tcount); X if (tleft) { X printf("ERROR: Interrupts Not Caught\n"); X exit(1); X } X exit(SS_NORMAL); X } X X do { X if (Dontread) { X n = Lastn; X } else { X n = zfilbuf(txbuf, blklen); X Lastread = Txpos; Lastn = n; X } X Dontread = FALSE; X if (n < blklen) X e = ZCRCE; X else if (junkcount > 3) X e = ZCRCW; X else if (bytcnt == Lastsync) X e = ZCRCW; X else if (Rxbuflen && (newcnt -= n) <= 0) X e = ZCRCW; X else if (Txwindow && (Txwcnt += n) >= Txwspac) { X Txwcnt = 0; e = ZCRCQ; X } X else X e = ZCRCG; X if (Verbose>1) X fprintf(stderr, "\r%7ld ZMODEM%s ", X Txpos, Crc32t?" CRC-32":""); X zsdata(txbuf, n, e); X bytcnt = Txpos += n; X if (e == ZCRCW) X goto waitack; X#ifdef READCHECK X /* X * If the reverse channel can be tested for data, X * this logic may be used to detect error packets X * sent by the receiver, in place of setjmp/longjmp X * rdchk(fdes) returns non 0 if a character is available X */ X fflush(stdout); X while (rdchk(iofd)) { X#ifdef SV X switch (checked) X#else X switch (readline(1)) X#endif X { X case CAN: X case ZPAD: X c = getinsync(1); X if (c == ZACK) X break; X#ifdef TCFLSH X ioctl(iofd, TCFLSH, 1); X#endif X /* zcrce - dinna wanna starta ping-pong game */ X zsdata(txbuf, 0, ZCRCE); X goto gotack; X case XOFF: /* Wait a while for an XON */ X case XOFF|0200: X readline(100); X default: X ++junkcount; X } X } X#endif /* READCHECK */ X if (Txwindow) { X while ((tcount = Txpos - Lrxpos) >= Txwindow) { X vfile("%ld window >= %u", tcount, Txwindow); X if (e != ZCRCQ) X zsdata(txbuf, 0, e = ZCRCQ); X c = getinsync(1); X if (c != ZACK) { X#ifdef TCFLSH X ioctl(iofd, TCFLSH, 1); X#endif X zsdata(txbuf, 0, ZCRCE); X goto gotack; X } X } X vfile("window = %ld", tcount); X } X } while (n == blklen); X if ( !Fromcu) X signal(SIGINT, SIG_IGN); X X for (;;) { X stohdr(Txpos); X zsbhdr(ZEOF, Txhdr); X switch (getinsync(0)) { X case ZACK: X continue; X case ZRPOS: X goto somemore; X case ZRINIT: X return OK; X case ZSKIP: X fclose(in); X return c; X default: X fclose(in); X return ERROR; X } X } X} X X/* X * Respond to receiver's complaint, get back in sync with receiver X */ Xgetinsync(flag) X{ X register c; X X for (;;) { X if (Test) { X printf("\r\n\n\n***** Signal Caught *****\r\n"); X Rxpos = 0; c = ZRPOS; X } else X c = zgethdr(Rxhdr, 0); X switch (c) { X case ZCAN: X case ZABORT: X case ZFIN: X case TIMEOUT: X return ERROR; X case ZRPOS: X /* ************************************* */ X /* If sending to a modem beuufer, you */ X /* might send a break at this point to */ X /* dump the modem's buffer. */ X if (Lastn >= 0 && Lastread == Rxpos) { X Dontread = TRUE; X } else { X clearerr(in); /* In case file EOF seen */ X fseek(in, Rxpos, 0); X } X bytcnt = Lrxpos = Txpos = Rxpos; X if (Lastsync == Rxpos) { X if (++Beenhereb4 > 4) X if (blklen > 32) X blklen /= 2; X } X Lastsync = Rxpos; X return c; X case ZACK: X Lrxpos = Rxpos; X if (flag || Txpos == Rxpos) X return ZACK; X continue; X case ZRINIT: X case ZSKIP: X fclose(in); X return c; X case ERROR: X default: X zsbhdr(ZNAK, Txhdr); X continue; X } X } X} X X X/* Say "bibi" to the receiver, try to do it cleanly */ Xsaybibi() X{ X for (;;) { X stohdr(0L); /* CAF Was zsbhdr - minor change */ X zshhdr(ZFIN, Txhdr); /* to make debugging easier */ X switch (zgethdr(Rxhdr, 0)) { X case ZFIN: X sendline('O'); sendline('O'); flushmo(); X case ZCAN: X case TIMEOUT: X return; X } X } X} X X/* Local screen character display function */ Xbttyout(c) X{ X if (Verbose) X putc(c, stderr); X} X X/* Send command and related info */ Xzsendcmd(buf, blen) Xchar *buf; X{ X register c; X long cmdnum; X X cmdnum = getpid(); X errors = 0; X for (;;) { X stohdr(cmdnum); X Txhdr[ZF0] = Cmdack1; X zsbhdr(ZCOMMAND, Txhdr); X zsdata(buf, blen, ZCRCW); Xlisten: X Rxtimeout = 100; /* Ten second wait for resp. */ X c = zgethdr(Rxhdr, 1); X X switch (c) { X case ZRINIT: X goto listen; /* CAF 8-21-87 */ X case ERROR: X case TIMEOUT: X if (++errors > Cmdtries) X return ERROR; X continue; X case ZCAN: X case ZABORT: X case ZFIN: X case ZSKIP: X case ZRPOS: X return ERROR; X default: X if (++errors > 20) X return ERROR; X continue; X case ZCOMPL: X Exitcode = Rxpos; X saybibi(); X return OK; X case ZRQINIT: X#ifdef vax11c /* YAMP :== Yet Another Missing Primitive */ X return ERROR; X#else X vfile("******** RZ *******"); X system("rz"); X vfile("******** SZ *******"); X goto listen; X#endif X } X } X} X X/* X * If called as sb use YMODEM protocol X */ Xchkinvok(s) Xchar *s; X{ X#ifdef vax11c X Progname = "sz"; X#else X register char *p; X X p = s; X while (*p == '-') X s = ++p; X while (*p) X if (*p++ == '/') X s = p; X if (*s == 'v') { X Verbose=1; ++s; X } X Progname = s; X if (s[0]=='s' && s[1]=='b') { X Nozmodem = TRUE; blklen=1024; X } X if (s[0]=='s' && s[1]=='x') { X Modem2 = TRUE; X } X#endif X} X Xcountem(argc, argv) Xregister char **argv; X{ X register c; X struct stat f; X X for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) { X f.st_size = -1; X if (Verbose>2) { X fprintf(stderr, "\nCountem: %03d %s ", argc, *argv); X fflush(stderr); X } X if (access(*argv, 04) >= 0 && stat(*argv, &f) >= 0) { X c = f.st_mode & S_IFMT; X if (c != S_IFDIR && c != S_IFBLK) { X ++Filesleft; Totalleft += f.st_size; X } X } X if (Verbose>2) X fprintf(stderr, " %ld", f.st_size); X } X if (Verbose>2) X fprintf(stderr, "\ncountem: Total %d %ld\n", X Filesleft, Totalleft); X} X Xchartest(m) X{ X register n; X X mode(m); X printf("\r\n\nCharacter Transparency Test Mode %d\r\n", m); X printf("If Pro-YAM/ZCOMM is not displaying ^M hit ALT-V NOW.\r\n"); X printf("Hit Enter.\021"); fflush(stdout); X readline(500); X X for (n = 0; n < 256; ++n) { X if (!(n%8)) X printf("\r\n"); X printf("%02x ", n); fflush(stdout); X sendline(n); flushmo(); X printf(" "); fflush(stdout); X if (n == 127) { X printf("Hit Enter.\021"); fflush(stdout); X readline(500); X printf("\r\n"); fflush(stdout); X } X } X printf("\021\r\nEnter Characters, echo is in hex.\r\n"); X printf("Hit SPACE or pause 40 seconds for exit.\r\n"); X X while (n != TIMEOUT && n != ' ') { X n = readline(400); X printf("%02x\r\n", n); X fflush(stdout); X } X printf("\r\nMode %d character transparency test ends.\r\n", m); X fflush(stdout); X} X/* End of sz.c */ SHAR_EOF echo "File sz.c is complete" chmod 0644 sz.c || echo "restore of sz.c fails" echo "x - extracting vmodem.h (Text)" sed 's/^X//' << 'SHAR_EOF' > vmodem.h && X/* X * VMODEM.H X * VMS support for UMODEM program X * X * #INCLUDE files defining structures associated with terminal X * information structure TT_INFO. X * Information about the terminal is passed around in UMODEM in a X * STRUCT TT_INFO. X * X * Walter Reiher X * Harvard University X * Department of Chemistry X * 12 Oxford Street X * Cambridge, MA 02138 X * March 10, 1983 X */ X Xstruct tt_mode /* Info for a IO$_SETMODE call */ X{ X char class; X char type; X short page_width; X char bcharacteristics[3]; X char page_length; X int echaracteristics; X}; X Xstruct tt_mode_iosb /* Terminal IO$_SENSEMODE IOSB */ X{ X short status; X char t_speed; X char r_speed; X char CR_fill; X char LF_fill; X char parity_flags; X char unused2; X}; X Xstruct tt_info /* Summary of terminal infomation */ X{ X struct tt_mode dev_characteristics; X struct tt_mode_iosb dev_modes; X}; SHAR_EOF chmod 0644 vmodem.h || echo "restore of vmodem.h fails" echo "x - extracting vrzsz.c (Text)" sed 's/^X//' << 'SHAR_EOF' > vrzsz.c && X#include "vmodem.h" X#include ssdef X#include tt2def X#include ttdef X#define SS_NORMAL SS$_NORMAL X X/* VMS structures */ X/* X * TT_INFO structures are used for passing information about X * the terminal. Used in GTTY and STTY calls. X */ Xstruct tt_info ttys, ttysnew, ttystemp; X X/* X * X */ X X/* X * return 1 iff stdout and stderr are different devices X * indicating this program operating with a modem on a X * different line X */ Xint Fromcu; /* Were called from cu or yam */ Xfrom_cu() X{ X} Xcucheck() X{ X} X X X X/* X * mode(n) X * 3: save old tty stat, set raw mode with flow control X * 2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g X * 1: save old tty stat, set raw mode X * 0: restore original tty mode X */ Xmode(n) X{ X int *iptr, parameters; X static savedmodes = FALSE; X X vfile("mode:%d", n); X X if (!savedmodes) { X if (gtty(&ttys) != SS$_NORMAL) X death("SETMODES: error return from GTTY (1)"); X if (gtty(&ttysnew) != SS$_NORMAL) X death("SETMODES: error return from GTTY (2)"); X savedmodes = TRUE; X } X X /* X * Set new terminal parameters. X * Note: there are three bytes of terminal characteristics, X * so we should make sure the fourth byte of the integer is unchanged. X */ X switch (n) { X case 1: X case 2: X case 3: X iptr = &(ttysnew.dev_characteristics.bcharacteristics); X parameters = *iptr; X X parameters &= ~TT$M_ESCAPE; /* ESCAPE OFF */ X parameters &= ~TT$M_HOSTSYNC; /* HOSTSYNC OFF */ X parameters |= TT$M_NOECHO; /* NOECHO ON */ X parameters |= TT$M_PASSALL; /* PASSALL ON */ X parameters &= ~TT$M_READSYNC; /* READSYNC OFF */ X parameters &= ~TT$M_TTSYNC; /* TTSYNC OFF */ X parameters &= ~TT$M_WRAP; /* WRAP OFF */ X parameters |= TT$M_EIGHTBIT; /* EIGHTBIT ON */ X if (n == 3) { X parameters |= TT$M_HOSTSYNC; /* HOSTSYNC On */ X } X if (n == 2) { X parameters |= TT$M_TTSYNC; /* TTSYNC On */ X } X X *iptr = parameters; X X if (stty(&ttysnew) != SS_NORMAL) X fatal("SETMODES: error return from STTY"); X break; X case 0: X stty(&ttys); /* Restore original modes */ X /* error return to /dev/null */ X break; X } X} X X X X/* set tty modes for vrzsz transfers */ Xsetmodes() X{ X/* Device characteristics for VMS */ X} X Xfatal(msg) Xchar *msg; X{ X mode(0); /* put back normal tty modes */ X printf("vrzsz: %s\n", msg); X exit(SS_NORMAL); X} X X/* Call this instead if funny modes haven't been set yet */ Xdeath(msg) Xchar *msg; X{ X printf("vrzsz: %s\n", msg); X exit(SS_NORMAL); X} X X#define LSIZE 64 /* Size of send & receive buffers */ X#ifdef BUFREAD X Xchar Rxlbuf[LSIZE+1]; Xint Rxleft=0; /* number of characters in Rxlbuf */ Xchar *Rxcdq = Rxlbuf; /* pointer for removing chars from Rxlbuf */ X X/* X * This version of readline is reasoably well suited for X * reading many characters. X * X * timeout is in tenths of seconds X */ X Xreadline(timeout) Xint timeout; X{ X register int c; X extern errno; X X if (--Rxleft>=0) X return (*Rxcdq++ & 0377); X#ifdef DEBUGG X eprintf("Calling read: "); X#endif X if ((c = timeout/10)<2) X c=2; X X do { X Rxleft = raw_read(LSIZE, Rxcdq=Rxlbuf, 1); X } while (Rxleft == SS$_TIMEOUT && --c >= 0); X#ifdef DEBUGG X eprintf("Read returned %d bytes\n", Rxleft); X#endif X if (Rxleft == SS$_TIMEOUT || --Rxleft < 0) { X Rxleft = 0; X return TIMEOUT; X } X return (*Rxcdq++ & 0377); X} X Xreadock(c, t) X{ X return(readline(t)); X} X X Xpurgeline() X{ X Rxleft=0; X} X X X#else /* BUFREAD */ X Xreadock(c, t) X{ X return readline(t); X} X X/* get a byte from data stream -- timeout if "dseconds" elapses */ X/* NOTE, however, that this function returns an INT, not a BYTE!!! */ Xreadline(dseconds) X{ X int seconds; X int ret, c; X X seconds = dseconds/10; X if (seconds < 2) X seconds = 2; X ret = raw_read(1, &c, seconds); X X if (ret == SS$_TIMEOUT) X return(TIMEOUT); X X return(c & 0377); /* return the char */ X} X Xpurgeline() X{ X int c; X X do { X c = readline(1); X } while (c != TIMEOUT); X} X#endif X X X#ifdef BUFWRITE Xchar Txlbuf[LSIZE+1]; Xint Txleft=LSIZE; /* number of characters in Txlbuf */ Xchar *Txcq = Txlbuf; /* pointer for removing chars from Rxlbuf */ X Xsendline(c) X{ X if (--Txleft >= 0) X *Txcq++ = c; X else { X Txleft = 0; X flushmoc(); X --Txleft; X *Txcq++ = c; X } X} X Xflushmoc() X{ X register int n; X X n = LSIZE - Txleft; X Txcq=Txlbuf; Txleft = LSIZE; X raw_wbuf(n, Txlbuf); X} X X/* X * Wait for the modem line outbuffer to drain X */ Xflushmo() X{ X fflush(stdout); X flushmoc(); X} X X#else /* BUFWRITE */ X X/* send a byte to data stream */ Xsendline(data) X{ X char dataout; X X dataout = data; X raw_write(dataout); X X} X Xflushmo() {} Xflushmoc() {} X#endif X Xsendbrk() X{ X} X X X/* End of vrzsz.c */ SHAR_EOF chmod 0644 vrzsz.c || echo "restore of vrzsz.c fails" echo "x - extracting vvmodem.c (Text)" sed 's/^X//' << 'SHAR_EOF' > vvmodem.c && X/* X * VMODEM X * VMS support for UMODEM and vvrb/vvsb programs X * X * Defined herein are some utility routines to make the UNIX X * program UMODEM run under VAX/VMS C: X * X * assign_channel Calls the VMS System Service $ASSIGN X * to assign a channel to a device. X * The routine currently has the device X * "TT" hardwired into it. X * gtty Gets terminal characteristics, almost X * like the UNIX GTTY system call. X * raw_read Reads characters from the terminal X * without any echoing or interpretation X * and with an optional timeout period. X * raw_write Writes a character to the terminal X * without any interpretation. X * raw_wbuf Writes a buffer to the terminal X * without any interpretation. X * stty Sets terminal characteristics, almost X * like the UNIX STTY system call. X * X * Some of the ideas used here were obtained from code written X * by Max Benson and Robert Bruccoleri. X * X * Walter Reiher X * Harvard University X * Department of Chemistry X * 12 Oxford Street X * Cambridge, MA 02138 X * March 11, 1983 X * X * Modified 4-20-88 Chuck Forsberg, Omen Technology INC X * 17505-V NW Sauvie IS RD Portland OR 97231 omen!caf X * Added primitives for for ZMODEM use. X */ X#include descrip X#include iodef X#include rms X#include ssdef X#include stdio X#include "vmodem.h" X X#define TRUE 1 X#define FALSE 0 X Xstatic char tt_name[] = "TT"; Xstatic short tt_chan = -1; /* Terminal channel number */ X Xstruct tt_io_iosb /* Terminal I/O IOSB */ X{ X short status; X short byte_count; X short terminator; X short terminator_size; X}; X X Xstruct tt_io_tacf /* Terminal I/O type ahead */ X{ X short byte_count; X char firstchar; X char something; X short whatever; X}; X X/* X * Terminator mask for PASSALL reads. X * Permits reads of all possible 8-bit characters. X */ Xint t_mask[32] = { X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, X 0, 0 }; X Xstruct terminator_mask { X short size ; X short unused ; X int *mask ; X} X Xtermin_mask = { 32, 0, t_mask }; X X/* X * ASSIGN a channel to the logical name TT, which is usually X * the terminal. X */ Xassign_channel() X{ X int status; X $DESCRIPTOR(tt_descriptor, tt_name); X X if (tt_chan == -1) X status = sys$assign(&tt_descriptor, &tt_chan, 0, 0); X else X status = SS$_NORMAL; X X if (status != SS$_NORMAL || tt_chan == -1) X fatal("ASSIGN_CHANNEL: error in SYS$ASSIGN\n"); X X return; X} X X/* X * Gets terminal information from VMS. X */ Xgtty(tt_characteristics) Xstruct tt_info *tt_characteristics; X{ X int c; X int status; X extern unsigned Baudrate; X int speeds[] = { 2400, 50, 75, 110, 134, 150, 300, 600, 1200, 1800, X 2000, 2400, 3600, 4800, 7200, 9600, 19200 }; X X if (tt_chan == -1) X assign_channel(); X X status = sys$qiow(0, tt_chan, IO$_SENSEMODE, X &(tt_characteristics->dev_modes), NULL, 0, X &(tt_characteristics->dev_characteristics), 12, X 0, 0, 0, 0); X if (status != SS$_NORMAL || X tt_characteristics->dev_modes.status != SS$_NORMAL) X fatal("GTTY: sense mode QIO error return.\n"); X X c = tt_characteristics.dev_modes.t_speed % 17; X Baudrate = speeds[c]; X X return(status); X} X X/* X * Return the number of characters waiting in TTY input buffer X */ Xrdchk() X{ X int status; X struct tt_io_iosb iosb; X struct tt_io_tacf typeahead; X X status = sys$qiow(0, tt_chan, IO$_SENSEMODE|IO$M_TYPEAHDCNT, X &iosb, NULL, 0, X &typeahead, 0, X 0, 0, 0, 0); X X return(typeahead.byte_count); X} X X/* X * Read NCHAR characters from the terminal without echoing or X * interpretation. X * If the argument SECONDS is non-zero, use that as the X * timeout period in seconds for the read. X * X * Returns SS$_TIMEOUT in case of timeout or other error. X * Otherwise, returns the number of characters read. X */ Xraw_read(nchar, charbuf, seconds) Xchar *charbuf; Xint nchar; Xunsigned seconds; X{ X short function; X int status; X struct tt_io_iosb iosb; X X if (tt_chan == -1) X assign_channel(); X X function = IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR; X X if (seconds) X status = sys$qiow(0, tt_chan, function | IO$M_TIMED, X &iosb, NULL, 0, X charbuf, nchar, seconds, X &termin_mask, NULL, 0); X else X status = sys$qiow(0, tt_chan, function, X &iosb, NULL, 0, X charbuf, nchar, 0, X &termin_mask, NULL, 0); X X if (iosb.byte_count) X return iosb.byte_count; X return SS$_TIMEOUT; X} X X/* X * Writes a character to the terminal without echoing or X * interpretation. X */ Xraw_write(c) Xchar c; X{ X int status; X struct tt_io_iosb iosb; X X if (tt_chan == -1) X assign_channel(); X X status = sys$qiow(0, tt_chan, X IO$_WRITEVBLK | IO$M_CANCTRLO | IO$M_NOFORMAT, X &iosb, NULL, 0, X &c, 1, 0, 0, 0, 0); X X if (status != SS$_NORMAL || iosb.status != SS$_NORMAL) X fatal("RAW_WRITE: write QIO error return.\n"); X X return; X} X X/* X * Writes a buffer to the terminal without echoing or X * interpretation. X */ Xraw_wbuf(nchar, charbuf) Xchar *charbuf; Xint nchar; X{ X int status; X struct tt_io_iosb iosb; X X if (tt_chan == -1) X assign_channel(); X X status = sys$qiow(0, tt_chan, X IO$_WRITEVBLK | IO$M_CANCTRLO | IO$M_NOFORMAT, X &iosb, NULL, 0, X charbuf, nchar, 0, 0, 0, 0); X X if (status != SS$_NORMAL || iosb.status != SS$_NORMAL) X fatal("RAW_WRITE: write QIO error return.\n"); X X return; X} X X/* X * Sets terminal information from VMS. X * Modified 12-85 Larry Farr/Chuck Forsberg to not use X * bad parity returned by VMS 4. X */ Xstty(tt_characteristics) Xstruct tt_info *tt_characteristics; X{ X short *f_ptr, /* *p_ptr, */ *s_ptr; X int status; X struct tt_mode_iosb iosb; X X if (tt_chan == -1) X assign_channel(); X X/* X * We do the following in order to get a full short, concatenating X * two adjacent chars: X */ X s_ptr = &(tt_characteristics->dev_modes.t_speed); /* Speeds */ X f_ptr = &(tt_characteristics->dev_modes.CR_fill); /* Fills */ X /* p_ptr = &(tt_characteristics->dev_modes.parity_flags); */ X X status = sys$qiow(0, tt_chan, IO$_SETMODE, X &iosb, NULL, 0, X &(tt_characteristics->dev_characteristics), 12, X /* *s_ptr, *f_ptr, *p_ptr, 0); */ X *s_ptr, *f_ptr, 0, 0); X if (status != SS$_NORMAL || iosb.status != SS$_NORMAL) X printf("STTY: set mode QIO returned %d\n", status); X X return(status); X} X SHAR_EOF chmod 0644 vvmodem.c || echo "restore of vvmodem.c fails" echo "x - extracting zm.c (Text)" sed 's/^X//' << 'SHAR_EOF' > zm.c && X/* X * Z M . C X * ZMODEM protocol primitives X * 11-10-87 Chuck Forsberg Omen Technology Inc X * X * Entry point Functions: X * zsbhdr(type, hdr) send binary header X * zshhdr(type, hdr) send hex header X * zgethdr(hdr, eflag) receive header - binary or hex X * zsdata(buf, len, frameend) send data X * zrdata(buf, len) receive data X * stohdr(pos) store position data in Txhdr X * long rclhdr(hdr) recover position offset from header X */ X X#ifndef CANFDX X#include "zmodem.h" Xint Rxtimeout = 100; /* Tenths of seconds to wait for something */ X#endif X X#ifndef UNSL X#define UNSL X#endif X X X/* Globals used by ZMODEM functions */ Xint Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame received */ Xint Rxtype; /* Type of header received */ Xint Rxcount; /* Count of data bytes received */ Xchar Rxhdr[4]; /* Received header */ Xchar Txhdr[4]; /* Transmitted header */ Xlong Rxpos; /* Received file position */ Xlong Txpos; /* Transmitted file position */ Xint Txfcs32; /* TURE means send binary frames with 32 bit FCS */ Xint Crc32t; /* Display flag indicating 32 bit CRC being sent */ Xint Crc32; /* Display flag indicating 32 bit CRC being received */ Xint Znulls; /* Number of nulls to send at beginning of ZDATA hdr */ Xchar Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */ X Xstatic lastsent; /* Last char we sent */ Xstatic evenp; /* Even parity seen on header */ X Xstatic char *frametypes[] = { X "Carrier Lost", /* -3 */ X "TIMEOUT", /* -2 */ X "ERROR", /* -1 */ X#define FTOFFSET 3 X "ZRQINIT", X "ZRINIT", X "ZSINIT", X "ZACK", X "ZFILE", X "ZSKIP", X "ZNAK", X "ZABORT", X "ZFIN", X "ZRPOS", X "ZDATA", X "ZEOF", X "ZFERR", X "ZCRC", X "ZCHALLENGE", X "ZCOMPL", X "ZCAN", X "ZFREECNT", X "ZCOMMAND", X "ZSTDERR", X "xxxxx" X#define FRTYPES 22 /* Total number of frame types in this array */ X /* not including psuedo negative entries */ X}; X Xstatic char masked[] = "8 bit transparent path required"; Xstatic char badcrc[] = "Bad CRC"; X X/* Send ZMODEM binary header hdr of type type */ Xzsbhdr(type, hdr) Xregister char *hdr; X{ X register int n; X register unsigned short crc; X X vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr)); X if (type == ZDATA) X for (n = Znulls; --n >=0; ) X xsendline(0); X X xsendline(ZPAD); xsendline(ZDLE); X X if (Crc32t=Txfcs32) X zsbh32(hdr, type); X else { X xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0); X X for (n=4; --n >= 0; ++hdr) { X zsendline(*hdr); X crc = updcrc((0377& *hdr), crc); X } X crc = updcrc(0,updcrc(0,crc)); X zsendline(crc>>8); X zsendline(crc); X } X if (type != ZDATA) X flushmo(); X} X X X/* Send ZMODEM binary header hdr of type type */ Xzsbh32(hdr, type) Xregister char *hdr; X{ X register int n; X register UNSL long crc; X X xsendline(ZBIN32); zsendline(type); X crc = 0xFFFFFFFFL; crc = UPDC32(type, crc); X X for (n=4; --n >= 0; ++hdr) { X crc = UPDC32((0377 & *hdr), crc); X zsendline(*hdr); X } X crc = ~crc; X for (n=4; --n >= 0;) { X zsendline((int)crc); X crc >>= 8; X } X} X X/* Send ZMODEM HEX header hdr of type type */ Xzshhdr(type, hdr) Xregister char *hdr; X{ X register int n; X register unsigned short crc; X X vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr)); X sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX); X zputhex(type); X Crc32t = 0; X X crc = updcrc(type, 0); X for (n=4; --n >= 0; ++hdr) { X zputhex(*hdr); crc = updcrc((0377 & *hdr), crc); X } X crc = updcrc(0,updcrc(0,crc)); X zputhex(crc>>8); zputhex(crc); X X /* Make it printable on remote machine */ X sendline(015); sendline(012); X /* X * Uncork the remote in case a fake XOFF has stopped data flow X */ X if (type != ZFIN && type != ZACK) X sendline(021); X flushmo(); X} X X/* X * Send binary array buf of length length, with ending ZDLE sequence frameend X */ Xstatic char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"}; Xzsdata(buf, length, frameend) Xregister char *buf; X{ X register unsigned short crc; X X vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]); X if (Crc32t) X zsda32(buf, length, frameend); X else { X crc = 0; X for (;--length >= 0; ++buf) { X zsendline(*buf); crc = updcrc((0377 & *buf), crc); X } X xsendline(ZDLE); xsendline(frameend); X crc = updcrc(frameend, crc); X X crc = updcrc(0,updcrc(0,crc)); X zsendline(crc>>8); zsendline(crc); X } X if (frameend == ZCRCW) { X xsendline(XON); flushmo(); X } X} X Xzsda32(buf, length, frameend) Xregister char *buf; X{ X register int c; X register UNSL long crc; X X crc = 0xFFFFFFFFL; X for (;--length >= 0; ++buf) { X c = *buf & 0377; X if (c & 0140) X xsendline(lastsent = c); X else X zsendline(c); X crc = UPDC32(c, crc); X } X xsendline(ZDLE); xsendline(frameend); X crc = UPDC32(frameend, crc); X X crc = ~crc; X for (length=4; --length >= 0;) { X zsendline((int)crc); crc >>= 8; X } X} X X/* X * Receive array buf of max length with ending ZDLE sequence X * and CRC. Returns the ending character or error code. X * NB: On errors may store length+1 bytes! X */ Xzrdata(buf, length) Xregister char *buf; X{ X register int c; X register unsigned short crc; X register char *end; X register int d; X X if (Rxframeind == ZBIN32) X return zrdat32(buf, length); X X crc = Rxcount = 0; end = buf + length; X while (buf <= end) { X if ((c = zdlread()) & ~0377) { Xcrcfoo: X switch (c) { X case GOTCRCE: X case GOTCRCG: X case GOTCRCQ: X case GOTCRCW: X crc = updcrc((d=c)&0377, crc); X if ((c = zdlread()) & ~0377) X goto crcfoo; X crc = updcrc(c, crc); X if ((c = zdlread()) & ~0377) X goto crcfoo; X crc = updcrc(c, crc); X if (crc & 0xFFFF) { X zperr(badcrc); X return ERROR; X } X Rxcount = length - (end - buf); X vfile("zrdata: %d %s", Rxcount, X Zendnames[d-GOTCRCE&3]); X return d; X case GOTCAN: X zperr("Sender Canceled"); X return ZCAN; X case TIMEOUT: X zperr("TIMEOUT"); X return c; X default: X zperr("Bad data subpacket"); X return c; X } X } X *buf++ = c; X crc = updcrc(c, crc); X } X zperr("Data subpacket too long"); X return ERROR; X} X Xzrdat32(buf, length) Xregister char *buf; X{ X register int c; X register UNSL long crc; X register char *end; X register int d; X X crc = 0xFFFFFFFFL; Rxcount = 0; end = buf + length; X while (buf <= end) { X if ((c = zdlread()) & ~0377) { Xcrcfoo: X switch (c) { X case GOTCRCE: X case GOTCRCG: X case GOTCRCQ: X case GOTCRCW: X d = c; c &= 0377; X crc = UPDC32(c, crc); X if ((c = zdlread()) & ~0377) X goto crcfoo; X crc = UPDC32(c, crc); X if ((c = zdlread()) & ~0377) X goto crcfoo; X crc = UPDC32(c, crc); X if ((c = zdlread()) & ~0377) X goto crcfoo; X crc = UPDC32(c, crc); X if ((c = zdlread()) & ~0377) X goto crcfoo; X crc = UPDC32(c, crc); X if (crc != 0xDEBB20E3) { X zperr(badcrc); X return ERROR; X } X Rxcount = length - (end - buf); X vfile("zrdat32: %d %s", Rxcount, X Zendnames[d-GOTCRCE&3]); X return d; X case GOTCAN: X zperr("Sender Canceled"); X return ZCAN; X case TIMEOUT: X zperr("TIMEOUT"); X return c; X default: X zperr("Bad data subpacket"); X return c; X } X } X *buf++ = c; X crc = UPDC32(c, crc); X } X zperr("Data subpacket too long"); X return ERROR; X} X X X/* X * Read a ZMODEM header to hdr, either binary or hex. X * eflag controls local display of non zmodem characters: X * 0: no display X * 1: display printing characters only X * 2: display all non ZMODEM characters X * On success, set Zmodem to 1, set Rxpos and return type of header. X * Otherwise return negative on error. X * Return ERROR instantly if ZCRCW sequence, for fast error recovery. X */ Xzgethdr(hdr, eflag) Xchar *hdr; X{ X register int c, n, cancount; X X n = Zrwindow + Baudrate; /* Max bytes before start of frame */ X Rxframeind = Rxtype = 0; X Xstartover: X cancount = 5; Xagain: X /* Return immediate ERROR if ZCRCW sequence seen */ X switch (c = readline(Rxtimeout)) { X case RCDO: X case TIMEOUT: X goto fifi; X case CAN: Xgotcan: X if (--cancount <= 0) { X c = ZCAN; goto fifi; X } X switch (c = readline(1)) { X case TIMEOUT: X goto again; X case ZCRCW: X c = ERROR; X /* **** FALL THRU TO **** */ X case RCDO: X goto fifi; X default: X break; X case CAN: X if (--cancount <= 0) { X c = ZCAN; goto fifi; X } X goto again; X } X /* **** FALL THRU TO **** */ X default: Xagn2: X if ( --n == 0) { X zperr("Garbage count exceeded"); X return(ERROR); X } X if (eflag && ((c &= 0177) & 0140)) X bttyout(c); X else if (eflag > 1) X bttyout(c); X#ifdef UNIX X fflush(stderr); X#endif X goto startover; X case ZPAD|0200: /* This is what we want. */ X case ZPAD: /* This is what we want. */ X evenp = c & 0200; X break; X } X cancount = 5; Xsplat: X switch (c = noxrd7()) { X case ZPAD: X goto splat; X case RCDO: X case TIMEOUT: X goto fifi; X default: X goto agn2; X case ZDLE: /* This is what we want. */ X break; X } X X switch (c = noxrd7()) { X case RCDO: X case TIMEOUT: X goto fifi; X case ZBIN: X Rxframeind = ZBIN; Crc32 = FALSE; X c = zrbhdr(hdr); X break; X case ZBIN32: X Crc32 = Rxframeind = ZBIN32; X c = zrbhdr32(hdr); X break; X case ZHEX: X Rxframeind = ZHEX; Crc32 = FALSE; X c = zrhhdr(hdr); X break; X case CAN: X goto gotcan; X default: X goto agn2; X } X Rxpos = hdr[ZP3] & 0377; X Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377); X Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377); X Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377); Xfifi: X switch (c) { X case GOTCAN: X c = ZCAN; X /* **** FALL THRU TO **** */ X case ZNAK: X case ZCAN: X case ERROR: X case TIMEOUT: X case RCDO: X zperr("Got %s", frametypes[c+FTOFFSET]); X /* **** FALL THRU TO **** */ X default: X if (c >= -3 && c <= FRTYPES) X vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos); X else X vfile("zgethdr: %d %lx", c, Rxpos); X } X return c; X} X X/* Receive a binary style header (type and position) */ Xzrbhdr(hdr) Xregister char *hdr; X{ X register int c, n; X register unsigned short crc; X X if ((c = zdlread()) & ~0377) X return c; X Rxtype = c; X crc = updcrc(c, 0); X X for (n=4; --n >= 0; ++hdr) { X if ((c = zdlread()) & ~0377) X return c; X crc = updcrc(c, crc); X *hdr = c; X } X if ((c = zdlread()) & ~0377) X return c; X crc = updcrc(c, crc); X if ((c = zdlread()) & ~0377) X return c; X crc = updcrc(c, crc); X if (crc & 0xFFFF) { X if (evenp) X zperr(masked); X zperr(badcrc); X return ERROR; X } X#ifdef ZMODEM X Protocol = ZMODEM; X#endif X Zmodem = 1; X return Rxtype; X} X X/* Receive a binary style header (type and position) with 32 bit FCS */ Xzrbhdr32(hdr) Xregister char *hdr; X{ X register int c, n; X register UNSL long crc; X X if ((c = zdlread()) & ~0377) X return c; X Rxtype = c; X crc = 0xFFFFFFFFL; crc = UPDC32(c, crc); X#ifdef DEBUGZ X vfile("zrbhdr32 c=%X crc=%lX", c, crc); X#endif X X for (n=4; --n >= 0; ++hdr) { X if ((c = zdlread()) & ~0377) X return c; X crc = UPDC32(c, crc); X *hdr = c; X#ifdef DEBUGZ X vfile("zrbhdr32 c=%X crc=%lX", c, crc); X#endif X } X for (n=4; --n >= 0;) { X if ((c = zdlread()) & ~0377) X return c; X crc = UPDC32(c, crc); X#ifdef DEBUGZ X vfile("zrbhdr32 c=%X crc=%lX", c, crc); X#endif X } X if (crc != 0xDEBB20E3) { X if (evenp) X zperr(masked); X zperr(badcrc); X return ERROR; X } X#ifdef ZMODEM X Protocol = ZMODEM; X#endif X Zmodem = 1; X return Rxtype; X} X X X/* Receive a hex style header (type and position) */ Xzrhhdr(hdr) Xchar *hdr; X{ X register int c; X register unsigned short crc; X register int n; X X if ((c = zgethex()) < 0) X return c; X Rxtype = c; X crc = updcrc(c, 0); X X for (n=4; --n >= 0; ++hdr) { X if ((c = zgethex()) < 0) X return c; X crc = updcrc(c, crc); X *hdr = c; X } X if ((c = zgethex()) < 0) X return c; X crc = updcrc(c, crc); X if ((c = zgethex()) < 0) X return c; X crc = updcrc(c, crc); X if (crc & 0xFFFF) { X zperr(badcrc); return ERROR; X } X if (readline(1) == '\r') /* Throw away possible cr/lf */ X readline(1); X#ifdef ZMODEM X Protocol = ZMODEM; X#endif X Zmodem = 1; return Rxtype; X} X X/* Send a byte as two hex digits */ Xzputhex(c) Xregister int c; X{ X static char digits[] = "0123456789abcdef"; X X if (Verbose>8) X vfile("zputhex: %02X", c); X sendline(digits[(c&0xF0)>>4]); X sendline(digits[(c)&0xF]); X} X X/* X * Send character c with ZMODEM escape sequence encoding. X * Escape XON, XOFF. Escape CR following @ (Telenet net escape) X */ Xzsendline(c) X{ X X /* Quick check for non control characters */ X if (c & 0140) X xsendline(lastsent = c); X else { X switch (c &= 0377) { X case ZDLE: X xsendline(ZDLE); X xsendline (lastsent = (c ^= 0100)); X break; X case 015: X case 0215: X if (!Zctlesc && (lastsent & 0177) != '@') X goto sendit; X /* **** FALL THRU TO **** */ X case 020: X case 021: X case 023: X case 0220: X case 0221: X case 0223: X xsendline(ZDLE); X c ^= 0100; X sendit: X xsendline(lastsent = c); X break; X default: X if (Zctlesc && ! (c & 0140)) { X xsendline(ZDLE); X c ^= 0100; X } X xsendline(lastsent = c); X } X } X} X X/* Decode two lower case hex digits into an 8 bit byte value */ Xzgethex() X{ X register int c; X X c = zgeth1(); X if (Verbose>8) X vfile("zgethex: %02X", c); X return c; X} Xzgeth1() X{ X register int c, n; X X if ((c = noxrd7()) < 0) X return c; X n = c - '0'; X if (n > 9) X n -= ('a' - ':'); X if (n & ~0xF) X return ERROR; X if ((c = noxrd7()) < 0) X return c; X c -= '0'; X if (c > 9) X c -= ('a' - ':'); X if (c & ~0xF) X return ERROR; X c += (n<<4); X return c; X} X X/* X * Read a byte, checking for ZMODEM escape encoding X * including CAN*5 which represents a quick abort X */ Xzdlread() X{ X register int c; X Xagain: X /* Quick check for non control characters */ X if ((c = readline(Rxtimeout)) & 0140) X return c; X switch (c) { X case ZDLE: X break; X case 023: X case 0223: X case 021: X case 0221: X goto again; X default: X if (Zctlesc && !(c & 0140)) { X goto again; X } X return c; X } Xagain2: X if ((c = readline(Rxtimeout)) < 0) X return c; X if (c == CAN && (c = readline(Rxtimeout)) < 0) X return c; X if (c == CAN && (c = readline(Rxtimeout)) < 0) X return c; X if (c == CAN && (c = readline(Rxtimeout)) < 0) X return c; X switch (c) { X case CAN: X return GOTCAN; X case ZCRCE: X case ZCRCG: X case ZCRCQ: X case ZCRCW: X return (c | GOTOR); X case ZRUB0: X return 0177; X case ZRUB1: X return 0377; X case 023: X case 0223: X case 021: X case 0221: X goto again2; X default: X if (Zctlesc && ! (c & 0140)) { X goto again2; X } X if ((c & 0140) == 0100) X return (c ^ 0100); X break; X } X if (Verbose>1) X zperr("Bad escape sequence %x", c); X return ERROR; X} X X/* X * Read a character from the modem line with timeout. X * Eat parity, XON and XOFF characters. X */ Xnoxrd7() X{ X register int c; X X for (;;) { X if ((c = readline(Rxtimeout)) < 0) X return c; X switch (c &= 0177) { X case XON: X case XOFF: X continue; X default: X if (Zctlesc && !(c & 0140)) X continue; X case '\r': X case '\n': X case ZDLE: X return c; X } X } X} X X/* Store long integer pos in Txhdr */ Xstohdr(pos) Xlong pos; X{ X Txhdr[ZP0] = pos; X Txhdr[ZP1] = pos>>8; X Txhdr[ZP2] = pos>>16; X Txhdr[ZP3] = pos>>24; X} X X/* Recover a long integer from a header */ Xlong Xrclhdr(hdr) Xregister char *hdr; X{ X register long l; X X l = (hdr[ZP3] & 0377); X l = (l << 8) | (hdr[ZP2] & 0377); X l = (l << 8) | (hdr[ZP1] & 0377); X l = (l << 8) | (hdr[ZP0] & 0377); X return l; X} X X/* End of zm.c */ SHAR_EOF chmod 0644 zm.c || echo "restore of zm.c fails" echo "x - extracting zmodem.h (Text)" sed 's/^X//' << 'SHAR_EOF' > zmodem.h && X/* X * Z M O D E M . H Manifest constants for ZMODEM X * application to application file transfer protocol X * 05-23-87 Chuck Forsberg Omen Technology Inc X */ X#define ZPAD '*' /* 052 Padding character begins frames */ X#define ZDLE 030 /* Ctrl-X Zmodem escape - `ala BISYNC DLE */ X#define ZDLEE (ZDLE^0100) /* Escaped ZDLE as transmitted */ X#define ZBIN 'A' /* Binary frame indicator */ X#define ZHEX 'B' /* HEX frame indicator */ X#define ZBIN32 'C' /* Binary frame with 32 bit FCS */ X X/* Frame types (see array "frametypes" in zm.c) */ X#define ZRQINIT 0 /* Request receive init */ X#define ZRINIT 1 /* Receive init */ X#define ZSINIT 2 /* Send init sequence (optional) */ X#define ZACK 3 /* ACK to above */ X#define ZFILE 4 /* File name from sender */ X#define ZSKIP 5 /* To sender: skip this file */ X#define ZNAK 6 /* Last packet was garbled */ X#define ZABORT 7 /* Abort batch transfers */ X#define ZFIN 8 /* Finish session */ X#define ZRPOS 9 /* Resume data trans at this position */ X#define ZDATA 10 /* Data packet(s) follow */ X#define ZEOF 11 /* End of file */ X#define ZFERR 12 /* Fatal Read or Write error Detected */ X#define ZCRC 13 /* Request for file CRC and response */ X#define ZCHALLENGE 14 /* Receiver's Challenge */ X#define ZCOMPL 15 /* Request is complete */ X#define ZCAN 16 /* Other end canned session with CAN*5 */ X#define ZFREECNT 17 /* Request for free bytes on filesystem */ X#define ZCOMMAND 18 /* Command from sending program */ X#define ZSTDERR 19 /* Output to standard error, data follows */ X X/* ZDLE sequences */ X#define ZCRCE 'h' /* CRC next, frame ends, header packet follows */ X#define ZCRCG 'i' /* CRC next, frame continues nonstop */ X#define ZCRCQ 'j' /* CRC next, frame continues, ZACK expected */ X#define ZCRCW 'k' /* CRC next, ZACK expected, end of frame */ X#define ZRUB0 'l' /* Translate to rubout 0177 */ X#define ZRUB1 'm' /* Translate to rubout 0377 */ X X/* zdlread return values (internal) */ X/* -1 is general error, -2 is timeout */ X#define GOTOR 0400 X#define GOTCRCE (ZCRCE|GOTOR) /* ZDLE-ZCRCE received */ X#define GOTCRCG (ZCRCG|GOTOR) /* ZDLE-ZCRCG received */ X#define GOTCRCQ (ZCRCQ|GOTOR) /* ZDLE-ZCRCQ received */ X#define GOTCRCW (ZCRCW|GOTOR) /* ZDLE-ZCRCW received */ X#define GOTCAN (GOTOR|030) /* CAN*5 seen */ X X/* Byte positions within header array */ X#define ZF0 3 /* First flags byte */ X#define ZF1 2 X#define ZF2 1 X#define ZF3 0 X#define ZP0 0 /* Low order 8 bits of position */ X#define ZP1 1 X#define ZP2 2 X#define ZP3 3 /* High order 8 bits of file position */ X X/* Bit Masks for ZRINIT flags byte ZF0 */ X#define CANFDX 01 /* Rx can send and receive true FDX */ X#define CANOVIO 02 /* Rx can receive data during disk I/O */ X#define CANBRK 04 /* Rx can send a break signal */ X#define CANCRY 010 /* Receiver can decrypt */ X#define CANLZW 020 /* Receiver can uncompress */ X#define CANFC32 040 /* Receiver can use 32 bit Frame Check */ X#define ESCCTL 0100 /* Receiver expects ctl chars to be escaped */ X#define ESC8 0200 /* Receiver expects 8th bit to be escaped */ X X/* Parameters for ZSINIT frame */ X#define ZATTNLEN 32 /* Max length of attention string */ X/* Bit Masks for ZSINIT flags byte ZF0 */ X#define TESCCTL 0100 /* Transmitter expects ctl chars to be escaped */ X#define TESC8 0200 /* Transmitter expects 8th bit to be escaped */ X X/* Parameters for ZFILE frame */ X/* Conversion options one of these in ZF0 */ X#define ZCBIN 1 /* Binary transfer - inhibit conversion */ X#define ZCNL 2 /* Convert NL to local end of line convention */ X#define ZCRESUM 3 /* Resume interrupted file transfer */ X/* Management include options, one of these ored in ZF1 */ X#define ZMSKNOLOC 0200 /* Skip file if not present at rx */ X/* Management options, one of these ored in ZF1 */ X#define ZMMASK 037 /* Mask for the choices below */ X#define ZMNEWL 1 /* Transfer if source newer or longer */ X#define ZMCRC 2 /* Transfer if different file CRC or length */ X#define ZMAPND 3 /* Append contents to existing file (if any) */ X#define ZMCLOB 4 /* Replace existing file */ X#define ZMNEW 5 /* Transfer if source newer */ X /* Number 5 is alive ... */ X#define ZMDIFF 6 /* Transfer if dates or lengths different */ X#define ZMPROT 7 /* Protect destination file */ X/* Transport options, one of these in ZF2 */ X#define ZTLZW 1 /* Lempel-Ziv compression */ X#define ZTCRYPT 2 /* Encryption */ X#define ZTRLE 3 /* Run Length encoding */ X/* Extended options for ZF3, bit encoded */ X#define ZXSPARS 64 /* Encoding for sparse file operations */ X X/* Parameters for ZCOMMAND frame ZF0 (otherwise 0) */ X#define ZCACK1 1 /* Acknowledge, then do command */ X Xlong rclhdr(); X X/* Globals used by ZMODEM functions */ Xextern Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame received */ Xextern Rxtype; /* Type of header received */ Xextern Rxcount; /* Count of data bytes received */ Xextern Zrwindow; /* RX window size (controls garbage count) */ Xextern Rxtimeout; /* Tenths of seconds to wait for something */ Xextern char Rxhdr[4]; /* Received header */ Xextern char Txhdr[4]; /* Transmitted header */ Xextern long Rxpos; /* Received file position */ Xextern long Txpos; /* Transmitted file position */ Xextern Txfcs32; /* TURE means send binary frames with 32 bit FCS */ Xextern Crc32t; /* Display flag indicating 32 bit CRC being sent */ Xextern Crc32; /* Display flag indicating 32 bit CRC being received */ Xextern Znulls; /* Number of nulls to send at beginning of ZDATA hdr */ Xextern char Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */ X X/* End of ZMODEM.H */ SHAR_EOF chmod 0644 zmodem.h || echo "restore of zmodem.h fails" echo "x - extracting zupl.t (Text)" sed 's/^X//' << 'SHAR_EOF' > zupl.t && X :: ProYAM/ZCOMM script to upload minirb and rz/sz to *nix X if S>1200 pt1 X ena -t X if !fminirb.c echo "Can't find minirb.c !!"; abort X putw "stty -echo; cat >minirb.c\r" X f -xHr minirb.c X putw "\r\4" X putw "stty echo\r" X dis -h X pat 1 "rwx" X pat 2 "%" X put "cc minirb.c -o minirb; ls -l minirb\r" X wait -f120 X if 1 goto okok X echo "The compiiation appears to have failed." X echo "Please compile minirb.c to minirb, then" X echo "hit F5 to upload the rest of the rz/sz files." X set f5 X@putw minirb\r; sb README zmodem.h zm.c sz.c rz.c crctab.c rbsb.c *.1 gz ptest.sh X t X return Xokok: echo "Minirb Compilation Appears Successful." X put minirb\r X sb README zmodem.h zm.c sz.c rz.c crctab.c rbsb.c *.1 gz ptest.sh X t X return SHAR_EOF chmod 0644 zupl.t || echo "restore of zupl.t fails" rm -f s2_seq_.tmp echo "You have unpacked the last part" exit 0 -- Keith Petersen Arpa: W8SDZ@SIMTEL20.ARPA Uucp: {bellcore,decwrl,harvard,lll-crg,ucbvax,uw-beaver}!simtel20.arpa!w8sdz GEnie: W8SDZ