[comp.os.minix] zterm - background zmodem with dialer

bob@dhw68k.cts.com (Bob Best) (06/08/89)

Here is zterm, an enhancement to minix term providing support for
background zmodem transfers and a background dialer with dialing
directory.  Although zmodem sources have been previously posted to this
newsgroup, I received numerous requests for a repost.  Hence, this
package is complete with all required zmodem source.
Please see README for additional details.
-------------------cut here----------------
#! /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 1 (of 5)."
# Contents:  MANIFEST Makefile README bell.c bgdial bgzmod crc.man
#   dial.c dial.dir dialer rbsb.c zmodem.h zterm.c
# Wrapped by bob@dallnix on Wed Jun  7 19:29:58 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(716 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	
X Makefile                   1	
X README                     1	
X bell.c                     1	
X bgdial                     1	
X bgzmod                     1	
X crc.c                      2	
X crc.man                    1	
X crctab.c                   2	
X dial.c                     1	
X dial.dir                   1	
X dialer                     1	
X rbsb.c                     1	
X rz.c                       4	
X rz.man                     2	
X sz.c                       5	
X sz.man                     3	
X zm.c                       3	
X zmodem.h                   1	
X zterm.c                    1	
END_OF_FILE
if test 716 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1592 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Makefile for Minix zterm serial communications
X# with support for background zmodem transfers
X# and background dialing
X
XBINDIR=/usr/bin
XZDIR=/usr/lib/zterm
X
XCFLAGS=
X
Xall:	rz sz dial zterm bell
X
Xrz:	rz.c zm.c zmodem.h rbsb.c crctab.c
X	cc -DMD=2 -Dstrchr=index -DV7 $(CFLAGS) rz.c -o rz
X	size rz
X
Xsz:	sz.c zm.c zmodem.h rbsb.c crctab.c
X	cc -DV7 $(CFLAGS) -DNFGVMIN sz.c -o sz
X	size sz
X
Xdial:	dial.c
X	cc $(CFLAGS) dial.c -o dial
X
Xzterm:	zterm.c
X	cc $(CFLAGS) zterm.c -o zterm
X
Xbell:	bell.c
X	cc $(CFLAGS) bell.c -o bell
X
Xinstall:
X	-mkdir $(ZDIR)
X	-chmod 755 $(ZDIR)
X	chown bin $(ZDIR)
X	rm $(BINDIR)/rb
X	rm $(BINDIR)/rx
X	rm $(BINDIR)/sb
X	rm $(BINDIR)/sx
X	cp sz rz zterm $(BINDIR)
X	ln $(BINDIR)/rz $(BINDIR)/rx
X	ln $(BINDIR)/rz $(BINDIR)/rb
X	ln $(BINDIR)/sz $(BINDIR)/sx
X	ln $(BINDIR)/sz $(BINDIR)/sb
X	-chmod 755 $(BINDIR)/zterm
X	chown bin $(BINDIR)/zterm
X#	chgrp bin $(BINDIR)/zterm
X	-chmod 755 $(BINDIR)/rz
X	-chmod 755 $(BINDIR)/sz
X	chown bin $(BINDIR)/rz
X	chown bin $(BINDIR)/sz
X#	chgrp bin $(BINDIR)/rz
X#	chgrp bin $(BINDIR)/sz
X	cp dial bell bgdial bgzmod dialer $(ZDIR)
X	-chmod 755 $(ZDIR)/dial
X	chown bin $(ZDIR)/dial
X#	chgrp bin $(ZDIR)/dial
X	-chmod 755 $(ZDIR)/bell
X	chown bin $(ZDIR)/bell
X#	chgrp bin $(ZDIR)/bell
X	-chmod 755 $(ZDIR)/bgdial
X	chown bin $(ZDIR)/bgdial
X#	chgrp bin $(ZDIR)/bgdial
X	-chmod 755 $(ZDIR)/bgzmod
X	chown bin $(ZDIR)/bgzmod
X#	chgrp bin $(ZDIR)/bgzmod
X	-chmod 755 $(ZDIR)/dialer
X	chown bin $(ZDIR)/dialer
X#	chgrp bin $(ZDIR)/dialer
X	chmem =4000 $(BINDIR)/sz
X	chmem =4000 $(BINDIR)/rz
X	chmem =1000 $(ZDIR)/bell
X	chmem =4000 $(ZDIR)/dial
X	chmem =8000 $(BINDIR)/zterm
END_OF_FILE
if test 1592 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(3699 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XWed Jun  7 19:29:29 PDT 1989
X
XZTERM - Background Zmodem Transfer and Auto Dialer for Minix
X		hacked by bob best (bob@dhw68k.cts.com)
X
XThe following hack provides support for zmodem transfers under Minix.
XThe term.c (now zterm.c) code has been modified to allow access to the
Xsz (send zmodem) and rz (receive zmodem) programs developed by Chuck
XForsberg.  The actual rz and sz sources used are based on the original
X2.0 release dating back to 5/88.  I have also included support for a background
Xdialer and dialing directory.  The dial.c code assumes a Hayes compatible
Xmodem ("AT" command set that sends a "CONNECT" string on carrier detect).
X
XThe file zterm.c uses some hard coded parameters that should be modified
Xfor compatibility with your system.  The definable constant MODEM is
Xcurrently set for /dev/tty1.  The constant ZDIR is set for
X'/usr/lib/zterm'.  The 'dialer' 'dial', 'bgdial', 'bgzmod', and 'bell'
Xprograms are all placed in ZDIR by 'make install'.  Similarly, the
Xprograms 'zterm', 'rz', and 'sz' are placed in /usr/bin.
XIf ZDIR is changed in zterm.c the absolute paths must be changed in the
Xvarious shell scripts.
X
XThe dialing directory is formatted as 5 tab separated fields defined as follows:
X1) a code number used to refer to a particular entry
X2) the telephone number to be dialed
X3) the baud rate used for dialing
X4) the date and time of the last connection to this system
X5) user description of this system (not used by software)
XEach field must be separated by exactly one tab character.
XA preformatted directory 'dial.dir' has been included.  The 'dial.dir'
Xshould be located in $HOME, the user's home directory.
X
XTo access the dialing directory in zterm, type a tilde '~' followed by
Xthe character 'd' for dial.  To access the zmodem protocol handlers,
Xtype a tilde followed by 't' for transfer.  You will be prompted for the
Xtransfer command.  To receive, simply type 'rz'.  To send, type 'sz'.
XYou will then be prompted for a list of files (shell wildcards accepted)
Xto transmit.  When the zmodem handlers start execution, zterm will exit
Xto the shell.  The transfers will continue in the background.  Upon
Xcompletion, a bell will sound and a message will be displayed on the
Xterminal.  The user can then return to zterm.  Do NOT run zterm while
Xthe transfers are taking place.  To monitor an ongoing transfer, examine
Xthe file /tmp/[rs]zlog.  To exit from the terminal, type a tilde
Xfollowed by a period '.'.  To enter a tilde, type 2 tildes.
X
XThe automatic dialing code has been designed to continuously dial in the
Xbackground until a connection is made.  The dialer will cycle through a
Xuser selected list of systems to dial.  During dialing, the user will be
Xable to access a shell to interact with the system.  When a connection
Xis made, the user will be rudely interrupted with a message to that effect.
XIf background dialing must be terminated prior to a connection, hit 'F1'
Xfor a process dump, and use the kill command with the 'bgdial' pid.
X
XThe zterm terminal can be entered or exited at anytime without
Xdropping carrier.  The user is solely responsible for disconnecting the
Xline.  This implementation is somewhat messy.  On my Xenix system, the
Xinterface is simplified via a window manager.  If anyone is working on a
Xwindow manager or job control for Minix, please notify.
XSome locking mechanism should be provided to prevent multiple access
Xto the modem.
X
XIt is not my intent to support this package.  For users with particular
Xneeds, the source is straightforward and can be easily modified.  If you
Xhave specific questions, please post them to comp.os.minix.  This
Xpackage has been tested using only the Evans kernel including the Evans
Xtty driver.
END_OF_FILE
if test 3699 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'bell.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bell.c'\"
else
echo shar: Extracting \"'bell.c'\" \(209 characters\)
sed "s/^X//" >'bell.c' <<'END_OF_FILE'
X#define BELL '\007'
X#define DEFCOUNT 3
Xchar c=BELL;
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	int count=DEFCOUNT;
X	
X	if (argc > 1)
X		count=atoi(argv[1]);
X	while (count--) {
X		write(1,&c,1);
X		sleep(1);
X	}
X}
X
END_OF_FILE
if test 209 -ne `wc -c <'bell.c'`; then
    echo shar: \"'bell.c'\" unpacked with wrong size!
