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