[comp.binaries.ibm.pc] Zmodem for Unix and VAX/VMS

w8sdz@brl-smoke.ARPA (Keith B. Petersen ) (05/03/88)

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
# shar:	Shell Archiver  (v1.20)
#	Packed Tue May  3 00:05:21 EDT 1988 by brl-smoke!w8sdz
#	from directory /pmsmoke/other/w8sdz/upload
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
#	Run the following text with /bin/sh to create:
#	  Makefile
#	  README
#	  crc.1
#	  crc.c
#	  crctab.c
#	  gz
#	  minirb.1
#	  minirb.c
#	  ptest.sh
#	  rbsb.c
#	  rz.1
#	  rz.c
#	  sz.1
#	  sz.c
#	  vmodem.h
#	  vrzsz.c
#	  vvmodem.c
#	  zm.c
#	  zmodem.h
#	  zupl.t
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
     next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
     exit 1; fi
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X# Makefile for Unix/Xenix rz and sz programs
X# the makefile is not too well tested yet
X
Xnothing:
X	@echo
X	@echo "Please study the #ifdef's in crctab.c rbsb.c, rz.c and sz.c,"
X	@echo "then type 'make system' where system is one of:"
X	@echo "	sysvr3	SYSTEM 5.3 Unix with mkdir(2)"
X	@echo "	sysv	SYSTEM 3/5 Unix"
X	@echo "	xenix	Xenix"
X	@echo "	x386	386 Xenix"
X	@echo "	bsd	Berkeley 4.x BSD, Ultrix, V7"
X	@echo
X
Xusenet:
X	shar -f /tmp/rzsz README Makefile zmodem.h zm.c sz.c rz.c rbsb.c \
X	 crc.c vmodem.h vvmodem.c vrzsz.c crctab.c minirb.c \
X	 *.1 gz ptest.sh zupl.t
X
Xshar:
X	shar -f /tmp/rzsz -m 2000000 README Makefile zmodem.h zm.c \
X	 vmodem.h vvmodem.c vrzsz.c sz.c rz.c crctab.c \
X	 crc.c rbsb.c minirb.c *.1 gz ptest.sh zupl.t
X
Xunixforum: shar
X	compress -b12 /tmp/rzsz.sh
X
Xarc:
X	rm -f /tmp/rzsz.arc
X	arc a /tmp/rzsz README Makefile zmodem.h zm.c sz.c rz.c \
X	 vmodem.h vvmodem.c vrzsz.c crctab.c rbsb.c \
X	 crc.c *.1 gz ptest.sh zupl.t minirb.c
X	chmod og-w /tmp/rzsz.arc
X	mv /tmp/rzsz.arc /t/yam
X
Xzoo:
X	rm -f /tmp/rzsz.zoo
X	zoo a /tmp/rzsz README Makefile zmodem.h zm.c sz.c rz.c \
X	 vmodem.h vvmodem.c vrzsz.c crctab.c rbsb.c *.1 \
X	 crc.c gz ptest.sh zupl.t minirb.c
X	chmod og-w /tmp/rzsz.zoo
X	mv /tmp/rzsz.zoo /t/yam
X
X.PRECIOUS:rz sz
X
Xxenix:
X	cc -M0 -Ox -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz
X	size sz
X	-ln sz sb
X	-ln sz sx
X	cc -M0 -Ox -K -i -DMD rz.c -o rz
X	size rz
X	-ln rz rb
X	-ln rz rx
X
Xx386:
X	cc -Ox -DMD rz.c -o rz
X	size rz
X	-ln rz rb
X	-ln rz rx
X	cc -Ox -DNFGVMIN -DREADCHECK sz.c -lx -o sz
X	size sz
X	-ln sz sb
X	-ln sz sx
X
Xsysv:
X	cc -O -DMD rz.c -o rz
X	size rz
X	-ln rz rb
X	-ln rz rx
X	cc -DSV -O -DNFGVMIN sz.c -o sz
X	size sz
X	-ln sz sb
X	-ln sz sx
X
Xsysvr3:
X	cc -O -DMD=2 rz.c -o rz
X	size rz
X	-ln rz rb
X	-ln rz rx
X	cc -DSV -O -DNFGVMIN sz.c -o sz
X	size sz
X	-ln sz sb
X	-ln sz sx
X
Xbsd:
X	cc -DMD=2 -Dstrchr=index -DV7 -O rz.c -o rz
X	size rz
X	-ln rz rb
X	-ln rz rx
X	cc -DV7 -O -DNFGVMIN sz.c -o sz
X	size sz
X	-ln sz sb
X	-ln sz sx
X
Xsz: nothing
Xsb: nothing
Xrz: nothing
Xrb: nothing
SHAR_EOF
chmod 0644 Makefile || echo "restore of Makefile fails"
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
XNew for April 1988:  VMS C flavors of rz and sz especially for tired
Xfrog stompers.  The following performance log entries give the story!
X
X 2400 Z  splat.arc         3968  220   18  0  0   0  512  30 (rz) 0 ccvax off
X 2400 K  splat.arc         3968  110   36  0  0   0   89  -1 get  -1 ccvax off
X
XThe contents of RZSZ.ARC are designed to be uploaded to a Unix or Xenix
Xsystem by ZCOMM or Professional-YAM using the supplied zupl.t script.
XConnect to your Unix/Xenix system, select an empty directory, and then
Xgive the YAM/ZCOMM command: "source zupl.t".  This will upload minirb.c,
Xcompile it, and then use minirb to upload the rz/sz files.
X
XOnce these files are on your Unix system, you can type "make".
XThe Makefile will list the various systems it knows how to
Xcompile the programs for, and the command to do so (e.g., "make bsd").
X
XThe Makefile is self explanatory; just say "make".
X
XNaturally, rz and sz work best with comm programs that seamlessly
Xsupport ZMODEM command and file AutoDownload (Pro-YAM and ZCOMM).
X
XThe "DSZ" shareware program allows ZMODEM file transfers with
Xtraditional DOS comm programs, but it must be called manually.
X(The computer should do that for you!)  DSZ provides a "mini term
Xfunction" that supports ZMODEM AutoDownload.  DSZ (part of DSZ.ARC) and
Xthe ZMODEM protocol description (YZMODEM.ARC) are on TeleGodzilla and
Xother fine bulletin boards.
X
XChuck Forsberg WA7KGX Author of Pro-YAM communications Tools for PCDOS and Unix
X...!tektronix!reed!omen!caf  Omen Technology Inc "The High Reliability Software"
X  17505-V Northwest Sauvie Island Road Portland OR 97231  Voice: 503-621-3406
XTeleGodzilla BBS: 621-3746 2400/1200  CIS:70007,2304  Genie:CAF  Source:TCE022
X  omen Any ACU 1200 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp
X  omen!/usr/spool/uucppublic/FILES lists all uucp-able files, updated hourly
SHAR_EOF
chmod 0644 README || echo "restore of README fails"
echo "x - extracting crc.1 (Text)"
sed 's/^X//' << 'SHAR_EOF' > crc.1 &&
X.TH CRC 1 OMEN 
X.SH NAME
Xcrc \- checksum files
X.SH SYNOPSIS
X.B crc
Xfile ...
X.SH DESCRIPTION
XFor each file,
X.I crc\^
Xcalculates and prints a 32-bit CRC,
Xthe byte count, and the file name.
XIt is typically used to validate files transferred between
Xdifferent systems, and is useful in detecting subtle disk corruption.
X.I Crc\^
Xuses a checksum compatible with the
XDOS
Xversion of crc,
Xas well as the "crc" command in ZCOMM and Professional-YAM
X(high reliability communications programs).
X
XThe 32-bit CRC used is the frame
Xcheck sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71
Xand FED-STD-1003, the U.S. versions of CCITT's X.25 link-level
Xprotocol).
X
X32 bit CRC code courtesy Gary S. Brown.
X.SH BUGS
XAlthough most unlikely,
Xfiles with different data may still produce the same crc value.
X.SH "SEE ALSO"
Xchek(1), tocpm(1), sum(1), wc(1).
SHAR_EOF
chmod 0644 crc.1 || echo "restore of crc.1 fails"
echo "x - extracting crc.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > crc.c &&
X/*% cc -O -K -dos % -o crc.exe
X*/
X
X/*
X *  Crc - 32 BIT ANSI X3.66 CRC checksum files
X */
X#include <stdio.h>
X#define OK 0
X#define ERROR (-1)
X#define LINT_ARGS
X
X/**********************************************************************\
X|*                                                                    *|
X|* Demonstration program to compute the 32-bit CRC used as the frame  *|
X|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71     *|
X|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level     *|
X|* protocol).  The 32-bit FCS was added via the Federal Register,     *|
X|* 1 June 1982, p.23798.  I presume but don't know for certain that   *|
X|* this polynomial is or will be included in CCITT V.41, which        *|
X|* defines the 16-bit CRC (often called CRC-CCITT) polynomial.  FIPS  *|
X|* PUB 78 says that the 32-bit FCS reduces otherwise undetected       *|
X|* errors by a factor of 10^-5 over 16-bit FCS.                       *|
X|*                                                                    *|
X\**********************************************************************/
X
X/* Need an unsigned type capable of holding 32 bits; */
Xtypedef unsigned long int UNS_32_BITS;
X
X/*
X * Copyright (C) 1986 Gary S. Brown.  You may use this program, or
X * code or tables extracted from it, as desired without restriction.
X */
X/* First, the polynomial itself and its table of feedback terms.  The  */
X/* polynomial is                                                       */
X/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
X/* Note that we take it "backwards" and put the highest-order term in  */
X/* the lowest-order bit.  The X^32 term is "implied"; the LSB is the   */
X/* X^31 term, etc.  The X^0 term (usually shown as "+1") results in    */
X/* the MSB being 1.                                                    */
X
X/* Note that the usual hardware shift register implementation, which   */
X/* is what we're using (we're merely optimizing it by doing eight-bit  */
X/* chunks at a time) shifts bits into the lowest-order term.  In our   */
X/* implementation, that means shifting towards the right.  Why do we   */
X/* do it this way?  Because the calculated CRC must be transmitted in  */
X/* order from highest-order term to lowest-order term.  UARTs transmit */
X/* characters in order from LSB to MSB.  By storing the CRC this way,  */
X/* we hand it to the UART in the order low-byte to high-byte; the UART */
X/* sends each low-bit to hight-bit; and the result is transmission bit */
X/* by bit from highest- to lowest-order term without requiring any bit */
X/* shuffling on our part.  Reception works similarly.                  */
X
X/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */
X/*                                                                     */
X/*  1. The table can be generated at runtime if desired; code to do so */
X/*     is shown later.  It might not be obvious, but the feedback      */
X/*     terms simply represent the results of eight shift/xor opera-    */
X/*     tions for all combinations of data and CRC register values.     */
X/*                                                                     */
X/*  2. The CRC accumulation logic is the same for all CRC polynomials, */
X/*     be they sixteen or thirty-two bits wide.  You simply choose the */
X/*     appropriate table.  Alternatively, because the table can be     */
X/*     generated at runtime, you can start by generating the table for */
X/*     the polynomial in question and use exactly the same "updcrc",   */
X/*     if your application needn't simultaneously handle two CRC       */
X/*     polynomials.  (Note, however, that XMODEM is strange.)          */
X/*                                                                     */
X/*  3. For 16-bit CRCs, the table entries need be only 16 bits wide;   */
X/*     of course, 32-bit entries work OK if the high 16 bits are zero. */
X/*                                                                     */
X/*  4. The values must be right-shifted by eight bits by the "updcrc"  */
X/*     logic; the shift must be unsigned (bring in zeroes).  On some   */
X/*     hardware you could probably optimize the shift in assembler by  */
X/*     using byte-swap instructions.                                   */
X
Xstatic UNS_32_BITS crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
X0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
X0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
X0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
X0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
X0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
X0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
X0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
X0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
X0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
X0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
X0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
X0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
X0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
X0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
X0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
X0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
X0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
X0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
X0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
X0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
X0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
X0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
X0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
X0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
X0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
X0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
X0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
X0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
X0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
X0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
X0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
X0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
X};
X
X#define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
X
Xmain(argc, argp)
Xchar **argp;
X{
X	register errors = 0;
X
X	while( --argc > 0)
X		errors |= crc32file( *++argp);
X	exit(errors != 0);
X}
X
Xcrc32file(name)
Xchar *name;
X{
X	register FILE *fin;
X	register unsigned long oldcrc32;
X	register unsigned long crc32;
X	register unsigned long oldcrc;
X	register c;
X	register long charcnt;
X
X	oldcrc32 = 0xFFFFFFFF; charcnt = 0;
X#ifdef M_I86SM
X	if ((fin=fopen(name, "rb"))==NULL)
X#else
X	if ((fin=fopen(name, "r"))==NULL)
X#endif
X	{
X		perror(name);
X		return ERROR;
X	}
X	while ((c=getc(fin))!=EOF) {
X		++charcnt;
X		oldcrc32 = UPDC32(c, oldcrc32);
X	}
X
X	if (ferror(fin)) {
X		perror(name);
X		charcnt = -1;
X	}
X	fclose(fin);
X
X	crc32 = oldcrc32;  oldcrc = oldcrc32 = ~oldcrc32;
X
X/*
X	crc32 = UPDC32((oldcrc32 & 0377), crc32);  oldcrc32 >>=8;
X	crc32 = UPDC32((oldcrc32 & 0377), crc32);  oldcrc32 >>=8;
X	crc32 = UPDC32((oldcrc32 & 0377), crc32);  oldcrc32 >>=8;
X	crc32 = UPDC32((oldcrc32 & 0377), crc32);  oldcrc32 >>=8;
X	printf("%08lX ", crc32);
X*/
X
X	printf("%08lX %7ld %s\n", oldcrc, charcnt, name);
X
X	return OK;
X}
X
SHAR_EOF
chmod 0644 crc.c || echo "restore of crc.c fails"
echo "x - extracting crctab.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > crctab.c &&
X/*
X *  Crc calculation stuff
X */
X
X/* crctab calculated by Mark G. Mendel, Network Systems Corporation */
Xstatic unsigned short crctab[256] = {
X    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
X    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
X    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
X    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
X    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
X    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
X    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
X    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
X    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
X    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
X    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
X    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
X    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
X    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
X    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
X    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
X    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
X    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
X    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
X    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
X    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
X    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
X    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
X    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
X    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
X    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
X    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
X    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
X    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
X    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
X    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
X    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
X};
X
X/*
X * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell. 
X *  NOTE: First srgument must be in range 0 to 255.
X *        Second argument is referenced twice.
X * 
X * Programmers may incorporate any or all code into their programs, 
X * giving proper credit within the source. Publication of the 
X * source routines is permitted so long as proper credit is given 
X * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, 
X * Omen Technology.
X */
X
X#define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
X
X/*
X * Copyright (C) 1986 Gary S. Brown.  You may use this program, or
X * code or tables extracted from it, as desired without restriction.
X */
X
X/* First, the polynomial itself and its table of feedback terms.  The  */
X/* polynomial is                                                       */
X/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
X/* Note that we take it "backwards" and put the highest-order term in  */
X/* the lowest-order bit.  The X^32 term is "implied"; the LSB is the   */
X/* X^31 term, etc.  The X^0 term (usually shown as "+1") results in    */
X/* the MSB being 1.                                                    */
X
X/* Note that the usual hardware shift register implementation, which   */
X/* is what we're using (we're merely optimizing it by doing eight-bit  */
X/* chunks at a time) shifts bits into the lowest-order term.  In our   */
X/* implementation, that means shifting towards the right.  Why do we   */
X/* do it this way?  Because the calculated CRC must be transmitted in  */
X/* order from highest-order term to lowest-order term.  UARTs transmit */
X/* characters in order from LSB to MSB.  By storing the CRC this way,  */
X/* we hand it to the UART in the order low-byte to high-byte; the UART */
X/* sends each low-bit to hight-bit; and the result is transmission bit */
X/* by bit from highest- to lowest-order term without requiring any bit */
X/* shuffling on our part.  Reception works similarly.                  */
X
X/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */
X/*                                                                     */
X/*     The table can be generated at runtime if desired; code to do so */
X/*     is shown later.  It might not be obvious, but the feedback      */
X/*     terms simply represent the results of eight shift/xor opera-    */
X/*     tions for all combinations of data and CRC register values.     */
X/*                                                                     */
X/*     The values must be right-shifted by eight bits by the "updcrc"  */
X/*     logic; the shift must be unsigned (bring in zeroes).  On some   */
X/*     hardware you could probably optimize the shift in assembler by  */
X/*     using byte-swap instructions.                                   */
X
Xstatic long cr3tab[] = { /* CRC polynomial 0xedb88320 */
X0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
X0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
X0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
X0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
X0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
X0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
X0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
X0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
X0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
X0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
X0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
X0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
X0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
X0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
X0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
X0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
X0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
X0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
X0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
X0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
X0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
X0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
X0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
X0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
X0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
X0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
X0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
X0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
X0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
X0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
X0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
X0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
X};
X
X#ifdef NFGM
Xlong
XUPDC32(b, c)
Xlong c;
X{
X	return (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF));
X}
X
X#else
X
X#define UPDC32(b, c) (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF))
X#endif
X
X/* End of crctab.c */
SHAR_EOF
chmod 0644 crctab.c || echo "restore of crctab.c fails"
echo "x - extracting gz (Text)"
sed 's/^X//' << 'SHAR_EOF' > gz &&
Xexec sz -c "sz $*"
SHAR_EOF
chmod 0644 gz || echo "restore of gz fails"
echo "x - extracting minirb.1 (Text)"
sed 's/^X//' << 'SHAR_EOF' > minirb.1 &&
X'\" Revision Level 
X'\" Last Delta     09-08-87
X.TH MINIRB 1 OMEN
X.SH NAME
Xminirb \- Bootstrap YMODEM Batch file receive
X.SH SYNOPSIS
X.B minirb
X.SH DESCRIPTION
X.I Minirb
Xreceives one or more files with YMODEM batch file transfer protocol.
X.I Minirb
Xwas developed for use as a bootstrap to simplify uploading of the longer
X.I rz
Xand
X.I sz
Xprograms, such as are contained in the
X.I rzsz.zoo
X"zoo" archive or the
X.I rzsz.sh
Xshell archive.
X.SH SEE ALSO
XYMODEM.DOC,
XProfessional-YAM manual,
Xsz(omen)
X.SH NOTES
XThe source file
X.I minirb.c
Xhas been ruthlessly pruned
X(4k, 175 lines)
Xto simplify uploading without benefit of
Xan error correcting file transfer protocol.
XDo not reformat or add tabs to the source file
Xas this would complicate uploading.
X
XPlease read the uploading suggestions in the chapter
X.I "File Transfer Basics"
Xin the Professional-YAM or ZCOMM user's manual.
X
X.I Minirb
Xuses 8 bit checksum which may not be compatible with some programs
Xclaiming to support YMODEM batch transfers.
X
X.I Minirb
Xuses the
XYMODEM header
Xfile length information
Xto avoid storing extraneous characters.
X.I Minirb
Xdeletes carriage returns and CPMEOF (^Z) characters
Xencountered in uploaded files.
X
X.I Minirb
Xcalls stty(1) to set and reset raw tty mode.
SHAR_EOF
chmod 0644 minirb.1 || echo "restore of minirb.1 fails"
echo "x - extracting minirb.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > minirb.c &&
X/*
X * minirb.c By Chuck Forsberg Omen Technology INC
X *        "The High Reliability Communications Software"
X *
X * A bootstrap program for Unix to receive files from computers running
X *  YMODEM Batch (Professional-YAM, PowerCom, ZCOMM, etc.).
X *
X *  Minirb uses system(3) to call stty, avoiding system dependent code.
X *   program strips CR and CPMEOF (^Z) characters (see putsec()).
X *  Please refer to rz.c for comments, etc.
X */
Xchar * Version = "minirb 2.00 05-25-87";
X
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X
X#define OK 0
X#define FALSE 0
X#define TRUE 1
X#define ERROR (-1)
X#define CAN ('X'&037)
X#define SOH 1
X#define STX 2
X#define EOT 4
X#define ACK 6
X#define NAK 025
X#define TIMEOUT (-2)
X#define RETRYMAX 9
X#define WCEOT (-10)
X
XFILE *fout;
Xlong Bytesleft;
Xint Blklen;
Xchar secbuf[1024];
Xchar linbuf[1024];
Xint Lleft=0;
Xjmp_buf tohere;
X
Xalrm() { longjmp(tohere, -1); }
X
Xbibi(n) {
X canit(); mode(0);
X fprintf(stderr, "minirb: caught signal %d; exiting", n);
X exit(128+n);
X}
X
Xmode(n) {
X if (n) system("stty raw -echo");
X else system("stty echo -raw");
X}
X
Xmain() {
X mode(1);
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 printf("minirb: Now send file(s) with \042sb file ...\042 command\r\n");
X
X if (wcreceive()==ERROR)
X  canit();
X mode(0); exit(0);
X}
X
Xwcreceive() {
X for (;;) {
X  if (wcrxpn(secbuf) == ERROR) break;
X  if (secbuf[0]==0) return OK;
X  if (procheader(secbuf)==ERROR || wcrx()==ERROR) break;
X }
X canit(); return ERROR;
X}
X
X
Xwcrxpn(rpn) char *rpn; {
X register c;
X
X purgeline();
Xet_tu:
X sendline(NAK); Lleft=0;
X while ((c = wcgetsec(rpn, 100)) != 0) {
X  if (c == WCEOT) { sendline(ACK); Lleft=0; readline(1); goto et_tu; }
X  return ERROR;
X }
X sendline(ACK); return OK;
X}
X
Xwcrx() {
X register int sectnum, sectcurr, sendchar, cblklen;
X
X sectnum=0; sendchar=NAK;
X for (;;) {
X  sendline(sendchar); Lleft=0;
X  sectcurr=wcgetsec(secbuf, 50);
X  if (sectcurr==(sectnum+1 & 0377)) {
X   sectnum++; cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
X   putsec(secbuf, cblklen);
X   if ((Bytesleft-=cblklen) < 0) Bytesleft = 0;
X   sendchar=ACK;
X  }
X  else if (sectcurr==(sectnum&0377)) sendchar=ACK;
X  else if (sectcurr==WCEOT) {
X   if (fclose(fout)==ERROR) return ERROR;
X   sendline(ACK); Lleft=0; return OK;
X  }
X  else if (sectcurr==ERROR) return ERROR;
X  else return ERROR;
X }
X}
X
Xwcgetsec(rxbuf, maxtime) char *rxbuf; int maxtime; {
X register checksum, wcj, firstch; register char *p; int sectcurr, errors;
X for (errors=0; errors<RETRYMAX; errors++) {
X  if ((firstch=readline(maxtime))==STX) { Blklen=1024; goto get2; }
X  if (firstch==SOH) {
X   Blklen=128;
Xget2:
X   sectcurr=readline(1); checksum=0;
X   if ((sectcurr+(readline(1)))==0377) {
X    for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
X     if ((firstch=readline(1)) < 0) goto bilge;
X     checksum += (*p++ = firstch);
X    }
X    if ((firstch=readline(1)) < 0) goto bilge;
X    if (((checksum-firstch)&0377)==0) return sectcurr;
X   }
X  }
X  else if (firstch==EOT) return WCEOT;
X  else if (firstch==CAN) return ERROR;
Xbilge:
X  while(readline(1)!=TIMEOUT)
X   ;
X  maxtime=40; sendline(NAK); Lleft=0;
X }
X canit(); return ERROR;
X}
X
Xreadline(timeout) int timeout; {
X register n; static char *cdq;
X
X if (--Lleft >= 0) return (*cdq++ & 0377);
X n = timeout/10;
X if (n < 2) n = 3;
X if (setjmp(tohere)) { Lleft = 0; return TIMEOUT; }
X signal(SIGALRM, alrm); alarm(n);
X Lleft=read(0, cdq=linbuf, 1024); alarm(0);
X if (Lleft < 1) return TIMEOUT;
X --Lleft; return (*cdq++ & 0377);
X}
X
Xpurgeline() { Lleft = 0; lseek(0, 0L, 2); }
X
X
Xprocheader(name) char *name; {
X register char *p;
X
X Bytesleft = 2000000000L; p = name + 1 + strlen(name);
X if (*p) sscanf(p, "%ld", &Bytesleft);
X if ((fout=fopen(name, "w")) == NULL) return ERROR;
X return OK;
X}
X
Xputsec(p, n) char *p; int n;
X{ for (; --n>=0; ++p) if (*p != 015 && *p != 032) putc(*p, fout); }
X
Xsendline(c) { char d; d = c; write(1, &d, 1); }
X
Xchar canistr[] = { 24,24,24,24,24,24,24,24,0 };
X
Xcanit() { printf(canistr); Lleft=0; }
X
X/* END of minirb.c */
X
SHAR_EOF
chmod 0644 minirb.c || echo "restore of minirb.c fails"
echo "x - extracting ptest.sh (Text)"
sed 's/^X//' << 'SHAR_EOF' > ptest.sh &&
X#a short test for sz and rz using a named pipe - no modem used.
X/etc/mknod fifo p
Xsz <fifo /etc/motd |rz >fifo
Xrm fifo
SHAR_EOF
chmod 0644 ptest.sh || echo "restore of ptest.sh fails"
echo "x - extracting rbsb.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > rbsb.c &&
X/*
X *
X *  Rev 03-06-1988
X *  This file contains Unix specific code for setting terminal modes,
X *  very little is specific to ZMODEM or YMODEM per se (that code is in
X *  sz.c and rz.c).  The CRC-16 routines used by XMODEM, YMODEM, and ZMODEM
X *  are also in this file, a fast table driven macro version
X *
X *	V7/BSD HACKERS:  SEE NOTES UNDER mode(2) !!!
X *
X *   This file is #included so the main file can set parameters such as HOWMANY.
X *   See the main files (rz.c/sz.c) for compile instructions.
X */
X
X#ifdef V7
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sgtty.h>
X#define OS "V7/BSD"
X#ifdef LLITOUT
Xlong Locmode;		/* Saved "local mode" for 4.x BSD "new driver" */
Xlong Locbit = LLITOUT;	/* Bit SUPPOSED to disable output translations */
X#include <strings.h>
X#endif
X#endif
X
X#ifndef OS
X#ifndef USG
X#define USG
X#endif
X#endif
X
X#ifdef USG
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <termio.h>
X#include <sys/ioctl.h>
X#define OS "SYS III/V"
X#define MODE2OK
X#include <string.h>
X#endif
X
X#if HOWMANY  > 255
XHowmany must be 255 or less
X#endif
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	struct stat a, b;
X
X	fstat(1, &a); fstat(2, &b);
X	Fromcu = a.st_rdev != b.st_rdev;
X	return;
X}
Xcucheck()
X{
X	if (Fromcu)
X		fprintf(stderr,"Please read the manual page BUGS chapter!\r\n");
X}
X
X
Xstruct {
X	unsigned baudr;
X	int speedcode;
X} speeds[] = {
X	110,	B110,
X	300,	B300,
X	600,	B600,
X	1200,	B1200,
X	2400,	B2400,
X	4800,	B4800,
X	9600,	B9600,
X	19200,	EXTA,
X	38400,	EXTB,
X	0,
X};
X
Xint Twostop;		/* Use two stop bits */
X
X
X#ifndef READCHECK
X#ifdef FIONREAD
X#define READCHECK
X/*
X *  Return non 0 iff something to read from io descriptor f
X */
Xrdchk(f)
X{
X	static long lf;
X
X	ioctl(f, FIONREAD, &lf);
X	return ((int) lf);
X}
X#endif
X#ifdef SV
X#define READCHECK
X#include <fcntl.h>
X
Xchar checked = '\0' ;
X/*
X * Nonblocking I/O is a bit different in System V, Release 2
X */
Xrdchk(f)
X{
X	int lf, savestat;
X
X	savestat = fcntl(f, F_GETFL) ;
X	fcntl(f, F_SETFL, savestat | O_NDELAY) ;
X	lf = read(f, &checked, 1) ;
X	fcntl(f, F_SETFL, savestat) ;
X	return(lf) ;
X}
X#endif
X#endif
X
X
Xstatic unsigned
Xgetspeed(code)
X{
X	register n;
X
X	for (n=0; speeds[n].baudr; ++n)
X		if (speeds[n].speedcode == code)
X			return speeds[n].baudr;
X	return 38400;	/* Assume fifo if ioctl failed */
X}
X
X
X
X#ifdef ICANON
Xstruct termio oldtty, tty;
X#else
Xstruct sgttyb oldtty, tty;
Xstruct tchars oldtch, tch;
X#endif
X
Xint iofd = 0;		/* File descriptor for ioctls & reads */
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	static did0 = FALSE;
X
X	vfile("mode:%d", n);
X	switch(n) {
X#ifdef USG
X	case 2:		/* Un-raw mode used by sz, sb when -g detected */
X		if(!did0)
X			(void) ioctl(iofd, TCGETA, &oldtty);
X		tty = oldtty;
X
X		tty.c_iflag = BRKINT|IXON;
X
X		tty.c_oflag = 0;	/* Transparent output */
X
X		tty.c_cflag &= ~PARENB;	/* Disable parity */
X		tty.c_cflag |= CS8;	/* Set character size = 8 */
X		if (Twostop)
X			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
X
X
X#ifdef READCHECK
X		tty.c_lflag = Zmodem ? 0 : ISIG;
X		tty.c_cc[VINTR] = Zmodem ? -1:030;	/* Interrupt char */
X#else
X		tty.c_lflag = ISIG;
X		tty.c_cc[VINTR] = Zmodem ? 03:030;	/* Interrupt char */
X#endif
X		tty.c_cc[VQUIT] = -1;			/* Quit char */
X#ifdef NFGVMIN
X		tty.c_cc[VMIN] = 1;
X#else
X		tty.c_cc[VMIN] = 3;	 /* This many chars satisfies reads */
X#endif
X		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
X
X		(void) ioctl(iofd, TCSETAW, &tty);
X		did0 = TRUE;
X		return OK;
X	case 1:
X	case 3:
X		if(!did0)
X			(void) ioctl(iofd, TCGETA, &oldtty);
X		tty = oldtty;
X
X		tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
X
X		 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
X		tty.c_lflag &= ~(ECHO | ICANON | ISIG);
X
X		tty.c_oflag = 0;	/* Transparent output */
X
X		tty.c_cflag &= ~PARENB;	/* Same baud rate, disable parity */
X		tty.c_cflag |= CS8;	/* Set character size = 8 */
X		if (Twostop)
X			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
X#ifdef NFGVMIN
X		tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
X#else
X		tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
X#endif
X		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
X		(void) ioctl(iofd, TCSETAW, &tty);
X		did0 = TRUE;
X		Baudrate = getspeed(tty.c_cflag & CBAUD);
X		return OK;
X#endif
X#ifdef V7
X	/*
X	 *  NOTE: this should transmit all 8 bits and at the same time
X	 *   respond to XOFF/XON flow control.  If no FIONREAD or other
X	 *   READCHECK alternative, also must respond to INTRRUPT char
X	 *   This doesn't work with V7.  It should work with LLITOUT,
X	 *   but LLITOUT was broken on the machine I tried it on.
X	 */
X	case 2:		/* Un-raw mode used by sz, sb when -g detected */
X		if(!did0) {
X			ioctl(iofd, TIOCEXCL, 0);
X			ioctl(iofd, TIOCGETP, &oldtty);
X			ioctl(iofd, TIOCGETC, &oldtch);
X#ifdef LLITOUT
X			ioctl(TIOCLGET, &Locmode);	/* Get "local mode" */
X#endif
X		}
X		tty = oldtty;
X		tch = oldtch;
X#ifdef READCHECK
X		tch.t_intrc = Zmodem ? -1:030;	/* Interrupt char */
X#else
X		tch.t_intrc = Zmodem ? 03:030;	/* Interrupt char */
X#endif
X		tty.sg_flags |= (ODDP|EVENP|CBREAK);
X		tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE);
X		ioctl(iofd, TIOCSETP, &tty);
X		ioctl(iofd, TIOCSETC, &tch);
X#ifdef LLITOUT
X		ioctl(TIOCLBIS, &Locbit);
X#endif
X		bibi(99);	/* un-raw doesn't work w/o lit out */
X		did0 = TRUE;
X		return OK;
X	case 1:
X	case 3:
X		if(!did0) {
X			ioctl(iofd, TIOCEXCL, 0);
X			ioctl(iofd, TIOCGETP, &oldtty);
X			ioctl(iofd, TIOCGETC, &oldtch);
X#ifdef LLITOUT
X			ioctl(TIOCLGET, &Locmode);	/* Get "local mode" */
X#endif
X		}
X		tty = oldtty;
X		tty.sg_flags |= RAW;
X		tty.sg_flags &= ~ECHO;
X		ioctl(iofd, TIOCSETP, &tty);
X		did0 = TRUE;
X		Baudrate = getspeed(tty.sg_ospeed);
X		return OK;
X#endif
X	case 0:
X		if(!did0)
X			return ERROR;
X#ifdef USG
X		(void) ioctl(iofd, TCSBRK, 1);	/* Wait for output to drain */
X		(void) ioctl(iofd, TCFLSH, 1);	/* Flush input queue */
X		(void) ioctl(iofd, TCSETAW, &oldtty);	/* Restore modes */
X		(void) ioctl(iofd, TCXONC,1);	/* Restart output */
X#endif
X#ifdef V7
X		ioctl(iofd, TIOCSETP, &oldtty);
X		ioctl(iofd, TIOCSETC, &oldtch);
X		ioctl(iofd, TIOCNXCL, 0);
X#ifdef LLITOUT
X		ioctl(TIOCLSET, &Locmode);	/* Restore "local mode" */
X#endif
X#endif
X
X		return OK;
X	default:
X		return ERROR;
X	}
X}
X
Xsendbrk()
X{
X#ifdef V7
X#ifdef TIOCSBRK
X#define CANBREAK
X	sleep(1);
X	ioctl(iofd, TIOCSBRK, 0);
X	sleep(1);
X	ioctl(iofd, TIOCCBRK, 0);
X#endif
X#endif
X#ifdef USG
X#define CANBREAK
X	ioctl(iofd, TCSBRK, 0);
X#endif
X}
X
X/* End of rbsb.c */
SHAR_EOF
chmod 0644 rbsb.c || echo "restore of rbsb.c fails"
echo "x - extracting rz.1 (Text)"
sed 's/^X//' << 'SHAR_EOF' > rz.1 &&
X'\" Revision Level 
X'\" Last Delta     04-22-88
X.TH RZ 1 OMEN
X.SH NAME
Xrx, rb, rz \- XMODEM, YMODEM, ZMODEM (Batch) file receive
X.SH SYNOPSIS
X.B rz
X.RB [\- "\ +abepqtuvy" ]
X.br
X.B rb
X.RB [\- "\ +abqtuvy" ]
X.br
X.B rx
X.RB [\- "\ abceqtuv" ]
X.I file
X.br
X.B gz
X.I "file ..."
X.br
X.RB [ \- ][ v ] rzCOMMAND
X.SH DESCRIPTION
XThis program uses error correcting protocols to receive
Xfiles over a dial-in serial port from a variety of programs running under
XPC-DOS, CP/M,
X.SM Unix,
Xand other operating systems.
XIt is invoked from a shell prompt
Xmanually, or automatically as a result of an
X"sz file ..." command given to the calling program.
X
XWhile
X.I rz
Xis smart enough to be called from
X.I cu(1),
Xvery few versions of
X.I cu(1)
Xare smart enough to allow
X.I rz
Xto work properly.
XUnix flavors of Professional-YAM are available for such dial-out application.
X
X
X.B Rz
X(Receive ZMODEM)
Xreceives files with the ZMODEM batch protocol.
XPathnames are supplied by the sending program,
Xand directories are made if necessary (and possible).
XNormally, the
X"rz" command is automatically issued by the calling ZMODEM program,
Xbut some defective ZMODEM implementations may require starting
X.I rz
Xthe old fashioned way.
X
X
X.B Rb
Xreceives file(s) with YMODEM,
Xaccepting either standard 128 byte sectors or
X1024 byte sectors
X(YAM sb
X.B -k
Xoption).
XThe user should determine when
Xthe 1024 byte block length
Xactually improves throughput without causing lost data
Xor even system crashes.
X
XIf True YMODEM (Omen Technology trademark) file information (file length, etc.)
Xis received,
Xthe file length controls the number of bytes written to
Xthe output dataset,
Xand the modify time and file mode
X(iff non zero)
Xare set accordingly.
X
XIf no True YMODEM file information is received,
Xslashes in the pathname are changed to underscore,
Xand any trailing period in the pathname is eliminated.
XThis conversion is useful for files received from CP/M systems.
XWith YMODEM, each file name is converted to lower case
Xunless it contains one or more lower case letters.
X
X
X.B Rx
Xreceives a single
X.I file
Xwith XMODEM or XMODEM-1k protocol.
XThe user should determine when
Xthe 1024 byte block length
Xactually improves throughput without causing problems.
XThe user must supply the file name to both sending and receiving programs.
XUp to 1023 garbage characters may be added to the received file.
X
X.B Gz
Xis a shell script which calls
X.I sz
Xto command Pro-YAM or ZCOMM to transmit the specified files.
XPathnames used with
X.I gz
Xmust be escaped if they have special significance to the Unix shell.
X.br
XEXAMPLE:
Xgz "-a C:*.c D:*.h"
X
X
X.B Rz
Xmay be invoked as
X.B rzCOMMAND
X(with an optional leading \- as generated by login(1)).
XFor each received file,
X.I rz
Xwill pipe the file to ``COMMAND filename''
Xwhere filename is the name of the transmitted file
Xwith the file contents as standard input.
X
XEach file transfer is acknowledged when COMMAND exits with 0 status.
XA non zero exit status terminates transfers.
X
XA typical use for this form is
X.I rzrmail
Xwhich calls rmail(1)
Xto post mail to the user specified by the transmitted file name.
XFor example, sending the file "caf" from a PC-DOS system to
X.I rzrmail
Xon a
X.SM Unix
Xsystem
Xwould result in the contents of the DOS file "caf" being mailed to user "caf".
X
XOn some
X.SM Unix
Xsystems, the login directory must contain a link to
XCOMMAND as login sets SHELL=rsh which disallows absolute
Xpathnames.
XIf invoked with a leading ``v'',
X.I rz
Xwill report progress to /tmp/rzlog.
XThe following entry works for
X.SM Unix
XSYS III/V:
X.ce
Xrzrmail::5:1::/bin:/usr/local/rzrmail
XIf the SHELL environment variable includes
X.I "rsh"
Xor
X.I "rksh"
X(restricted shell),
X.I rz
Xwill not accept absolute pathnames
Xor references to a parent directory,
Xwill not modify an existing file, and
Xremoves any files received in error.
X
XIf
X.B rz
Xis invoked with stdout and stderr to different datasets,
XVerbose is set to 2, causing frame by frame progress reports
Xto stderr.
XThis may be disabled with the
X.B q
Xoption.
X
X.PP
XThe meanings of the available options are:
X.PP
X.PD 0
X.TP
X.B a
XConvert files to
X.SM Unix
Xconventions by stripping carriage returns and all characters
Xbeginning with the first Control Z (CP/M end of file).
X.TP
X.B b
XBinary
X(tell it like it is)
Xfile transfer override.
X.TP
X.B c
XRequest 16 bit CRC.
XXMODEM file transfers default to 8 bit checksum.
XYMODEM and ZMODEM normally use 16 bit CRC.
X.TP
X.B D
XOutput file data to /dev/null; for testing.
X(Unix only)
X.TP
X.B e
XForce sender to escape all control characters;
Xnormally XON, XOFF, DLE, CR-@-CR, and Ctrl-X are escaped.
X.TP
X.B p
X(ZMODEM) Protect: skip file if destination file exists.
X.TP
X.B q
XQuiet suppresses verbosity.
X.TP
X.B "t tim"
XChange timeout to
X.I tim
Xtenths of seconds.
X.TP
X.B v
XVerbose
Xcauses a list of file
Xnames to be appended to
X/tmp/rzlog .
XMore v's generate more output.
X.TP
X.B y
XYes, clobber any existing files with the same name.
X.PD
X.ne 6
X.SH EXAMPLES
X.RE
X(Pro-YAM command)
X.RS
X.I <ALT-2>
X.br
XPro-YAM Command:
X.I "sz *.h *.c"
X.br
X(This automatically invokes
X.I rz
Xon the connected system.)
X.RE
X.SH SEE ALSO
XZMODEM.DOC,
XYMODEM.DOC,
XProfessional-YAM,
Xcrc(omen),
Xsz(omen),
Xusq(omen),
Xundos(omen)
X
XCompile time options required
Xfor various operating systems are described in the
Xsource file.
X.SH NOTES
XSending serial data to timesharing minicomputers
Xat sustained high speeds
Xhas been known to cause lockups, system halts, kernel panics,
Xand occasional antisocial behaviour.
XWhen experimenting with high speed input to a
Xsystem, consider rebooting the system
Xif the file transfers are not successful,
Xespecially if the personality of the system appears altered.
X
XThe Unix "ulimit" parameter must be set high enough
Xto permit large file transfers.
X
XThe TTY input buffering on some systems may not allow long blocks
Xor streaming input at high speed.
XYou should suspect this problem when you
Xcan't send data to the Unix system at high speeds using ZMODEM,
XYMODEM-1k or XMODEM-1k,
Xwhen YMODEM with 128 byte blocks works properly.
XIf the system's tty line handling is really broken, the serial port
Xor the entire system may not survive the onslaught of long bursts
Xof high speed data.
X
XThe DSZ or Pro-YAM
X.B "zmodem l"
Xnumeric parameter may be set to a value between 64 and 1024 to limit the
Xburst length ("zmodem pl128").
X
X32 bit CRC code courtesy Gary S. Brown.
XDirectory creation code from John Gilmore's PD TAR program.
X.SH BUGS
XCalling
X.I rz
Xfrom most versions of cu(1) doesn't work because cu's receive process
Xfights
X.I rz
Xfor characters from the modem.
X
XPrograms that do not properly implement the specified file transfer protocol
Xmay cause
X.I sz
Xto "hang" the port for a minute or two.
XEvery reported instance of this problem has been corrected by using
XZCOMM, Pro-YAM, or other program with a correct implementation
Xof the specified protocol.
X
XMany programs claiming to support YMODEM only support XMODEM with 1k blocks,
Xand they often don't get that quite right.
X
XPathnames are restricted to 127 characters.
XIn XMODEM single file mode, the pathname given on the command line
Xis still processed as described above.
XThe ASCII option\'s CR/LF to NL translation merely deletes CR\'s;
Xundos(omen) performs a more intelligent translation.
X.SH "VMS VERSION"
XThe VMS version does not set the file time.
X
XVMS C Standard I/O and RMS may interact to modify
Xfile contents unexpectedly.
X
XThe VMS version does not support invocation as
X.B rzCOMMAND .
XThe current VMS version does not support XMODEM, XMODEM-1k, or YMODEM.
X
XAccording to the VMS documentation,
Xthe buffered input routine used on the VMS version of
X.I rz
Xintroduces a delay
Xof up to one second for each protocol transaction.
XThis delay may be significant for very short files.
XRemoving the "#define BUFREAD" line from rz.c will
Xeliminate this delay at the expense of increased
XCPU utilization.
X
XThe VMS version causes DCL to generate a random off the wall
Xerror message under some error conditions; this is a result of
Xthe incompatibility of the VMS "exit" function with the
XUnix/MSDOS standard.
X.SH "ZMODEM CAPABILITIES"
X.I Rz
Xsupports incoming ZMODEM binary (-b), ASCII (-a),
Xprotect (-p),
Xclobber (-y),
Xand append (-+)
Xrequests.
XThe default is protect (-p) and binary (-b).
X
XThe Unix versions support ZMODEM command execution.
X.SH FILES
Xrz.c, crctab.c, rbsb.c, zm.c, zmodem.h Unix source files.
X
Xrz.c, crctab.c, vrzsz.c, zm.c, zmodem.h, vmodem.h, vvmodem.c,
XVMS source files.
X
X/tmp/rzlog stores debugging output generated with -vv option
X(rzlog on VMS).
SHAR_EOF
chmod 0644 rz.1 || echo "restore of rz.1 fails"
echo "x - extracting rz.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > rz.c &&
X#define VERSION "2.02 04-22-88"
X#define PUBDIR "/usr/spool/uucppublic"
X
X/*% cc -compat -M2 -Ox -K -i -DMD % -o rz; size rz;
X<-xtx-*> cc386 -Ox -DMD -DSEGMENTS=8 rz.c -o $B/rz;  size $B/rz
X *
X * rz.c By Chuck Forsberg
X *
X *	cc -O rz.c -o rz		USG (3.0) Unix
X * 	cc -O -DV7  rz.c -o rz		Unix V7, BSD 2.8 - 4.3
X *
X *	ln rz rb;  ln rz rx			For either system
X *
X *	ln rz /usr/bin/rzrmail		For remote mail.  Make this the
X *					login shell. rzrmail then calls
X *					rmail(1) to deliver mail.
X *
X * To compile on VMS:
X *
X *	define LNK$LIBRARY   SYS$LIBRARY:VAXCRTL.OLB
X *	cc rz.c
X *	cc vvmodem.c
X *	link rz,vvmodem
X *	rz :== $disk:[username.subdir]rz.exe
X *
X *
X *  Unix is a trademark of Western Electric Company
X *
X * A program for Unix to receive files and commands from computers running
X *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
X *  rz uses Unix buffered input to reduce wasted CPU time.
X *
X * Iff the program is invoked by rzCOMMAND, output is piped to 
X * "COMMAND filename"  (Unix only)
X *
X *  Some systems (Venix, Coherent, Regulus) may not support tty raw mode
X *  read(2) the same way as Unix. ONEREAD must be defined to force one
X *  character reads for these systems. Added 7-01-84 CAF
X *
X *  Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF 
X *
X *  BIX added 6-30-87 to support BIX(TM) upload protocol used by the
X *  Byte Information Exchange.
X *
X *  NFGVMIN Updated 2-18-87 CAF for Xenix systems where c_cc[VMIN]
X *  doesn't work properly (even though it compiles without error!),
X *
X *  SEGMENTS=n added 2-21-88 as a model for CP/M programs
X *    for CP/M-80 systems that cannot overlap modem and disk I/O.
X *
X *  VMS flavor hacks begin with rz version 2.00
X *
X *  -DMD may be added to compiler command line to compile in
X *    Directory-creating routines from Public Domain TAR by John Gilmore
X *
X *  HOWMANY may be tuned for best performance
X *
X *  USG UNIX (3.0) ioctl conventions courtesy  Jeff Martin
X */
X
X#ifdef vax11c
X#include <types.h>
X#include <stat.h>
X#define LOGFILE "rzlog.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 BUFREAD
Xextern int errno;
X#define SS_NORMAL SS$_NORMAL
X#else
X#define SS_NORMAL 0
X#define LOGFILE "/tmp/rzlog"
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <ctype.h>
X#include <errno.h>
Xextern int errno;
XFILE *popen();
X#endif
X
X#define OK 0
X#define FALSE 0
X#define TRUE 1
X#define ERROR (-1)
X
X/*
X * Max value for HOWMANY is 255.
X *   A larger value reduces system overhead but may evoke kernel bugs.
X *   133 corresponds to an XMODEM/CRC sector
X */
X#ifndef HOWMANY
X#define HOWMANY 133
X#endif
X
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 TIMEOUT (-2)
X#define RCDO (-3)
X#define ERRORMAX 5
X#define RETRYMAX 5
X#define WCEOT (-10)
X#define PATHLEN 257	/* ready for 4.2 bsd ? */
X#define UNIXFILE 0xF000	/* The S_IFMT file mask bit for stat */
X
Xint Zmodem=0;		/* ZMODEM protocol requested */
Xint Nozmodem = 0;	/* If invoked as "rb" */
Xunsigned Baudrate = 2400;
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
Xchar *substr();
XFILE *fout;
X
X/*
X * Routine to calculate the free bytes on the current file system
X *  ~0 means many free bytes (unknown)
X */
Xlong getfree()
X{
X	return(~0L);	/* many free bytes ... */
X}
X
Xint Lastrx;
Xint Crcflg;
Xint Firstsec;
Xint Eofseen;		/* indicates cpm eof (^Z) has been received */
Xint errors;
Xint Restricted=0;	/* restricted; no /.. or ../ in filenames */
X#ifdef ONEREAD
X/* Sorry, Regulus and some others don't work right in raw mode! */
Xint Readnum = 1;	/* Number of bytes to ask for in read() from modem */
X#else
Xint Readnum = HOWMANY;	/* Number of bytes to ask for in read() from modem */
X#endif
X
X#define DEFBYTL 2000000000L	/* default rx file size */
Xlong Bytesleft;		/* number of bytes of incoming file left */
Xlong Modtime;		/* Unix style mod time for incoming file */
Xint Filemode;		/* Unix style mode for incoming file */
Xchar Pathname[PATHLEN];
Xchar *Progname;		/* the name by which we were called */
X
Xint Batch=0;
Xint Topipe=0;
Xint MakeLCPathname=TRUE;	/* make received pathname lower case */
Xint Verbose=0;
Xint Quiet=0;		/* overrides logic that would otherwise set verbose */
Xint Nflag = 0;		/* Don't really transfer files */
Xint Rxclob=FALSE;	/* Clobber existing file */
Xint Rxbinary=FALSE;	/* receive all files in bin mode */
Xint Rxascii=FALSE;	/* receive files in ascii (translate) mode */
Xint Thisbinary;		/* current file is to be received in bin mode */
Xint Blklen;		/* record length of received packets */
X
X#ifdef SEGMENTS
Xint chinseg = 0;	/* Number of characters received in this data seg */
Xchar secbuf[1+(SEGMENTS+1)*1024];
X#else
Xchar secbuf[1025];
X#endif
X
X
Xchar linbuf[HOWMANY];
Xint Lleft=0;		/* number of characters in linbuf */
Xtime_t timep[2];
Xchar Lzmanag;		/* Local file management request */
Xchar zconv;		/* ZMODEM file conversion request */
Xchar zmanag;		/* ZMODEM file management request */
Xchar ztrans;		/* ZMODEM file transport request */
Xint Zctlesc;		/* Encode control characters */
Xint Zrwindow = 1400;	/* RX window size (controls garbage count) */
X
Xjmp_buf tohere;		/* For the interrupt on RX timeout */
X
X#define xsendline(c) sendline(c)
X#include "zm.c"
X
Xint tryzhdrtype=ZRINIT;	/* Header type to send corresponding to Last rx close */
X
Xalrm()
X{
X	longjmp(tohere, -1);
X}
X
X/* called by signal interrupt or terminate to clean things up */
Xbibi(n)
X{
X	if (Zmodem)
X		zmputs(Attn);
X	canit(); mode(0);
X	fprintf(stderr, "rz: caught signal %d; exiting", n);
X	cucheck();
X	exit(128+n);
X}
X
Xmain(argc, argv)
Xchar *argv[];
X{
X	register char *cp;
X	register npats;
X	char *virgin, **patts;
X	char *getenv();
X	int exitcode;
X
X	Rxtimeout = 100;
X	setbuf(stderr, NULL);
X	if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
X		Restricted=TRUE;
X
X	from_cu();
X#ifdef vax11c
X	Progname = virgin = "rz";
X#else
X	chkinvok(virgin=argv[0]);	/* if called as [-]rzCOMMAND set flag */
X#endif
X	npats = 0;
X	while (--argc) {
X		cp = *++argv;
X		if (*cp == '-') {
X			while( *++cp) {
X				switch(*cp) {
X				case '\\':
X					 cp[1] = toupper(cp[1]);  continue;
X				case '+':
X					Lzmanag = ZMAPND; break;
X				case 'a':
X					Rxascii=TRUE;  break;
X				case 'b':
X					Rxbinary=TRUE; break;
X				case 'c':
X					Crcflg=TRUE; break;
X#ifndef vax11c
X				case 'D':
X					Nflag = TRUE; break;
X#endif
X				case 'e':
X					Zctlesc = 1; break;
X				case 'p':
X					Lzmanag = ZMPROT;  break;
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 'w':
X					if (--argc < 1) {
X						usage();
X					}
X					Zrwindow = atoi(*++argv);
X					break;
X				case 'u':
X					MakeLCPathname=FALSE; break;
X				case 'v':
X					++Verbose; break;
X				case 'y':
X					Rxclob=TRUE; 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			}
X		}
X	}
X	if (npats > 1)
X		usage();
X	if (Batch && npats)
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		fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
X	}
X	if (Fromcu && !Quiet) {
X		if (Verbose == 0)
X			Verbose = 2;
X	}
X	mode(1);
X	if (signal(SIGINT, bibi) == SIG_IGN) {
X		signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
X	}
X	else {
X		signal(SIGINT, bibi); signal(SIGKILL, bibi);
X	}
X	signal(SIGTERM, bibi);
X	if (wcreceive(npats, patts)==ERROR) {
X		exitcode=0200;
X		canit();
X	}
X	mode(0);
X	if (exitcode && !Zmodem)	/* bellow again with all thy might. */
X		canit();
X	if (exitcode)
X		cucheck();
X	exit(exitcode ? exitcode:SS_NORMAL);
X}
X
X
Xusage()
X{
X	cucheck();
X#ifdef vax11c
X	fprintf(stderr,"Usage:	rz [-abeuvy]\n");
X#else
X	fprintf(stderr,"Usage:	rz [-abeuvy]		(ZMODEM)\n");
X	fprintf(stderr,"or	rb [-abuvy]		(YMODEM)\n");
X	fprintf(stderr,"or	rx [-abcv] file	(XMODEM or XMODEM-1k)\n");
X#endif
X	fprintf(stderr,"	  -a ASCII transfer (strip CR)\n");
X	fprintf(stderr,"	  -b Binary transfer for all files\n");
X#ifndef vax11c
X	fprintf(stderr,"	  -c Use 16 bit CRC	(XMODEM)\n");
X#endif
X	fprintf(stderr,"	  -e Escape control characters	(ZMODEM)\n");
X	fprintf(stderr,"	  -v Verbose more v's give more info\n");
X	fprintf(stderr,"	  -y Yes, clobber existing file if any\n");
X	fprintf(stderr,"%s %s for %s by Chuck Forsberg, Omen Technology INC\n",
X	  Progname, VERSION, OS);
X	fprintf(stderr, "\t\t\042The High Reliability Software\042\n");
X	exit(SS_NORMAL);
X}
X/*
X *  Debugging information output interface routine
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/*
X * Let's receive something already.
X */
X
Xchar *rbmsg =
X"%s ready. To begin transfer, type \"%s file ...\" to your modem program\r\n\n";
X
Xwcreceive(argc, argp)
Xchar **argp;
X{
X	register c;
X
X	if (Batch || argc==0) {
X		Crcflg=1;
X		if ( !Quiet)
X			fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz");
SHAR_EOF
echo "End of part 1"
echo "File rz.c is continued in part 2"
echo "2" > s2_seq_.tmp
exit 0
-- 
Keith Petersen
Arpa: W8SDZ@SIMTEL20.ARPA
Uucp: {bellcore,decwrl,harvard,lll-crg,ucbvax,uw-beaver}!simtel20.arpa!w8sdz
GEnie: W8SDZ

w8sdz@brl-smoke.ARPA (Keith B. Petersen ) (05/03/88)

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 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file rz.c continued
#
CurArch=2
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 rz.c"
sed 's/^X//' << 'SHAR_EOF' >> rz.c
X		if (c=tryz()) {
X			if (c == ZCOMPL)
X				return OK;
X			if (c == ERROR)
X				goto fubar;
X			c = rzfiles();
X			if (c)
X				goto fubar;
X		} else {
X			for (;;) {
X				if (wcrxpn(secbuf)== ERROR)
X					goto fubar;
X				if (secbuf[0]==0)
X					return OK;
X				if (procheader(secbuf) == ERROR)
X					goto fubar;
X				if (wcrx()==ERROR)
X					goto fubar;
X			}
X		}
X	} else {
X		Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
X
X		procheader(""); strcpy(Pathname, *argp); checkpath(Pathname);
X		fprintf(stderr, "\nrz: ready to receive %s\r\n", Pathname);
X		if ((fout=fopen(Pathname, "w")) == NULL)
X			return ERROR;
X		if (wcrx()==ERROR)
X			goto fubar;
X	}
X	return OK;
Xfubar:
X	canit();
X#ifndef vax11c
X	if (Topipe && fout) {
X		pclose(fout);  return ERROR;
X	}
X#endif
X	if (fout)
X		fclose(fout);
X#ifndef vax11c
X	if (Restricted) {
X		unlink(Pathname);
X		fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);
X	}
X#endif
X	return ERROR;
X}
X
X
X/*
X * Fetch a pathname from the other end as a C ctyle ASCIZ string.
X * Length is indeterminate as long as less than Blklen
X * A null string represents no more files (YMODEM)
X */
Xwcrxpn(rpn)
Xchar *rpn;	/* receive a pathname */
X{
X	register c;
X
X#ifdef NFGVMIN
X	readline(1);
X#else
X	purgeline();
X#endif
X
Xet_tu:
X	Firstsec=TRUE;  Eofseen=FALSE;
X	sendline(Crcflg?WANTCRC:NAK);
X	Lleft=0;	/* Do read next time ... */
X	while ((c = wcgetsec(rpn, 100)) != 0) {
X		if (c == WCEOT) {
X			zperr( "Pathname fetch returned %d", c);
X			sendline(ACK);
X			Lleft=0;	/* Do read next time ... */
X			readline(1);
X			goto et_tu;
X		}
X		return ERROR;
X	}
X	sendline(ACK);
X	return OK;
X}
X
X/*
X * Adapted from CMODEM13.C, written by
X * Jack M. Wierda and Roderick W. Hart
X */
X
Xwcrx()
X{
X	register int sectnum, sectcurr;
X	register char sendchar;
X	register char *p;
X	int cblklen;			/* bytes to dump this block */
X
X	Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
X	sendchar=Crcflg?WANTCRC:NAK;
X
X	for (;;) {
X		sendline(sendchar);	/* send it now, we're ready! */
X		Lleft=0;	/* Do read next time ... */
X		sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
X		report(sectcurr);
X		if (sectcurr==(sectnum+1 &0377)) {
X			sectnum++;
X			cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
X			if (putsec(secbuf, cblklen)==ERROR)
X				return ERROR;
X			if ((Bytesleft-=cblklen) < 0)
X				Bytesleft = 0;
X			sendchar=ACK;
X		}
X		else if (sectcurr==(sectnum&0377)) {
X			zperr( "Received dup Sector");
X			sendchar=ACK;
X		}
X		else if (sectcurr==WCEOT) {
X			if (closeit())
X				return ERROR;
X			sendline(ACK);
X			Lleft=0;	/* Do read next time ... */
X			return OK;
X		}
X		else if (sectcurr==ERROR)
X			return ERROR;
X		else {
X			zperr( "Sync Error");
X			return ERROR;
X		}
X	}
X}
X
X/*
X * Wcgetsec fetches a Ward Christensen type sector.
X * Returns sector number encountered or ERROR if valid sector not received,
X * or CAN CAN received
X * or WCEOT if eot sector
X * time is timeout for first char, set to 4 seconds thereafter
X ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
X *    (Caller must do that when he is good and ready to get next sector)
X */
X
Xwcgetsec(rxbuf, maxtime)
Xchar *rxbuf;
Xint maxtime;
X{
X	register checksum, wcj, firstch;
X	register unsigned short oldcrc;
X	register char *p;
X	int sectcurr;
X
X	for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
X
X		if ((firstch=readline(maxtime))==STX) {
X			Blklen=1024; goto get2;
X		}
X		if (firstch==SOH) {
X			Blklen=128;
Xget2:
X			sectcurr=readline(1);
X			if ((sectcurr+(oldcrc=readline(1)))==0377) {
X				oldcrc=checksum=0;
X				for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
X					if ((firstch=readline(1)) < 0)
X						goto bilge;
X					oldcrc=updcrc(firstch, oldcrc);
X					checksum += (*p++ = firstch);
X				}
X				if ((firstch=readline(1)) < 0)
X					goto bilge;
X				if (Crcflg) {
X					oldcrc=updcrc(firstch, oldcrc);
X					if ((firstch=readline(1)) < 0)
X						goto bilge;
X					oldcrc=updcrc(firstch, oldcrc);
X					if (oldcrc & 0xFFFF)
X						zperr( "CRC");
X					else {
X						Firstsec=FALSE;
X						return sectcurr;
X					}
X				}
X				else if (((checksum-firstch)&0377)==0) {
X					Firstsec=FALSE;
X					return sectcurr;
X				}
X				else
X					zperr( "Checksum");
X			}
X			else
X				zperr("Sector number garbled");
X		}
X		/* make sure eot really is eot and not just mixmash */
X#ifdef NFGVMIN
X		else if (firstch==EOT && readline(1)==TIMEOUT)
X			return WCEOT;
X#else
X		else if (firstch==EOT && Lleft==0)
X			return WCEOT;
X#endif
X		else if (firstch==CAN) {
X			if (Lastrx==CAN) {
X				zperr( "Sender CANcelled");
X				return ERROR;
X			} else {
X				Lastrx=CAN;
X				continue;
X			}
X		}
X		else if (firstch==TIMEOUT) {
X			if (Firstsec)
X				goto humbug;
Xbilge:
X			zperr( "TIMEOUT");
X		}
X		else
X			zperr( "Got 0%o sector header", firstch);
X
Xhumbug:
X		Lastrx=0;
X		while(readline(1)!=TIMEOUT)
X			;
X		if (Firstsec) {
X			sendline(Crcflg?WANTCRC:NAK);
X			Lleft=0;	/* Do read next time ... */
X		} else {
X			maxtime=40; sendline(NAK);
X			Lleft=0;	/* Do read next time ... */
X		}
X	}
X	/* try to stop the bubble machine. */
X	canit();
X	return ERROR;
X}
X
X#ifndef vax11c
X/*
X * This version of readline is reasoably well suited for
X * reading many characters.
X *  (except, currently, for the Regulus version!)
X *
X * timeout is in tenths of seconds
X */
Xreadline(timeout)
Xint timeout;
X{
X	register n;
X	static char *cdq;	/* pointer for removing chars from linbuf */
X
X	if (--Lleft >= 0) {
X		if (Verbose > 8) {
X			fprintf(stderr, "%02x ", *cdq&0377);
X		}
X		return (*cdq++ & 0377);
X	}
X	n = timeout/10;
X	if (n < 2)
X		n = 3;
X	if (Verbose > 5)
X		fprintf(stderr, "Calling read: alarm=%d  Readnum=%d ",
X		  n, Readnum);
X	if (setjmp(tohere)) {
X#ifdef TIOCFLUSH
X/*		ioctl(iofd, TIOCFLUSH, 0); */
X#endif
X		Lleft = 0;
X		if (Verbose>1)
X			fprintf(stderr, "Readline:TIMEOUT\n");
X		return TIMEOUT;
X	}
X	signal(SIGALRM, alrm); alarm(n);
X	Lleft=read(iofd, cdq=linbuf, Readnum);
X	alarm(0);
X	if (Verbose > 5) {
X		fprintf(stderr, "Read returned %d bytes\n", Lleft);
X	}
X	if (Lleft < 1)
X		return TIMEOUT;
X	--Lleft;
X	if (Verbose > 8) {
X		fprintf(stderr, "%02x ", *cdq&0377);
X	}
X	return (*cdq++ & 0377);
X}
X
X
X
X/*
X * Purge the modem input queue of all characters
X */
Xpurgeline()
X{
X	Lleft = 0;
X#ifdef USG
X	ioctl(iofd, TCFLSH, 0);
X#else
X	lseek(iofd, 0L, 2);
X#endif
X}
X#endif
X
X
X/*
X * Process incoming file information header
X */
Xprocheader(name)
Xchar *name;
X{
X	register char *openmode, *p, **pp;
X
X	/* set default parameters and overrides */
X	openmode = "w";
X	Thisbinary = (!Rxascii) || Rxbinary;
X	if (Lzmanag)
X		zmanag = Lzmanag;
X
X	/*
X	 *  Process ZMODEM remote file management requests
X	 */
X	if (!Rxbinary && zconv == ZCNL)	/* Remote ASCII override */
X		Thisbinary = 0;
X	if (zconv == ZCBIN)	/* Remote Binary override */
X		Thisbinary = TRUE;
X	else if (zmanag == ZMAPND)
X		openmode = "a";
X
X#ifndef BIX
X	/* Check for existing file */
X	if (!Rxclob && (zmanag&ZMMASK) != ZMCLOB && (fout=fopen(name, "r"))) {
X		fclose(fout);  return ERROR;
X	}
X#endif
X
X	Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
X
X	p = name + 1 + strlen(name);
X	if (*p) {	/* file coming from Unix or DOS system */
X		sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
X#ifndef vax11c
X		if (Filemode & UNIXFILE)
X			++Thisbinary;
X#endif
X		if (Verbose) {
X			fprintf(stderr,  "Incoming: %s %ld %lo %o\n",
X			  name, Bytesleft, Modtime, Filemode);
X		}
X	}
X
X#ifdef BIX
X	if ((fout=fopen("scratchpad", openmode)) == NULL)
X		return ERROR;
X	return OK;
X#else
X
X	else {		/* File coming from CP/M system */
X		for (p=name; *p; ++p)		/* change / to _ */
X			if ( *p == '/')
X				*p = '_';
X
X		if ( *--p == '.')		/* zap trailing period */
X			*p = 0;
X	}
X
X#ifndef vax11c
X	if (!Zmodem && MakeLCPathname && !IsAnyLower(name)
X	  && !(Filemode&UNIXFILE))
X		uncaps(name);
X#endif
X	if (Topipe) {
X		sprintf(Pathname, "%s %s", Progname+2, name);
X		if (Verbose)
X			fprintf(stderr,  "Topipe: %s %s\n",
X			  Pathname, Thisbinary?"BIN":"ASCII");
X#ifndef vax11c
X		if ((fout=popen(Pathname, "w")) == NULL)
X			return ERROR;
X#endif
X	} else {
X		strcpy(Pathname, name);
X		if (Verbose) {
X			fprintf(stderr,  "Receiving %s %s %s\n",
X			  name, Thisbinary?"BIN":"ASCII", openmode);
X		}
X		checkpath(name);
X		if (Nflag)
X			name = "/dev/null";
X#ifdef MD
X		fout = fopen(name, openmode);
X		if ( !fout)
X			if (make_dirs(name))
X				fout = fopen(name, openmode);
X#else
X		fout = fopen(name, openmode);
X#endif
X		if ( !fout)
X			return ERROR;
X	}
X	return OK;
X#endif /* BIX */
X}
X
X#ifdef MD
X/*
X *  Directory-creating routines from Public Domain TAR by John Gilmore
X */
X
X/*
X * After a file/link/symlink/dir creation has failed, see if
X * it's because some required directory was not present, and if
X * so, create all required dirs.
X */
Xmake_dirs(pathname)
Xregister char *pathname;
X{
X	register char *p;		/* Points into path */
X	int madeone = 0;		/* Did we do anything yet? */
X	int save_errno = errno;		/* Remember caller's errno */
X
X	if (errno != ENOENT)
X		return 0;		/* Not our problem */
X
X	for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) {
X		/* Avoid mkdir of empty string, if leading or double '/' */
X		if (p == pathname || p[-1] == '/')
X			continue;
X		/* Avoid mkdir where last part of path is '.' */
X		if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
X			continue;
X		*p = 0;				/* Truncate the path there */
X		if ( !mkdir(pathname, 0777)) {	/* Try to create it as a dir */
X			vfile("Made directory %s\n", pathname);
X			madeone++;		/* Remember if we made one */
X			*p = '/';
X			continue;
X		}
X		*p = '/';
X		if (errno == EEXIST)		/* Directory already exists */
X			continue;
X		/*
X		 * Some other error in the mkdir.  We return to the caller.
X		 */
X		break;
X	}
X	errno = save_errno;		/* Restore caller's errno */
X	return madeone;			/* Tell them to retry if we made one */
X}
X
X#if (MD != 2)
X#define	TERM_SIGNAL(status)	((status) & 0x7F)
X#define TERM_COREDUMP(status)	(((status) & 0x80) != 0)
X#define TERM_VALUE(status)	((status) >> 8)
X/*
X * Make a directory.  Compatible with the mkdir() system call on 4.2BSD.
X */
Xmkdir(dpath, dmode)
Xchar *dpath;
Xint dmode;
X{
X	int cpid, status;
X	struct stat statbuf;
X
X	if (stat(dpath,&statbuf) == 0) {
X		errno = EEXIST;		/* Stat worked, so it already exists */
X		return -1;
X	}
X
X	/* If stat fails for a reason other than non-existence, return error */
X	if (errno != ENOENT) return -1; 
X
X	switch (cpid = fork()) {
X
X	case -1:			/* Error in fork() */
X		return(-1);		/* Errno is set already */
X
X	case 0:				/* Child process */
X		/*
X		 * Cheap hack to set mode of new directory.  Since this
X		 * child process is going away anyway, we zap its umask.
X		 * FIXME, this won't suffice to set SUID, SGID, etc. on this
X		 * directory.  Does anybody care?
X		 */
X		status = umask(0);	/* Get current umask */
X		status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
X		execl("/bin/mkdir", "mkdir", dpath, (char *)0);
X		_exit(-1);		/* Can't exec /bin/mkdir */
X	
X	default:			/* Parent process */
X		while (cpid != wait(&status)) ;	/* Wait for kid to finish */
X	}
X
X	if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
X		errno = EIO;		/* We don't know why, but */
X		return -1;		/* /bin/mkdir failed */
X	}
X
X	return 0;
X}
X#endif /* MD != 2 */
X#endif /* MD */
X
X/*
X * Putsec writes the n characters of buf to receive file fout.
X *  If not in binary mode, carriage returns, and all characters
X *  starting with CPMEOF are discarded.
X */
Xputsec(buf, n)
Xchar *buf;
Xregister n;
X{
X	register char *p;
X
X	if (n == 0)
X		return OK;
X	if (Thisbinary) {
X		for (p=buf; --n>=0; )
X			putc( *p++, fout);
X	}
X	else {
X		if (Eofseen)
X			return OK;
X		for (p=buf; --n>=0; ++p ) {
X			if ( *p == '\r')
X				continue;
X			if (*p == CPMEOF) {
X				Eofseen=TRUE; return OK;
X			}
X			putc(*p ,fout);
X		}
X	}
X	return OK;
X}
X
X#ifndef vax11c
X/*
X *  Send a character to modem.  Small is beautiful.
X */
Xsendline(c)
X{
X	char d;
X
X	d = c;
X	if (Verbose>6)
X		fprintf(stderr, "Sendline: %x\n", c);
X	write(1, &d, 1);
X}
X
Xflushmo() {}
X#endif
X
X
X
X
X
X/* make string s lower case */
Xuncaps(s)
Xregister char *s;
X{
X	for ( ; *s; ++s)
X		if (isupper(*s))
X			*s = tolower(*s);
X}
X/*
X * IsAnyLower returns TRUE if string s has lower case letters.
X */
XIsAnyLower(s)
Xregister char *s;
X{
X	for ( ; *s; ++s)
X		if (islower(*s))
X			return TRUE;
X	return FALSE;
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
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/* 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	Lleft=0;	/* Do read next time ... */
X	fflush(stdout);
X#endif
X}
X
X
Xreport(sct)
Xint sct;
X{
X	if (Verbose>1)
X		fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
X}
X
X#ifndef vax11c
X/*
X * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
X * If called as [-][dir/../]rzCOMMAND set the pipe flag
X * If called as rb use YMODEM protocol
X */
Xchkinvok(s)
Xchar *s;
X{
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]=='r' && s[1]=='z')
X		Batch = TRUE;
X	if (s[0]=='r' && s[1]=='b')
X		Batch = Nozmodem = TRUE;
X	if (s[2] && s[0]=='r' && s[1]=='b')
X		Topipe=TRUE;
X	if (s[2] && s[0]=='r' && s[1]=='z')
X		Topipe=TRUE;
X}
X#endif
X
X/*
X * Totalitarian Communist pathname processing
X */
Xcheckpath(name)
Xchar *name;
X{
X	if (Restricted) {
X		if (fopen(name, "r") != NULL) {
X			canit();
X			fprintf(stderr, "\r\nrz: %s exists\n", name);
X			bibi(-1);
X		}
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\nrz:\tSecurity Violation\r\n");
X			bibi(-1);
X		}
X	}
X}
X
X/*
X * Initialize for Zmodem receive attempt, try to activate Zmodem sender
X *  Handles ZSINIT frame
X *  Return ZFILE if Zmodem filename received, -1 on error,
X *   ZCOMPL if transaction finished,  else 0
X */
Xtryz()
X{
X	register c, n;
X	register cmdzack1flg;
X
X	if (Nozmodem)		/* Check for "rb" program name */
X		return 0;
X
X
X	for (n=Zmodem?15:5; --n>=0; ) {
X		/* Set buffer length (0) and capability flags */
X#ifdef SEGMENTS
X		stohdr(SEGMENTS*1024L);
X#else
X		stohdr(0L);
X#endif
X#ifdef CANBREAK
X		Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
X#else
X		Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
X#endif
X		if (Zctlesc)
X			Txhdr[ZF0] |= TESCCTL;
X		zshhdr(tryzhdrtype, Txhdr);
X		if (tryzhdrtype == ZSKIP)	/* Don't skip too far */
X			tryzhdrtype = ZRINIT;	/* CAF 8-21-87 */
Xagain:
X		switch (zgethdr(Rxhdr, 0)) {
X		case ZRQINIT:
X			continue;
X		case ZEOF:
X			continue;
X		case TIMEOUT:
X			continue;
X		case ZFILE:
X			zconv = Rxhdr[ZF0];
X			zmanag = Rxhdr[ZF1];
X			ztrans = Rxhdr[ZF2];
X			tryzhdrtype = ZRINIT;
X			c = zrdata(secbuf, 1024);
X			mode(3);
X			if (c == GOTCRCW)
X				return ZFILE;
X			zshhdr(ZNAK, Txhdr);
X			goto again;
X		case ZSINIT:
X			Zctlesc = TESCCTL & Rxhdr[ZF0];
X			if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {
X				stohdr(1L);
X				zshhdr(ZACK, Txhdr);
X				goto again;
X			}
X			zshhdr(ZNAK, Txhdr);
X			goto again;
X		case ZFREECNT:
X			stohdr(getfree());
X			zshhdr(ZACK, Txhdr);
X			goto again;
X		case ZCOMMAND:
X#ifdef vax11c
X			return ERROR;
X#else
X			cmdzack1flg = Rxhdr[ZF0];
X			if (zrdata(secbuf, 1024) == GOTCRCW) {
X				if (cmdzack1flg & ZCACK1)
X					stohdr(0L);
X				else
X					stohdr((long)sys2(secbuf));
X				purgeline();	/* dump impatient questions */
X				do {
X					zshhdr(ZCOMPL, Txhdr);
X				}
X				while (++errors<20 && zgethdr(Rxhdr,1) != ZFIN);
X				ackbibi();
X				if (cmdzack1flg & ZCACK1)
X					exec2(secbuf);
X				return ZCOMPL;
X			}
X			zshhdr(ZNAK, Txhdr); goto again;
X#endif
X		case ZCOMPL:
X			goto again;
X		default:
X			continue;
X		case ZFIN:
X			ackbibi(); return ZCOMPL;
X		case ZCAN:
X			return ERROR;
X		}
X	}
X	return 0;
X}
X
X/*
X * Receive 1 or more files with ZMODEM protocol
X */
Xrzfiles()
X{
X	register c;
X
X	for (;;) {
X		switch (c = rzfile()) {
X		case ZEOF:
X		case ZSKIP:
X			switch (tryz()) {
X			case ZCOMPL:
X				return OK;
X			default:
X				return ERROR;
X			case ZFILE:
X				break;
X			}
X			continue;
X		default:
X			return c;
X		case ERROR:
X			return ERROR;
X		}
X	}
X}
X
X/*
X * Receive a file with ZMODEM protocol
X *  Assumes file name frame is in secbuf
X */
Xrzfile()
X{
X	register c, n;
X	long rxbytes;
X
X	Eofseen=FALSE;
X	if (procheader(secbuf) == ERROR) {
X		return (tryzhdrtype = ZSKIP);
X	}
X
X	n = 20; rxbytes = 0l;
X
X	for (;;) {
X#ifdef SEGMENTS
X		chinseg = 0;
X#endif
X		stohdr(rxbytes);
X		zshhdr(ZRPOS, Txhdr);
Xnxthdr:
X		switch (c = zgethdr(Rxhdr, 0)) {
X		default:
X			vfile("rzfile: zgethdr returned %d", c);
X			return ERROR;
X		case ZNAK:
X		case TIMEOUT:
X#ifdef SEGMENTS
X			putsec(secbuf, chinseg);
X			chinseg = 0;
X#endif
X			if ( --n < 0) {
X				vfile("rzfile: zgethdr returned %d", c);
X				return ERROR;
X			}
X		case ZFILE:
X			zrdata(secbuf, 1024);
X			continue;
X		case ZEOF:
X#ifdef SEGMENTS
X			putsec(secbuf, chinseg);
X			chinseg = 0;
X#endif
X			if (rclhdr(Rxhdr) != rxbytes) {
X				/*
X				 * Ignore eof if it's at wrong place - force
X				 *  a timeout because the eof might have gone
X				 *  out before we sent our zrpos.
X				 */
X				errors = 0;  goto nxthdr;
X			}
X			if (closeit()) {
X				tryzhdrtype = ZFERR;
X				vfile("rzfile: closeit returned <> 0");
X				return ERROR;
X			}
X			vfile("rzfile: normal EOF");
X			return c;
X		case ERROR:	/* Too much garbage in header search error */
X#ifdef SEGMENTS
X			putsec(secbuf, chinseg);
X			chinseg = 0;
X#endif
X			if ( --n < 0) {
X				vfile("rzfile: zgethdr returned %d", c);
X				return ERROR;
X			}
X			zmputs(Attn);
X			continue;
X		case ZSKIP:
X#ifdef SEGMENTS
X			putsec(secbuf, chinseg);
X			chinseg = 0;
X#endif
X			closeit();
X			vfile("rzfile: Sender SKIPPED file");
X			return c;
X		case ZDATA:
X			if (rclhdr(Rxhdr) != rxbytes) {
X				if ( --n < 0) {
X					return ERROR;
X				}
X#ifdef SEGMENTS
X				putsec(secbuf, chinseg);
X				chinseg = 0;
X#endif
X				zmputs(Attn);  continue;
X			}
Xmoredata:
X			if (Verbose>1)
X				fprintf(stderr, "\r%7ld ZMODEM%s    ",
X				  rxbytes, Crc32?" CRC-32":"");
X#ifdef SEGMENTS
X			if (chinseg >= (1024 * SEGMENTS)) {
X				putsec(secbuf, chinseg);
X				chinseg = 0;
X			}
X			switch (c = zrdata(secbuf+chinseg, 1024))
X#else
X			switch (c = zrdata(secbuf, 1024))
X#endif
X			{
X			case ZCAN:
X#ifdef SEGMENTS
X				putsec(secbuf, chinseg);
X				chinseg = 0;
X#endif
X				vfile("rzfile: zgethdr returned %d", c);
X				return ERROR;
X			case ERROR:	/* CRC error */
X#ifdef SEGMENTS
X				putsec(secbuf, chinseg);
X				chinseg = 0;
X#endif
X				if ( --n < 0) {
X					vfile("rzfile: zgethdr returned %d", c);
X					return ERROR;
X				}
X				zmputs(Attn);
X				continue;
X			case TIMEOUT:
X#ifdef SEGMENTS
X				putsec(secbuf, chinseg);
X				chinseg = 0;
X#endif
X				if ( --n < 0) {
X					vfile("rzfile: zgethdr returned %d", c);
X					return ERROR;
X				}
X				continue;
X			case GOTCRCW:
X				n = 20;
X#ifdef SEGMENTS
X				chinseg += Rxcount;
X				putsec(secbuf, chinseg);
X				chinseg = 0;
X#else
X				putsec(secbuf, Rxcount);
X#endif
X				rxbytes += Rxcount;
X				stohdr(rxbytes);
X				zshhdr(ZACK, Txhdr);
X				sendline(XON);
X				goto nxthdr;
X			case GOTCRCQ:
X				n = 20;
X#ifdef SEGMENTS
X				chinseg += Rxcount;
X#else
X				putsec(secbuf, Rxcount);
X#endif
X				rxbytes += Rxcount;
X				stohdr(rxbytes);
X				zshhdr(ZACK, Txhdr);
X				goto moredata;
X			case GOTCRCG:
X				n = 20;
X#ifdef SEGMENTS
X				chinseg += Rxcount;
X#else
X				putsec(secbuf, Rxcount);
X#endif
X				rxbytes += Rxcount;
X				goto moredata;
X			case GOTCRCE:
X				n = 20;
X#ifdef SEGMENTS
X				chinseg += Rxcount;
X#else
X				putsec(secbuf, Rxcount);
X#endif
X				rxbytes += Rxcount;
X				goto nxthdr;
X			}
X		}
X	}
X}
X
X/*
X * Send a string to the modem, processing for \336 (sleep 1 sec)
X *   and \335 (break signal)
X */
Xzmputs(s)
Xchar *s;
X{
X	register c;
X
X	while (*s) {
X		switch (c = *s++) {
X		case '\336':
X			sleep(1); continue;
X		case '\335':
X			sendbrk(); continue;
X		default:
X			sendline(c);
X		}
X	}
X}
X
X/*
X * Close the receive dataset, return OK or ERROR
X */
Xcloseit()
X{
X#ifndef vax11c
X	if (Topipe) {
X		if (pclose(fout)) {
X			return ERROR;
X		}
X		return OK;
X	}
X#endif
X	if (fclose(fout)==ERROR) {
X		fprintf(stderr, "file close ERROR\n");
X		return ERROR;
X	}
X#ifndef vax11c
X	if (Modtime) {
X		timep[0] = time(NULL);
X		timep[1] = Modtime;
X		utime(Pathname, timep);
X	}
X#endif
X	if ((Filemode&S_IFMT) == S_IFREG)
X		chmod(Pathname, (07777 & Filemode));
X	return OK;
X}
X
X/*
X * Ack a ZFIN packet, let byegones be byegones
X */
Xackbibi()
X{
X	register n;
X
X	vfile("ackbibi:");
X	Readnum = 1;
X	stohdr(0L);
X	for (n=3; --n>=0; ) {
X		purgeline();
X		zshhdr(ZFIN, Txhdr);
X		switch (readline(100)) {
X		case 'O':
X			readline(1);	/* Discard 2nd 'O' */
X			vfile("ackbibi complete");
X			return;
X		case RCDO:
X			return;
X		case TIMEOUT:
X		default:
X			break;
X		}
X	}
X}
X
X
X
X/*
X * Local console output simulation
X */
Xbttyout(c)
X{
X	if (Verbose || Fromcu)
X		putc(c, stderr);
X}
X
X#ifndef vax11c
X/*
X * Strip leading ! if present, do shell escape. 
X */
Xsys2(s)
Xregister char *s;
X{
X	if (*s == '!')
X		++s;
X	return system(s);
X}
X/*
X * Strip leading ! if present, do exec.
X */
Xexec2(s)
Xregister char *s;
X{
X	if (*s == '!')
X		++s;
X	mode(0);
X	execl("/bin/sh", "sh", "-c", s);
X}
X#endif
X/* End of rz.c */
SHAR_EOF
echo "File rz.c is complete"
chmod 0644 rz.c || echo "restore of rz.c fails"
echo "x - extracting sz.1 (Text)"
sed 's/^X//' << 'SHAR_EOF' > sz.1 &&
X'\" Revision Level 
X'\" Last Delta     04-21-88
X.TH SZ 1 OMEN
X.SH NAME
Xsx, sb, sz \- XMODEM, YMODEM, ZMODEM file send
X.SH SYNOPSIS
Xsz
X.RB [\- +abdefkLlNnopqTtuvyY ]
X.I file ...
X.br
Xsb
X.RB [\- adfkqtuv ]
X.I file ...
X.br
Xsx
X.RB [\- akqtuv ]
X.I file
X.br
Xsz
X.RB [\- oqtv ]
X.B "-c COMMAND"
X.br
Xsz
X.RB [\- oqtv ]
X.B "-i COMMAND"
X.br
Xsz -TT
X.SH DESCRIPTION
X.B Sz
Xuses the ZMODEM, YMODEM or XMODEM error correcting protocol to send
Xone or more files over a dial-in serial port to a variety of programs running under
XPC-DOS, CP/M, Unix, VMS, and other operating systems.
X
XWhile
X.I rz
Xis smart enough to be called from
X.I cu(1),
Xvery few versions of
X.I cu(1)
Xare smart enough to allow
X.I sz
Xto work properly.
XUnix flavors of Professional-YAM are available for such dial-out application.
X
X
X.B Sz
Xsends one or more files with ZMODEM protocol.
X
XZMODEM
Xgreatly simplifies file transfers compared to XMODEM.
XIn addition to a friendly user interface, ZMODEM
Xprovides Personal Computer and other users
Xan efficient, accurate, and robust file transfer method.
X
XZMODEM provides complete
X.B "END-TO-END"
Xdata integrity between application programs.
XZMODEM's 32 bit CRC catches errors
Xthat sneak into even the most advanced networks.
X
XAdvanced file management features include
XAutoDownload (Automatic file Download initiated without user intervention),
XDisplay of individual and total file lengths and transmission time estimates,
XCrash Recovery,
Xselective file transfers,
Xand preservation of
Xexact file date and length.
X
XOutput from another program may be piped to
X.B sz
Xfor transmission by denoting standard input with "-":
X.ce
Xls -l | sz -
XThe program output is transmitted with the filename sPID.sz
Xwhere PID is the process ID of the
X.B sz
Xprogram.
XIf the environment variable
X.B ONAME
Xis set, that is used instead.
XIn this case, the Unix command:
X.ce
Xls -l | ONAME=con sz -ay -
Xwill send a "file" to the PC-DOS console display.
XThe
X.B -y
Xoption instructs the receiver to open the file for writing unconditionally.
XThe
X.B -a
Xoption
Xcauses the receiver to convert Unix newlines to PC-DOS carriage returns
Xand linefeeds.
X
X
X.B Sb
Xbatch sends one or more files with YMODEM or ZMODEM protocol.
XThe initial ZMODEM initialization is not sent.
XWhen requested by the receiver,
X.B sb
Xsupports
X.B YMODEM-g
Xwith "cbreak" tty mode, XON/XOFF flow control,
Xand interrupt character set to CAN (^X).
X.B YMODEM-g
X(Professional-YAM
X.B g
Xoption)
Xincreases throughput over error free channels
X(direct connection, X.PC, etc.)
Xby not acknowledging each transmitted sector.
X
XOn
X.SM Unix
Xsystems, additional information about the file is transmitted.
XIf the receiving program uses this information,
Xthe transmitted file length controls the exact number of bytes written to
Xthe output dataset,
Xand the modify time and file mode
Xare set accordingly.
X
X
X.B Sx
Xsends a single
X.I file
Xwith
X.B XMODEM
Xor
X.B XMODEM-1k
Xprotocol
X(sometimes incorrectly called "ymodem").
XThe user must supply the file name to both sending and receiving programs.
X
XIff
X.B sz
Xis invoked with $SHELL set and iff that variable contains the
Xstring
X.I "rsh"
Xor
X.I "rksh"
X(restricted shell),
X.B sz
Xoperates in restricted mode.
XRestricted mode restricts pathnames to the current directory and
XPUBDIR (usually /usr/spool/uucppublic) and/or subdirectories
Xthereof.
X
X
XThe fourth form sends a single COMMAND to a ZMODEM receiver for execution.
X.B Sz
Xexits with the COMMAND return value.
XIf COMMAND includes spaces or characters special to the shell,
Xit must be quoted.
X
X
XThe fifth form sends a single COMMAND to a ZMODEM receiver for execution.
X.B Sz
Xexits as soon as the receiver has correctly received the command,
Xbefore it is executed.
X
X
XThe sixth form (sz -TT)
Xattempts to output all 256 code combinations to the terminal.
XIn you are having difficulty sending files,
Xthis command lets you see which character codes are being
Xeaten by the operating system.
X
X
XIf
X.B sz
Xis invoked with stdout and stderr to different datasets,
XVerbose is set to 2, causing frame by frame progress reports
Xto stderr.
XThis may be disabled with the
X.B q
Xoption.
X.PP
XThe meanings of the available options are:
X.PP
X.PD 0
X.TP
X.B
X\\
X.R
X(VMS) Force the next option letter to upper case.
X.TP
X.B +
XInstruct the receiver to append transmitted data to an existing file
X(ZMODEM only).
X.TP
X.B a
XConvert NL characters in the transmitted file to CR/LF.
XThis is done by the sender for XMODEM and YMODEM, by the receiver
Xfor ZMODEM.
X.TP
X.B b
X(ZMODEM) Binary override: transfer file without any translation.
X.TP
X.B "c COMMAND"
XSend COMMAND to the receiver for execution, return with COMMAND\'s exit status.
X.TP
X.B d
XChange all instances of "." to "/" in the transmitted pathname.
XThus, C.omenB0000 (which is unacceptable to MSDOS or CP/M)
Xis transmitted as C/omenB0000.
XIf the resultant filename has more than 8 characters in the stem,
Xa "." is inserted to allow a total of eleven.
X.TP
X.B e
XEscape all control characters;
Xnormally XON, XOFF, DLE, CR-@-CR, and Ctrl-X are escaped.
X.TP
X.B f
XSend Full pathname.
XNormally directory prefixes are stripped from the transmitted
Xfilename.
X.TP
X.B "i COMMAND"
XSend COMMAND to the receiver for execution, return Immediately
Xupon the receiving program's successful recption of the command.
X.TP
X.B k
X(XMODEM/YMODEM) Send files using 1024 byte blocks
Xrather than the default 128 byte blocks.
X1024 byte packets speed file transfers at high bit rates.
X(ZMODEM streams the data for the best possible throughput.)
X.TP
X.B "L N"
XUse ZMODEM sub-packets of length N.
XA larger N (32 <= N <= 1024) gives slightly higher throughput,
Xa smaller N speeds error recovery.
XThe default is 128 below 300 baud, 256 above 300 baud, or 1024 above 2400 baud.
X.TP
X.B "l N"
XWait for the receiver to acknowledge correct data every
X.B N
X(32 <= N <= 1024)
Xcharacters.
XThis may be used to avoid network overrun when XOFF flow control is lacking.
X.TP
X.B n
X(ZMODEM) Send each file if
Xdestination file does not exist.
XOverwrite destination file if
Xsource file is newer than the destination file.
X.TP
X.B N
X(ZMODEM) Send each file if
Xdestination file does not exist.
XOverwrite destination file if
Xsource file is newer or longer than the destination file.
X.TP
X.B o
X(ZMODEM) Disable automatic selection of 32 bit CRC.
X.TP
X.B p
X(ZMODEM) Protect existing destination files by skipping transfer if the
Xdestination file exists.
X.TP
X.B q
XQuiet suppresses verbosity.
X.TP
X.B r
X(ZMODEM) Resume interrupted file transfer.
XIf the source file is longer than the destination file,
Xthe transfer commences at the offset in the source file that equals
Xthe length of the destination file.
X.TP
X.B "t tim"
XChange timeout to
X.I tim
Xtenths of seconds.
X.TP
X.B u
XUnlink the file after successful transmission.
X.TP
X.B "w N"
XLimit the transmit window size to N bytes (ZMODEM).
X.TP
X.B v
XVerbose
Xcauses a list of file
Xnames to be appended to
X/tmp/szlog .
XMore v's generate more output.
X.TP
X.B y
XInstruct a ZMODEM receiving program to overwrite any existing file
Xwith the same name.
X.TP
X.B Y
XInstruct a ZMODEM receiving program to overwrite any existing file
Xwith the same name,
Xand to skip any source files that do have a file with the same
Xpathname on the destination system.
X.PD
X.SH EXAMPLES
X.ne 7
X.B "ZMODEM File Transfer"
X(Unix to DSZ/ZCOMM/Professional-YAM)
X.br
X.B "% sz \-a *.c"
X.br
XThis single command transfers all .c files in the current Unix directory
Xwith conversion
X.RB ( \-a )
Xto end of line conventions appropriate to the receiving environment.
XWith ZMODEM AutoDownload enabled, Professional-YAM  and ZCOMM
Xwill automatically recieve
Xthe files after performing a security check.
X
X.br
X.B "% sz \-Yan *.c *.h"
X.br
XSend only the .c and .h files that exist on both systems,
Xand are newer on the sending system than the
Xcorresponding version on the receiving system, converting Unix to
XDOS text format.
X.br
X.B
X$ sz -\\Yan file1.c file2.c file3.c foo.h baz.h
X.R
X(for VMS)
X.br
X
X.B "ZMODEM Command Download"
X(Unix to Professional-YAM)
X.br
X cpszall:all
X    sz \-c "c:;cd /yam/dist"
X    sz \-ya $(YD)/*.me
X    sz \-yqb y*.exe
X    sz \-c "cd /yam"
X    sz \-i "!insms"
X.br
XThis Makefile fragment uses
X.B sz
Xto issue commands to Professional-YAM to change current disk and directory.
XNext,
X.B sz
Xtransfers the
X.I .me
Xfiles from the $YD directory, commanding the receiver to overwrite the old files
Xand to convert from Unix end of line conventions to PC-DOS conventions.
XThe third line transfers some
X.I .exe
Xfiles.
XThe fourth and fifth lines command Pro-YAM to
Xchange directory and execute a PC-DOS batch file
X.I insms .
XSince the batch file takes considerable time, the
X.B "\-i"
Xform is used to allow
X.B sz
Xto exit immediately.
X
X.B "XMODEM File Transfer"
X(Unix to Crosstalk)
X.br
X%
X.B "sx \-a foo.c"
X.br
X.B "ESC"
X.br
X.B "rx foo.c"
X.br
XThe above three commands transfer a single file
Xfrom Unix to a PC and Crosstalk with
X.I sz
Xtranslating Unix newlines to DOS CR/LF.
XThis combination is much slower and far less reliable than ZMODEM.
X.SH ERROR MESSAGES
X"Caught signal 99"
Xindicates the program was not properly compiled,
Xrefer to "bibi(99)" in rbsb.c for details.
X.SH SEE ALSO
Xrz(omen),
XZMODEM.DOC,
XYMODEM.DOC,
XProfessional-YAM,
Xcrc(omen),
Xsq(omen),
Xtodos(omen),
Xtocpm(omen),
Xtomac(omen),
Xyam(omen)
X
XCompile time options required for various operating systems are described in
Xthe source file.
X.SH "VMS VERSION"
XThe VMS version does not support wild cards.
XBecause of VMS DCL, upper case option letters muse be represented
Xby \\ proceding the letter.
X
XThe current VMS version does not support XMODEM, XMODEM-1k, or YMODEM.
X
XVMS C Standard I/O and RMS may interact to modify the file contents.
X.SH FILES
X32 bit CRC code courtesy Gary S. Brown.
X
Xsz.c, crctab.c, rbsb.c, zm.c, zmodem.h Unix source files
X
Xsz.c, crctab.c, vrzsz.c, zm.c, zmodem.h, vmodem.h, vvmodem.c,
XVMS source files.
X
X/tmp/szlog stores debugging output (sz -vv)
X(szlog on VMS).
X.SH "TESTING FEATURE"
XThe command "sz -T file"
Xexercises the
X.B Attn
Xsequence error recovery by commanding
Xerrors with unterminated packets.
XThe receiving program should complain five times about
Xbinary data packets being too long.
XEach time
X.B sz
Xis interrupted,
Xit should send a ZDATA header followed by another defective packet.
XIf the receiver does not detect five long data packets,
Xthe
X.B Attn
Xsequence is not interrupting the sender, and the
X.B Myattn
Xstring in
X.B sz.c
Xmust be modified.
X
XAfter 5 packets,
X.B sz
Xstops the "transfer" and
Xprints the total number of characters "sent" (Tcount).
XThe difference between Tcount and 5120 represents the number of characters
Xstored in various buffers when the Attn sequence is generated.
X.SH BUGS
XCalling
X.I sz
Xfrom most versions of cu(1) doesn't work because cu's receive process
Xfights
X.I sz
Xfor characters from the modem.
X
XPrograms that do not properly implement the specified file transfer protocol
Xmay cause
X.I sz
Xto "hang" the port for a minute or two.
XEvery reported instance of this problem has been corrected by using
XZCOMM, Pro-YAM, or other program with a correct implementation
Xof the specified protocol.
X
XMany programs claiming to support YMODEM only support XMODEM with 1k blocks,
Xand they often don't get that quite right.
X
XXMODEM transfers add up to 127 garbage bytes per file.
XXMODEM-1k and YMODEM-1k transfers use 128 byte blocks
Xto avoid extra padding.
X
XYMODEM programs use the file length transmitted at the beginning of the
Xtransfer to prune the file to the correct length; this may cause problems with
Xsource files that grow during the course of the transfer.
XThis problem does not pertain to ZMODEM transfers, which preserve the exact
Xfile length unconditionally.
X
XMost ZMODEM options are merely passed to the receiving program;
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
chmod 0644 sz.1 || echo "restore of sz.1 fails"
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&&sectnum) ? 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);
SHAR_EOF
echo "End of part 2"
echo "File sz.c is continued in part 3"
echo "3" > s2_seq_.tmp
exit 0
-- 
Keith Petersen
Arpa: W8SDZ@SIMTEL20.ARPA
Uucp: {bellcore,decwrl,harvard,lll-crg,ucbvax,uw-beaver}!simtel20.arpa!w8sdz
GEnie: W8SDZ

w8sdz@brl-smoke.ARPA (Keith B. Petersen ) (05/03/88)

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