fi
# end of 'bell.c'
fi
if test -f 'bgdial' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bgdial'\"
else
echo shar: Extracting \"'bgdial'\" \(872 characters\)
sed "s/^X//" >'bgdial' <<'END_OF_FILE'
X#	bgdial - auto-redial till connect
X#	written by bob best (bob@dhw68k.cts.com)
X#
XZDIR="/usr/lib/zterm"
XTTY="$1"
Xshift
Xfor i
Xdo
X	set `grep "^${i}	" ${HOME}/dial.dir`
X	lines="$lines $1 $2 $3"
Xdone
Xwhile :
Xdo
X	set $lines
X	while :
X	do
X		system=$1
X		case $system in
X		"")	#break # bug in shell! must use continue
X			continue 2
X			;;
X		*)	shift
X			telno=$1
X			shift
X			baud=$1
X			shift
X#			echo "dialing $system $telno $baud"
X			${ZDIR}/dial $TTY $telno $baud
X			case $? in
X			0)	${ZDIR}/bell
X				clr
X				echo "CONNECTION ESTABLISHED TO $system $telno $baud"
X				echo "Exit to shell and type 'zterm $baud' to enter terminal"
X				cp $HOME/dial.dir $HOME/dial.dirbak
X				sed  "s/^\\($system	.*	.*	\\)\\(.*\\)\\(	.*\\)/\\1`date|sed -f /tmp/sed.in`\\3/" $HOME/dial.dirbak >$HOME/dial.dir
X				rm /tmp/dial.menu
X				rm /tmp/sed.in
X				exit 0
X				;;
X			*)	;;
X			esac
X		esac
X	done
Xdone
END_OF_FILE
if test 872 -ne `wc -c <'bgdial'`; then
    echo shar: \"'bgdial'\" unpacked with wrong size!
fi
chmod +x 'bgdial'
# end of 'bgdial'
fi
if test -f 'bgzmod' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bgzmod'\"
else
echo shar: Extracting \"'bgzmod'\" \(480 characters\)
sed "s/^X//" >'bgzmod' <<'END_OF_FILE'
X# bgzmod - run zmodem transfers in the background
X#          called by zterm
XZDIR=/usr/lib/zterm
Xcommand="$1"
Xshift
Xcase $command in
Xrz) ;;
Xsz) for i
X    do
X    files="$files $i"
X    done
X    ;;
X*)  echo "Bad command - exiting" >/dev/tty
X    exit 1;
X    ;;
Xesac
X$command -vvv $files # add more v's for more output (see /tmp/[rs]zlog)
X#exec </dev/tty >/dev/tty
X(${ZDIR}/bell;clr;echo "Zmodem Transfers Completed";echo "Exit to shell and type 'zterm' to enter terminal") >/dev/tty
X
END_OF_FILE
if test 480 -ne `wc -c <'bgzmod'`; then
    echo shar: \"'bgzmod'\" unpacked with wrong size!
