w8sdz@brl-smoke.ARPA (Keith B. Petersen ) (04/28/88)
---- 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.1 continued # CurArch=3 if test ! -r ._seq_ 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 ) < ._seq_ || exit 1 echo "x - Continuing file sz.1" sed 's/^X//' << 'SHAR_EOF' >> sz.1 Xsome do not implement all these options. X XCircular buffering and a ZMODEM sliding window should be used Xwhen input is from pipes instead of acknowledging frames each 1024 bytes. XIf no files can be opened, X.B sz Xsends a ZMODEM command to echo a suitable complaint; Xperhaps it should check for the presence of at least one accessible file before Xgetting hot and bothered. XThe test mode leaves a zero length file on the receiving system. X XA few high speed modems have a firmware bug that drops characters when the Xdirection of high speed transmissson is reversed. XThe environment variable ZNULLS may be used to specify the number of nulls to Xsend before a ZDATA frame. XValues of 101 for a 4.77 mHz PC and 124 for an AT are typical. SHAR_EOF echo "File sz.1 is complete" chmod 0644 sz.1 || echo "restore of sz.1 fails" fi if test -f sz.c; then echo "File sz.c exists"; else echo "x - extracting sz.c (Text)" sed 's/^X//' << 'SHAR_EOF' > sz.c && X#define VERSION "sz 2.02 04-27-88" X#define PUBDIR "/usr/spool/uucppublic" X X/*% cc -compat -M2 -Ox -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz; size sz X<-xtx-*> cc -Osal -K -i -DSV sz.c -lx -o $B/sz; size $B/sz X * X * sz.c By Chuck Forsberg X * X * cc -O sz.c -o sz USG (SYS III/V) Unix X * cc -O -DSV sz.c -o sz Sys V Release 2 with non-blocking input X * Define to allow reverse channel checking X * cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD X * X * cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz Xenix X * X * ln sz sb **** All versions **** X * ln sz sx **** All versions **** X * X * X * Typical VMS compile and install sequence: X * define LNK$LIBRARY SYS$LIBRARY:VAXCRTL.OLB X * cc sz.c X * cc vvmodem.c X * link sz,vvmodem X * X * sz :== $disk$user2:[username.subdir]sz.exe X * X * X * ******* Some systems (Venix, Coherent, Regulus) do not ******* X * ******* support tty raw mode read(2) identically to ******* X * ******* Unix. ONEREAD must be defined to force one ******* X * ******* character reads for these systems. ******* X * X * A program for Unix to send files and commands to computers running X * Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM. X * X * Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM. X * X * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin X * X * 2.x has mods for VMS flavor X * X * 1.34 implements tx backchannel garbage count and ZCRCW after ZRPOS X * in accordance with the 7-31-87 ZMODEM Protocol Description X */ X X Xchar *substr(), *getenv(); X X#ifdef vax11c X#include <types.h> X#include <stat.h> X#define LOGFILE "szlog.tmp" X#include <stdio.h> X#include <signal.h> X#include <setjmp.h> X#include <ctype.h> X#include <errno.h> X#define OS "VMS" X#define READCHECK X#define BUFWRITE X#define iofd Xextern int errno; X#define SS_NORMAL SS$_NORMAL X#define xsendline(c) sendline(c) X X X#else /* vax11c */ X X X#define SS_NORMAL 0 X#define LOGFILE "/tmp/szlog" X#include <stdio.h> X#include <signal.h> X#include <setjmp.h> X#include <ctype.h> X#include <errno.h> Xextern int errno; X X#define sendline(c) putchar(c & 0377) X#define xsendline(c) putchar(c) X X#endif X X#define PATHLEN 256 X#define OK 0 X#define FALSE 0 X#define TRUE 1 X#define ERROR (-1) X/* Ward Christensen / CP/M parameters - Don't change these! */ X#define ENQ 005 X#define CAN ('X'&037) X#define XOFF ('s'&037) X#define XON ('q'&037) X#define SOH 1 X#define STX 2 X#define EOT 4 X#define ACK 6 X#define NAK 025 X#define CPMEOF 032 X#define WANTCRC 0103 /* send C not NAK to get crc not checksum */ X#define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */ X#define TIMEOUT (-2) X#define RCDO (-3) X#define RETRYMAX 10 X X X#define HOWMANY 2 Xint Zmodem=0; /* ZMODEM protocol requested by receiver */ Xunsigned Baudrate=2400; /* Default, should be set by first mode() call */ Xunsigned Txwindow; /* Control the size of the transmitted window */ Xunsigned Txwspac; /* Spacing between zcrcq requests */ Xunsigned Txwcnt; /* Counter used to space ack requests */ Xlong Lrxpos; /* Receiver's last reported offset */ Xint errors; X X#ifdef vax11c X#include "vrzsz.c" /* most of the system dependent stuff here */ X#else X#include "rbsb.c" /* most of the system dependent stuff here */ X#endif X#include "crctab.c" X Xint Filesleft; Xlong Totalleft; X X/* X * Attention string to be executed by receiver to interrupt streaming data X * when an error is detected. A pause (0336) may be needed before the X * ^C (03) or after it. X */ X#ifdef READCHECK Xchar Myattn[] = { 0 }; X#else X#ifdef USG Xchar Myattn[] = { 03, 0336, 0 }; X#else Xchar Myattn[] = { 0 }; X#endif X#endif X XFILE *in; Xchar Lastrx; Xchar Crcflg; Xint Verbose=0; Xint Modem2=0; /* XMODEM Protocol - don't send pathnames */ Xint Restricted=0; /* restricted; no /.. or ../ in filenames */ Xint Quiet=0; /* overrides logic that would otherwise set verbose */ Xint Ascii=0; /* Add CR's for brain damaged programs */ Xint Fullname=0; /* transmit full pathname */ Xint Unlinkafter=0; /* Unlink file after it is sent */ Xint Dottoslash=0; /* Change foo.bar.baz to foo/bar/baz */ Xint firstsec; Xint errcnt=0; /* number of files unreadable */ Xint blklen=128; /* length of transmitted records */ Xint Optiong; /* Let it rip no wait for sector ACK's */ Xint Noeofseen; Xint Totsecs; /* total number of sectors this file */ Xchar txbuf[1024]; Xint Filcnt=0; /* count of number of files opened */ Xint Lfseen=0; Xunsigned Rxbuflen = 16384; /* Receiver's max buffer length */ Xint Tframlen = 0; /* Override for tx frame length */ Xint blkopt=0; /* Override value for zmodem blklen */ Xint Rxflags = 0; Xlong bytcnt; Xint Wantfcs32 = TRUE; /* want to send 32 bit FCS */ Xchar Lzconv; /* Local ZMODEM file conversion request */ Xchar Lzmanag; /* Local ZMODEM file management request */ Xint Lskipnocor; Xchar Lztrans; Xchar zconv; /* ZMODEM file conversion request */ Xchar zmanag; /* ZMODEM file management request */ Xchar ztrans; /* ZMODEM file transport request */ Xint Command; /* Send a command, then exit. */ Xchar *Cmdstr; /* Pointer to the command string */ Xint Cmdtries = 11; Xint Cmdack1; /* Rx ACKs command, then do it */ Xint Exitcode; Xint Test; /* 1= Force receiver to send Attn, etc with qbf. */ X /* 2= Character transparency test */ Xchar *qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n"; Xlong Lastread; /* Beginning offset of last buffer read */ Xint Lastn; /* Count of last buffer read or -1 */ Xint Dontread; /* Don't read the buffer, it's still there */ Xlong Lastsync; /* Last offset to which we got a ZRPOS */ Xint Beenhereb4; /* How many times we've been ZRPOS'd same place */ X Xjmp_buf tohere; /* For the interrupt on RX timeout */ Xjmp_buf intrjmp; /* For the interrupt on RX CAN */ X X/* called by signal interrupt or terminate to clean things up */ Xbibi(n) X{ X canit(); fflush(stdout); mode(0); X fprintf(stderr, "sz: caught signal %d; exiting\n", n); X if (n == SIGQUIT) X abort(); X if (n == 99) X fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n"); X cucheck(); X exit(128+n); X} X/* Called when ZMODEM gets an interrupt (^X) */ Xonintr() X{ X signal(SIGINT, SIG_IGN); X longjmp(intrjmp, -1); X} X Xint Zctlesc; /* Encode control characters */ Xint Nozmodem = 0; /* If invoked as "sb" */ Xchar *Progname = "sz"; Xint Zrwindow = 1400; /* RX window size (controls garbage count) */ X#include "zm.c" X X Xmain(argc, argv) Xchar *argv[]; X{ X register char *cp; X register npats; X int dm; X char **patts; X static char xXbuf[BUFSIZ]; X X if ((cp = getenv("ZNULLS")) && *cp) X Znulls = atoi(cp); X if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh"))) X Restricted=TRUE; X from_cu(); X chkinvok(argv[0]); X X Rxtimeout = 600; X npats=0; X if (argc<2) X usage(); X setbuf(stdout, xXbuf); X while (--argc) { X cp = *++argv; X if (*cp++ == '-' && *cp) { X while ( *cp) { X switch(*cp++) { X case '\\': X *cp = toupper(*cp); continue; X case '+': X Lzmanag = ZMAPND; break; X#ifdef CSTOPB X case '2': X Twostop = TRUE; break; X#endif X case 'a': X Lzconv = ZCNL; X Ascii = TRUE; break; X case 'b': X Lzconv = ZCBIN; break; X case 'C': X if (--argc < 1) { X usage(); X } X Cmdtries = atoi(*++argv); X break; X case 'i': X Cmdack1 = ZCACK1; X /* **** FALL THROUGH TO **** */ X case 'c': X if (--argc != 1) { X usage(); X } X Command = TRUE; X Cmdstr = *++argv; X break; X case 'd': X ++Dottoslash; X /* **** FALL THROUGH TO **** */ X case 'f': X Fullname=TRUE; break; X case 'e': X Zctlesc = 1; break; X case 'k': X blklen=1024; break; X case 'L': X if (--argc < 1) { X usage(); X } X blkopt = atoi(*++argv); X if (blkopt<24 || blkopt>1024) X usage(); X break; X case 'l': X if (--argc < 1) { X usage(); X } X Tframlen = atoi(*++argv); X if (Tframlen<32 || Tframlen>1024) X usage(); X break; X case 'N': X Lzmanag = ZMNEWL; break; X case 'n': X Lzmanag = ZMNEW; break; X case 'o': X Wantfcs32 = FALSE; break; X case 'p': X Lzmanag = ZMPROT; break; X case 'r': X Lzconv = ZCRESUM; X case 'q': X Quiet=TRUE; Verbose=0; break; X case 't': X if (--argc < 1) { X usage(); X } X Rxtimeout = atoi(*++argv); X if (Rxtimeout<10 || Rxtimeout>1000) X usage(); X break; X case 'T': X if (++Test > 1) { X chartest(1); chartest(2); X mode(0); exit(0); X } X break; X#ifndef vax11c X case 'u': X ++Unlinkafter; break; X#endif X case 'v': X ++Verbose; break; X case 'w': X if (--argc < 1) { X usage(); X } X Txwindow = atoi(*++argv); X if (Txwindow < 256) X Txwindow = 256; X Txwindow = (Txwindow/64) * 64; X Txwspac = Txwindow/4; X if (blkopt > Txwspac X || (!blkopt && Txwspac < 1024)) X blkopt = Txwspac; X break; X case 'X': X ++Modem2; break; X case 'Y': X Lskipnocor = TRUE; X /* **** FALLL THROUGH TO **** */ X case 'y': X Lzmanag = ZMCLOB; break; X default: X usage(); X } X } X } X else if ( !npats && argc>0) { X if (argv[0][0]) { X npats=argc; X patts=argv; X#ifndef vax11c X if ( !strcmp(*patts, "-")) X iofd = 1; X#endif X } X } X } X if (npats < 1 && !Command && !Test) X usage(); X if (Verbose) { X if (freopen(LOGFILE, "a", stderr)==NULL) { X printf("Can't open log file %s\n",LOGFILE); X exit(0200); X } X setbuf(stderr, NULL); X } X if (Fromcu && !Quiet) { X if (Verbose == 0) X Verbose = 2; X } X X mode(1); X X if (signal(SIGINT, bibi) == SIG_IGN) { X signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN); X } else { X signal(SIGINT, bibi); signal(SIGKILL, bibi); X } X if ( !Fromcu) X signal(SIGQUIT, SIG_IGN); X signal(SIGTERM, bibi); X X if ( !Modem2) { X if (!Nozmodem) { X printf("rz\r"); fflush(stdout); X } X countem(npats, patts); X if (!Nozmodem) { X stohdr(0L); X if (Command) X Txhdr[ZF0] = ZCOMMAND; X zshhdr(ZRQINIT, Txhdr); X } X } X fflush(stdout); X X if (Command) { X if (getzrxinit()) { X Exitcode=0200; canit(); X } X else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) { X Exitcode=0200; canit(); X } X } else if (wcsend(npats, patts)==ERROR) { X Exitcode=0200; X canit(); X } X fflush(stdout); X mode(0); X dm = ((errcnt != 0) | Exitcode); X if (dm) { X cucheck(); exit(dm); X } X exit(SS_NORMAL); X /*NOTREACHED*/ X} X Xwcsend(argc, argp) Xchar *argp[]; X{ X register n; X X Crcflg=FALSE; X firstsec=TRUE; X bytcnt = -1; X for (n=0; n<argc; ++n) { X Totsecs = 0; X if (wcs(argp[n])==ERROR) X return ERROR; X } X Totsecs = 0; X if (Filcnt==0) { /* bitch if we couldn't open ANY files */ X if ( !Modem2) { X Command = TRUE; X Cmdstr = "echo \"sz: Can't open any requested files\""; X if (getnak()) { X Exitcode=0200; canit(); X } X if (!Zmodem) X canit(); X else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) { X Exitcode=0200; canit(); X } X Exitcode = 1; return OK; X } X canit(); X fprintf(stderr,"\r\nCan't open any requested files.\r\n"); X return ERROR; X } X if (Zmodem) X saybibi(); X else if ( !Modem2) X wctxpn(""); X return OK; X} X Xwcs(oname) Xchar *oname; X{ X register c; X register char *p; X struct stat f; X char name[PATHLEN]; X X strcpy(name, oname); X X if (Restricted) { X /* restrict pathnames to current tree or uucppublic */ X if ( substr(name, "../") X || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) { X canit(); X fprintf(stderr,"\r\nsz:\tSecurity Violation\r\n"); X return ERROR; X } X } X X if ( !strcmp(oname, "-")) { X if ((p = getenv("ONAME")) && *p) X strcpy(name, p); X else X sprintf(name, "s%d.sz", getpid()); X in = stdin; X } X else if ((in=fopen(oname, "r"))==NULL) { X ++errcnt; X return OK; /* pass over it, there may be others */ X } X ++Noeofseen; Lastread = 0; Lastn = -1; Dontread = FALSE; X /* Check for directory or block special files */ X fstat(fileno(in), &f); X c = f.st_mode & S_IFMT; X if (c == S_IFDIR || c == S_IFBLK) { X fclose(in); X return OK; X } X X ++Filcnt; X switch (wctxpn(name)) { X case ERROR: X return ERROR; X case ZSKIP: X return OK; X } X if (!Zmodem && wctx(f.st_size)==ERROR) X return ERROR; X#ifndef vax11c X if (Unlinkafter) X unlink(oname); X#endif X return 0; X} X X/* X * generate and transmit pathname block consisting of X * pathname (null terminated), X * file length, mode time and file mode in octal X * as provided by the Unix fstat call. X * N.B.: modifies the passed name, may extend it! X */ Xwctxpn(name) Xchar *name; X{ X register char *p, *q; X char name2[PATHLEN]; X struct stat f; X X if (Modem2) { X if ((in!=stdin) && *name && fstat(fileno(in), &f)!= -1) { X fprintf(stderr, "Sending %s, %ld blocks: ", X name, f.st_size>>7); X } X fprintf(stderr, "Give your local XMODEM receive command now.\r\n"); X return OK; X } X zperr("Awaiting pathname nak for %s", *name?name:"<END>"); X if ( !Zmodem) X if (getnak()) X return ERROR; X X q = (char *) 0; X if (Dottoslash) { /* change . to . */ X for (p=name; *p; ++p) { X if (*p == '/') X q = p; X else if (*p == '.') X *(q=p) = '/'; X } X if (q && strlen(++q) > 8) { /* If name>8 chars */ X q += 8; /* make it .ext */ X strcpy(name2, q); /* save excess of name */ X *q = '.'; X strcpy(++q, name2); /* add it back */ X } X } X X for (p=name, q=txbuf ; *p; ) X if ((*q++ = *p++) == '/' && !Fullname) X q = txbuf; X *q++ = 0; X p=q; X while (q < (txbuf + 1024)) X *q++ = 0; X if (!Ascii && (in!=stdin) && *name && fstat(fileno(in), &f)!= -1) X sprintf(p, "%lu %lo %o 0 %d %ld", f.st_size, f.st_mtime, X f.st_mode, Filesleft, Totalleft); X Totalleft -= f.st_size; X if (--Filesleft <= 0) X Totalleft = 0; X if (Totalleft < 0) X Totalleft = 0; X X /* force 1k blocks if name won't fit in 128 byte block */ X if (txbuf[125]) X blklen=1024; X else { /* A little goodie for IMP/KMD */ X txbuf[127] = (f.st_size + 127) >>7; X txbuf[126] = (f.st_size + 127) >>15; X } X if (Zmodem) X return zsendfile(txbuf, 1+strlen(p)+(p-txbuf)); X if (wcputsec(txbuf, 0, 128)==ERROR) X return ERROR; X return OK; X} X Xgetnak() X{ X register firstch; X X Lastrx = 0; X for (;;) { X switch (firstch = readock(800,1)) { X case ZPAD: X if (getzrxinit()) X return ERROR; X Ascii = 0; /* Receiver does the conversion */ X return FALSE; X case TIMEOUT: X zperr("Timeout on pathname"); X return TRUE; X case WANTG: X#ifdef MODE2OK X mode(2); /* Set cbreak, XON/XOFF, etc. */ X#endif X Optiong = TRUE; X blklen=1024; X case WANTCRC: X Crcflg = TRUE; X case NAK: X return FALSE; X case CAN: X if ((firstch = readock(20,1)) == CAN && Lastrx == CAN) X return TRUE; X default: X break; X } X Lastrx = firstch; X } X} X X Xwctx(flen) Xlong flen; X{ X register int thisblklen; X register int sectnum, attempts, firstch; X long charssent; X X charssent = 0; firstsec=TRUE; thisblklen = blklen; X vfile("wctx:file length=%ld", flen); X X while ((firstch=readock(Rxtimeout, 2))!=NAK && firstch != WANTCRC X && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN) X ; X if (firstch==CAN) { X zperr("Receiver CANcelled"); X return ERROR; X } X if (firstch==WANTCRC) X Crcflg=TRUE; X if (firstch==WANTG) X Crcflg=TRUE; X sectnum=0; X for (;;) { X if (flen <= (charssent + 896L)) X thisblklen = 128; X if ( !filbuf(txbuf, thisblklen)) X break; X if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR) X return ERROR; X charssent += thisblklen; X } X fclose(in); X attempts=0; X do { X purgeline(); X sendline(EOT); X fflush(stdout); X ++attempts; X } X while ((firstch=(readock(Rxtimeout, 1)) != ACK) && attempts < RETRYMAX); X if (attempts == RETRYMAX) { X zperr("No ACK on EOT"); X return ERROR; X } X else X return OK; X} X Xwcputsec(buf, sectnum, cseclen) Xchar *buf; Xint sectnum; Xint cseclen; /* data length of this sector to send */ X{ X register checksum, wcj; X register char *cp; X unsigned oldcrc; X int firstch; X int attempts; X X firstch=0; /* part of logic to detect CAN CAN */ X X if (Verbose>2) X fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs/8 ); X else if (Verbose>1) X fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 ); X for (attempts=0; attempts <= RETRYMAX; attempts++) { X Lastrx= firstch; X sendline(cseclen==1024?STX:SOH); X sendline(sectnum); X sendline(-sectnum -1); X oldcrc=checksum=0; X for (wcj=cseclen,cp=buf; --wcj>=0; ) { X sendline(*cp); X oldcrc=updcrc((0377& *cp), oldcrc); X checksum += *cp++; X } X if (Crcflg) { X oldcrc=updcrc(0,updcrc(0,oldcrc)); X sendline((int)oldcrc>>8); X sendline((int)oldcrc); X } X else X sendline(checksum); X X if (Optiong) { X firstsec = FALSE; return OK; X } X firstch = readock(Rxtimeout, (Noeofseen&§num) ? 2:1); Xgotnak: X switch (firstch) { X case CAN: X if(Lastrx == CAN) { Xcancan: X zperr("Cancelled"); return ERROR; X } X break; X case TIMEOUT: X zperr("Timeout on sector ACK"); continue; X case WANTCRC: X if (firstsec) X Crcflg = TRUE; X case NAK: X zperr("NAK on sector"); continue; X case ACK: X firstsec=FALSE; X Totsecs += (cseclen>>7); X return OK; X case ERROR: X zperr("Got burst for sector ACK"); break; X default: X zperr("Got %02x for sector ACK", firstch); break; X } X for (;;) { X Lastrx = firstch; X if ((firstch = readock(Rxtimeout, 2)) == TIMEOUT) X break; X if (firstch == NAK || firstch == WANTCRC) X goto gotnak; X if (firstch == CAN && Lastrx == CAN) X goto cancan; X } X } X zperr("Retry Count Exceeded"); X return ERROR; X} X X/* fill buf with count chars padding with ^Z for CPM */ Xfilbuf(buf, count) Xregister char *buf; X{ X register c, m; X X if ( !Ascii) { X m = read(fileno(in), buf, count); X if (m <= 0) X return 0; X while (m < count) X buf[m++] = 032; X return count; X } X m=count; X if (Lfseen) { X *buf++ = 012; --m; Lfseen = 0; X } X while ((c=getc(in))!=EOF) { X if (c == 012) { X *buf++ = 015; X if (--m == 0) { X Lfseen = TRUE; break; X } X } X *buf++ =c; X if (--m == 0) X break; X } X if (m==count) X return 0; X else X while (--m>=0) X *buf++ = CPMEOF; X return count; X} X/* fill buf with count chars */ Xzfilbuf(buf, count) Xregister char *buf; X{ X register c, m; X X m=count; X while ((c=getc(in))!=EOF) { X *buf++ =c; X if (--m == 0) X break; X } X return (count - m); X} X X/* VARARGS1 */ Xvfile(f, a, b, c) Xregister char *f; X{ X if (Verbose > 2) { X fprintf(stderr, f, a, b, c); X fprintf(stderr, "\n"); X } X} X X Xalrm() X{ X longjmp(tohere, -1); X} X X X#ifndef vax11c X/* X * readock(timeout, count) reads character(s) from file descriptor 0 X * (1 <= count <= 3) X * it attempts to read count characters. If it gets more than one, X * it is an error unless all are CAN X * (otherwise, only normal response is ACK, CAN, or C) X * Only looks for one if Optiong, which signifies cbreak, not raw input X * X * timeout is in tenths of seconds X */ Xreadock(timeout, count) X{ X register int c; X static char byt[5]; X X if (Optiong) X count = 1; /* Special hack for cbreak */ X X fflush(stdout); X if (setjmp(tohere)) { X zperr("TIMEOUT"); X return TIMEOUT; X } X c = timeout/10; X if (c<2) X c=2; X if (Verbose>5) { X fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c); X byt[1] = 0; X } X signal(SIGALRM, alrm); alarm(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 chmod 0644 sz.c || echo "restore of sz.c fails" fi if test -f vmodem.h; then echo "File vmodem.h exists"; else 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" fi if test -f vrzsz.c; then echo "File vrzsz.c exists"; else 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" fi if test -f vvmodem.c; then echo "File vvmodem.c exists"; else 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 }; SHAR_EOF echo "End of part 3" echo "File vvmodem.c is continued in part 4" echo "4" > ._seq_ -- Keith Petersen Arpa: W8SDZ@SIMTEL20.ARPA Uucp: {bellcore,decwrl,harvard,lll-crg,ucbvax,uw-beaver}!simtel20.arpa!w8sdz GEnie: W8SDZ