[comp.sources.atari.st] v01i037: rzsz -- UNIX side for zmdm file transfer program part02/05

koreth@ssyx.ucsc.edu (Steven Grimm) (05/28/88)

Submitted-by: bammi@mandrill.ces.cwru.edu (Jwahar R. Bammi)
Posting-number: Volume 1, Issue 37
Archive-name: rzsz/part02

#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file rbsb.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
sed 's/^X//' << 'SHAR_EOF' >> rbsb.c
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 *   Need an unsigned type capable of holding 32 bits;
X */
Xtypedef unsigned long int UNS_32_BITS;
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 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
X/* End of rbsb.c */
X
SHAR_EOF
chmod 0600 rbsb.c || echo "restore of rbsb.c fails"
sed 's/^X//' << 'SHAR_EOF' > rz.1 &&
X'\" Revision Level 
X'\" Last Delta     02-10-87
X.TH RZ 1 OMEN
X.SH NAME
Xrb, rz \- XMODEM, YMODEM, ZMODEM (Batch) file receive
X.SH SYNOPSIS
X.B rz
X.RB [\- "\ +1abpqtuv" ]
X.br
X.B rb
X.RB [\- "\ +1abqtuv" ]
X.br
X.B rz
X.RB [\- "\ 1abcqtuv" ]
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 protocol to receive
Xfiles over a serial port from a variety of programs running under
XPC-DOS, CP/M,
X.SM Unix,
Xand other operating systems.
X
XThe first form of
X.I rz
X(Receive ZMODEM)
Xreceives files with the ZMODEM batch protocol.
XIf the sending program does not support ZMODEM,
X.I rz
Xsteps down to YMODEM protocol
Xafter 50 seconds.
XThis delay can be eliminated by calling the program as
X.I rb .
X
XWhen receiving with XMODEM or YMODEM,
X.I Rz
Xaccepts either standard 128 byte sectors or
X1024 byte sectors
X(YAM
X.B -k
Xoption).
XThe user should determine when
Xthe longer block length
Xactually improves throughput without causing problems.
X
XIf extended file information (file length, etc.)
Xis received,
Xthe file length controls the number of bytes written to
Xthe output dataset (YMODEM only),
Xand the modify time and file mode
X(iff non zero)
Xare set accordingly.
X
XIf no extended 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
XThe second form of
X.I rz
Xreceives a single
X.I file
Xwith XMODEM protocol.
XThe user must supply the file name to both sending and receiving programs.
X
X.I Gz
Xis a shell script which calls
X.I sz
Xto command a Pro-YAM or compatible program 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 "-1 C:*.c D:*.h"
X
X
XThe third form of
X.I rz
Xis invoked as
X.B rzCOMMAND
X(with an optional leading \- as generated by login(1)).
XFor each received file,
Xrz will 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
X3.0:
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),
Xrz will 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 1
XUse file descriptor 1 for ioctls and reads (Unix only).
XBy default, file descriptor 0 is used for ioctls and reads.
XThis option allows
X.B zz
Xto be used with the
X.I Professional-YAM
X.B $
Xcommand.
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.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.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,
XIMP(CP/M),
XProfessional-YAM,
Xsz(omen),
Xusq(omen),
Xundos(omen)
X
XCompile time options required
Xfor various operating systems are described in the
Xsource file.
X.SH NOTES
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, especially at high baud rates.
XThe Pro-YAM
X.B "zmodem l"
Xnumeric parameter may be set to a value between 64 and 1024 to limit the
Xburst length ("zmodem pl100").
X
X32 bit CRC code courtesy Gary S. Brown.
X.SH BUGS
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"
XSome of the #includes with file names enclosed with angle brackets <>
Xmay need to have the angle brackets changed to "", or vice versa.
X
XThe VMS version does not set binary mode according to the incoming
Xfile type.
XNon binary file processing consists of stripping all characters beginning
Xwith CPMEOF (^Z).
X
XThe VMS version does not set the file time.
X
XAt high speeds,
XVMS sometimes loses incoming characters, resulting in retries
Xand degradation of throughput.
X
XThe mysterious
XVMS C Standard I/O Package and RMS may interact to modify
Xfile contents unexpectedly.
X
XThe VMS version does not support invocation as
X.B rzCOMMAND .
XZMODEM has not yet been implemented on the VMS version.
X.SH "ZMODEM CAPABILITIES"
X.I Rz
Xsupports incoming ZMODEM binary (-b), ASCII (-a),
Xprotect (-p),
Xand append (-+)
Xrequests, and ZMODEM command execution.
X.SH FILES
Xrz.c, rbsb.c, zm.c, zmodem.h source files.
X
X/tmp/rzlog stores debugging output generated with -vv option.
X.SH CWRU `ENHANCEMENTS'
XIf you compiled
X.I rz
Xwith the pre-processor symbol `CASE' defined, then when the
Xremote sends files with full path names (with
X.I sz -f
Xin Zmodem mode), all subdirectories that are needed to receive
Xthese files will be created, if they do not already exist. Note that
Xpathnames are always considered relative to the current directory,
Xso even if the remote sends a file with the pathname "/foo/bar", the
Xfile goes into "./foo/bar". If the directory "./foo" does not exist,
Xit will be created.
X.sp 1
XThe CWRU `enhancements' use Berkeley Unix specific code, and have been
Xtested only under BSD4.3. When making
X.I rz
Xplease make sure that you are using the appropriate flavor of Unix, before
Xdefining the pre processor symbol `CASE'.
SHAR_EOF
chmod 0600 rz.1 || echo "restore of rz.1 fails"
sed 's/^X//' << 'SHAR_EOF' > rz.c &&
X#define VERSION "1.18 02-18-87"
X#define PUBDIR "/usr/spool/uucppublic"
X
X/*% cc  -K -O -i % -o rz; size rz
X *  (above for Xenix SYS V 2.2 delta+)
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			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 *
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"
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 *  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 *  HOWMANY should be tuned for best performance
X *
X *  USG UNIX (3.0) ioctl conventions courtesy  Jeff Martin
X */
X#define LOGFILE "/tmp/rzlog"
X#define zperr vfile
X
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <ctype.h>
XFILE *popen();
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
Xint Zmodem=0;		/* ZMODEM protocol requested */
Xint Nozmodem = 0;	/* If invoked as "rb" */
Xunsigned Baudrate;
X#include "rbsb.c"	/* most of the system dependent stuff here */
X
Xchar *substr();
XFILE *fout;
X#ifdef CASE
Xchar myfilebuf[16384];
X#endif
X
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
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 SECSIZ 128	/* cp/m's Magic Number record size */
X#define PATHLEN 257	/* ready for 4.2 bsd ? */
X#define KSIZE 1024	/* record size with k option */
X#define UNIXFILE 0x8000	/* happens to the the S_IFREG file mask bit for stat */
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 */
Xshort Filemode;		/* Unix style mode for incoming file */
Xchar Pathname[PATHLEN];
Xchar *Progname;		/* the name by which we were called */
X
Xint Batch=0;
Xint Wcsmask=0377;
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 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 */
Xchar secbuf[KSIZE];
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 */
X
Xjmp_buf tohere;		/* For the interrupt on RX timeout */
X
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	exit(128+n);
X}
X
Xmain(argc, argv)
Xint argc;
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	chkinvok(virgin=argv[0]);	/* if called as [-]rzCOMMAND set flag */
X	npats = 0;
X	while ((--argc) > 0) {
X		cp = *++argv;
X		if (*cp == '-') {
X			while( *++cp) {
X				switch(*cp) {
X				case '+':
X					Lzmanag = ZMAPND; break;
X				case '1':
X					iofd = 1; break;
X				case '7':
X					Wcsmask = 0177;
X				case 'a':
X					Rxascii=TRUE;  break;
X				case 'b':
X					Rxbinary=TRUE; break;
X				case 'c':
X					Crcflg=TRUE; break;
X				case 'D':
X					Nflag = TRUE; 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 'u':
X					MakeLCPathname=FALSE; break;
X				case 'v':
X					++Verbose; 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 (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	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	exit(exitcode);
X}
X
X
Xusage()
X{
X	fprintf(stderr,"%s %s for %s by Chuck Forsberg\n",
X	  Progname, VERSION, OS);
X	fprintf(stderr,"Usage:	rz [-1abuv]		(ZMODEM Batch)\n");
X	fprintf(stderr,"or	rb [-1abuv]		(YMODEM Batch)\n");
X	fprintf(stderr,"or	rz [-1abcv] file	(XMODEM or XMODEM-1k)\n");
X	fprintf(stderr,"	  -1 For cu(1): Use fd 1 for input\n");
X	fprintf(stderr,"	  -a ASCII transfer (strip CR)\n");
X	fprintf(stderr,"	  -b Binary transfer for all files\n");
X	fprintf(stderr,"	  -v Verbose more v's give more info\n");
X	fprintf(stderr,"	  -c Use 16 bit CRC	(XMODEM)\n");
X	exit(1);
X}
X/*
X *  Debugging information output interface routine
X */
X/* VARARGS1 */
Xvfile(f, a, b, c)
Xregister char *f;
X{
X	if (Verbose > 1) {
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";
X
Xwcreceive(argc, argp)
Xchar **argp;
X{
X	register c;
X
X	if (Batch || argc==0) {
X		Crcflg=(Wcsmask==0377);
X		if ( !Quiet)
X			fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz");
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 		Thisbinary = Rxbinary; /* ++Jrb */
X
X		/* procheader(""); */
X		strcpy(Pathname, *argp); checkpath(Pathname);
X#ifdef CASE
X		if(Verbose)
X		    fprintf(stderr, "\nrz: ready to receive %s [%s mode]\r\n",
X 			Pathname, Thisbinary?"BIN":"ASCII");
X#endif
X
X		if ((fout=fopen(Pathname, "w")) == NULL)
X			return ERROR;
X#ifdef CASE
X 		setbuffer(fout, myfilebuf, sizeof(myfilebuf));
X#endif
X		if (wcrx()==ERROR)
X			goto fubar;
X	}
X	return OK;
Xfubar:
X	canit();
X	if (Topipe && fout) {
X		pclose(fout);  return ERROR;
X	}
X	if (fout)
X		fclose(fout);
X	if (Restricted) {
X		unlink(Pathname);
X		fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);
X	}
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		log( "Pathname fetch returned %d\n", c);
X		if (c == WCEOT) {
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 &Wcsmask)) {
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&Wcsmask)) {
X			log( "Received dup Sector\n");
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			log( "Sync Error\n");
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=KSIZE; goto get2;
X		}
X		if (firstch==SOH) {
X			Blklen=SECSIZ;
Xget2:
X			sectcurr=readline(1);
X			if ((sectcurr+(oldcrc=readline(1)))==Wcsmask) {
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						log("CRC=0%o\n", oldcrc);
X					else {
X						Firstsec=FALSE;
X						return sectcurr;
X					}
X				}
X				else if (((checksum-firstch)&Wcsmask)==0) {
X					Firstsec=FALSE;
X					return sectcurr;
X				}
X				else
X					log( "Checksum Error\n");
X			}
X			else
X				log("Sector number garbled 0%o 0%o\n",
X				 sectcurr, oldcrc);
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				log( "Sender CANcelled\n");
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			log( "Timeout\n");
X		}
X		else
X			log( "Got 0%o sector header\n", 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/*
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#ifdef RDEBUG
X		if (Verbose > 8) {
X			fprintf(stderr, "%02x ", *cdq&0377);
X		}
X#endif
X		return (*cdq++ & Wcsmask);
X	}
X	n = timeout/10;
X	if (n < 2)
X		n = 3;
X#ifdef RDEBUG
X	if (Verbose > 3)
X		fprintf(stderr, "Calling read: alarm=%d  Readnum=%d ",
X		  n, Readnum);
X#endif
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#ifdef RDEBUG
X	if (Verbose > 3) {
X		fprintf(stderr, "Read returned %d bytes\n", Lleft);
X	}
X#endif
X	if (Lleft < 1)
X		return TIMEOUT;
X	--Lleft;
X	if (Verbose > 8) {
X		fprintf(stderr, "%02x ", *cdq&0377);
X	}
X	return (*cdq++ & Wcsmask);
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
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	/* ZMPROT check for existing file */
X	if (zmanag == ZMPROT && (fout=fopen(name, "r"))) {
X		fclose(fout);  return ERROR;
X	}
X
X#ifdef CASE
X/* CWRU NOTE:
X *	We will not accept rooted paths ie. paths that begin in '/' or './'
X *	If the incoming filename is rooted, we skip the beginning
SHAR_EOF
echo "End of part 2, continue with part 3"
echo "3" > s2_seq_.tmp
exit 0