fi
chmod +x 'bgzmod'
# end of 'bgzmod'
fi
if test -f 'crc.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'crc.man'\"
else
echo shar: Extracting \"'crc.man'\" \(995 characters\)
sed "s/^X//" >'crc.man' <<'END_OF_FILE'
X
X
X
X     CRC(1)		   MINIX Version 1.3+ (OMEN)		CRC(1)
X
X
X
X     NAME
X	  crc -	checksum files
X
X     SYNOPSIS
X	  crc file ...
X
X     DESCRIPTION
X	  For each file, crc calculates	and prints a 32-bit CRC, the
X	  byte count, and the file name.  It is	typically used to
X	  validate files transferred between different systems,	and is
X	  useful in detecting subtle disk corruption.  Crc uses	a
X	  checksum compatible with the DOS version of crc, as well as
X	  the "crc" command in ZCOMM and Professional-YAM (high
X	  reliability communications programs).
X
X	  The 32-bit CRC used is the frame check sequence in ADCCP
X	  (ANSI	X3.66, also known as FIPS PUB 71 and FED-STD-1003, the
X	  U.S. versions	of CCITT's X.25	link-level protocol).
X
X	  32 bit CRC code courtesy Gary	S. Brown.
X
X     BUGS
X	  Although most	unlikely, files	with different data may	still
X	  produce the same crc value.
X
X     SEE ALSO
X	  chek(1), tocpm(1), sum(1), wc(1).
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X     Page 1					      (printed 6/6/89)
X
X
X
END_OF_FILE
if test 995 -ne `wc -c <'crc.man'`; then
    echo shar: \"'crc.man'\" unpacked with wrong size!
fi
# end of 'crc.man'
fi
if test -f 'dial.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dial.c'\"
else
echo shar: Extracting \"'dial.c'\" \(1981 characters\)
sed "s/^X//" >'dial.c' <<'END_OF_FILE'
X/* dial.c
X * written by bob best (bob@dhw68k.cts.com)
X * 
X * supports Hayes compatible modems
X * Usage: dial device telno baudrate
X * 
X * this program is called by the 'dialer' shell script that is part
X * of the zterm package posted to comp.os.minix
X */
X#include <stdio.h>
X#include <signal.h>
X#include <fcntl.h>
X#include <sgtty.h>
X
X#define	FAIL    1
X#define	SUCCESS	0
X#define BUFLINE	256	
X#define CMDLINE	80
X#define TIMEOUT	30
X
Xchar *strchr();
Xint alarmsig();
Xint fd;
X
Xmain(argc,argv)
X	int argc;
X	char *argv[];
X{
X	char *device;
X	char *telno;
X	char cmdbuf[CMDLINE];
X	int timeout, baudrate;
X	char *p;
X	struct sgttyb sgtty;
X
X	device = argv[1];
X	telno = argv[2];
X/*	baudrate = atoi(argv[3]);*/
X	switch(atoi(argv[3])) {
X	case 1200:
X		baudrate=B1200;
X		break;
X	case 2400:
X		baudrate=B2400;
X		break;
X	case 9600:
X		baudrate=B9600;
X		break;
X	default:
X		printf("Bad baudrate %s - exiting\r\n",argv[3]);
X		exit(1);
X	}	
X	if ((fd = open(device, O_RDWR)) < 0) {
X		printf("dial: Can't open device: %s\n", device);
X		exit(FAIL);
X	}
X
X	ioctl(fd, TIOCGETP, &sgtty);
X	sgtty.sg_ispeed = baudrate;
X	sgtty.sg_ospeed = baudrate;
X	ioctl(fd, TIOCSETP, &sgtty);
X	sleep(1);
X	write(fd,"AT\r",3);
X	sleep(2);
X	sprintf(cmdbuf, "ATDT%s\r", telno);
X	timeout = TIMEOUT;
X	signal(SIGALRM, alarmsig);
X	p=cmdbuf;
X	while (*p)
X		write(fd, p++, 1);
X	if (getmodem(timeout))
X		exit(FAIL);
X	else
X		exit(SUCCESS);
X}
X
Xgetmodem(timer)
X	int timer;
X{
X	char c;
X	register char *p;
X	char buf[BUFLINE];
X
X	p = buf;
X	alarm(timer);
X	while (read(fd, &c, 1) == 1) {
X		*p++ = c;
X		if (p >= buf + BUFLINE) {
X			alarm(0);
X			return(FAIL);
X		}
X		if (c == '\r') {
X			if (getCONNECT(buf) == SUCCESS) {
X				alarm(0);
X				return(SUCCESS);
X			}
X			p=buf; /* reset pointer for next string */
X		}
X	}
X	alarm(0);
X	return(FAIL);
X}
X
XgetCONNECT(l)
X	register char *l;
X{
X	int len = strlen("CONNECT");
X
X	while ((l = strchr(l, 'C')) != NULL) {
X		if (strncmp("CONNECT", l, len) == 0)
X			return(SUCCESS);
X		l++;
X	}
X	return(FAIL);
X}
X
Xalarmsig()
X{
X	exit(FAIL);
X}
END_OF_FILE
if test 1981 -ne `wc -c <'dial.c'`; then
    echo shar: \"'dial.c'\" unpacked with wrong size!
fi
# end of 'dial.c'
fi
if test -f 'dial.dir' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dial.dir'\"
else
echo shar: Extracting \"'dial.dir'\" \(380 characters\)
sed "s/^X//" >'dial.dir' <<'END_OF_FILE'
Xa0	5551234	2400	Jan  1 00:00	System 0
Xa1	5551234	2400	Jan  1 00:00	System 1
Xa2	5551234	2400	Jan  1 00:00	System 2
Xa3	5551234	2400	Jan  1 00:00	System 3
Xa4	5551234	2400	Jan  1 00:00	System 4
Xa5	5551234	2400	Jan  1 00:00	System 5
Xa6	5551234	2400	Jan  1 00:00	System 6
Xa7	5551234	2400	Jan  1 00:00	System 7
Xa8	5551234	2400	Jan  1 00:00	System 8
Xa9	5551234	2400	Jan  1 00:00	System 9
END_OF_FILE
if test 380 -ne `wc -c <'dial.dir'`; then
    echo shar: \"'dial.dir'\" unpacked with wrong size!
fi
# end of 'dial.dir'
fi
if test -f 'dialer' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dialer'\"
else
echo shar: Extracting \"'dialer'\" \(1421 characters\)
sed "s/^X//" >'dialer' <<'END_OF_FILE'
X#	Auto Dialer shell script for minix
X#	Written by bob best (bob@dhw68k.cts.com)
X#
XZDIR=/usr/lib/zterm
XTTY=$1
X
Xcat	>/tmp/dial.menu <<'FOO'
X		MINIX TERMINAL DIALER
X		D  Dial once only
X		A  Auto-redial till connect
X		Q  Quit to Terminal
X
XFOO
X
X# this is a hack, but I couldn't fix the shell
Xcat	>/tmp/sed.in <<'FOO'
Xs/^[A-Z].. \([A-Z].*\):.*/\1/
XFOO
X
Xwhile :
Xdo
X	clr
X	cat /tmp/dial.menu
X	echo -n "		Enter your choice: "
X	read choice
X	case $choice in
X	a|A)    clr
X			cat $HOME/dial.dir
X			echo -n "Enter the code name of the system(s) you wish to dial: "
X			read choice
X			${ZDIR}/bgdial $TTY $choice &
X			sleep 2
X			clr
X			echo "Dialing in progress - exiting terminal & returning to shell"
X			exit 1
X			;;
X	d|D)    clr
X			cat $HOME/dial.dir
X			echo -n "Enter the code name of the system you wish to dial: "
X			read choice
X			set `grep "^${choice}	" ${HOME}/dial.dir`
X			echo "dialing $choice $2 $3"
X			${ZDIR}/dial $TTY $2 $3
X			case $? in
X				0) ${ZDIR}/bell 1
X				   echo "CONNECTION ESTABLISHED TO $choice $2"
X				   cp $HOME/dial.dir $HOME/dial.dirbak
X				   sed  "s/^\\($choice	.*	.*	\\)\\(.*\\)\\(	.*\\)/\\1`date|sed -f /tmp/sed.in`\\3/" $HOME/dial.dirbak >$HOME/dial.dir
X				   rm /tmp/dial.menu
X				   rm /tmp/sed.in
X				   exit 0
X				   ;;
X				*) echo "NO CONNECTION"
X				   sleep 2
X				   ;;
X			esac
X			;;
X	q|Q)	rm /tmp/dial.menu
X			rm /tmp/sed.in
X			exit 0
X			;;
X	*)      echo "Invalid character"
X			;;
X	esac
Xdone
END_OF_FILE
if test 1421 -ne `wc -c <'dialer'`; then
    echo shar: \"'dialer'\" unpacked with wrong size!
fi
chmod +x 'dialer'
# end of 'dialer'
fi
if test -f 'rbsb.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rbsb.c'\"
else
echo shar: Extracting \"'rbsb.c'\" \(6735 characters\)
sed "s/^X//" >'rbsb.c' <<'END_OF_FILE'
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		tty.sg_flags &= ~(CRMOD|ECHO);
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 */
END_OF_FILE
if test 6735 -ne `wc -c <'rbsb.c'`; then
    echo shar: \"'rbsb.c'\" unpacked with wrong size!
fi
# end of 'rbsb.c'
fi
if test -f 'zmodem.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'zmodem.h'\"
else
echo shar: Extracting \"'zmodem.h'\" \(5487 characters\)
sed "s/^X//" >'zmodem.h' <<'END_OF_FILE'
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 */
END_OF_FILE
if test 5487 -ne `wc -c <'zmodem.h'`; then
    echo shar: \"'zmodem.h'\" unpacked with wrong size!
