[comp.sources.atari.st] v01i038: rzsz -- UNIX side for zmdm file transfer program part03/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 38
Archive-name: rzsz/part03

#!/bin/sh
# this is part 3 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file rz.c continued
#
CurArch=3
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
sed 's/^X//' << 'SHAR_EOF' >> rz.c
X *	'/'   './'  or  '../'. If you want to allow rooted paths just
X *	remove the next block. NOTE that the code does not handle
X *	the '../../foo' case, which is unlikely to occur as normally
X *	you would be sending (with -f) from using something like
X *	sz -f foo/* or similar reg. expressions.
X */
X
X	if( (name[0] == '/') || (name[0] == '.')  )
X	{
X		/* skip over the leading stuff */
X		if(name[0] == '/')
X			name = &name[1];
X		else
X		{
X			if((name[1] == '.') && (name[2] == '/'))
X				name = &name[3];  /* Skip the "../" */
X			else
X			    if(name[1] == '/')
X				name = &name[2];  /* Skip the "./"  */
X		}
X	}
X
X     /* CWRU addition, create any dierctories in the path that don't exist */
X	if( pathensure(name) == ERROR)
X		return ERROR;
X#endif
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		if (Filemode & UNIXFILE)
X			++Thisbinary;
X		if (Verbose) {
X			fprintf(stderr,  "Incoming: %s %ld %lo %o\n",
X			  name, Bytesleft, Modtime, Filemode);
X		}
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	if (!Zmodem && MakeLCPathname && !IsAnyLower(name))
X		uncaps(name);
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		if ((fout=popen(Pathname, "w")) == NULL)
X			return ERROR;
X#ifdef CASE
X		setbuffer(fout, myfilebuf, sizeof(myfilebuf));
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		if ((fout=fopen(name, openmode)) == NULL)
X			return ERROR;
X	}
X	return OK;
X}
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 (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/*
X *  Send a character to modem.  Small is beautiful.
X */
Xsendline(c)
X{
X	char d;
X
X	d = c;
X	if (Verbose>4)
X		fprintf(stderr, "Sendline: %x\n", c);
X	write(1, &d, 1);
X}
X
Xxsendline(c)
X{
X	sendline(c);
X}
X
Xflushmo() {}
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*/
Xlog(s,p,u)
Xchar *s, *p, *u;
X{
X	if (!Verbose)
X		return;
X	fprintf(stderr, "error %d: ", errors);
X	fprintf(stderr, s, p, u);
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	printf(canistr);
X	Lleft=0;	/* Do read next time ... */
X	fflush(stdout);
X}
X
X
X/*
X * Return 1 iff stdout and stderr are different devices
X *  indicating this program operating with a modem on a
X *  different line
X */
Xfromcu()
X{
X	struct stat a, b;
X	fstat(1, &a); fstat(2, &b);
X	return (a.st_rdev != b.st_rdev);
X}
X
Xreport(sct)
Xint sct;
X{
X	if (Verbose>1)
X		fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
X}
X
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]=='b')
X		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
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();
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();
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?10:5; --n>=0; ) {
X		/* Set buffer length (0) and capability flags */
X		stohdr(0L);
X#ifdef CANBREAK
X		Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
X#else
X		Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
X#endif
X		zshhdr(tryzhdrtype, Txhdr);
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, KSIZE);
X			mode(3);
X			if (c == GOTCRCW)
X				return ZFILE;
X			zshhdr(ZNAK, Txhdr);
X			goto again;
X		case ZSINIT:
X			if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {
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			cmdzack1flg = Rxhdr[ZF0];
X			if (zrdata(secbuf, KSIZE) == 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<10 && zgethdr(Rxhdr,1) != ZFIN);
X				ackbibi();
X				if (cmdzack1flg & ZCACK1)
X					exec2(secbuf);
X				return ZCOMPL;
X			}
X			zshhdr(ZNAK, Txhdr); goto again;
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 = 10; rxbytes = 0l;
X
X	for (;;) {
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			if ( --n < 0) {
X				vfile("rzfile: zgethdr returned %d", c);
X				return ERROR;
X			}
X		case ZFILE:
X			zrdata(secbuf, KSIZE);
X			continue;
X		case ZEOF:
X			if (rclhdr(Rxhdr) != rxbytes) {
X				continue;
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			if ( --n < 0) {
X				vfile("rzfile: zgethdr returned %d", c);
X				return ERROR;
X			}
X			zmputs(Attn);
X			continue;
X		case ZDATA:
X			if (rclhdr(Rxhdr) != rxbytes) {
X				if ( --n < 0) {
X					return ERROR;
X				}
X				zmputs(Attn);  continue;
X			}
Xmoredata:
X			switch (c = zrdata(secbuf, KSIZE)) {
X			case ZCAN:
X				vfile("rzfile: zgethdr returned %d", c);
X				return ERROR;
X			case ERROR:	/* CRC error */
X				if ( --n < 0) {
X					vfile("rzfile: zgethdr returned %d", c);
X					return ERROR;
X				}
X				zmputs(Attn);
X				continue;
X			case TIMEOUT:
X				if ( --n < 0) {
X					vfile("rzfile: zgethdr returned %d", c);
X					return ERROR;
X				}
X				continue;
X			case GOTCRCW:
X				n = 10;
X				putsec(secbuf, Rxcount);
X				rxbytes += Rxcount;
X				stohdr(rxbytes);
X				zshhdr(ZACK, Txhdr);
X				goto nxthdr;
X			case GOTCRCQ:
X				n = 10;
X				putsec(secbuf, Rxcount);
X				rxbytes += Rxcount;
X				stohdr(rxbytes);
X				zshhdr(ZACK, Txhdr);
X				goto moredata;
X			case GOTCRCG:
X				n = 10;
X				putsec(secbuf, Rxcount);
X				rxbytes += Rxcount;
X				goto moredata;
X			case GOTCRCE:
X				n = 10;
X				putsec(secbuf, Rxcount);
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	if (Topipe) {
X		if (pclose(fout)) {
X			return ERROR;
X		}
X		return OK;
X	}
X	if (fclose(fout)==ERROR) {
X		fprintf(stderr, "file close ERROR\n");
X		return ERROR;
X	}
X	if (Modtime) {
X		timep[0] = time(NULL);
X		timep[1] = Modtime;
X		utime(Pathname, timep);
X	}
X	if (Filemode)
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=4; --n>=0; ) {
X		zshhdr(ZFIN, Txhdr);
X		for (;;) {
X			switch (readline(100)) {
X			case 'O':
X				readline(1);	/* Discard 2nd 'O' */
X				/* ***** FALL THRU TO ***** */
X			case TIMEOUT:
X				vfile("ackbibi complete");
X				return;
X			default:
X				break;
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/*
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
X#ifdef CASE
X/* CWRU enhancement- create all subdirectories as required
X * Author : jrbammi
X * tested on Unix 4.3BSD ONLY.
X */
X
X#ifdef USG
X#define index strchr
X#endif
X
X/* default directory creation mode, note that this is modified by
X   umask */
X#define DIRMODE 0755
X
X/*
X * Ensure that each subdirectory in the pathname exists.
X * If one doesn'nt, make the rest of the directory
X * Returns ERROR if it has trouble creating a path
X *
X */
Xint pathensure(name)
Xchar *name;
X{
X	extern char *index();
X
X	if(index(name, '/') == (char *)NULL)
X		/* nothing to check */
X		return OK;
X
X	return pathrest(name, (char *)NULL);
X}
X
X/*
X * check rest of the path recursively
X *
X */
Xint pathrest(name, prev)
Xchar *name, *prev;
X{
X	char previous[256];
X	char component[33];
X	register char *p, *q, *r;
X	register int i;
X	extern char *index();
X
X	if((r = index(name, '/')) == (char *)NULL)
X		/* nothing more to check */
X		return OK;
X
X	/* pick up the next component of the path name, 32 chars max  */
X	for(p = name, q = component, i = 0; (p != r) && (i < 32); i++)
X		*q++ = *p++;
X	*q = '\0';
X
X	if(i >= 32)
X	{
X		log("A component of the path name is longer than 32 characters\n");
X		return ERROR;
X	}
X
X	if(prev == (char *)NULL)
X		strcpy(previous, component);
X	else
X	{
X		strcpy(previous, prev);
X		strcat(previous, "/");
X		strcat(previous, component);		
X	}
X
X	if(existd(previous))
X		/* it exists - go do rest */
X		return pathrest(++r, previous);
X
X	/* does not exist, 			    */
X	/* make this component and all its children */
X	return makesubtree(++r, previous);
X}
X
X/*
X * make a subtree
X */
Xint makesubtree(name, prev)
Xchar *name, *prev;
X{
X	char previous[256];
X	char component[33];
X	register char *p, *q, *r;
X	register int i;
X	extern char *index();
X
X	if(mkdir(prev,DIRMODE) != 0)
X	{
X		log("Trouble trying to create subtree\n");
X		return ERROR;
X	}
X	if(Verbose > 2)
X	    fprintf(stderr,"Made directory %s\n",prev);
X	
X
X	if((r = index(name, '/')) == (char *)NULL)
X		/* nothing more to do */
X		return OK;
X
X	/* pick up the next component of the path name, 32 chars max */
X	for(p = name, q = component, i = 0; (p != r) && (i < 32); i++)
X		*q++ = *p++;
X
X	*q = '\0';
X
X	if(i >= 32)
X	{
X		log("A component of the path name is longer than 32 characters\n");
X		return ERROR;
X	}
X
X	strcpy(previous, prev);
X	strcat(previous, "/");
X	strcat(previous, component);		
X
X	/* go do the rest of them */
X	return makesubtree(++r, previous);
X}
X
X
X/*
X * test if a subdirectory exists
X */
Xint existd(name)
Xregister char *name;
X{
X	struct stat statbuf;
X	
X	if(stat(name, &statbuf) != 0)
X	    return FALSE;
X	
X	return (statbuf.st_mode & S_IFMT) == S_IFDIR;
X	
X}
X#endif
SHAR_EOF
chmod 0600 rz.c || echo "restore of rz.c fails"
sed 's/^X//' << 'SHAR_EOF' > sz.1 &&
X'\" Revision Level 
X'\" Last Delta     03-10-87
X.TH SZ 1 OMEN
X.SH NAME
Xsz \- XMODEM, YMODEM, ZMODEM Batch file Send
X.SH SYNOPSIS
Xsz
X.RB [\- +1abdefkLlNnopqTtuvy ]
X.I file ...
X.br
Xsz -X
X.RB [\- 1kqtuv ]
X.I file
X.br
Xsz
X.RB [\- 1oqtv ]
X.B "-c COMMAND"
X.br
Xsz
X.RB [\- 1oqtv ]
X.B "-i COMMAND"
X.SH DESCRIPTION
X.B Sz
Xuses the ZMODEM, YMODEM or XMODEM error correcting protocol to send
Xone or more files over a serial port to a variety of programs running under
XPC-DOS, CP/M, Unix, VMS, and other operating systems.
X
X
XThe first form of
X.B sz
Xsends one or more files with ZMODEM or YMODEM batch protocol.
XNormally, only the file name part of the pathname is transmitted.
XOn
X.SM Unix
Xsystems, additional information about the file is transmitted.
XIf the receiving program uses this information,
Xthe transmitted file length controls the exact number of bytes written to
Xthe output dataset,
Xand the modify time and file mode
Xare set accordingly.
X
XOutput from another program may be piped to
X.B sz
Xfor transmission by specifying the
X.B -1
Xoption and denoting standard input by "-":
X.ce
Xps -ef | sz -
XThe program output is transmitted with the filename sPID.sz
Xwhere PID is the process ID of the
X.B sz
Xprogram.
XIf the environment variable
X.B ONAME
Xis set, that is used instead.
XIn this case, the Unix command:
X.ce
XONAME=con ps -ef|sz -ay -
Xwill send a "file" to the PC-DOS console display.
XThe
X.B -y
Xoption instructs the receiver to open the file for writing unconditionally.
XThe
X.B -a
Xoption
Xcauses the receiver to convert Unix newlines to PC-DOS carriage returns
Xand linefeeds.
X
XUnix
X.B sz
Xsupports
X.B YMODEM-g
Xwith "cbreak" tty mode, XON/XOFF flow control,
Xand the interrupt character set to CAN.
X.B YMODEM-g
X(Professional-YAM
X.B g
Xoption)
Xincreases throughput over error free channels
X(direct connection, X.PC, etc.)
Xby not acknowledging each transmitted sector.
X
X
XThe second form of
X.B sz
Xuses the
X.B -X
Xflag to send a single
X.I file
Xwith
X.B XMODEM
Xor
X.B XMODEM-1k
Xprotocol.
XThe user must supply the file name to both sending and receiving programs.
X
XIff
X.B sz
Xis invoked with $SHELL set and iff that variable contains the
Xstring
X.I "rsh"
Xor
X.I "rksh"
X(restricted shell), sz operates in restricted mode.
XRestricted mode restricts pathnames to the current directory and
XPUBDIR (usually /usr/spool/uucppublic) and/or subdirectories
Xthereof.
X
X
XThe third form sends a single COMMAND to the receiver for execution.
X.B Sz
Xexits with the COMMAND return value.
XIf COMMAND includes spaces or characters special to the shell,
Xit must be quoted.
X
X
XThe fourth form sends a single COMMAND to the receiver for execution.
X.B Sz
Xexits as soon as the receiver has correctly received the command,
Xbefore it is executed.
X
X
XIf sz is invoked with stdout and stderr to different datasets,
XVerbose is set to 2, causing frame by frame progress reports
Xto stderr.
XThis may be disabled with the
X.B q
Xoption.
X.PP
XThe meanings of the available options are:
X.PP
X.PD 0
X.TP
X.B +
XInstruct the receiver to append transmitted data to an existing file
X(ZMODEM only).
X.TP
X.B 1
XUse file descriptor 1 for ioctls and reads (Unix only).
XBy default, file descriptor 0 is used.
XThis option allows
X.B sz
Xto be used with the
X.I Professional-YAM
X$
Xcommand.
X.TP
X.B a
XConvert NL characters in the transmitted file to CR/LF.
XThis is done by the sender for XMODEM and YMODEM, by the receiver
Xfor ZMODEM.
X.TP
X.B b
X(ZMODEM) Binary override: transfer file without any translation.
X.TP
X.B "c COMMAND"
XSend COMMAND to the receiver for execution, return with COMMAND\'s exit status.
X.TP
X.B d
XChange all instances of "." to "/" in the transmitted pathname.
XThus, C.omenB0000 (which is unacceptable to MSDOS or CP/M)
Xis transmitted as C/omenB0000.
XIf the resultant filename has more than 8 characters in the stem,
Xa "." is inserted to allow a total of eleven.
X.TP
X.B E
XEscape only Ctrl-X control characters;
Xnormally XON, XOFF, CR-@-CR, and Ctrl-X are escaped.
X.TP
X.B e
XEscape all control characters;
Xnormally XON, XOFF, CR-@-CR, and Ctrl-X are escaped.
X.TP
X.B f
XSend Full pathname.
XNormally directory prefixes are stripped from the transmitted
Xfilename.
X.TP
X.B "i COMMAND"
XSend COMMAND to the receiver for execution, return Immediately
Xupon the receiving program's successful recption of the command.
X.TP
X.B k
X(XMODEM/YMODEM) Send files using 1024 byte blocks
Xrather than the default 128 byte blocks.
X1024 byte packets speed file transfers at high bit rates.
X(ZMODEM streams the data for the best possible throughput.)
X.TP
X.B "L N"
XUse ZMODEM sub-packets of length N.
XA larger N (32 <= N <= 1024) gives slightly higher throughput,
Xa smaller N speeds error recovery.
XThe default is 128 below 300 baud, 256 above 300 baud, or 1024 above 2400 baud.
X.TP
X.B "l N"
XWait for the receiver to acknowledge correct data every
X.B N
X(32 <= N <= 1024)
Xcharacters.
XThis may be used to avoid network overrun when XOFF flow control is lacking.
X.TP
X.B n
X(ZMODEM) Send each file if
Xdestination file does not exist.
XOverwrite destination file if
Xsource file is newer or longer than the destination file.
X.TP
X.B N
X(ZMODEM) Send each file if
Xdestination file does not exist.
XOverwrite destination file if
Xsource file has different length or date.
X.TP
X.B o
X(ZMODEM) Disable automatic selection of 32 bit CRC.
X.TP
X.B p
X(ZMODEM) Protect existing destination files by skipping transfer if the
Xdestination file exists.
X.TP
X.B q
XQuiet suppresses verbosity.
X.TP
X.B r
XResume interrupted file transfer.
XIf the source file is longer than the destination file,
Xthe transfer commences at the offset in the source file that equals
Xthe length of the destination file.
X.TP
X.B "t tim"
XChange timeout to
X.I tim
Xtenths of seconds.
X.TP
X.B u
XUnlink the file after successful transmission.
X.TP
X.B v
XVerbose
Xcauses a list of file
Xnames to be appended to
X/tmp/szlog .
XMore v's generate more output.
X.TP
X.B X
XSend a single file with
X.B XMODEM
Xor
X.B XMODEM-1k
Xprotocol.
X.TP
X.B y
XInstruct a ZMODEM receiving program to overwrite any existing file
Xwith the same name.
X.PD
X.SH EXAMPLES
X.ne 7
X.B "ZMODEM File Transfer"
X.br
X.B "$ sz -a *.c"
X.br
XThis single command transfers all .c files in the current Unix directory
Xwith conversion
X.RB ( -a )
Xto end of line conventions appropriate to the receiving environment.
XWith ZMODEM AutoDownload enabled, Professional-YAM  and ZCOMM
Xwill automatically recieve
Xthe files after performing a security check.
X
X.B "ZMODEM Command Download"
X.br
X cpszall:all
X    sz -c "c:;cd /yam/dist"
X    sz -ya $(YD)/*.me
X    sz -yqb y*.exe
X    sz -c "cd /yam"
X    sz -i "!insms"
X.br
XThis Makefile fragment uses
X.B sz
Xto issue commands to Professional-YAM to change current disk and directory.
XNext,
X.B sz
Xtransfers the
X.I .me
Xfiles from the $YD directory, commanding the receiver to overwrite the old files
Xand to convert from Unix end of line conventions to PC-DOS conventions.
XThe third line transfers some
X.I .exe
Xfiles.
XThe fourth and fifth lines command Pro-YAM to
Xchange directory and execute a PC-DOS batch file
X.I insms .
XSince the batch file takes considerable time, the
X.B "-i"
Xform is used to allow
X.B sz
Xto exit immediately.
X
X.B "XMODEM File Transfer"
X.br
X$
X.B "sz -Xa foo.c"
X.br
X.B "ESC"
X.br
X.B "rx foo.c"
X.br
XThe above three commands transfer a single file
Xfrom Unix to a PC and Crosstalk XVI 3.6,
Xtranslating Unix newlines to DOS CR/LF.
X
X32 bit CRC code courtesy Gary S. Brown.
X.SH SEE ALSO
Xrz(omen),
XZMODEM.DOC,
XYMODEM.DOC,
XProfessional-YAM,
XIMP(CP/M),
Xsq(omen),
Xtodos(omen),
Xtocpm(omen),
Xtomac(omen),
Xyam(omen)
X
XCompile time options required for various operating systems are described in
Xthe source file.
X.SH "VMS VERSION"
XThe VMS version does not transmit the file date.
XThe VMS version calculates the file length by reading the file
Xand counting the bytes.
X
XThe VMS version does not support YMODEM-g or ZMODEM.
X
XWhen VMS is lightly loaded, the response time may be too quick for MODEM7
Xunless the MODEM7
X.B "q"
Xmodifier is used.
X
XThe VMS C standard i/o package and RMS sometimes interact to modify
Xfile contents unexpectedly.
X.SH FILES
Xsz.c, rbsb.c, zm.c, zmodem.h source files
X
X/tmp/szlog stores debugging output (sz -vv)
X.SH "TESTING FEATURE"
XThe command "sz -T file"
Xexercises the
X.B Attn
Xsequence error recovery by commanding
Xerrors with unterminated packets.
XThe receiving program should complain five times about
Xbinary data packets being too long.
XEach time
X.B sz
Xis interrupted,
Xit should send a ZDATA header followed by another defective packet.
XIf the receiver does not detect five long data packets,
Xthe
X.B Attn
Xsequence is not interrupting the sender, and the
X.B Myattn
Xstring in
X.B sz.c
Xmust be modified.
X
XAfter 5 packets,
X.B sz
Xstops the "transfer" and
Xprints the total number of characters "sent" (Tcount).
XThe difference between Tcount and 5120 represents the number of characters
Xstored in various buffers when the Attn sequence is generated.
X.SH BUGS
XXMODEM transfers add up to 127 garbage bytes per file (1023 bytes with
XXMODEM-k).
XMost YMODEM programs use the file length transmitted at the beginning of the
Xtransfer to prune the file to the correct length; this may cause problems with
Xsource files that grow during the course of the transfer.
XThis problem does not pertain to ZMODEM transfers, which preserve the exact
Xfile length unconditionally.
X
XMost ZMODEM options are merely passed to the receiving program;
Xsome do not implement all these options.
X
XCircular buffering and a ZMODEM sliding window should be used
Xwhen input is from pipes instead of acknowledging frames each 1024 bytes.
XIf no files can be opened,
X.B sz
Xsends a ZMODEM command to echo a suitable complaint;
Xperhaps it should check for the presence of at least one accessible file before
Xgetting hot and bothered.
XThe test mode leaves a zero length file on the receiving system.
X
XSome high speed modems have a firmware bug that drops characters when the
Xdirection of high speed transmissson is reversed.
XThe environment variable ZNULLS may be used to specify the number of nulls to
Xsend before a ZDATA frame.
XValues of 101 for a 4.77 mHz PC and 124 for an AT are typical.
X.SH CWRU `ENHANCEMENTS'
XIf you compiled
X.B sz
Xwith the preprocessor symbol `CASE' defined then you will be able to use
Xthe following `features'.
X.sp 1
XIf sz if given the name of a directory as its arguement, then it will
Xsend the contents of the named directory, and of all the subdirectories.
XIf you need to send full path names, you still have to specify the
X.I -f
Xoption to
X.I sz.
X.sp 1
XIf you want to skip a branch of a directory, and do the rest, then you
Xmay use the
X.I -P name
Xoption, to `prune' off that branch of the tree. You may specify multiple
X.I -P name
Xoptions on the command line. They may appear anywhere on the command line,
Xso long as they appear before the name of a branch they prune, if thats
Xat the top level.
X.sp 1
XFor instance, let us suppose that you want to back up your unix system
Xto another system over the serial line, using zmodem. You  want to
Xback up all directories, except /tmp and say /usr/lib. Then you would
Xissue the following command:
X.sp 1
X.ce
Xsz -f -P /tmp -P /usr/lib /
X.sp 1
Xand go away for a loooong time!
X.sp 1
XThe CWRU `enhancements' use Berkeley Unix specific code, and have been
Xtested only under BSD4.3. When making
X.I sz
Xplease make sure that you are using the appropriate flavor of Unix, before
Xdefining the pre processor symbol `CASE'.
SHAR_EOF
chmod 0600 sz.1 || echo "restore of sz.1 fails"
sed 's/^X//' << 'SHAR_EOF' > sz.c &&
X#define VERSION "sz 1.26 03-10-87"
X#define PUBDIR "/usr/spool/uucppublic"
X
X/*% cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz; size sz
X *  (above for SYS III/V Xenix)
X
X * sz.c By Chuck Forsberg
X *
X *	cc -O sz.c -o sz		USG (SYS III/V) Unix
X *	cc -O -DSVR2 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 *
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
X
Xchar *substr(), *getenv();
X
X#define LOGFILE "/tmp/szlog"
X#define zperr vfile
X
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <ctype.h>
X
X#define PATHLEN 256
X#define OK 0
X#define FALSE 0
X#define TRUE 1
X#define ERROR (-1)
X
X#define HOWMANY 2
Xint Zmodem=0;		/* ZMODEM protocol requested */
Xunsigned Baudrate;
Xint Fromcu = 0;		/* Were called from cu or yam */
X#include "rbsb.c"	/* most of the system dependent stuff here */
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;
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 WANTG 0107	/* Send G not NAK to get nonstop batch xmsn */
X#define TIMEOUT (-2)
X#define RCDO (-3)
X#define RETRYMAX 10
X#define SECSIZ 128	/* cp/m's Magic Number record size */
X#define KSIZE 1024
X
Xchar Lastrx;
Xchar Crcflg;
Xint Wcsmask=0377;
Xint Verbose=0;
Xint Modem=0;		/* MODEM - 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=SECSIZ;		/* 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[KSIZE];
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;
Xint Wantfcs32 = TRUE;	/* want to send 32 bit FCS */
SHAR_EOF
echo "End of part 3, continue with part 4"
echo "4" > s2_seq_.tmp
exit 0