#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 4)."
# Contents:  sz.c
# Wrapped by hankin@sauron on Tue Dec  5 10:22:27 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'sz.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sz.c'\"
else
echo shar: Extracting \"'sz.c'\" \(44054 characters\)
sed "s/^X//" >'sz.c' <<'END_OF_FILE'
X#define VERSION "sz 3.03 5-09-89"
X#define PUBDIR "/usr/spool/uucppublic"
X
X/*% cc -compat -M2 -Ox -K -i -DTXBSIZE=16384  -DNFGVMIN -DREADCHECK
sz.c -lx -o sz; size sz
X
X/*% cc -Zi -DXX -DNFGVMIN -DREADCHECK sz.c -lx -o xsz; size xsz
X<-xtx-*> cc -Osal -DTXBSIZE=32768  -DSV sz.c -lx -o $B/sz; size $B/sz
X
X ****************************************************************************
X *
X * sz.c By Chuck Forsberg,  Omen Technology INC
X *
X ****************************************************************************
X *
X * Typical Unix/Xenix/Clone compiles:
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	Classic Xenix
X *
X *	ln sz sb			**** All versions ****
X *	ln sz sx			**** All versions ****
X *
X ****************************************************************************
X *
X * Typical VMS compile and install sequence:
X *
X *		define LNK$LIBRARY   SYS$LIBRARY:VAXCRTL.OLB
X *		cc sz.c
X *		cc vvmodem.c
X *		link sz,vvmodem
X *	sz :== $disk$user2:[username.subdir]sz.exe
X *
X *  If you feel adventureous, remove the #define BADSEEK line
X *  immediately following the #ifdef vax11c line!  Some VMS
X *  systems know how to fseek, some don't.
X *
X ****************************************************************************
X *
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 *	This version implements ZMODEM Run Length Encoding, Comparision,
X *	and variable length headers.  These features were not funded
X *	by the original Telenet development contract.  This software,
X *	including these features, may be freely used for non
X *	commercial and educational purposes.  This software may also
X *	be freely used to support file transfer operations to or from
X *	licensed Omen Technology products.  Contact Omen Technology
X *	for licensing for other uses.  Any programs which use part or
X *	all of this software must be provided in source form with this
X *	notice intact except by written permission from Omen
X *	Technology Incorporated.
X *
X *		Omen Technology Inc		FAX: 503-621-3745
X *		Post Office Box 4681
X *		Portland OR 97208
X *
X *	Previous versions of this program (not containing the extensions
X *	listed above) remain in the public domain.
X *
X *	This code is made available in the hope it will be useful,
X *	BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
X *	DAMAGES OF ANY KIND.
X *
X *  2.1x hacks to avoid VMS fseek() bogosity, allow input from pipe
X *     -DBADSEEK -DTXBSIZE=32768  
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#ifdef XX
X#define XARGSFILE "args"
Xlong Thisflen;
X#endif
X
Xchar *substr(), *getenv();
X
X#ifdef vax11c
X#define STATIC
X#define BADSEEK
X#define TXBSIZE 32768		/* Must be power of two, < MAXINT */
X#include <types.h>
X#include <stat.h>
X#define STAT
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 ROPMODE "r"
X#define READCHECK
X#define BUFWRITE
Xextern int errno;
X#define SS_NORMAL SS$_NORMAL
X#define xsendline(c) sendline(c)
X
X#ifndef PROGNAME
X#define PROGNAME "sz"
X#endif
X
X
X#else	/* vax11c */
X
X#ifdef GENIE
X#define STATIC static
X#define LOGFILE "szlog"
X#define BADSEEK
X#define TXBSIZE 32768		/* Must be power of two, < MAXINT */
X#define OS "GEnie"
X#define SS_NORMAL 0
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <ctype.h>
X#include <errno.h>
X#include <stdlib.h>
X#include <fildes.h>
XFILDES fdes;
Xextern int errno;
Xint Binfile;
Xlong Thisflen;
X
X#define sendline(c) putchar(c & 0377)
X#define xsendline(c) putchar(c)
X
X#else	/* GENIE */
X
X#define LOGFILE "/tmp/szlog"
X#define SS_NORMAL 0
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <ctype.h>
X#include <errno.h>
Xextern int errno;
X#define STATIC
X
X#define sendline(c) putchar(c & 0377)
X#define xsendline(c) putchar(c)
X
X#endif
X#endif
X
X#define PATHLEN 256
X#define OK 0
X#define FALSE 0
X#ifdef TRUE
X#undef TRUE
X#endif
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 GCOUNT (-4)
X#define RETRYMAX 10
X
X
X#define HOWMANY 2
XSTATIC int Zmodem=0;		/* ZMODEM protocol requested by receiver */
Xunsigned Baudrate=4800;		/* Default, set by first mode() call */
XSTATIC unsigned Effbaud = 4800;
XSTATIC unsigned Txwindow;	/* Control the size of the transmitted window */
XSTATIC unsigned Txwspac;	/* Spacing between zcrcq requests */
XSTATIC unsigned Txwcnt;	/* Counter used to space ack requests */
XSTATIC long Lrxpos;		/* Receiver's last reported offset */
XSTATIC int errors;
X
X#ifdef vax11c
X#include "vrzsz.c"	/* most of the system dependent stuff here */
X#else
X#ifdef GENIE
X#include "genie.c"	/* most of the system dependent stuff here */
X#else
X#include "rbsb.c"	/* most of the system dependent stuff here */
X#ifdef XX
X#undef STAT
X#endif
X#endif
X#endif
X
X#include "crctab.c"
X
XSTATIC int Filesleft;
XSTATIC long 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
XSTATIC char Myattn[] = { 0 };
X#else
X#ifdef USG
XSTATIC char Myattn[] = { 03, 0336, 0 };
X#else
X#ifndef GENIE
XSTATIC char Myattn[] = { 0 };
X#endif
X#endif
X#endif
X
XFILE *in;
X
X#ifdef BADSEEK
XSTATIC int Canseek = 0;	/* 1: Can seek 0: only rewind -1: neither (pipe) */
X#ifndef TXBSIZE
X#define TXBSIZE 16384		/* Must be power of two, < MAXINT */
X#endif
X#else
XSTATIC int Canseek = 1;	/* 1: Can seek 0: only rewind -1: neither (pipe) */
X#endif
X
X#ifdef TXBSIZE
X#define TXBMASK (TXBSIZE-1)
XSTATIC char Txb[TXBSIZE];		/* Circular buffer for file reads */
XSTATIC char *txbuf = Txb;		/* Pointer to current file segment */
X#else
XSTATIC char txbuf[1024];
X#endif
XSTATIC long vpos = 0;			/* Number of bytes read from file */
X
XSTATIC char Lastrx;
XSTATIC char Crcflg;
XSTATIC int Verbose=0;
XSTATIC int Modem2=0;		/* XMODEM Protocol - don't send pathnames */
XSTATIC int Restricted=0;	/* restricted; no /.. or ../ in filenames */
XSTATIC int Quiet=0;		/* overrides logic that would otherwise
set verbose */
XSTATIC int Ascii=0;		/* Add CR's for brain damaged programs */
XSTATIC int Fullname=0;		/* transmit full pathname */
XSTATIC int Unlinkafter=0;	/* Unlink file after it is sent */
XSTATIC int Dottoslash=0;	/* Change foo.bar.baz to foo/bar/baz */
XSTATIC int firstsec;
XSTATIC int errcnt=0;		/* number of files unreadable */
XSTATIC int blklen=128;		/* length of transmitted records */
XSTATIC int Optiong;		/* Let it rip no wait for sector ACK's */
XSTATIC int Eofseen;		/* EOF seen on input set by zfilbuf */
XSTATIC int BEofseen;		/* EOF seen on input set by fooseek */
XSTATIC int Totsecs;		/* total number of sectors this file */
XSTATIC int Filcnt=0;		/* count of number of files opened */
XSTATIC int Lfseen=0;
XSTATIC unsigned Rxbuflen = 16384;	/* Receiver's max buffer length */
XSTATIC int Tframlen = 0;	/* Override for tx frame length */
XSTATIC int blkopt=0;		/* Override value for zmodem blklen */
XSTATIC int Rxflags = 0;
XSTATIC long bytcnt;
XSTATIC int Wantfcs32 = TRUE;	/* want to send 32 bit FCS */
XSTATIC char Lzconv;	/* Local ZMODEM file conversion request */
XSTATIC char Lzmanag;	/* Local ZMODEM file management request */
XSTATIC int Lskipnocor;
XSTATIC char Lztrans;
XSTATIC int Command;		/* Send a command, then exit. */
XSTATIC char *Cmdstr;		/* Pointer to the command string */
XSTATIC int Cmdtries = 11;
XSTATIC int Cmdack1;		/* Rx ACKs command, then do it */
XSTATIC int Exitcode;
XSTATIC int Test;		/* 1= Force receiver to send Attn, etc with qbf. */
X			/* 2= Character transparency test */
XSTATIC char *qbf=
X "The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
XSTATIC long Lastsync;		/* Last offset to which we got a ZRPOS */
XSTATIC int Beenhereb4;		/* How many times we've been ZRPOS'd same place */
X
XSTATIC jmp_buf tohere;		/* For the interrupt on RX timeout */
XSTATIC jmp_buf intrjmp;	/* For the interrupt on RX CAN */
X
X#ifdef XARGSFILE
Xchar *
Xmystrsave(s)
Xchar *s;
X{
X	register char *p;
X	char *malloc();
X
X	if (p = malloc(strlen(s)+1) ) {
X		strcpy(p, s); return p;
X	}
X	fprintf(stderr, "No memory for mystrsave!\n");
X	exit(1);
X}
X
X/* Remove (presumably) terminating CR and/or LF from string */
Xuncrlf(s)
Xregister char *s;
X{
X	for ( ; *s; ++s)
X		switch (*s) {
X		case '\r':
X		case '\n':
X			*s = 0;  return;
X		}
X}
X#endif
X
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#ifndef GENIE
X	if (n == SIGQUIT)
X		abort();
X#endif
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
XSTATIC int Zctlesc;	/* Encode control characters */
XSTATIC int Nozmodem = 0;	/* If invoked as "sb" */
XSTATIC char *Progname = "sz";
XSTATIC int Zrwindow = 1400;	/* RX window size (controls garbage count) */
X#include "zm.c"
X
X#include "zmr.c"
X
X#ifdef XARGSFILE
X#define XARGSMAX 256
Xchar *xargv[XARGSMAX+1];
X#endif
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#ifdef vax11c
X	chkinvok(PROGNAME);
X#else
X	chkinvok(argv[0]);
X#endif
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					if (Lzconv == ZCRESUM)
X						Lzmanag = (Lzmanag &
ZMMASK) | ZMCRC;
X					Lzconv = ZCRESUM; 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 '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				case 'Z':
X				case 'z':
X					Lztrans = ZTRLE;  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 && !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	vfile("%s %s for %s\n", Progname, VERSION, OS);
X
X#ifdef XARGSFILE
X	vfile("npats=%d *patts=%s", npats, *patts);
X	if (npats == 1 && !strcmp(XARGSFILE, *patts)) {
X		in = fopen(XARGSFILE, "r");
X		if (!in) {
X			printf(stderr, "Can't open / control file!\n");
X			exit(2);
X		}
X		for (npats=0,argv=patts=xargv; npats<XARGSMAX; ++npats,++argv) {
X			if (fgets(txbuf, 1024, in) <= 0)
X				break;
X			uncrlf(txbuf);
X			*argv = mystrsave(txbuf);
X		}
X		fclose(in);
X	}
X#endif
X
X	mode(1);
X
X#ifdef GENIE
X	signal(SIGINT, SIG_IGN);
X#else
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#endif
X#ifdef SIGQUIT
X	if ( !Fromcu)
X		signal(SIGQUIT, SIG_IGN);
X#endif
X#ifdef SIGTERM
X	signal(SIGTERM, bibi);
X#endif
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(4, 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	if (Nozmodem) {
X		printf("Start your YMODEM receive. ");  fflush(stdout);
X	}
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 (!Nozmodem && !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, *q;
X#ifdef STAT
X	struct stat f;
X#endif
X	char name[PATHLEN];
X
X	strcpy(name, oname);
X
X#ifdef XARGSFILE
X	/* Parse GEniename:REALname:length pathname syntax */
X	Thisflen = -1;
X	for (p = oname; *p; ++p) {
X		if (*p == ':') {
X			*p++ = 0;
X			q = p;
X			for (++p; *p; ++p) {
X				if (*p == ':') {
X					*p++ = 0;
X					Thisflen = atol(p);
X					break;
X				}
X			}
X			strcpy(name, q);
X			break;
X		}
X	}
X#endif
X
X#ifdef GENIE
X	_describe(oname,&fdes);		/* An undocumented goodie */
X	if (fdes.type_file == 1) {	/* Fortran Sequential Binary */
X		Binfile = 1;
X		in = fopen(oname,"rB");
X	}
X	else if (fdes.type_file == 0)  { /* Ascii */
X		Binfile = 0;
X		in = fopen(oname,"r");
X	}
X	else {				/* not a SL filetype */
X		fprintf(stderr, "\nUnknown file type %d\n",fdes.type_file);
X		++errcnt;
X		return OK;		/* pass over it, there may be others */
X	}
X#else
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	in=fopen(oname, ROPMODE);
X#endif
X
X	if (in==NULL) {
X		++errcnt;
X		return OK;	/* pass over it, there may be others */
X	}
X	BEofseen = Eofseen = 0;  vpos = 0;
X
X#ifdef STAT
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#endif
X
X	++Filcnt;
X	switch (wctxpn(name)) {
X	case ERROR:
X		return ERROR;
X	case ZSKIP:
X		return OK;
X	}
X#ifdef STAT
X	if (!Zmodem && wctx(f.st_size)==ERROR)
X		return ERROR;
X#else
X	if (!Zmodem && wctx(1000000000L)==ERROR)
X		return ERROR;
X#endif
X
X#ifndef vax11c
X#ifndef GENIE
X	if (Unlinkafter)
X		unlink(oname);
X#endif
X#endif
X
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#ifdef STAT
X	struct stat f;
X#endif
X
X	if (Modem2) {
X#ifdef STAT
X		if (*name && fstat(fileno(in), &f)!= -1) {
X			fprintf(stderr, "Sending %s, %ld XMODEM blocks. ",
X			  name, (127+f.st_size)>>7);
X		}
X#endif
X		fprintf(stderr, "Give your local XMODEM receive command now.\r\n");
X		fflush(stderr);
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 (*name) {
X#ifdef XX
X		if (Thisflen >= 0) {
X			sprintf(p, "%u 0 0 0 %d %ld",
X			  Thisflen, Filesleft, Totalleft);
X			Totalleft -= Thisflen;
X		}
X#endif
X#ifdef GENIE
X		else
X			sprintf(p, "%d", fdes.current_file_size * 1260);
X		vfile("%s open Binfile=%d size=%ld", name, Binfile,
X		  fdes.current_file_size * 1260);
X#endif
X
X#ifdef STAT
X#ifndef XX
X		if (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#endif
X#endif
X
X	}
X	if (--Filesleft <= 0)
X		Totalleft = 0;
X	if (Totalleft < 0)
X		Totalleft = 0;
X
X#ifdef STAT
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#endif
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 = readline(800)) {
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 = readline(20)) == 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=readline(Rxtimeout))!=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		flushmo();
X		++attempts;
X	}
X		while ((firstch=(readline(Rxtimeout)) != 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		flushmo();
X
X		if (Optiong) {
X			firstsec = FALSE; return OK;
X		}
X		firstch = readline(Rxtimeout);
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 = readline(Rxtimeout)) == 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
X/* Fill buffer with blklen chars */
Xzfilbuf()
X{
X	int n;
X
X#ifdef TXBSIZE
X	vfile("zfilbuf: bytcnt =%lu vpos=%lu blklen=%d", bytcnt, vpos, blklen);
X	/* We assume request is within buffer, or just beyond */
X	txbuf = Txb + (bytcnt & TXBMASK);
X	if (vpos <= bytcnt) {
X#ifdef GENIE
X		if (Binfile) {
X			long l, m;  char *p;
X
X			for (p=txbuf, n=0, l=blklen;  l;  l -= 128, p+= 128) {
X				n += m = fgetb(p, 128, in);
X				if (m == 0)
X					break;
X			}
X		} else
X#endif
X		n = fread(txbuf, 1, blklen, in);
X
X		vpos += n;
X		if (n < blklen)
X			Eofseen = 1;
X		vfile("zfilbuf: n=%d vpos=%lu Eofseen=%d", n, vpos, Eofseen);
X		return n;
X	}
X	if (vpos >= (bytcnt+blklen))
X		return blklen;
X	/* May be a short block if crash recovery etc. */
X	Eofseen = BEofseen;
X	return (vpos - bytcnt);
X#else
X	n = fread(txbuf, 1, blklen, in);
X	if (n < blklen)
X		Eofseen = 1;
X	return n;
X#endif
X}
X
X#ifdef TXBSIZE
X/* Replacement for brain damaged fseek function.  Returns 0==success */
Xfooseek(fptr, pos, whence)
XFILE *fptr;
Xlong pos;
X{
X	long m, n;
X#ifdef GENIE
X	long l, k;  char *p;
X#endif
X
X	vfile("fooseek: pos =%lu vpos=%lu Canseek=%d", pos, vpos, Canseek);
X	/* Seek offset < current buffer */
X	if (pos < (vpos -TXBSIZE +1024)) {
X		BEofseen = 0;
X		if (Canseek > 0) {
X			vpos = pos & ~TXBMASK;
X			if (vpos >= pos)
X				vpos -= TXBSIZE;
X			if (fseek(fptr, vpos, 0))
X				return 1;
X		}
X		else if (Canseek == 0) {
X#ifdef GENIE
X			if (Binfile) {
X				if (fseekb(fptr, vpos = 0L, 0))
X					return 1;
X				} else
X#endif
X			if (fseek(fptr, vpos = 0L, 0))
X				return 1;
X		} else
X			return 1;
X		while (vpos < pos) {
X#ifdef GENIE
X			if (Binfile) {
X				for (p=Txb,n=0,l=TXBSIZE; l; l -= 128,p+= 128) {
X					n += (k = fgetb(p, 128, fptr));
X					vfile("bsk1: l=%d k=%d", l, k);
X					if (k == 0)
X						break;
X				}
X			} else
X#endif
X			n = fread(Txb, 1, TXBSIZE, fptr);
X			vpos += n;
X			vfile("n=%d vpos=%ld", n, vpos);
X			if (n < TXBSIZE) {
X				BEofseen = 1;
X				break;
X			}
X		}
X		vfile("vpos=%ld", vpos);
X		return 0;
X	}
X	/* Seek offset > current buffer (Crash Recovery, etc.) */
X	if (pos > vpos) {
X		if (Canseek)
X			if (fseek(fptr, vpos = (pos & ~TXBMASK), 0))
X				return 1;
X		while (vpos <= pos) {
X			txbuf = Txb + (vpos & TXBMASK);
X			m = TXBSIZE - (vpos & TXBMASK);
X			vfile("m=%ld vpos=%ld", m,vpos);
X#ifdef GENIE
X			if (Binfile) {
X				for (p=txbuf,n=0,l=m; l; l -= 128,p+= 128) {
X					n += (k = fgetb(p, 128, fptr));
X					vfile("bsk2: l=%d k=%d n=%d", l, k, n);
X					if (k == 0)
X						break;
X				}
X			} else
X#endif
X				n = fread(txbuf, 1, m, fptr);
X			vfile("n=%ld vpos=%ld", n,vpos);
X			vpos += n;
X			vfile("bo=%d m=%ld vpos=%ld", txbuf-Txb,m,vpos);
X			if (n < m) {
X				BEofseen = 1;
X				break;
X			}
X		}
X		return 0;
X	}
X	/* Seek offset is within current buffer */
X	vfile("within buffer: vpos=%ld", vpos);
X	return 0;
X}
X#define fseek fooseek
X#endif
X
X
X/* VARARGS1 */
Xvfile(f, a, b, c, d)
Xregister char *f;
X{
X	if (Verbose > 2) {
X		fprintf(stderr, f, a, b, c, d);
X		fprintf(stderr, "\n");
X	}
X}
X
X
Xalrm()
X{
X	longjmp(tohere, -1);
X}
X
X
X#ifndef GENIE
X#ifndef vax11c
X/*
X * readline(timeout) reads character(s) from file descriptor 0
X * timeout is in tenths of seconds
X */
Xreadline(timeout)
X{
X	register int c;
X	static char byt[1];
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	}
X	signal(SIGALRM, alrm); alarm(c);
X	c=read(0, byt, 1);
X	alarm(0);
X	if (Verbose>5)
X		fprintf(stderr, "ret %x\n", byt[0]);
X	if (c<1)
X		return TIMEOUT;
X	return (byt[0]&0377);
X}
X
Xflushmo()
X{
X	fflush(stdout);
X}
X
X
Xpurgeline()
X{
X#ifdef USG
X	ioctl(0, TCFLSH, 0);
X#else
X	lseek(0, 0L, 2);
X#endif
X}
X#endif
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/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	"	\\ Force next option letter to upper case",
X	"	sb [-2adfkquv] [-] file ...",
X	"	sx [-2akquv] [-] file",
X#endif
X#ifndef vax11c
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 only if source newer (Z)",
X	"	N   send file only 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 (remove) file after transmission",
X#endif
X	"	v   Verbose - provide debugging information",
X	"	w N restrict Window to N bytes (Z)",
X	"	Y   Yes, overwrite existing file, skip if not present at rx (Z)",
X	"	y   Yes, overwrite existing file (Z)",
X	"	Z   Activate ZMODEM compression(Z)",
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#ifdef STAT
X	struct stat f;
X#endif
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(4, ZACK, Txhdr);
X			continue;
X		case ZCOMMAND:		/* They didn't see out ZRQINIT */
X			stohdr(0L);
X			zshhdr(4, ZRQINIT, Txhdr);
X			continue;
X		case ZRINIT:
X			Rxflags = 0377 & Rxhdr[ZF0];
X			Usevhdrs = Rxhdr[ZF1] & CANVHDR;
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
X#ifndef READCHECK
X#ifndef USG
X#ifndef GENIE
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#endif
X
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 GENIE
X#ifndef vax11c
X#ifdef STAT
X			/* If using a pipe for testing set lower buf len */
X			fstat(0, &f);
X			if ((f.st_mode & S_IFMT) != S_IFCHR) {
X				Rxbuflen = 1024;
X			}
X#endif
X#endif
X#endif
X
X#ifdef BADSEEK
X#ifdef GENIE
X			if (Txwindow == 0) {
X				Txwspac = (Txwindow = 4096)/4;
X			}
X#else
X			if (Txwindow == 0)
X				Txwindow = TXBSIZE - 1024;
X			Txwspac = TXBSIZE/4;
X#endif
X			Canseek = 0;
X#endif
X
X			/*
X			 * If input is not a regular file, force ACK's to
X			 *  prevent running beyond the buffer limits
X			 */
X#ifdef STAT
X			if ( !Command) {
X				fstat(fileno(in), &f);
X				if ((f.st_mode & S_IFMT) != S_IFREG) {
X					Canseek = -1;
X#ifdef TXBSIZE
X					Txwindow = TXBSIZE - 1024;
X					Txwspac = TXBSIZE/4;
X#else
X					return ERROR;
X#endif
X				}
X			}
X#endif
X
X			/* Set initial subpacket length */
X			if (blklen < 1024) {	/* Command line override? */
X				if (Effbaud > 300)
X					blklen = 256;
X				if (Effbaud > 1200)
X					blklen = 512;
X				if (Effbaud > 2400)
X					blklen = 1024;
X			}
X			if (Rxbuflen && blklen>Rxbuflen)
X				blklen = Rxbuflen;
X			if (blkopt && blklen > blkopt)
X				blklen = blkopt;
X#ifdef GENIE
X			blklen /= 128;  blklen *= 128;
X			if (blklen < 128)
X				blklen = 128;
X#endif
X			vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
X			vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
X
X
X			if (Lztrans == ZTRLE && (Rxflags & CANRLE))
X				Txfcs32 = 2;
X			else
X				Lztrans = 0;
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(4, 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#ifdef ALTCANOFF
X		Txhdr[ALTCOFF] = ALTCANOFF;
X#endif
X		if (Zctlesc) {
X			Txhdr[ZF0] |= TESCCTL; zshhdr(4, ZSINIT, Txhdr);
X		}
X		else
X			zsbhdr(4, ZSINIT, Txhdr);
X		zsdata(Myattn, ZATTNLEN, 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	register UNSL long crc;
X	long lastcrcrq = -1;
X	char *p;
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(4, 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 ZCRC:
X			if (Rxpos != lastcrcrq) {
X				lastcrcrq = Rxpos;
X				crc = 0xFFFFFFFFL;
X				if (Canseek >= 0) {
X					fseek(in, 0L, 0);
X					while (((c = getc(in)) != EOF)
&& --lastcrcrq)
X						crc = UPDC32(c, crc);
X					crc = ~crc;
X					clearerr(in);	/* Clear possible EOF */
X					lastcrcrq = Rxpos;
X				}
X			}
X			stohdr(crc);
X			zsbhdr(4, ZCRC, Txhdr);
X			goto again;
X		case ZSKIP:
X			fclose(in); return c;
X		case ZRPOS:
X			/*
X			 * Suppress zcrcw request otherwise triggered by
X			 * lastyunc==bytcnt
X			 */
X#ifdef GENIE
X			/*
X			 *  Special case - turn on RLE if not archive, etc.
X			 *   otherwise turn off RLE unless cmd line specified
X			 */
X			if (Rxflags & CANRLE) {		/* RX can do it */
X				bytcnt = 0;
X				zfilbuf();
X				vfile("txbuf012: %x %x %x", txbuf[0], txbuf[1],
X				  txbuf[2]);
X				if ((txbuf[0] != 032)	/* .ARC file */
X				 && (txbuf[0] != 0x1f)	/* .Z file */
X				 && (txbuf[0] != 0x1c)	/* .LHZ file */
X				 && strncmp(txbuf, "ZOO", 3)
X				 && strncmp(txbuf, "GIF", 3)
X				 && (txbuf[2] != 3))	/* .ZIP file */
X					Txfcs32 = 2;
X				else if ( !(Lztrans & ZTRLE))
X					Txfcs32 = 1;
X			}
X			/* GEnie binary can't seek to byte */
X			if (Binfile) {
X				Rxpos &= ~127L;
X			}
X#endif
X			if (fseek(in, Rxpos, 0))
X				return ERROR;
X			Lastsync = (bytcnt = Txpos = Lrxpos = Rxpos) -1;
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	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(fd) returns non 0 if a character is available
X		 */
X		while (rdchk(0)) {
X#ifdef EATSIT
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(4, 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(0)) {
X#ifdef EATSIT
X					switch (checked)
X#else
X					switch (readline(1))
X#endif
X					{
X					case CAN:
X					case ZPAD:
X#ifdef TCFLSH
X						ioctl(0, 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		n = zfilbuf();
X		if (Eofseen)
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		} 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(fd) returns non 0 if a character is available
X		 */
X		fflush(stdout);
X		while (rdchk(0)) {
X#ifdef EATSIT
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(0, 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(0, TCFLSH, 1);
X#endif
X					zsdata(txbuf, 0, ZCRCE);
X					goto gotack;
X				}
X			}
X			vfile("window = %ld", tcount);
X		}
X	} while (!Eofseen);
X	if ( !Fromcu)
X		signal(SIGINT, SIG_IGN);
X
X	for (;;) {
X		stohdr(Txpos);
X		zsbhdr(4, 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 buffered modem, you  */
X			/*   might send a break at this point to */
X			/*   dump the modem's buffer.		 */
X			clearerr(in);	/* In case file EOF seen */
X			if (fseek(in, Rxpos, 0))
X				return ERROR;
X			Eofseen = 0;
X			bytcnt = Lrxpos = Txpos = Rxpos;
X#ifndef GENIE
X			if (Lastsync == Rxpos) {
X				if (++Beenhereb4 > 4)
X					if (blklen > 32)
X						blklen /= 2;
X			}
X#endif
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(4, 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(4, 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#ifdef GENIE
X	cmdnum = 69;
X#else
X	cmdnum = getpid();
X#endif
X	errors = 0;
X	for (;;) {
X		stohdr(cmdnum);
X		Txhdr[ZF0] = Cmdack1;
X		zsbhdr(4, ZCOMMAND, Txhdr);
X		zsdata(buf, blen, ZCRCW);
Xlisten:
X		Rxtimeout = 100;		/* Ten second wait for resp. */
X		Usevhdrs = 0;		/* Allow rx to send fixed len headers */
X		c = zgethdr(Rxhdr, 1);
X
X		switch (c) {
X		case ZRINIT:
X			goto listen;	/* CAF 8-21-87 */
X		case ERROR:
X		case GCOUNT:
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	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}
X
X#ifdef STAT
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#else
Xcountem(argc, argv)
Xregister char **argv;
X{
X	register c;
X	register char *p;
X	long size;
X
X	for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) {
X		size = -1;
X		if (Verbose>2) {
X			fprintf(stderr, "\nCountem: %03d %s ", argc, *argv);
X			fflush(stderr);
X		}
X		++Filesleft;  
X#ifdef XARGSFILE
X		/* Look for file length in third colon sep field */
X		for (p = *argv; *p; ++p) {
X			if (*p == ':') {
X				for (++p; *p; ++p) {
X					if (*p == ':') {
X						++p;
X						size = atol(p);
X						Totalleft += size;
X						break;
X					}
X				}
X			break;
X			}
X		}
X#endif
X
X		if (Verbose>2)
X			fprintf(stderr, " %ld", size);
X	}
X	if (Verbose>2)
X		fprintf(stderr, "\ncountem: Total %d %ld\n",
X		  Filesleft, Totalleft);
X}
X#endif
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
X/* End of sz.c */
END_OF_FILE
if test 44054 -ne `wc -c <'sz.c'`; then
    echo shar: \"'sz.c'\" unpacked with wrong size!
fi
# end of 'sz.c'
fi
echo shar: End of archive 4 \(of 4\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