fi
# end of 'zmodem.h'
fi
if test -f 'zterm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'zterm.c'\"
else
echo shar: Extracting \"'zterm.c'\" \(5517 characters\)
sed "s/^X//" >'zterm.c' <<'END_OF_FILE'
X/* term - terminal simulator		Author: Andy Tanenbaum */
X/* support for zmodem transfers and auto dialer added by
X * bob best (bob@dhw68k.cts.com)
X */
X/* This program allows the user to turn a MINIX system into a dumb
X * terminal to communicate with a remote computer over a modem.  It
X * forks into two processes.  The parent sits in a tight loop copying
X * from the keyboard to the modem.  The child sits in a tight loop
X * copying from the modem to the screen.
X *
X * Example usage:
X *	term			: 1200 baud, 8 bits/char, no parity
X *	term 9600 7 even	: 9600 baud, 7 bits/char, even parity
X *	term odd 300 7		:  300 baud, 7 bits/char, odd parity
X *
X * The constant MODEM should be configured by the user
X */
X#define MODEM "/dev/tty1"	/* special file attached to the modem */
X#define ZDIR "/usr/lib/zterm"
X#include <setjmp.h>
X#include <stdio.h>
X#include <signal.h>
X#include <sgtty.h>
X
X#define MAXARGS 3		/* maximum number of uart params */
X#define NCHECKS 10
X#define BAD -1
X#define GOOD 1
X#define DEF_SPEED B2400		/* default baudrate */
X#define DEF_BITS BITS8		/* default bits/char */
X#define TILDE '~'
X#define CHUNK 1024		/* how much to read at once */
X
Xint modem, pid;			/* file descriptor for modem */
Xchar *pat[NCHECKS] = 
X{
X	"5", "6", "7", "8", "110", "300", "1200", "2400", "4800", "9600"};
X
Xint value[NCHECKS] = 
X{
X	BITS5, BITS6, BITS7, BITS8, B110, B300, B1200, B2400, B4800, B9600};
X
Xint hold[MAXARGS];
Xstruct sgttyb sgtty, sgsave1, sgsave2;
Xjmp_buf jbuf;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X
X	sync();
X	modem = open(MODEM, 2);
X	if (modem < 0) {
X		printf("Can't open modem on %s\n", MODEM);
X		exit(1);
X	}
X	setjmp(jbuf);
X	set_uart(argc, argv);
X	/* Main body of the terminal simulator. */
X	if ( (pid = fork()))
X		copy(0, modem, 1);	/* copy from stdin to modem */
X	else
X		copy(modem, 1, -1);	/* copy from modem to stdout */
X}
X
Xset_uart(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	/* Set up the UART parameters. */
X
X	int i, k, v, nspeeds = 0, speed, nbits = 0, bits, parity = 0;
X
X	if (argc > MAXARGS + 1)
X		error("Usage: term [baudrate] [data_bits] [parity]\n");
X
X	/* Examine all the parameters and check for validity. */
X	speed = DEF_SPEED;		/* default line speed */
X	bits = DEF_BITS;		/* default bits/char */
X	for (i = 1; i < argc; i++) {
X		if (strcmp(argv[i], "even") == 0) {
X			parity = EVENP; 
X			continue;
X		}
X		if (strcmp(argv[i], "odd") == 0)  {
X			parity = ODDP; 
X			continue;
X		}
X		v = validity(argv[i]);
X		if (v == BAD) {
X			printf("Invalid parameter: %s\n", argv[i]);
X			exit(1);
X		}
X		k = atoi(argv[i]);
X		if (k > 100) {
X			speed = value[v];
X			nspeeds++;
X		}
X		if ( k < 10) {
X			bits = value[v];
X			nbits++;
X		}
X		if (nspeeds > 1) error("Too many speeds\n");
X		if (nbits > 1) error("Too many character sizes\n");
X	}
X
X	/* Fetch the modem parameters, save them, and set new ones. */
X	ioctl(modem, TIOCGETP, &sgtty);
X	sgsave1 = sgtty;		/* modem parameters */
X	sgtty.sg_ispeed = speed;
X	sgtty.sg_ospeed = speed;
X	sgtty.sg_flags = RAW | parity | bits;
X	ioctl(modem, TIOCSETP, &sgtty);
X	sleep(1);
X/*	write(modem,"AT\r",3);*/
X
X	/* Fetch the keyboard parameters, save them, and set new ones. */
X	ioctl(0, TIOCGETP, &sgtty);
X	sgsave2 = sgtty;		/* modem parameters */
X	sgtty.sg_flags = (sgtty.sg_flags & 01700) + RAW;
X	ioctl(0, TIOCSETP, &sgtty);
X}
X
X
Xint validity(s)
Xchar *s;
X{
X	/* Check parameter for legality. */
X
X	int i;
X
X	for (i = 0; i < NCHECKS; i++) {
X		if (strcmp(s, pat[i]) == 0) return(i);
X	}
X	return(BAD);
X}
X
X
Xcopy(in, out, end)
Xint in, out, end;
X{
X/* Copy from the keyboard to the modem or vice versa. If the end character
X * is seen LIMIT times in a row, quit.  For the traffic from the modem, the
X * end character is -1, which cannot occur since the characters from the
X * modem are unsigned integers in the range 0 to 255.
X */
X
X	int t, count, rc, size;
X	char buf[CHUNK], tmpbuf[CHUNK], *p;
X
X	if (end > 0)
X		size=1;
X	else
X		size=CHUNK;
X
X	while (1) {
X		if ( (count = read(in, buf, size)) < 0) {
X			printf("Can't read from modem\r\n");
X			kill_child();
X			mdm_restore();
X			kbd_restore();
X			exit(0);
X		}
X
X		if (end > 0) {
X			t = buf[0] & 0377;		/* t is unsigned int 0 - 255 */
X			if (t == TILDE) {
X				count=read(in,buf,1);
X				t = buf[0] & 0377;
X				switch (t) {
X				case '.':
X					kill_child();
X					mdm_restore();
X					kbd_restore();
X					printf("End of terminal session\r\n");
X					exit(0);
X				case 'd':
X					kill_child();
X					kbd_restore();
X					strcpy(buf,ZDIR);
X					strcat(buf,"/dialer ");
X					strcat(buf,MODEM);
X					if (system(buf))
X						exit(0);
X					mdm_restore();
X					longjmp(jbuf,0);
X					break;
X				case 't':
X					kbd_restore();
X					kill_child();
X					strcpy(buf,ZDIR);
X					strcat(buf,"/bgzmod ");
X					puts("\r\nEnter file transfer command (rz or sz):");
X					fflush(stdout);
X					gets(tmpbuf);
X					strcat(buf,tmpbuf);
X					strcat(buf," ");
X					if (!strcmp(tmpbuf,"sz")) {
X						puts("Enter files to send:");
X						fflush(stdout);
X						gets(tmpbuf);
X						strcat(buf,tmpbuf);
X					}
X					strcat(buf," <");
X					strcat(buf,MODEM);
X					strcat(buf," >");
X					strcat(buf,MODEM);
X					strcat(buf," &");
X					system(buf);
X					printf("\r\nReturning to shell\r\n");
X					fflush(stdout);
X					exit(0);
X/*					mdm_restore();*/
X/*					longjmp(jbuf,0);*/
X					break;
X				case '~':
X					break;
X				default:
X					break;
X
X				}
X			}
X		}
X		write(out, buf, count);
X	}
X}
X
X
Xerror(s)
Xchar *s;
X{
X	printf("%s", s);
X	exit(1);
X}
X
Xmdm_restore()
X{
X	ioctl(modem, TIOCSETP, &sgsave1);
X}
X
Xkbd_restore()
X{
X	ioctl(0, TIOCSETP, &sgsave2);
X}
X
Xkill_child()
X{
X	if (getpid() != pid) kill(pid, SIGINT);
X}
END_OF_FILE
if test 5517 -ne `wc -c <'zterm.c'`; then
    echo shar: \"'zterm.c'\" unpacked with wrong size!
fi
# end of 'zterm.c'
fi
echo shar: End of archive 1 \(of 5\).
>ark1isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 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
-- 
Bob Best
uucp: {spsd, zardoz, felix}!dhw68k!bob	InterNet: bob@dhw68k.cts.com

bob@dhw68k.cts.com (Bob Best) (06/08/89)

#! /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 2 (of 5)."
# Contents:  crc.c crctab.c rz.man
# Wrapped by bob@dallnix on Wed Jun  7 19:29:59 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'crc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'crc.c'\"
else
echo shar: Extracting \"'crc.c'\" \(8566 characters\)
sed "s/^X//" >'crc.c' <<'END_OF_FILE'
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
END_OF_FILE
if test 8566 -ne `wc -c <'crc.c'`; then
    echo shar: \"'crc.c'\" unpacked with wrong size!
fi
# end of 'crc.c'
fi
if test -f 'crctab.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'crctab.c'\"
else
echo shar: Extracting \"'crctab.c'\" \(8737 characters\)
sed "s/^X//" >'crctab.c' <<'END_OF_FILE'
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 */
END_OF_FILE
if test 8737 -ne `wc -c <'crctab.c'`; then
    echo shar: \"'crctab.c'\" unpacked with wrong size!
