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

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

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

[This is the UNIX end to the zmdm file transfer program in comp.binaries.
 It provides for batch transfers, among other things.  You'll probably
 only want this if you plan to use zmdm. -sg]

#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
#	Run the following text with /bin/sh to create:
#	  Makefile
#	  README
#	  expandar.c
#	  gz
#	  minirb.1
#	  minirb.c
#	  rbsb.c
#	  rz.1
#	  rz.c
#	  sz.1
#	  sz.c
#	  zm.c
#	  zmodem.h
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
     next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
     exit 1; fi
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X#
X# Please note:
X#	Define the symbol `CASE' only if you want the CWRU
X#	enhancements AND you are running on a BSD 4.N system.
X#
X
X#all: rz sz minirb
Xall: rz sz
X
X#CC = gcc
X#CFLAGS=-O -DCRCTABLE -DV7 -DCASE
XCC = cc
XCFLAGS=-O -DCRCTABLE -DV7 -DCASE -v -mc68020
X
X# define BIN appropriately
XBIN=/usr/local/bin
X
Xrz: rz.o
X	$(CC) -o rz rz.o -s -x -n
X#	$(CC) -o rz rz.o
X
Xsz: sz.o expandargs.o
X	$(CC) -o sz sz.o expandargs.o -s -x -n
X#	$(CC) -o sz sz.o expandargs.o
X
X#minirb:
X#	$(CC) $(CFLAGS) -o minirb minirb.c -s -x -n
X
Xrz.o: rz.c rbsb.c zm.c zmodem.h
X
Xsz.o: sz.c rbsb.c zm.c zmodem.h
X
X# define BIN appropriately
X# You may need to change `ln -s' to the appropriate
X# link command if you are not running BSD4.N
X#
X#install: sz rz minirb
Xinstall: sz rz
X	rm -f $(BIN)/rb $(BIN)/sb $(BIN)/rz $(BIN)/sz $(BIN)/minirb
X#	mv rz sz minirb $(BIN)
X	mv rz sz $(BIN)
X	ln -s $(BIN)/rz $(BIN)/rb
X	ln -s $(BIN)/sz $(BIN)/sb
X
Xclean:
X	rm -f *.o report
SHAR_EOF
chmod 0600 Makefile || echo "restore of Makefile fails"
sed 's/^X//' << 'SHAR_EOF' > README &&
XNOTE::
X	Users of zmdm on the Atari ST's please see note at end of file.
X------------------------------------------------------------------------------
XCompile instructions are located in the comments at the beginning of the rz.c
Xans sz.c files.  The main compiler flags are -DV7 for V7 and BSD systems and
X-DSVR2 for sVr2.  Other #ifdefs in the files may be activated to deal with
Xvarious types of kernel brain damage if you have a mutant system.
X
XNaturally, rz ans sz work best with comm programs that seamlessly support ZMODEM
Xcommand and file AutoDownload (PowerCOm, Pro-YAM and ZCOMM).  Ths DOS "DSZ"
Xsub-program allows ZMODEM file transfers with older programs, but it must be
Xcalled manually.  DSZ and the ZMODEM protocol description are on TeleGodzilla
Xand other bulletin boards.  They may be obtained via UUCP from site "omen", for
Xwhich a direct UUCP login and telephone number are provided below.  You may uucp
X~uucp/FILES first to determine the pathnames for the "goodies".
X
XChuck Forsberg WA7KGX Author of Pro-YAM communications Tools for PCDOS and Unix
X...!tektronix!reed!omen!caf  Omen Technology Inc "The High Reliability Software"
X  17505-V Northwest Sauvie Island Road Portland OR 97231  Voice: 503-621-3406
XTeleGodzilla BBS: 621-3746 2400/1200  CIS:70007,2304  Genie:CAF  Source:TCE022
X  omen Any ACU 1200 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp
X  omen!/usr/spool/uucppublic/FILES lists all uucp-able files, updated hourly
X
X--------------------------------------------------------------------------
X
X		Case Western Reserve U 'enhancements':
X	(feed back about these enhancements to bammi@mandrill.cwru.edu)
X
XThis distribution contains some enhancements to the code as distributed
Xby Chuck Forsberg. These enhancements will only work if the proprocessor
Xsymbol 'CASE' if defined. PLEASE NOTE THAT THESE ENHANCEMENTS HAVE ONLY
XBEEN TESTED ON Unix (Vax/Sun) BSD4.X SYSTEMS. They should work on
Xother flavors of BSD, but WILL NOT WORK ON ANY OTHER FLAVORS OF UNIX
X(ie. when you compile make sure that the preprocessor symbol `CASE' is
XNOT defined, if you are not using BSD Unix).
X
XThe 'enhancements':
X
X1) When sending files with SZ, if one of the arguments is the name
Xof a directory, then all the files in that directory, and all the
Xsub-directories thereof will be sent. If you want the complete
Xpath names to be sent also, use the -f option of SZ. Also, to give
Xbetter control the  -P name switch was added. -P name prunes the
Xsubdirectory named, so that it is not included. The arguement to
X-P can be the name of a sub-directory, of the name of a file. If it
Xis the name of a sub-directory, then that branch of the file hierarcy
Xis 'pruned' and is not sent. If it the name of a file, then that
Xparticular file is not sent. For example, if you were backing up the
Xfile system of your unix system (hypothetical of course :-) to your ST,
Xand did'nt want to backup /tmp amd /etc, then you would issue the
Xfollowing command to your unix system:
X
X	sz -f -P /tmp -P /etc /
X
X	(and come back the next day!!)
X	
X2) When receiving files with RZ, if the sender is sending full
Xpath names (-f option to SZ), then all directories that do not exist,
Xwill be automatically created by RZ.
X
X3) sz now allows you to send long blocks at low baud rates (<= 2400 baud).
X	try sz -l 1024 files ...
XEarlier it insisted on 256 byte blocks max at 2400 baud or less.
X
X	Any comments and/or suggestions about these enhancements should
Xbe directed to
Xusenet:      {decvax,sun}!cwruecmp!bammi	jwahar r. bammi
Xarpa/csnet:  bammi@mandrill.cwru.edu
XcompuServe:  71515,155
SHAR_EOF
chmod 0600 README || echo "restore of README fails"
sed 's/^X//' << 'SHAR_EOF' > expandar.c &&
X#ifdef CASE
X
X	/* CWRU specific extention(hack :-)
X	 * 	Examine each argument given to main,
X	 * 	If it is a directory, then expand it
X	 *	to all its component files, recursively
X	 *	till you bottom out.
X	 *	If it is not a directory, then just pass it on.
X	 *
X	 *	Inputs: argc, argv
X	 *	Outputs: nargc, nargv (calls MAIN(nargc, nargv))
X	 *	To test: compile with -DCASE -DTEST
X	 *		 run with a directory as an arg
X	 *	Hacker: JRB
X	 *	Requirements: BSD 4.2/3	specific routines used
X	 *		      only tested on Vax BSD 4.3
X	 *
X	 *	Added -P name prune option at the suggestion of dietz@zhmti
X	 *	Multiple -P's may be given on the command line.
X	 *	-P name may be given anywhere on the command line. -P name
X	 *	will prune the subdirectories named as arguement to -P.
X	 *	ie: when the program is decending the file hierarchy it
X	 *	will not visit the pruned branches.
X	 * 	NOTE that the option is -P and not -p
X	 *	      (-p is a valid sz option).
X	 *	NOTE that the arguement given to -P can be the name
X	 * 	of a file or a directory. In case it is a file,
X	 *	that file is skipped.
X	 *
X	 */
X
X/*
X * Expand argc, so that the called MAIN(nargc,nargv) receives only
X * filenames, in nargv[][]
X *
X *	WARNING: Contains BSD specific code, tested on BSD4.3 ONLY.
X *
X *	Jwahar Bammi
X *	usenet: {decvax,cbatt,cbosgd,sun}!cwruecmp!bammi
X *	csnet:       bammi@case
X *	arpa:        bammi%case@csnet-relay
X *	compuServe:  71515,155
X *
X */
X#include <stdio.h>
X
X#define OK	 0
X#define FALSE	 0
X#define Realloc	 realloc
X
Xtypedef struct _prunelist {
X	char *name;			/* name of subdirectory to prune */
X	struct _prunelist *next;	/* ptr to next */
X} PRUNELIST;
X
Xstatic char *ProgName;
Xstatic PRUNELIST *PruneList = (PRUNELIST *)NULL; /* Head of PruneList */
X
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	register int status;
X	int nargc = 0;
X	char **nargv = (char **)NULL;
X	extern int MAIN();
X	extern char **CopyToNargv();
X	extern PRUNELIST *AddPrune();
X
X	ProgName = *argv;
X	
X	/* copy argv[0] blindly */
X	if((nargv = CopyToNargv(*argv, nargc, nargv)) == (char **)NULL)
X	    return(~OK);
X
X	nargc++;
X	
X	while((--argc) > 0)
X	{
X		argv++;
X		if(**argv == '-')
X		{
X			/* copy any options except -P */
X			if( (*argv)[1] == 'P')
X			{
X				if((--argc) <= 0)
X				{
X					fprintf(stderr,"no argument given to -P\n");
X					return(~OK);
X				}
X				if((PruneList = AddPrune(PruneList,*++argv))
X				   == (PRUNELIST *)NULL)
X				    return(~OK);
X			}
X			else
X			{
X				if((nargv = CopyToNargv(*argv, nargc, nargv))
X				   == (char **)NULL)
X				    return(~OK);
X				else
X				    nargc++;
X			}
X			
X		}
X		else
X		{
X			/* If its not on the PruneList then */
X			if(!OnPruneList(PruneList, *argv))
X			{
X				/* if it is a directory, push it */
X				if(isdir(*argv))
X				{
X					if((status = PushDir(*argv)) != OK)
X					{
X						return(status);
X					}
X				}
X				else
X				{
X				    /* it is NOT a directory, copy to nargv */
X					if((nargv = CopyToNargv(*argv, nargc, nargv))
X					   == (char **)NULL)
X					    return(~OK);
X					else
X					    nargc++;
X				}
X			}
X		}
X	} /* while */
X
X	/* process pushed directories if any */
X	if((status = ProcessDirs(&nargc, &nargv)) != OK)
X	    return(status);
X	/* else Free the Stack and call MAIN */
X	FreeStack();
X	return (MAIN(nargc, nargv));
X}
X
X#include <sys/types.h>
X#include <sys/stat.h>
X
X/*
X * is name a directory ?
X *
X */
Xint isdir(name)
Xchar *name;
X{
X	struct stat st;
X	
X	if(stat(name, &st) != 0)
X	    return (FALSE);	/* assume its not a directory */
X
X	/* NOTE: the expression below eliminates Sockets.
X	   (st.st_mode & S_IFMT)& S_IFDIR does not!
X	 */
X	return( ( (st.st_mode & S_IFMT) == S_IFDIR) );
X}
X
X/*
X * Expand nargv by an element and copy a String into the new element
X *
X */
Xchar **CopyToNargv(string, nargc, nargv)
Xchar *string;
Xint nargc;
Xchar **nargv;
X{
X	extern char *malloc(), *Realloc(), *strcpy();
X	extern int strlen();
X	
X	/* expand nargv by 1 element */
X	if(nargv == (char **)NULL)
X	    /* do it with malloc for the first one */
X	    nargv = (char **)malloc(sizeof(char **));
X	else
X	    /* do it with Realloc for others */
X	    nargv = (char **)Realloc(nargv, (nargc+1)*sizeof(char **));
X	
X	if(nargv == (char **)NULL)
X	{
X		/* failed to get memory */
X		perror(ProgName);
X		return ((char **)NULL);
X	}
X
X	/* Get mem for string */
X	if(( nargv[nargc] = malloc(strlen(string)+1)) == (char *)NULL)
X	{
X		/* failed to get memory */
X		perror(ProgName);
X		return ((char **)NULL);
X	}
X
X	/* copy string into nargv[nargc] */
X	(void)strcpy( nargv[nargc], string);
X	return(nargv);
X}
X
Xstatic char **Stack = (char **)NULL;	/* directory stack */
Xstatic char StackSize = 0;		/* Size of current Stack */
Xstatic int    Top   = -1;
X#define STACK_EMPTY	(Top < 0)
X#define CHUNKSIZE	16
X
X/*
X * Grow the Stack by one chunk of CHUNKSIZE elements
X *
X */
Xchar **ExpandStack(Stack)
Xchar **Stack;
X{
X	extern char *malloc(), *Realloc();
X	
X	/* Grow Stack */
X	if(Stack == (char **)NULL)
X	    /* with malloc */
X	    Stack = (char **)malloc(CHUNKSIZE * sizeof(char **));
X	else
X	    /* with Realloc */
X	    Stack = (char **)Realloc(Stack, (StackSize+CHUNKSIZE) *
X				             sizeof(char **));
X
X	if(Stack == (char **)NULL)
X	{
X		/* outa mem */
X		perror(ProgName);
X		return((char **)NULL);
X	}
X	StackSize += CHUNKSIZE;
X	return(Stack);
X}
X
X/*
X * Free the Stack
X *
X */
XFreeStack()
X{
X	if(StackSize > 0)
X		(void)free(Stack);
X}
X
X
X/*
X * Push a directory name on Stack
X *
X */
Xint PushDir(name)
Xchar *name;
X{
X	register int status;
X	extern char *malloc(), *strcpy();
X	extern int strlen();
X	extern char **ExpandStack();
X
X	++Top;
X	if(Top >= StackSize)
X	{
X		if((Stack = ExpandStack(Stack)) == (char **)NULL)
X		    return(~OK);
X	}
X	
X	if((Stack[Top] = malloc(strlen(name)+1)) == (char *)NULL)
X	{
X		/* outa mem */
X		perror(ProgName);
X		return(~OK);
X	}
X	(void)strcpy(Stack[Top], name);
X	return(OK);
X}
X
X/*
X * Pop a directory name from the stack
X *
X */
Xchar *PopDir()
X{
X	register char *r;
X	extern char **ShrinkStack();
X	
X	if(STACK_EMPTY)
X	    return ((char *)NULL);
X	
X	r = Stack[Top];
X	Top--;
X	return(r);
X}
X
Xstatic int BadStatus = FALSE;
X#define BADSTATUS (BadStatus != FALSE)
X
X#include <sys/dir.h>
X/*
X * Process directories on the Stack, by adding all the
X * files in a directory to nargv.
X */
Xint ProcessDirs(nargc, nargv)
Xint *nargc;
Xchar ***nargv;
X{
X	register char *name;
X	register DIR *dirp;
X	register struct direct *dp;
X	register int status;
X	char path[MAXNAMLEN+1];
X	extern DIR *opendir();
X	extern struct direct *readdir();
X	extern char **CopyToNargv();
X	extern char *PopDir();
X	
X	if(BADSTATUS)
X	    return(~OK);
X
X	if(STACK_EMPTY)
X	    /* Nothing more to do */
X	    return(OK);
X
X	/* Pop a directory from Stack and process */
X	if((name = PopDir()) == (char *)NULL)
X	{
X		/* Oh Oh */
X		fprintf(stderr,"Internal Error (BUG), PopDir returns NULL\n");
X		BadStatus = (~FALSE);
X		return(~OK);
X	}
X	
X	/* Open the directory */
X	if((dirp = opendir(name)) == (DIR *)NULL)
X	{
X		/* trouble opening directory */
X		perror(name);
X		/* set BADSTATUS and return */
X		BadStatus = (~FALSE);
X		return(~OK);
X	}
X	
X	/* for each entry in the directory, if it is a file
X	   add to nargv. If it is a directory, Push it onto
X	   the directory stack.
X	 */
X	for (dp = readdir(dirp); dp != (struct direct *)NULL;
X	     dp = readdir(dirp))
X	{
X		if( (!((strcmp(dp->d_name,".") == 0) ||
X		      (strcmp(dp->d_name,"..") == 0))) &&
X		   (dp->d_ino != 0 ))  /* not a free entry */
X		{
X			strcpy(path, name);
X			strcat(path,"/");
X			strcat(path,dp->d_name);
X
X			/* If this path is on the PruneList skip */
X			if(OnPruneList(PruneList, path))
X			    continue;
X
X			if(!isdir(path))
X			{
X				/* not a dir -- add this to nargv */
X				if((*nargv = CopyToNargv(path, *nargc, *nargv))
X				   == (char **)NULL)
X				{
X					closedir(dirp);
X					BadStatus = (~FALSE);
X					return(~OK);
X				}
X				else
X				{
X					*nargc += 1;
X				}
X				
X			}
X			else
X			{
X				/* Note: At this point we could have
X				   simply recursed on ProcessDirs()
X				   totally eliminating the directory Stack.
X				   This was not done as it is possible
X				   to run out of dirp's on deep
X				   file hierarchies. Yet another (ir)rational
X				   design decision.
X				 */
X
X				/* Push This directory */
X				if((status = PushDir(path)) != OK)
X				{
X					closedir(dirp);
X					BadStatus = (~FALSE);
X					return(status);
X				}
X			}
X		}
X	} /* for */
X	closedir(dirp);
X	free(name);	/* done with this directory */
X	
X	/* go do the rest */
X	return (ProcessDirs(nargc, nargv));
X}
X
X/*
X * Add a name to PruneList
X *
X */
XPRUNELIST *AddPrune(list, name)
XPRUNELIST *list;
Xchar *name;
X{
X	extern char *malloc();
X	register PRUNELIST *new;
X	
X	if((new = (PRUNELIST *)malloc(sizeof(PRUNELIST))) == (PRUNELIST *)NULL)
X	{
X		/* outa mem */
X		perror(ProgName);
X		return(new);
X	}
X
X	new->name = name;
X	new->next = list;
X	
X	return(new);
X}
X
X/*
X * Search for name on PruneList
X *
X */
Xint OnPruneList(list, name)
Xregister PRUNELIST *list;
Xregister char *name;		
X{
X	for(; list != (PRUNELIST *)NULL; list = list->next)
X	{
X		if(strcmp(list->name, name) == 0)
X		    return(~FALSE);
X	}
X	
X	return(FALSE);
X}
X
X	
X
X#ifdef TEST
X/* to test: cc -o name name.c -DTEST -DCASE; name ~ */
Xint MAIN(argc, argv)
Xint argc;
Xchar **argv;
X{
X	register int i;
X	
X	for(i = 0; i < argc; i++)
X	    printf("%d:\t%s\n", i, argv[i]);
X
X
X	return(0);
X}
X#endif /* TEST */
X
X#endif /* CASE */
SHAR_EOF
chmod 0600 expandar.c || echo "restore of expandar.c fails"
sed 's/^X//' << 'SHAR_EOF' > gz &&
Xsz -c "sz $*"
SHAR_EOF
chmod 0600 gz || echo "restore of gz fails"
sed 's/^X//' << 'SHAR_EOF' > minirb.1 &&
X'\" Revision Level 
X'\" Last Delta     11-15-86
X.TH MINIRB 1 OMEN
X.SH NAME
Xminirb \- Bootstrap YMODEM Batch file receive
X.SH SYNOPSIS
X.B minirb
X.SH DESCRIPTION
X.I Minirb
Xreceives one or more files with YMODEM batch file transfer protocol.
X.I Minirb
Xwas developed for use as a bootstrap to simplify uploading of the longer
X.I rz
Xand
X.I sz
Xprograms contained in the
X.I rzsz1et2.sh
Xshell archive.
X.SH SEE ALSO
XYMODEM.DOC,
XProfessional-YAM manual,
Xsz(omen),
Xusq(omen),
Xundos(omen)
X.SH NOTES
XThe source file
X.I minirb.c
Xhas been ruthlessly pruned to simplify uploading without benefit of
Xany file transfer protocol.
XDo not reformat or add tabs to the source file
Xas this would complicate uploading.
X
XPlease read the uploading suggestions in the chapter
X.I "File Transfer Basics"
Xin the Professional-YAM or ZCOMM user's manual.
X
X.I Minirb
Xuses 8 bit checksum which may not be compatible with some programs
Xclaiming to support YMODEM batch transfers.
X
X.I Minirb
Xuses the
XYMODEM header
Xfile length information
Xto prevent extraneous characters.
X.I Minirb
Xdoes not delete carriage returns from uploaded files.
XIt does not delete ^Z or other padding added by some CP/M or PC-DOS
Xprograms, including the Xenix "doscp" command.
X
X.I Minirb
Xcalls stty(1) to set and reset raw tty mode.
SHAR_EOF
chmod 0600 minirb.1 || echo "restore of minirb.1 fails"
sed 's/^X//' << 'SHAR_EOF' > minirb.c &&
X/*
X * minirb.c By Chuck Forsberg Omen Technology INC
X *        "The High Reliability Communications Software"
X *
X * A bootstrap program for Unix to receive files from computers running
X *  YMODEM Batch (Professional-YAM, PowerCom, ZCOMM, etc.).
X *
X *  Minirb uses system(3) to call stty, avoiding system dependent code.
X *  Please refer to rz.c for comments, etc.
X */
Xchar * Version = "minirb 1.00 11-15-86";
X
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X
X#define OK 0
X#define FALSE 0
X#define TRUE 1
X#define ERROR (-1)
X#define CAN ('X'&037)
X#define SOH 1
X#define STX 2
X#define EOT 4
X#define ACK 6
X#define NAK 025
X#define TIMEOUT (-2)
X#define RETRYMAX 9
X#define WCEOT (-10)
X
XFILE *fout;
Xlong Bytesleft;
Xint Blklen;
Xchar secbuf[1024];
Xchar linbuf[1024];
Xint Lleft=0;
Xjmp_buf tohere;
X
Xalrm() { longjmp(tohere, -1); }
X
Xbibi(n) {
X canit(); mode(0);
X fprintf(stderr, "minirb: caught signal %d; exiting", n);
X exit(128+n);
X}
X
Xmode(n) {
X if (n) system("stty raw -echo");
X else system("stty echo -raw");
X}
X
Xmain() {
X mode(1);
X if (signal(SIGINT, bibi) == SIG_IGN) {
X  signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
X } else {
X  signal(SIGINT, bibi); signal(SIGKILL, bibi);
X }
X#ifndef CASE
X printf("minirb: Now send file(s) with \042sb file ...\042 command\r\n");
X#endif
X
X if (wcreceive()==ERROR)
X  canit();
X mode(0); exit(0);
X}
X
Xwcreceive() {
X for (;;) {
X  if (wcrxpn(secbuf) == ERROR) break;
X  if (secbuf[0]==0) return OK;
X  if (procheader(secbuf)==ERROR || wcrx()==ERROR) break;
X }
X canit(); return ERROR;
X}
X
X
Xwcrxpn(rpn) char *rpn; {
X register c;
X
X purgeline();
Xet_tu:
X sendline(NAK); Lleft=0;
X while ((c = wcgetsec(rpn, 100)) != 0) {
X  if (c == WCEOT) { sendline(ACK); Lleft=0; readline(1); goto et_tu; }
X  return ERROR;
X }
X sendline(ACK); return OK;
X}
X
Xwcrx() {
X register int sectnum, sectcurr, sendchar, cblklen;
X
X sectnum=0; sendchar=NAK;
X for (;;) {
X  sendline(sendchar); Lleft=0;
X  sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
X  if (sectcurr==(sectnum+1)) {
X   sectnum++; cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
X   if (putsec(secbuf, cblklen)==ERROR) return ERROR;
X   if ((Bytesleft-=cblklen) < 0) Bytesleft = 0;
X   sendchar=ACK;
X  }
X  else if (sectcurr==sectnum) sendchar=ACK;
X  else if (sectcurr==WCEOT) {
X   if (fclose(fout)==ERROR) return ERROR;
X   sendline(ACK); Lleft=0; return OK;
X  }
X  else if (sectcurr==ERROR) return ERROR;
X  else return ERROR;
X }
X}
X
Xwcgetsec(rxbuf, maxtime) char *rxbuf; int maxtime; {
X register checksum, wcj, firstch; register char *p; int sectcurr, errors;
X for (errors=0; errors<RETRYMAX; errors++) {
X  if ((firstch=readline(maxtime))==STX) { Blklen=1024; goto get2; }
X  if (firstch==SOH) {
X   Blklen=128;
Xget2:
X   sectcurr=readline(1); checksum=0;
X   if ((sectcurr+(readline(1)))==0377) {
X    for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
X     if ((firstch=readline(1)) < 0) goto bilge;
X     checksum += (*p++ = firstch);
X    }
X    if ((firstch=readline(1)) < 0) goto bilge;
X    if (((checksum-firstch)&0377)==0) return sectcurr;
X   }
X  }
X  else if (firstch==EOT) return WCEOT;
X  else if (firstch==CAN) return ERROR;
Xbilge:
X  while(readline(1)!=TIMEOUT)
X   ;
X  maxtime=40; sendline(NAK); Lleft=0;
X }
X canit(); return ERROR;
X}
X
Xreadline(timeout) int timeout; {
X register n; static char *cdq;
X
X if (--Lleft >= 0) return (*cdq++ & 0377);
X n = timeout/10;
X if (n < 2) n = 3;
X if (setjmp(tohere)) { Lleft = 0; return TIMEOUT; }
X signal(SIGALRM, alrm); alarm(n);
X Lleft=read(0, cdq=linbuf, 1024); alarm(0);
X if (Lleft < 1) return TIMEOUT;
X --Lleft; return (*cdq++ & 0377);
X}
X
Xpurgeline() { Lleft = 0; lseek(0, 0L, 2); }
X
X
Xprocheader(name) char *name; {
X register char *p;
X
X Bytesleft = 2000000000L; p = name + 1 + strlen(name);
X if (*p) sscanf(p, "%ld", &Bytesleft);
X if ((fout=fopen(name, "w")) == NULL) return ERROR;
X return OK;
X}
X
Xputsec(buf, n) char *buf; register n;
X{
X register char *p;
X for (p=buf; --n>=0; ) putc( *p++, fout);
X return OK;
X}
X
Xsendline(c) { char d; d = c; write(1, &d, 1); }
X
Xchar canistr[] = { 24,24,24,24,24,24,24,24,0 };
X
Xcanit() { printf(canistr); Lleft=0; }
X
X/* END of minirb.c */
X
SHAR_EOF
chmod 0600 minirb.c || echo "restore of minirb.c fails"
sed 's/^X//' << 'SHAR_EOF' > rbsb.c &&
X/*% shar -f /tmp/rzsz README zmodem.h zm.c sz.c rz.c rbsb.c minirb.c *.1 gz ptest.sh; shar -f /tmp/rzsz1et2 -m 1000000 zmodem.h zm.c sz.c rz.c rbsb.c minirb.c *.1 gz ptest.sh
X *
X * -rev 03-10-87
X *  This file contains Unix specific stuff for setting terminal modes,
X *  very little is specific to ZMODEM or YMODEM per se (that stuff 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 *   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#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#endif
X
X#if HOWMANY  > 255
XHowmany must be 255 or less
X#endif
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	9600,	EXTB,
X	0,
X};
X
Xint Twostop;		/* Use two stop bits */
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 0;
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 a cbreak, XON/XOFF control mode if using Pro-YAM's -g option
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:	/* Cbreak mode used by 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		tty.c_lflag = 
X#ifdef XCLUDE
X		  XCLUDE |
X#endif
X		  Zmodem ? 0 : ISIG;
X
X		tty.c_cc[VINTR] = 030;		/* Interrupt char */
X		tty.c_cc[VMIN] = 1;
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#ifdef XCLUDE
X		tty.c_lflag |= XCLUDE;
X#endif
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	case 2:	/*  This doesn't work ... */
X		printf("No mode(2) in V7/BSD!"); bibi(99);
X		if(!did0) {
X			ioctl(iofd, TIOCEXCL, 0);
X			ioctl(iofd, TIOCGETP, &oldtty);
X			ioctl(iofd, TIOCGETC, &oldtch);
X		}
X		tty = oldtty;
X		tch = oldtch;
X		tch.t_intrc = Zmodem ? 03:030;	/* Interrupt char */
X		tty.sg_flags |= (ODDP|EVENP|CBREAK);
X		tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE);
X		ioctl(iofd, TIOCSETP, &tty);
X		ioctl(iofd, TIOCSETC, &tch);
X		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		}
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 original 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#endif
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#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 SVR2
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 = fcntl(f, F_GETFL) ;
X
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
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, 
SHAR_EOF
echo "End of part 1, continue with part 2"
echo "2" > s2_seq_.tmp
exit 0