fi
# end of 'crctab.c'
fi
if test -f 'rz.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rz.man'\"
else
echo shar: Extracting \"'rz.man'\" \(9207 characters\)
sed "s/^X//" >'rz.man' <<'END_OF_FILE'
X
X
X
X     RZ(1)		   MINIX Version 1.3+ (OMEN)		 RZ(1)
X
X
X
X     NAME
X	  rx, rb, rz - XMODEM, YMODEM, ZMODEM (Batch) file receive
X
X     SYNOPSIS
X	  rz [-	+abepqtuvy]
X	  rb [-	+abqtuvy]
X	  rx [-	abceqtuv] file
X	  gz file ...
X	  [-][v]rzCOMMAND
X
X     DESCRIPTION
X	  This program uses error correcting protocols to receive
X	  files	over a dial-in serial port from	a variety of programs
X	  running under	PC-DOS,	CP/M, Unix, and	other operating
X	  systems.  It is invoked from a shell prompt manually,	or
X	  automatically	as a result of an "sz file ..."	command	given
X	  to the calling program.
X
X	  While	rz is smart enough to be called	from cu(1), very few
X	  versions of cu(1) are	smart enough to	allow rz to work
X	  properly.  Unix flavors of Professional-YAM are available
X	  for such dial-out application.
X
X
X	  Rz (Receive ZMODEM) receives files with the ZMODEM batch
X	  protocol.  Pathnames are supplied by the sending program,
X	  and directories are made if necessary	(and possible).
X	  Normally, the	"rz" command is	automatically issued by	the
X	  calling ZMODEM program, but some defective ZMODEM
X	  implementations may require starting rz the old fashioned
X	  way.
X
X
X	  Rb receives file(s) with YMODEM, accepting either standard
X	  128 byte sectors or 1024 byte	sectors	(YAM sb	-k option).
X	  The user should determine when the 1024 byte block length
X	  actually improves throughput without causing lost data or
X	  even system crashes.
X
X	  If True YMODEM (Omen Technology trademark) file information
X	  (file	length,	etc.) is received, the file length controls
X	  the number of	bytes written to the output dataset, and the
X	  modify time and file mode (iff non zero) are set
X	  accordingly.
X
X	  If no	True YMODEM file information is	received, slashes in
X	  the pathname are changed to underscore, and any trailing
X	  period in the	pathname is eliminated.	 This conversion is
X	  useful for files received from CP/M systems.	With YMODEM,
X	  each file name is converted to lower case unless it contains
X	  one or more lower case letters.
X
X
X
X
X     Page 1					      (printed 6/6/89)
X
X
X
X
X
X
X     RZ(1)		   MINIX Version 1.3+ (OMEN)		 RZ(1)
X
X
X
X	  Rx receives a	single file with XMODEM	or XMODEM-1k protocol.
X	  The user should determine when the 1024 byte block length
X	  actually improves throughput without causing problems.  The
X	  user must supply the file name to both sending and receiving
X	  programs.  Up	to 1023	garbage	characters may be added	to the
X	  received file.
X
X	  Gz is	a shell	script which calls sz to command Pro-YAM or
X	  ZCOMM	to transmit the	specified files.  Pathnames used with
X	  gz must be escaped if	they have special significance to the
X	  Unix shell.
X	  EXAMPLE: gz "-a C:*.c	D:*.h"
X
X
X	  Rz may be invoked as rzCOMMAND (with an optional leading -
X	  as generated by login(1)).  For each received	file, rz will
X	  pipe the file	to ``COMMAND filename''	where filename is the
X	  name of the transmitted file with the	file contents as
X	  standard input.
X
X	  Each file transfer is	acknowledged when COMMAND exits	with 0
X	  status.  A non zero exit status terminates transfers.
X
X	  A typical use	for this form is rzrmail which calls rmail(1)
X	  to post mail to the user specified by	the transmitted	file
X	  name.	 For example, sending the file "caf" from a PC-DOS
X	  system to rzrmail on a Unix system would result in the
X	  contents of the DOS file "caf" being mailed to user "caf".
X
X	  On some Unix systems,	the login directory must contain a
X	  link to COMMAND as login sets	SHELL=rsh which	disallows
X	  absolute pathnames.  If invoked with a leading ``v'',	rz
X	  will report progress to /tmp/rzlog.  The following entry
X	  works	for Unix SYS III/V:
X		     rzrmail::5:1::/bin:/usr/local/rzrmail
X	  If the SHELL environment variable includes rsh or rksh
X	  (restricted shell), rz will not accept absolute pathnames or
X	  references to	a parent directory, will not modify an
X	  existing file, and removes any files received	in error.
X
X	  If rz	is invoked with	stdout and stderr to different
X	  datasets, Verbose is set to 2, causing frame by frame
X	  progress reports to stderr.  This may	be disabled with the q
X	  option.
X
X
X	  The meanings of the available	options	are:
X
X	  a    Convert files to	Unix conventions by stripping carriage
X	       returns and all characters beginning with the first
X	       Control Z (CP/M end of file).
X	  b    Binary (tell it like it is) file	transfer override.
X
X
X
X     Page 2					      (printed 6/6/89)
X
X
X
X
X
X
X     RZ(1)		   MINIX Version 1.3+ (OMEN)		 RZ(1)
X
X
X
X	  c    Request 16 bit CRC.  XMODEM file	transfers default to 8
X	       bit checksum.  YMODEM and ZMODEM	normally use 16	bit
X	       CRC.
X	  D    Output file data	to /dev/null; for testing.  (Unix
X	       only)
X	  e    Force sender to escape all control characters; normally
X	       XON, XOFF, DLE, CR-@-CR,	and Ctrl-X are escaped.
X	  p    (ZMODEM)	Protect: skip file if destination file exists.
X	  q    Quiet suppresses	verbosity.
X	  t tim
X	       Change timeout to tim tenths of seconds.
X	  v    Verbose causes a	list of	file names to be appended to
X	       /tmp/rzlog .  More v's generate more output.
X	  y    Yes, clobber any	existing files with the	same name.
X
X     EXAMPLES
X	  (Pro-YAM command)
X	  <ALT-2>
X	  Pro-YAM Command: sz *.h *.c
X	  (This	automatically invokes rz on the	connected system.)
X
X     SEE ALSO
X	  ZMODEM.DOC, YMODEM.DOC, Professional-YAM, crc(omen),
X	  sz(omen), usq(omen), undos(omen)
X
X	  Compile time options required	for various operating systems
X	  are described	in the source file.
X
X     NOTES
X	  Sending serial data to timesharing minicomputers at
X	  sustained high speeds	has been known to cause	lockups,
X	  system halts,	kernel panics, and occasional antisocial
X	  behaviour.  When experimenting with high speed input to a
X	  system, consider rebooting the system	if the file transfers
X	  are not successful, especially if the	personality of the
X	  system appears altered.
X
X	  The Unix "ulimit" parameter must be set high enough to
X	  permit large file transfers.
X
X	  The TTY input	buffering on some systems may not allow	long
X	  blocks or streaming input at high speed.  You	should suspect
X	  this problem when you	can't send data	to the Unix system at
X	  high speeds using ZMODEM, YMODEM-1k or XMODEM-1k, when
X	  YMODEM with 128 byte blocks works properly.  If the system's
X	  tty line handling is really broken, the serial port or the
X	  entire system	may not	survive	the onslaught of long bursts
X	  of high speed	data.
X
X	  The DSZ or Pro-YAM zmodem l numeric parameter	may be set to
X	  a value between 64 and 1024 to limit the burst length
X	  ("zmodem pl128").
X
X
X
X     Page 3					      (printed 6/6/89)
X
X
X
X
X
X
X     RZ(1)		   MINIX Version 1.3+ (OMEN)		 RZ(1)
X
X
X
X	  32 bit CRC code courtesy Gary	S. Brown.  Directory creation
X	  code from John Gilmore's PD TAR program.
X
X     BUGS
X	  Calling rz from most versions	of cu(1) doesn't work because
X	  cu's receive process fights rz for characters	from the
X	  modem.
X
X	  Programs that	do not properly	implement the specified	file
X	  transfer protocol may	cause sz to "hang" the port for	a
X	  minute or two.  Every	reported instance of this problem has
X	  been corrected by using ZCOMM, Pro-YAM, or other program
X	  with a correct implementation	of the specified protocol.
X
X	  Many programs	claiming to support YMODEM only	support	XMODEM
X	  with 1k blocks, and they often don't get that	quite right.
X
X	  Pathnames are	restricted to 127 characters.  In XMODEM
X	  single file mode, the	pathname given on the command line is
X	  still	processed as described above.  The ASCII option's
X	  CR/LF	to NL translation merely deletes CR's; undos(omen)
X	  performs a more intelligent translation.
X
X     VMS VERSION
X	  The VMS version does not set the file	time.
X
X	  VMS C	Standard I/O and RMS may interact to modify file
X	  contents unexpectedly.
X
X	  The VMS version does not support invocation as rzCOMMAND .
X	  The current VMS version does not support XMODEM, XMODEM-1k,
X	  or YMODEM.
X
X	  According to the VMS documentation, the buffered input
X	  routine used on the VMS version of rz	introduces a delay of
X	  up to	one second for each protocol transaction.  This	delay
X	  may be significant for very short files.  Removing the
X	  "#define BUFREAD" line from rz.c will	eliminate this delay
X	  at the expense of increased CPU utilization.
X
X	  The VMS version causes DCL to	generate a random off the wall
X	  error	message	under some error conditions; this is a result
X	  of the incompatibility of the	VMS "exit" function with the
X	  Unix/MSDOS standard.
X
X     ZMODEM CAPABILITIES
X	  Rz supports incoming ZMODEM binary (-b), ASCII (-a), protect
X	  (-p),	clobber	(-y), and append (-+) requests.	 The default
X	  is protect (-p) and binary (-b).
X
X	  The Unix versions support ZMODEM command execution.
X
X
X
X
X     Page 4					      (printed 6/6/89)
X
X
X
X
X
X
X     RZ(1)		   MINIX Version 1.3+ (OMEN)		 RZ(1)
X
X
X
X     FILES
X	  rz.c,	crctab.c, rbsb.c, zm.c,	zmodem.h Unix source files.
X
X	  rz.c,	crctab.c, vrzsz.c, zm.c, zmodem.h, vmodem.h,
X	  vvmodem.c, VMS source	files.
X
X	  /tmp/rzlog stores debugging output generated with -vv	option
X	  (rzlog on VMS).
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X     Page 5					      (printed 6/6/89)
X
X
X
END_OF_FILE
if test 9207 -ne `wc -c <'rz.man'`; then
    echo shar: \"'rz.man'\" unpacked with wrong size!
fi
# end of 'rz.man'
fi
echo shar: End of archive 2 \(of 5\).
>ark2isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 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
-- 
Bob Best
uucp: {spsd, zardoz, felix}!dhw68k!bob	InterNet: bob@dhw68k.cts.com

bob@dhw68k.cts.com (Bob Best) (06/08/89)

#! /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 3 (of 5)."
# Contents:  sz.man zm.c
# Wrapped by bob@dallnix on Wed Jun  7 19:30:00 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'sz.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sz.man'\"
else
echo shar: Extracting \"'sz.man'\" \(13392 characters\)
sed "s/^X//" >'sz.man' <<'END_OF_FILE'
X
X
X
X     SZ(1)		   MINIX Version 1.3+ (OMEN)		 SZ(1)
X
X
X
X     NAME
X	  sx, sb, sz - XMODEM, YMODEM, ZMODEM file send
X
X     SYNOPSIS
X	  sz [-+abdefkLlNnopqTtuvyY] file ...
X	  sb [-adfkqtuv] file ...
X	  sx [-akqtuv] file
X	  sz [-oqtv] -c	COMMAND
X	  sz [-oqtv] -i	COMMAND
X	  sz -TT
X
X     DESCRIPTION
X	  Sz uses the ZMODEM, YMODEM or	XMODEM error correcting
X	  protocol to send one or more files over a dial-in serial
X	  port to a variety of programs	running	under PC-DOS, CP/M,
X	  Unix,	VMS, and other operating systems.
X
X	  While	rz is smart enough to be called	from cu(1), very few
X	  versions of cu(1) are	smart enough to	allow sz to work
X	  properly.  Unix flavors of Professional-YAM are available
X	  for such dial-out application.
X
X
X	  Sz sends one or more files with ZMODEM protocol.
X
X	  ZMODEM greatly simplifies file transfers compared to XMODEM.
X	  In addition to a friendly user interface, ZMODEM provides
X	  Personal Computer and	other users an efficient, accurate,
X	  and robust file transfer method.
X
X	  ZMODEM provides complete END-TO-END data integrity between
X	  application programs.	 ZMODEM's 32 bit CRC catches errors
X	  that sneak into even the most	advanced networks.
X
X	  Advanced file	management features include AutoDownload
X	  (Automatic file Download initiated without user
X	  intervention), Display of individual and total file lengths
X	  and transmission time	estimates, Crash Recovery, selective
X	  file transfers, and preservation of exact file date and
X	  length.
X
X	  Output from another program may be piped to sz for
X	  transmission by denoting standard input with "-":
X				  ls -l	| sz -
X	  The program output is	transmitted with the filename sPID.sz
X	  where	PID is the process ID of the sz	program.  If the
X	  environment variable ONAME is	set, that is used instead.  In
X	  this case, the Unix command:
X			   ls -l | ONAME=con sz	-ay -
X	  will send a "file" to	the PC-DOS console display.  The -y
X	  option instructs the receiver	to open	the file for writing
X	  unconditionally.  The	-a option causes the receiver to
X
X
X
X     Page 1					      (printed 6/6/89)
X
X
X
X
X
X
X     SZ(1)		   MINIX Version 1.3+ (OMEN)		 SZ(1)
X
X
X
X	  convert Unix newlines	to PC-DOS carriage returns and
X	  linefeeds.
X
X
X	  Sb batch sends one or	more files with	YMODEM or ZMODEM
X	  protocol.  The initial ZMODEM	initialization is not sent.
X	  When requested by the	receiver, sb supports YMODEM-g with
X	  "cbreak" tty mode, XON/XOFF flow control, and	interrupt
X	  character set	to CAN (^X).  YMODEM-g (Professional-YAM g
X	  option) increases throughput over error free channels
X	  (direct connection, X.PC, etc.) by not acknowledging each
X	  transmitted sector.
X
X	  On Unix systems, additional information about	the file is
X	  transmitted.	If the receiving program uses this
X	  information, the transmitted file length controls the	exact
X	  number of bytes written to the output	dataset, and the
X	  modify time and file mode are	set accordingly.
X
X
X	  Sx sends a single file with XMODEM or	XMODEM-1k protocol
X	  (sometimes incorrectly called	"ymodem").  The	user must
X	  supply the file name to both sending and receiving programs.
X
X	  Iff sz is invoked with $SHELL	set and	iff that variable
X	  contains the string rsh or rksh (restricted shell), sz
X	  operates in restricted mode.	Restricted mode	restricts
X	  pathnames to the current directory and PUBDIR	(usually
X	  /usr/spool/uucppublic) and/or	subdirectories thereof.
X
X
X	  The fourth form sends	a single COMMAND to a ZMODEM receiver
X	  for execution.  Sz exits with	the COMMAND return value.  If
X	  COMMAND includes spaces or characters	special	to the shell,
X	  it must be quoted.
X
X
X	  The fifth form sends a single	COMMAND	to a ZMODEM receiver
X	  for execution.  Sz exits as soon as the receiver has
X	  correctly received the command, before it is executed.
X
X
X	  The sixth form (sz -TT) attempts to output all 256 code
X	  combinations to the terminal.	 In you	are having difficulty
X	  sending files, this command lets you see which character
X	  codes	are being eaten	by the operating system.
X
X
X	  If sz	is invoked with	stdout and stderr to different
X	  datasets, Verbose is set to 2, causing frame by frame
X	  progress reports to stderr.  This may	be disabled with the q
X	  option.
X
X
X
X     Page 2					      (printed 6/6/89)
X
X
X
X
X
X
X     SZ(1)		   MINIX Version 1.3+ (OMEN)		 SZ(1)
X
X
X
X	  The meanings of the available	options	are:
X
X	  \h|120u+0u(Reg.)(VMS)	Force the next option letter to	upper
X	       case.
X	  +    Instruct	the receiver to	append transmitted data	to an
X	       existing	file (ZMODEM only).
X	  a    Convert NL characters in	the transmitted	file to	CR/LF.
X	       This is done by the sender for XMODEM and YMODEM, by
X	       the receiver for	ZMODEM.
X	  b    (ZMODEM)	Binary override: transfer file without any
X	       translation.
X	  c COMMAND
X	       Send COMMAND to the receiver for	execution, return with
X	       COMMAND's exit status.
X	  d    Change all instances of "." to "/" in the transmitted
X	       pathname.  Thus,	C.omenB0000 (which is unacceptable to
X	       MSDOS or	CP/M) is transmitted as	C/omenB0000.  If the
X	       resultant filename has more than	8 characters in	the
X	       stem, a "." is inserted to allow	a total	of eleven.
X	  e    Escape all control characters; normally XON, XOFF, DLE,
X	       CR-@-CR,	and Ctrl-X are escaped.
X	  f    Send Full pathname.  Normally directory prefixes	are
X	       stripped	from the transmitted filename.
X	  i COMMAND
X	       Send COMMAND to the receiver for	execution, return
X	       Immediately upon	the receiving program's	successful
X	       recption	of the command.
X	  k    (XMODEM/YMODEM) Send files using	1024 byte blocks
X	       rather than the default 128 byte	blocks.	 1024 byte
X	       packets speed file transfers at high bit	rates.
X	       (ZMODEM streams the data	for the	best possible
X	       throughput.)
X	  L N  Use ZMODEM sub-packets of length	N.  A larger N (32 <=
X	       N <= 1024) gives	slightly higher	throughput, a smaller
X	       N speeds	error recovery.	 The default is	128 below 300
X	       baud, 256 above 300 baud, or 1024 above 2400 baud.
X	  l N  Wait for	the receiver to	acknowledge correct data every
X	       N (32 <=	N <= 1024) characters.	This may be used to
X	       avoid network overrun when XOFF flow control is
X	       lacking.
X	  n    (ZMODEM)	Send each file if destination file does	not
X	       exist.  Overwrite destination file if source file is
X	       newer than the destination file.
X	  N    (ZMODEM)	Send each file if destination file does	not
X	       exist.  Overwrite destination file if source file is
X	       newer or	longer than the	destination file.
X	  o    (ZMODEM)	Disable	automatic selection of 32 bit CRC.
X	  p    (ZMODEM)	Protect	existing destination files by skipping
X	       transfer	if the destination file	exists.
X	  q    Quiet suppresses	verbosity.
X	  r    (ZMODEM)	Resume interrupted file	transfer.  If the
X	       source file is longer than the destination file,	the
X
X
X
X     Page 3					      (printed 6/6/89)
X
X
X
X
X
X
X     SZ(1)		   MINIX Version 1.3+ (OMEN)		 SZ(1)
X
X
X
X	       transfer	commences at the offset	in the source file
X	       that equals the length of the destination file.
X	  t tim
X	       Change timeout to tim tenths of seconds.
X	  u    Unlink the file after successful	transmission.
X	  w N  Limit the transmit window size to N bytes (ZMODEM).
X	  v    Verbose causes a	list of	file names to be appended to
X	       /tmp/szlog .  More v's generate more output.
X	  y    Instruct	a ZMODEM receiving program to overwrite	any
X	       existing	file with the same name.
X	  Y    Instruct	a ZMODEM receiving program to overwrite	any
X	       existing	file with the same name, and to	skip any
X	       source files that do have a file	with the same pathname
X	       on the destination system.
X
X     EXAMPLES
X	  ZMODEM File Transfer (Unix to	DSZ/ZCOMM/Professional-YAM)
X	  % sz -a *.c
X	  This single command transfers	all .c files in	the current
X	  Unix directory with conversion (-a) to end of	line
X	  conventions appropriate to the receiving environment.	 With
X	  ZMODEM AutoDownload enabled, Professional-YAM	 and ZCOMM
X	  will automatically recieve the files after performing	a
X	  security check.
X
X	  % sz -Yan *.c	*.h
X	  Send only the	.c and .h files	that exist on both systems,
X	  and are newer	on the sending system than the corresponding
X	  version on the receiving system, converting Unix to DOS text
X	  format.
X	  $ sz -\Yan file1.c file2.c file3.c foo.h baz.h (Reg.)(for
X	  VMS)
X
X	  ZMODEM Command Download (Unix	to Professional-YAM)
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	  This Makefile	fragment uses sz to issue commands to
X	  Professional-YAM to change current disk and directory.
X	  Next,	sz transfers the .me files from	the $YD	directory,
X	  commanding the receiver to overwrite the old files and to
X	  convert from Unix end	of line	conventions to PC-DOS
X	  conventions.	The third line transfers some .exe files.  The
X	  fourth and fifth lines command Pro-YAM to change directory
X	  and execute a	PC-DOS batch file insms	. Since	the batch file
X	  takes	considerable time, the -i form is used to allow	sz to
X	  exit immediately.
X
X	  XMODEM File Transfer (Unix to	Crosstalk)
X
X
X
X     Page 4					      (printed 6/6/89)
X
X
X
X
X
X
X     SZ(1)		   MINIX Version 1.3+ (OMEN)		 SZ(1)
X
X
X
X	  % sx -a foo.c
X	  ESC
X	  rx foo.c
X	  The above three commands transfer a single file from Unix to
X	  a PC and Crosstalk with sz translating Unix newlines to DOS
X	  CR/LF.  This combination is much slower and far less
X	  reliable than	ZMODEM.
X
X     ERROR MESSAGES
X	  "Caught signal 99" indicates the program was not properly
X	  compiled, refer to "bibi(99)"	in rbsb.c for details.
X
X     SEE ALSO
X	  rz(omen), ZMODEM.DOC,	YMODEM.DOC, Professional-YAM,
X	  crc(omen), sq(omen), todos(omen), tocpm(omen), tomac(omen),
X	  yam(omen)
X
X	  Compile time options required	for various operating systems
X	  are described	in the source file.
X
X     VMS VERSION
X	  The VMS version does not support wild	cards.	Because	of VMS
X	  DCL, upper case option letters muse be represented by	\
X	  proceding the	letter.
X
X	  The current VMS version does not support XMODEM, XMODEM-1k,
X	  or YMODEM.
X
X	  VMS C	Standard I/O and RMS may interact to modify the	file
X	  contents.
X
X     FILES
X	  32 bit CRC code courtesy Gary	S. Brown.
X
X	  sz.c,	crctab.c, rbsb.c, zm.c,	zmodem.h Unix source files
X
X	  sz.c,	crctab.c, vrzsz.c, zm.c, zmodem.h, vmodem.h,
X	  vvmodem.c, VMS source	files.
X
X	  /tmp/szlog stores debugging output (sz -vv) (szlog on	VMS).
X
X     TESTING FEATURE
X	  The command "sz -T file" exercises the Attn sequence error
X	  recovery by commanding errors	with unterminated packets.
X	  The receiving	program	should complain	five times about
X	  binary data packets being too	long.  Each time sz is
X	  interrupted, it should send a	ZDATA header followed by
X	  another defective packet.  If	the receiver does not detect
X	  five long data packets, the Attn sequence is not
X	  interrupting the sender, and the Myattn string in sz.c must
X	  be modified.
X
X
X
X
X     Page 5					      (printed 6/6/89)
X
X
X
X
X
X
X     SZ(1)		   MINIX Version 1.3+ (OMEN)		 SZ(1)
X
X
X
X	  After	5 packets, sz stops the	"transfer" and prints the
X	  total	number of characters "sent" (Tcount).  The difference
X	  between Tcount and 5120 represents the number	of characters
X	  stored in various buffers when the Attn sequence is
X	  generated.
X
X     BUGS
X	  Calling sz from most versions	of cu(1) doesn't work because
X	  cu's receive process fights sz for characters	from the
X	  modem.
X
X	  Programs that	do not properly	implement the specified	file
X	  transfer protocol may	cause sz to "hang" the port for	a
X	  minute or two.  Every	reported instance of this problem has
X	  been corrected by using ZCOMM, Pro-YAM, or other program
X	  with a correct implementation	of the specified protocol.
X
X	  Many programs	claiming to support YMODEM only	support	XMODEM
X	  with 1k blocks, and they often don't get that	quite right.
X
X	  XMODEM transfers add up to 127 garbage bytes per file.
X	  XMODEM-1k and	YMODEM-1k transfers use	128 byte blocks	to
X	  avoid	extra padding.
X
X	  YMODEM programs use the file length transmitted at the
X	  beginning of the transfer to prune the file to the correct
X	  length; this may cause problems with source files that grow
X	  during the course of the transfer.  This problem does	not
X	  pertain to ZMODEM transfers, which preserve the exact	file
X	  length unconditionally.
X
X	  Most ZMODEM options are merely passed	to the receiving
X	  program; some	do not implement all these options.
X
X	  Circular buffering and a ZMODEM sliding window should	be
X	  used when input is from pipes	instead	of acknowledging
X	  frames each 1024 bytes.  If no files can be opened, sz sends
X	  a ZMODEM command to echo a suitable complaint; perhaps it
X	  should check for the presence	of at least one	accessible
X	  file before getting hot and bothered.	 The test mode leaves
X	  a zero length	file on	the receiving system.
X
X	  A few	high speed modems have a firmware bug that drops
X	  characters when the direction	of high	speed transmissson is
X	  reversed.  The environment variable ZNULLS may be used to
X	  specify the number of	nulls to send before a ZDATA frame.
X	  Values of 101	for a 4.77 mHz PC and 124 for an AT are
X	  typical.
X
X
X
X
X
X
X
X     Page 6					      (printed 6/6/89)
X
X
X
END_OF_FILE
if test 13392 -ne `wc -c <'sz.man'`; then
    echo shar: \"'sz.man'\" unpacked with wrong size!
fi
# end of 'sz.man'
fi
if test -f 'zm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'zm.c'\"
else
echo shar: Extracting \"'zm.c'\" \(14903 characters\)
sed "s/^X//" >'zm.c' <<'END_OF_FILE'
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 */
END_OF_FILE
if test 14903 -ne `wc -c <'zm.c'`; then
    echo shar: \"'zm.c'\" unpacked with wrong size!
fi
# end of 'zm.c'
fi
echo shar: End of archive 3 \(of 5\).
>ark3isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 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
-- 
Bob Best
uucp: {spsd, zardoz, felix}!dhw68k!bob	InterNet: bob@dhw68k.cts.com

bob@dhw68k.cts.com (Bob Best) (06/08/89)

#! /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 5)."
# Contents:  rz.c
# Wrapped by bob@dallnix on Wed Jun  7 19:30:01 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'rz.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rz.c'\"
else
echo shar: Extracting \"'rz.c'\" \(30798 characters\)
sed "s/^X//" >'rz.c' <<'END_OF_FILE'
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");
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	char str[128];
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/* RSB - no mkdir(2) in minix */
X		strcpy(str,"/bin/mkdir ");
X		strcat(str,pathname);
X		if ( !system(str)) {
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 */
END_OF_FILE
if test 30798 -ne `wc -c <'rz.c'`; then
    echo shar: \"'rz.c'\" unpacked with wrong size!
fi
# end of 'rz.c'
fi
echo shar: End of archive 4 \(of 5\).
>ark4isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 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
-- 
Bob Best
uucp: {spsd, zardoz, felix}!dhw68k!bob	InterNet: bob@dhw68k.cts.com

bob@dhw68k.cts.com (Bob Best) (06/08/89)

#! /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 5 (of 5)."
# Contents:  sz.c
# Wrapped by bob@dallnix on Wed Jun  7 19:30:02 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'\" \(33991 characters\)
sed "s/^X//" >'sz.c' <<'END_OF_FILE'
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);
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/* RSB - no clearerr() in minix */
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 */
END_OF_FILE
if test 33991 -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 5 \(of 5\).
>ark5isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 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
-- 
Bob Best
uucp: {spsd, zardoz, felix}!dhw68k!bob	InterNet: bob@dhw68k.cts.com

jdeitch@pnet01.cts.com (Jim Deitch) (06/11/89)

Bob,
 I just have to say THANK YOU for this wonderful program.  It works like a
champ and compiled ok without having to change anything.

 I say a round of applause is due Bob on this answer to a lot of people's
problems.

 Again, thank you Bob.

 Jim

UUCP: {nosc ucsd hplabs!hp-sdd}!crash!pnet01!jdeitch
ARPA: crash!pnet01!jdeitch@nosc.mil
INET: jdeitch@pnet01.cts.com

rwa@aurora (Ross Alexander) (06/12/89)

I'd like to add my thanks to those of Jim Deitch re Bob Best's zterm stuff.
I really look forward to using it.  Could someone mail me a copy of the
serial port driver for the Atari ST port of Minix - I definitely saw one
go by a month or so ago, but lost my copy somehow in one of my periodic
housecleaning fits. PUH-LEASE !?

On another topic, has anyone gotten kpatch to build ?  strings.h, aout.h,
and some other random /usr/include/?.h file are #included but not present
in the base Atari distribution.  I have ordered the ST ACK-based C compiler,
as, ld, ar & c. suite and expect to pick up some of this stuff that way,
but it was a little disappointing to find that the kpatch.shar wouldn't
stand on its own...  anyone out there got the right .h's?  Posting would
be a good thing in this case, I'm sure there are _tons_ of ST people who need
that stuff for kpatch :-)
--
Ross Alexander
alberta!aurora!rwa
alberta!auvax!aungbad!rwa
rwa@aungbad.AthabascaU.CA