[comp.sources.misc] v13i014: tipx

wht@gatech.edu@tridom.UUCP (Warren H. Tucker) (05/30/90)

Posting-number: Volume 13, Issue 14
Submitted-by: wht@gatech.edu@tridom.UUCP (Warren H. Tucker)
Archive-name: tipx/part02

#!/bin/sh
# This is part 02 of tipx
if touch 2>&1 | fgrep 'mmdd' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= xfer/tiprz.c ==============
echo "x - extracting xfer/tiprz.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > xfer/tiprz.c &&
Xchar *numeric_revision = "tiprz 1.00";
X/*+-------------------------------------------------------------------------
X	tiprz.c - X/Y/ZMODEM receive program
X  Derived from public domain source by Chuck Forsberg, Omen Technologies
X  wht%n4hgf@emory.mathcs.emory.edu
X
X  Defined functions:
X	SIGALRM_handler()
X	arg_token(parsestr,termchars)
X	bye_bye(sig)
X	cancel_transaction(sig)
X	close_and_report()
X	flushline()
X	fname_split(cmd,arg,arg_max_quan,narg_rtn)
X	fname_too_long(fname)
X	fname_truncated()
X	getfree()
X	isanylc(str)
X	main(argc,argv,envp)
X	make_dirs(pathname)
X	mkdir(dpath,dmode)
X	procheader(name)
X	purgeline()
X	readline(timeout)
X	rzfile()
X	rzfiles()
X	send_ZFIN_and_exit()
X	send_cancel()
X	sendline(c)
X	substr(str,token)
X	sys2(shellcmd)
X	tryz()
X	uncaps(str)
X	usage(fail_reason)
X	wcgetsec(rxbuf,maxtime)
X	wcreceive(argc,argp)
X	wcrx()
X	wcrxpn(rpn)
X	write_sec_to_disk(buf,n)
X	xsendline(c)
X
X      Usage:    tiprz -Z [-abeuy]    (ZMODEM)
X                tiprz -Y [-abuy]     (YMODEM)
X                tiprz -X [-abc] file (XMODEM or XMODEM-1k)
X
X          -a ASCII transfer (strip CR)
X          -b Binary transfer for all files
X          -c Use 16 bit CRC (XMODEM)
X          -e Escape control characters  (ZMODEM)
X          -p protect local files (ZMODEM)
X          -t <tenths> rx timeout seconds
X          -+ force append
X          -u convert uppercase filenames to lower case
X          -y Yes, clobber existing file if any
X          -. line fd to use
X          -, log protocol packets
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:05-21-1990-16:00-wht@tridom-adapt ecu xfer protocols for tipwht */
X
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <ctype.h>
X#include <errno.h>
X#include <fcntl.h>
X#include "zmodem.h"
X#include "zlint.h"
X
Xchar *strrchr();
X
X#if defined(M_UNIX)
Xchar *fname_truncated();
X#endif
X
Xextern unsigned short crctab[];
Xextern unsigned long total_data_chars_xfered; /* zcurses.c */
Xextern int errno;
Xextern char *sys_errlist[];
Xextern char Attn[];		/* Attention string rx sends to tx on err */
Xextern int Crc32;		/* Display flag indicating 32 bit CRC being received */
Xextern int Rxcount;		/* Count of data bytes received */
Xextern char Rxhdr[];	/* Received header */
Xextern char Txhdr[];	/* Transmitted header */
Xextern int Rxtimeout;	/* Tenths of seconds to wait for something */
Xextern char s256[];
X
X/* Max value for VMIN_COUNT is 255.  A larger value reduces system
Xoverhead but may evoke kernel bugs.  133 corresponds to an XMODEM/CRC
Xsector */
X#if !defined(VMIN_COUNT)
X#define VMIN_COUNT 133
X#endif
Xunsigned char vmin_count = VMIN_COUNT;
Xint Readnum = VMIN_COUNT;	/* num bytes to ask for in read() from modem */
X
X#define DEFBYTL 2000000000L	/* default rx file size */
X#define RETRYMAX 5
X
XFILE *fout;
Xchar Lzmanag;		/* Local file management request */
Xchar Pathname[PATHLEN];
Xchar curr_dir[256];
Xunsigned char linbuf[VMIN_COUNT];
Xchar s128[128];
Xchar secbuf[1025];
Xchar zconv;				/* ZMODEM file conversion request */
Xchar zmanag;			/* ZMODEM file management request */
Xchar ztrans;			/* ZMODEM file transport request */
Xint Batch=0;
Xint Blklen;				/* record length of received packets */
Xint Crcflg;
Xint Eofseen;			/* indicates cpm eof (^Z) has been received */
Xint Filcnt=0;			/* count of number of files opened */
Xint Filemode;			/* Unix style mode for incoming file */
Xint Firstsec;
Xint Lastrx;
Xint Lleft=0;			/* number of characters in linbuf */
Xint MakeLCPathname=1;	/* make received pathname lower case */
Xint Nozmodem = 0;		/* If invoked as "rb" */
Xint Rxascii=0;			/* receive files in ascii (translate) mode */
Xint Rxbinary=0;			/* receive all files in bin mode */
Xint Rxclob=0;			/* Clobber existing file */
Xint Thisbinary;			/* current file is to be received in bin mode */
Xint Twostop = 0;		/* use two stop bits */
Xint Zctlesc;			/* Encode control characters */
Xint Zmodem=0;			/* ZMODEM protocol requested */
Xint Zrwindow = 1400;	/* RX window size (controls garbage count) */
Xint tipsz_flag = 0;
Xint skip_count = 0;		/* skipped files */
Xint errors;
Xint iofd = 0;
Xint log_packets = 0;
Xint npats = 0;
Xint oldBlklen = -1;		/* last block length */
Xint this_file_errors = 0;
Xint tryzhdrtype=ZRINIT;	/* Header type to send corresponding to Last rx close */
Xjmp_buf tohere;			/* For the interrupt on RX timeout */
Xlong Bytesleft;			/* number of bytes of incoming file left */
Xlong Modtime;			/* Unix style mod time for incoming file */
Xlong TotalToReceive = 0L;
Xlong rx_char_count = 0L;
Xlong tx_char_count = 0L;
Xstruct stat fout_stat;
Xtime_t timep[2];
Xunsigned Baudrate;
Xunsigned long this_file_length;
Xint required_type = 0;
Xchar *bottom_label = (char *)0;
X
X/*+-----------------------------------------------------------------------
X	arg_token(parsestr,termchars)
X
XGet next token from string parsestr ((char *)0 on 2nd, 3rd, etc.
Xcalls), where tokens are nonempty strings separated by runs of chars
Xfrom termchars.  Writes nulls into parsestr to end tokens.
Xtermchars need not remain constant from call to call.
X
XTreats multiple occurrences of a termchar as one delimiter (does not
Xallow null fields).
X------------------------------------------------------------------------*/
X#if defined(M_UNIX)
Xstatic char *arg_token_static = (char *)0;
Xchar *arg_token(parsestr,termchars)
Xchar *parsestr;
Xchar *termchars;
X{
Xregister int first = 1;
Xregister char *termptr;
Xregister char *parseptr;
Xchar *token;
X
X	if(parsestr == (char *)0 && arg_token_static == (char *)0)
X		return((char *)0);
X
X	if(parsestr)
X		parseptr = parsestr;
X	else
X       parseptr = arg_token_static;
X
X	while(*parseptr)
X	{
X		if(!strchr(termchars,*parseptr))
X			break;
X		parseptr++;
X	}
X
X	if(!*parseptr)
X	{
X		arg_token_static = (char *)0;
X		return((char *)0);
X	}
X
X	token = parseptr;
X	if(*token == '\'')
X	{
X		token++;
X		parseptr++;
X		while(*parseptr)
X		{
X			if(*parseptr == '\'')
X			{
X				arg_token_static = parseptr + 1;
X				*parseptr = 0;
X				return(token);
X			}
X			parseptr++;
X		}
X		arg_token_static = (char *)0;
X		return(token);
X	}
X	while(*parseptr)
X	{
X		if(strchr(termchars,*parseptr))
X		{
X			*parseptr = 0;
X			arg_token_static = parseptr + 1;
X			while(*arg_token_static)
X			{
X				if(!strchr(termchars,*arg_token_static))
X					break;
X				arg_token_static++;
X			}
X			return(token);
X		}
X		parseptr++;
X	}
X	arg_token_static = (char *)0;
X	return(token);
X}	/* end of arg_token */
X#endif
X
X/*+-------------------------------------------------------------------------
X	fname_split(cmd,arg,arg_max_quan,&narg)
X--------------------------------------------------------------------------*/
X#if defined(M_UNIX)
Xvoid
Xfname_split(cmd,arg,arg_max_quan,narg_rtn)
Xchar *cmd;
Xchar **arg;
Xint arg_max_quan;
Xint *narg_rtn;
X{
Xregister itmp;
Xregister narg;
X
X	for(itmp = 0; itmp < arg_max_quan; itmp++)
X		arg[itmp] = (char *)0;
X	arg[0] = arg_token(cmd,"/");
X
X	for(narg = 1; narg < arg_max_quan; ++narg)
X	{
X		if((arg[narg] = arg_token((char *)0,"/")) == (char *)0) 
X			break;
X	}
X
X	*narg_rtn = narg;
X
X}	/* end of fname_split */
X#endif
X
X#if defined(M_UNIX)
X#define MAX_COMPONENT_LEN	14
X#define MAX_PATH_COMPONENTS	16
Xstatic char trunc_fname[257];
Xstatic char *trunc_components[MAX_PATH_COMPONENTS];
Xstatic int trunc_components_quan;
Xstatic int trunc_absolute_path;
X#endif
X
X/*+-------------------------------------------------------------------------
X	fname_too_long(fname) - check for any pathname component too long
X--------------------------------------------------------------------------*/
X#if defined(M_UNIX)
Xint
Xfname_too_long(fname)
Xregister char *fname;
X{
Xregister int itmp;
Xregister char **cpptr;
X
X	if(trunc_absolute_path = (*fname == '/'))
X		fname++;
X	strncpy(trunc_fname,fname,sizeof(trunc_fname) - 1);
X	fname_split(trunc_fname,trunc_components,
X		MAX_PATH_COMPONENTS,&trunc_components_quan);
X	itmp = trunc_components_quan;
X	cpptr = trunc_components;
X	while(itmp--)
X	{
X		if(strlen(*cpptr) > MAX_COMPONENT_LEN)
X			return(1);
X		cpptr++;
X	}
X	return(0);
X}	/* end of fname_too_long */
X#endif
X
X/*+-------------------------------------------------------------------------
X	fname_truncated() - build truncated path last checked by fname_too_long
X--------------------------------------------------------------------------*/
X#if defined(M_UNIX)
Xchar *
Xfname_truncated()
X{
Xregister int icomp;
Xchar new_fname[257];
Xregister char *cptr = new_fname;
X
X	if(trunc_absolute_path)
X	{
X		*cptr = '/';
X		*(cptr + 1) = 0;
X	}
X	else
X		*cptr = 0;
X	for(icomp = 0; icomp < trunc_components_quan; icomp++)
X	{
X		if(strlen(trunc_components[icomp]) > MAX_COMPONENT_LEN)
X			*(trunc_components[icomp] + MAX_COMPONENT_LEN) = 0;
X		strcat(cptr,trunc_components[icomp]);
X		if(icomp < trunc_components_quan - 1)
X			strcat(cptr,"/");
X	}
X	strcpy(trunc_fname,cptr);
X	return(trunc_fname);
X
X}	/* end of fname_truncated */
X#endif
X
X/*+-------------------------------------------------------------------------
X	substr(str,token)
X
X  searches for token in string str returns pointer to token within
X  string if found,NULL otherwise
X--------------------------------------------------------------------------*/
Xchar *
Xsubstr(str,token)
Xregister char *str,*token;
X{
Xregister char *ss,*tt;
X
X	/* search for first char of token */
X	for(ss=str; *str; str++)
X		if(*str == *token)
X			/* compare token with substring */
X			for(ss=str,tt=token; ;)
X			{
X				if(*tt == 0)
X					return(str);
X				if(*ss++ != *tt++)
X					break;
X			}
X	return(NULL);
X}	/* end of substr */
X
X/*+-------------------------------------------------------------------------
X	getfree()
X
X  Routine to calculate the free bytes on the current file system ~0
X  means many free bytes (unknown)
X--------------------------------------------------------------------------*/
Xlong
Xgetfree()
X{
X	return(~0L);	/* many free bytes ... */
X}	/* end of getfree */
X
X/*+-------------------------------------------------------------------------
X	usage(fail_reason)
X--------------------------------------------------------------------------*/
Xvoid
Xusage(fail_reason)
Xchar *fail_reason;
X{
X	fprintf(stderr,"%s\n",fail_reason);
X	exit(255);
X}	/* end of usage */
X
X/*+-------------------------------------------------------------------------
X	SIGALRM_handler()
X--------------------------------------------------------------------------*/
Xvoid
XSIGALRM_handler()
X{
X	report_tx_ind(0);
X	report_rx_ind(0);
X	longjmp(tohere,-1);
X}	/* end of SIGALRM_handler */
X
X/*+-------------------------------------------------------------------------
X	bye_bye(sig)
X--------------------------------------------------------------------------*/
Xvoid
Xbye_bye(sig)
Xint sig;
X{
X	exit(sig+128);
X}	/* end of bye_bye */
X
X/*+-------------------------------------------------------------------------
X	cancel_transaction(sig)
Xcalled by signal interrupt or terminate to clean things up
X--------------------------------------------------------------------------*/
Xvoid
Xcancel_transaction(sig)
X{
X	if(Zmodem)
X		zmputs(Attn);
X	send_cancel();
X	mode(0);
X	if(sig >= 0)
X	{
X		sprintf(s128,"tiprz aborted (signal %d)",sig);
X		report_str(s128,0);
X	}
X	report_tx_ind(0);
X	report_rx_ind(0);
X	report_uninit(0);
X	bye_bye(sig);
X}	/* end of cancel_transaction */
X
X/*+-------------------------------------------------------------------------
X	sendline(c) -  send a character to DCE
X--------------------------------------------------------------------------*/
Xsendline(c)
Xchar c;
X{
X	write(iofd,&c,1);
X	++tx_char_count;
X}	/* end of sendline */
X
X/*+-------------------------------------------------------------------------
X	xsendline(c)
X--------------------------------------------------------------------------*/
Xxsendline(c)
X{
X	sendline(c);
X}	/* end of xsendline */
X
X/*+-------------------------------------------------------------------------
X	flushline()
X--------------------------------------------------------------------------*/
Xflushline()
X{
X}	/* end of flushline */
X
X/*+-------------------------------------------------------------------------
X	purgeline() - purge the modem input queue of all characters
X--------------------------------------------------------------------------*/
Xpurgeline()
X{
X	Lleft = 0;
X#if defined(M_XENIX) || defined(M_UNIX)
X	ioctl(iofd,TCFLSH,0);
X#else
X	lseek(iofd,0L,2);
X#endif
X}	/* end of purgeline */
X
X/*+-------------------------------------------------------------------------
X	wcreceive(argc,argp)
X--------------------------------------------------------------------------*/
Xwcreceive(argc,argp)
Xint argc;
Xchar **argp;
X{
Xregister c;
X
X	if(Batch || argc==0)
X	{
X		Crcflg=1;
X		c=tryz();
X		if(Zmodem)
X		{
X			report_protocol_type("ZMODEM");
X			report_protocol_crc_type((Crc32) ? "/CRC32" : "/CRC16");
X		}
X		if(c)
X		{
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		{
X			report_protocol_type("YMODEM");
X			report_protocol_crc_type((Crcflg) ? "/CRC" : "/CHK");
X			for(;;)
X			{
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				report_str("Receiving data",0);
X				if(wcrx()==ERROR)
X					goto fubar;
X			}
X		}
X	}
X	else 
X	{
X		report_protocol_type("XMODEM");
X		report_protocol_crc_type((Crcflg) ? "/CRC" : "/CHK");
X		Bytesleft = DEFBYTL;
X		Filemode = 0;
X		Modtime = 0L;
X		procheader("");
X		strcpy(Pathname,*argp);
X		if((fout=fopen(Pathname,"w")) == NULL)
X		{
X			sprintf(s128,"%-0.85s: %-0.40s",Pathname,sys_errlist[errno]);
X			report_str(s128,1);
X			goto fubar;
X		}
X
X		report_file_rcv_started( Pathname,0L,Modtime,Filemode);
X		this_file_length = 0;
X		report_rxpos(0L);
X		report_str("Receiving data",0);
X		if(wcrx()==ERROR)
X			goto fubar;
X	}
X	return(OK);
Xfubar:
X	send_cancel();
X	if(fout)
X	{
X		fflush(fout);
X		fstat(fileno(fout),&fout_stat);
X		report_file_byte_io((long)fout_stat.st_size);
X		report_file_close();
X		fclose(fout);
X	}
X	return(ERROR);
X}	/* end of wcreceive */
X
X/*+-------------------------------------------------------------------------
X	wcgetsec(rxbuf,maxtime)
X
X  Wcgetsec fetches a Ward Christensen type sector.  Returns sector
X  number encountered or ERROR if valid sector not received, or CAN CAN
X  received or WCEOT if eot sector time is timeout for first char,set to
X  4 seconds thereafter. NO ACK IS SENT IF SECTOR IS RECEIVED OK. Caller
X  must do that when he is good and ready to get next sector.
X--------------------------------------------------------------------------*/
Xunsigned int
Xwcgetsec(rxbuf,maxtime)
Xchar *rxbuf;
Xint maxtime;
X{
Xregister unsigned int firstch;
Xregister unsigned short oldcrc;
Xregister unsigned char checksum;
Xregister wcj;
Xregister char *p;
Xint sectcurr;
X
X	for(Lastrx=errors=0; errors<RETRYMAX; errors++)
X	{
X
X		firstch=readline(maxtime);
X		if((firstch == STX) || (firstch == SOH))
X		{
X			oldBlklen = Blklen;
X			if(firstch == STX)
X				Blklen=1024;
X			else
X				Blklen=128;
X			if(oldBlklen != Blklen)
X				report_rxblklen(Blklen);
X
X			sectcurr=readline(1);
X			if((sectcurr + (oldcrc=readline(1))) == 0xFF)
X			{
X				oldcrc=checksum=0;
X				for(p=rxbuf,wcj=Blklen; --wcj>=0; )
X				{
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				{
X					oldcrc=updcrc(firstch,oldcrc);
X					if((firstch=readline(1)) < 0)
X						goto bilge;
X					oldcrc=updcrc(firstch,oldcrc);
X					if(oldcrc)
X					{
X						sprintf(s128,"CRC error = 0x%04x",oldcrc);
X						report_str(s128,1);
X					}
X					else 
X					{
X						Firstsec=0;
X						return(sectcurr);
X					}
X				}
X				else if((checksum-firstch)==0)
X				{
X					Firstsec=0;
X					return(sectcurr);
X				}
X				else
X					report_str("checksum error",1);
X			}
X			else
X			{
X				report_last_txhdr("Noise",0);
X				sprintf(s128,"Sector garbled 0x%x 0x%x",sectcurr,oldcrc);
X				report_str(s128,1);
X			}
X		}
X		/* make sure eot really is eot and not just mixmash */
X#if defined(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==EOT)
X		{
X			report_str("Noisy EOT",2);
X		}
X		else if(firstch==CAN)
X		{
X			if(Lastrx==CAN)
X			{
X				report_str("Sender CANcelled",1);
X				report_last_rxhdr("CAN",1);
X				return(ERROR);
X			} else 
X			{
X				Lastrx=CAN;
X				continue;
X			}
X		}
X		else if(firstch==TIMEOUT)
X		{
X			if(Firstsec)
X				goto humbug;
Xbilge:
X			report_str("Timeout",1);
X		}
X		else
X		{
X			sprintf(s128,"Got 0x%02x sector header",firstch);
X			report_str(s128,1);
X		}
X
Xhumbug:
X		Lastrx=0;
X		while(readline(1)!=TIMEOUT)
X			;
X		if(Firstsec)
X		{
X			sendline(Crcflg?WANTCRC:NAK);
X			report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
X			Lleft=0;	/* Do read next time ... */
X		} else 
X		{
X			maxtime=40;
X			sendline(NAK);
X			report_last_txhdr("NAK",1);
X			Lleft=0;	/* Do read next time ... */
X		}
X	}
X	/* try to stop the bubble machine. */
X	send_cancel();
X	return(ERROR);
X}	/* end of wcgetsec */
X
X/*+-------------------------------------------------------------------------
X	wcrxpn(rpn)
X
X  Fetch a pathname from the other end.  Length is indeterminate as long
X  as less than Blklen.  During YMODEM xfers, a null string represents no
X  more files.
X--------------------------------------------------------------------------*/
Xwcrxpn(rpn)
Xchar *rpn;	/* receive a pathname */
X{
Xregister c;
X
X#if defined(NFGVMIN)
X	readline(1);
X#else
X	purgeline();
X#endif
X
Xet_tu:
X	Firstsec=1;
X	Eofseen=0;
X	sendline(Crcflg?WANTCRC:NAK);
X	report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
X	Lleft=0;	/* Do read next time ... */
X	while((c = wcgetsec(rpn,100)) != 0)
X	{
X		if(c == WCEOT)
X		{
X			sprintf(s128,"Pathname fetch returned %d",c);
X			report_str(s128,1);
X			sendline(ACK);
X			report_last_txhdr("ACK",0);
X			Lleft=0;	/* Do read next time ... */
X			readline(1);
X			goto et_tu;
X		}
X		return(ERROR);
X	}
X	sendline(ACK);
X	report_last_txhdr("ACK",0);
X	return(OK);
X}	/* end of wcrxpn */
X
X/*+-------------------------------------------------------------------------
X	write_sec_to_disk(buf,n)
X
X  Putsec writes the n characters of buf to receive file fout.  If not in
X  binary mode, carriage returns, and all characters starting with CPMEOF
X  are discarded.
X--------------------------------------------------------------------------*/
Xwrite_sec_to_disk(buf,n)
Xchar *buf;
Xregister n;
X{
Xregister char *p;
X
X	if(n == 0)
X		return(OK);
X	if(Thisbinary)
X	{
X		for(p=buf; --n>=0; )
X			putc( *p++,fout);
X	}
X	else 
X	{
X		if(Eofseen)
X			return(OK);
X		for(p=buf; --n>=0; ++p )
X		{
X			if( *p == '\r')
X				continue;
X			if(*p == CPMEOF)
X			{
X				Eofseen=1;
X				fflush(fout);
X				fstat(fileno(fout),&fout_stat);
X				report_rxpos(fout_stat.st_size);
X				return(OK);
X			}
X			putc(*p ,fout);
X		}
X	}
X	fflush(fout);
X	fstat(fileno(fout),&fout_stat);
X	report_rxpos(fout_stat.st_size);
X	if(this_file_length != 0)
X	{
X		sprintf(s128,"Receiving data (%u%% complete)",
X		    (unsigned int)(
X		    ((unsigned long)fout_stat.st_size * (unsigned long)100)
X		    / this_file_length));
X		report_str(s128,0);
X	}
X	return(OK);
X}	/* end of write_sec_to_disk */
X
X/*+-------------------------------------------------------------------------
X	wcrx() - receive an X/YMODEM sector
X
X  Adapted from CMODEM13.C,written by Jack M.  Wierda and Roderick W. Hart
X--------------------------------------------------------------------------*/
Xint
Xwcrx()
X{
Xregister unsigned int sectnum,sectcurr;
Xregister unsigned char sendchar;
Xregister unsigned char *p;
Xint cblklen;			/* bytes to dump this block */
X
X	Firstsec=1;
X	sectnum=0;
X	Eofseen=0;
X	sendchar=Crcflg ? WANTCRC : NAK;
X	report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
X
X	for(;;)
X	{
X		sendline(sendchar);	/* send it now,we're ready! */
X		if(sendchar == ACK)
X			report_last_txhdr("ACK",0);
X		Lleft=0;	/* Do read next time ... */
X		sectcurr=wcgetsec(secbuf,(sectnum&0177)?50:130);
X		sprintf(s128,"Block %d received",sectnum);
X		report_last_rxhdr(s128,0);
X		fstat(fileno(fout),&fout_stat);
X		report_rxpos(fout_stat.st_size);
X		if(sectcurr == (sectnum+1 & 0xFF))
X		{
X			sectnum++;
X			cblklen = Bytesleft>Blklen ? Blklen : Bytesleft;
X			if(write_sec_to_disk(secbuf,cblklen) == ERROR)
X				return(ERROR);
X			if((Bytesleft-=cblklen) < 0)
X				Bytesleft = 0;
X			sendchar=ACK;
X		}
X		else if(sectcurr == sectnum)
X		{
X			report_str("Received duplicate Sector",-1);
X			sendchar = ACK;
X		}
X		else if(sectcurr == WCEOT)
X		{
X			if(close_and_report())
X				return(ERROR);
X			sendline(ACK);
X			report_last_txhdr("ACK",0);
X			Lleft=0;	/* Do read next time ... */
X			return(OK);
X		}
X		else if(sectcurr==ERROR)
X			return(ERROR);
X		else 
X		{
X			report_str( "Sync Error",1);
X			return(ERROR);
X		}
X	}
X}	/* end of wcrx */
X
X/*+-------------------------------------------------------------------------
X	readline(timeout)
X
X  read one or more characters timeout is in tenths of seconds
X--------------------------------------------------------------------------*/
Xreadline(timeout)
Xint timeout;
X{
Xregister n;
Xstatic unsigned char *cdq;	/* pointer for removing chars from linbuf */
X
X	if(--Lleft >= 0)
X		return(*cdq++);
X
X	n = timeout/10;
X	if(n < 2)
X		n = 3;
X	if(setjmp(tohere))
X	{
X		Lleft = 0;
X		return(TIMEOUT);
X	}
X	signal(SIGALRM,SIGALRM_handler);
X	alarm(n);
X	Lleft = read(iofd,cdq = linbuf,Readnum);
X	alarm(0);
X	rx_char_count += Lleft;
X
X	if(Lleft < 1)
X		return(TIMEOUT);
X
X	--Lleft;
X	return(*cdq++);
X
X}	/* end of readline */
X
X/*+-------------------------------------------------------------------------
X	mkdir(dpath,dmode)
X Directory-creating routines from Public Domain TAR by John Gilmore
X Make a directory.  Compatible with the mkdir() system call on 4.2BSD.
X--------------------------------------------------------------------------*/
X#if defined(MD)
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)
Xmkdir(dpath,dmode)
Xchar *dpath;
Xint dmode;
X{
Xint cpid,status;
Xstruct stat statbuf;
X
X	if(stat(dpath,&statbuf) == 0)
X	{
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)
X		return(-1);
X
X	switch(cpid = fork())
X	{
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	{
X		errno = EIO;		/* We don't know why,but */
X		return(-1);		/* /bin/mkdir failed */
X	}
X
X	return(0);
X}	/* end of mkdir */
X#endif /* MD != 2 */
X#endif /* if defined(MD) */
X
X/*+-------------------------------------------------------------------------
X	make_dirs(pathname)
X
X  Directory-creating routines from Public Domain TAR by John Gilmore
X  After a file/link/symlink/dir creation has failed, see if it's because
X  some required directory was not present, and if so, create all
X  required dirs.
X--------------------------------------------------------------------------*/
X#if defined(MD)
Xmake_dirs(pathname)
Xregister char *pathname;
X{
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	{
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		{
X			sprintf(s128,"Made directory %s",pathname);
X			report_str(s128,-1);
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}	/* end of make_dirs */
X#endif /* MD */
X
X/*+-------------------------------------------------------------------------
X	uncaps(str) - make string str lower case
X--------------------------------------------------------------------------*/
Xvoid
Xuncaps(str)
Xregister char *str;
X{
Xregister int itmp;
X
X	while(itmp = *str)
X	{
X		if(isupper(itmp))
X			*str = tolower(itmp);
X		str++;
X	}
X}	/* end of uncaps */
X
X/*+-------------------------------------------------------------------------
X	isanylc(str) - returns 1 if string str has any lower case letters
X--------------------------------------------------------------------------*/
Xint
Xisanylc(str)
Xregister char *str;
X{
X	while(*str)
X	{
X		if(islower(*str))
X			return(1);
X		str++;
X	}
X	return(0);
X}	/* end of isanylc */
X
X/*+-------------------------------------------------------------------------
X	procheader(name) - process incoming file information header
X--------------------------------------------------------------------------*/
Xint
Xprocheader(name)
Xchar *name;
X{
Xregister char *openmode,*p,**pp;
X#if defined(M_UNIX)
Xchar *cptr;
Xchar name2[PATHLEN];
X#endif
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 = 1;
X	else if(zmanag == ZMAPND)
X		openmode = "a";
X
X	report_xfer_mode(Thisbinary ? "BINARY" : "ASCII");
X	this_file_errors = 0;
X
X	Bytesleft = DEFBYTL;
X	Filemode = 0;
X	Modtime = 0L;
X	this_file_length = 0;
X
X	if(strlen(name))
X		p = name + 1 + strlen(name);
X	else
X		p = name;
X
X	if(*p)
X	{	/* file coming from Unix or DOS system */
X	int sscanf_count;
X	int SerialNumber;
X	int Filesleft;
X	long TotalLeft;
X
X		sscanf_count = sscanf(p,"%ld%lo%o%d&d&ld",
X		    &Bytesleft,&Modtime,&Filemode,&SerialNumber,
X		    &Filesleft,&TotalLeft);
X
X		switch(sscanf_count)
X		{
X		case 6:	/* TotalLeft */
X			if(!TotalToReceive)
X				TotalToReceive = TotalLeft;
X		case 5:	/* Filesleft */
X			if(!npats)
X				npats = Filesleft;
X		default:
X			break;
X		}
X
X		if((zmanag & ZMMASK) == ZMNEW)
X		{
X			if(stat(name,&fout_stat) == 0)			/* if file accessable ... */
X			{
X				if(Modtime <= fout_stat.st_mtime)	/* ... and not older */
X				{
X					sprintf(s128,"RECEIVE skipped: %s (same or later date)",
X						name);
X					report_str(s128 + 8,-1);
X					skip_count++;
X					report_error_count();
X					return(ERROR);
X				}
X			}
X		}
X		/* Check for existing file */
X		else if(!Rxclob && ((zmanag & ZMMASK) != ZMCLOB) &&
X			(fout=fopen(name,"r")))
X		{
X			fclose(fout);
X			sprintf(s128,"RECEIVE skipped: %s (already exists)",name);
X			report_str(s128 + 8,-1);
X			skip_count++;
X			report_error_count();
X			return(ERROR);
X		}
X
X		if(Filemode & UNIXFILE)
X			++Thisbinary;
X		++Filcnt;
X
X		report_file_rcv_started( name,
X			(Bytesleft != DEFBYTL) ? Bytesleft : 0,Modtime,Filemode);
X		report_rxpos(0L);
X		report_str("",0);	/* get rid of End of File */
X		if(Bytesleft != DEFBYTL)
X		{
X			long min_100;
X			this_file_length = Bytesleft;
X			min_100 = 2L + (((Bytesleft * 11L)) * 10L) / (Baudrate * 6L);
X			sprintf(s128,"Receive time this file ~= %2lu:%02lu",
X			    min_100 / 100,((min_100 % 100) * 60L) / 100L);
X			if(TotalToReceive)
X			{
X				min_100 = 2L +
X				    (((TotalToReceive * 11L)) * 10L) / (Baudrate * 6L);
X				if(Baudrate > 4800)
X				{
X					min_100 *= 13;
X					min_100 /= 9;	/* yech ... empirical */
X				}
X				sprintf(&s128[strlen(s128)],", transaction ~= %2lu:%02lu",
X				    min_100 / 100,((min_100 % 100) * 60L) / 100L);
X			}
X			report_transaction(s128);
X			sprintf(s128,"Receiving data (%d%% complete)",(int)0);
X			report_str(s128,0);
X		}
X	}
X	else 
X	{		/* File coming from CP/M system */
X	long now;
X		for(p=name; *p; ++p)		/* change / to _ */
X		{
X			if( *p == '/')
X				*p = '_';
X		}
X
X		if( *--p == '.')		/* zap trailing period */
X			*p = 0;
X		time(&now);
X		report_file_rcv_started( name,
X			(Bytesleft != DEFBYTL) ? Bytesleft : 0,now,0);
X	}
X
X	if(!Zmodem && MakeLCPathname && !isanylc(name) && !(Filemode&UNIXFILE))
X		uncaps(name);
X
X	strcpy(Pathname,name);
X	report_xfer_mode(Thisbinary?"BINARY":"ASCII");
X	fout = fopen(name,openmode);
X#if defined(MD)
X	if( !fout)
X		if(make_dirs(name))
X			fout = fopen(name,openmode);
X#endif
X	if( !fout)
X		return(ERROR);
X	this_file_errors = 0;
X	return(OK);
X}	/* end of procheader */
X
X/*+-------------------------------------------------------------------------
X	send_cancel() - send cancel string
X--------------------------------------------------------------------------*/
Xsend_cancel()
X{
Xstatic char canistr[] = 
X{
X	24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
X};
Xregister char *cptr = canistr;
X
X	report_str("",0);
X	report_last_txhdr("^X CAN",1);
X	while(*cptr)
X		sendline(*cptr++);
X	Lleft=0;
X}	/* end of send_cancel */
X
X/*+-------------------------------------------------------------------------
X	tryz()
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--------------------------------------------------------------------------*/
Xint
Xtryz()
X{
Xregister c,n;
X
X	if(Nozmodem)		/* Check for "rb" program name */
X		return(0);
X
X	for(n=Zmodem?15:5; --n>=0; )
X	{
X		/* Set buffer length (0) and capability flags */
X		stohdr(0L);
X#if defined(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		{
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
X			strcpy(s128,"Transfer: ");
X			switch(zmanag & ZMMASK)
X			{
X			case 0:
X				strcat(s128,"if destination nonexistent");
X				break;
X			case ZMAPND:	/* Append contents to existing file (if any) */
X				strcat(s128,"append to destination");
X				break;
X			case ZMCLOB:	/* Replace existing file */
X				strcat(s128,"absolute (overwrite)");
X				break;
X			case ZMNEW:
X				strcat(s128,"if source newer");
X				break;
X			default:
X				sprintf(s128 + strlen(s128),
X				    "absolute (%02x)",zmanag & ZMMASK);
X				break;
X			}
X			report_str(s128,2);
X
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			{
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			if(zrdata(secbuf,1024) == GOTCRCW)
X			{
X				stohdr(-1L);
X				purgeline();	/* dump impatient questions */
X				while(errors < 20)
X				{
X					zshhdr(ZCOMPL,Txhdr);
X					if(zgethdr(Rxhdr,1) == ZFIN)
X						break;
X				}
X				send_ZFIN_and_exit();
X				return(ZCOMPL);
X			}
X			zshhdr(ZNAK,Txhdr);
X			goto again;
X		case ZCOMPL:
X			goto again;
X		default:
X			continue;
X		case ZFIN:
X			send_ZFIN_and_exit();
X			return(ZCOMPL);
X		case ZCAN:
X			return(ERROR);
X		}
X	}
X	return(0);
X}	/* end of tryz */
X
X/*+-------------------------------------------------------------------------
X	rzfile() - receive a file with ZMODEM protocol
X
X  assumes file name frame is in secbuf
X--------------------------------------------------------------------------*/
Xrzfile()
X{
Xregister c,n;
Xlong rxbytes;
X
X	Eofseen=0;
X	if(procheader(secbuf) == ERROR)
X	{
X		return(tryzhdrtype = ZSKIP);
X	}
X
X	n = 20;
X	rxbytes = 0l;
X
X	for(;;)
X	{
X		stohdr(rxbytes);
X		zshhdr(ZRPOS,Txhdr);
X		if(rxbytes)
X			report_str("Sending ZRPOS",1);
Xnxthdr:
X		switch(c = zgethdr(Rxhdr,0))
X		{
X		default:
X			sprintf(s128,"zgethdr returned %02x",c);
X			report_str(s128,1);
X			return(ERROR);
X		case ZNAK:
X		case TIMEOUT:
X			if( --n < 0)
X			{
X				sprintf(s128,"zgethdr returned %02x",c);
X				report_str(s128,1);
X				return(ERROR);
X			}
X		case ZFILE:
X			zrdata(secbuf,1024);
X			continue;
X		case ZEOF:
X			if(rclhdr(Rxhdr) != rxbytes)
X			{
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;
X				goto nxthdr;
X			}
X			if(close_and_report())
X			{
X				tryzhdrtype = ZFERR;
X				return(ERROR);
X			}
X			report_str("End of file",0);
X			return(c);
X		case ERROR:	/* Too much garbage in header search error */
X			if( --n < 0)
X			{
X				sprintf(s128,"zgethdr returned %02x",c);
X				report_str(s128,1);
X				return(ERROR);
X			}
X			zmputs(Attn);
X			continue;
X		case ZSKIP:
X			close_and_report();
X			sprintf(s128,"rzfile: Sender SKIPPED file");
X			report_str(s128,1);
X			return(c);
X		case ZDATA:
X			if(rclhdr(Rxhdr) != rxbytes)
X			{
X				if( --n < 0)
X				{
X					return(ERROR);
X				}
X				zmputs(Attn);
X				continue;
X			}
Xmoredata:
X			switch(c = zrdata(secbuf,1024))
X			{
X			case ZCAN:
X				sprintf(s128,"zgethdr returned %02x",c);
X				report_str(s128,1);
X				return(ERROR);
X			case ERROR:	/* CRC error */
X				if( --n < 0)
X				{
X					sprintf(s128,"zgethdr returned %02x",c);
X					report_str(s128,1);
X					return(ERROR);
X				}
X				zmputs(Attn);
X				continue;
X			case TIMEOUT:
X				if( --n < 0)
X				{
X					sprintf(s128,"zgethdr returned %02x",c);
X					report_str(s128,1);
X					return(ERROR);
X				}
X				continue;
X			case GOTCRCW:
X				n = 20;
X				write_sec_to_disk(secbuf,Rxcount);
X				rxbytes += Rxcount;
X				stohdr(rxbytes);
X				zshhdr(ZACK,Txhdr);
X				sendline(XON);
X				goto nxthdr;
X			case GOTCRCQ:
X				n = 20;
X				write_sec_to_disk(secbuf,Rxcount);
X				rxbytes += Rxcount;
X				stohdr(rxbytes);
X				zshhdr(ZACK,Txhdr);
X				goto moredata;
X			case GOTCRCG:
X				n = 20;
X				write_sec_to_disk(secbuf,Rxcount);
X				rxbytes += Rxcount;
X				goto moredata;
X			case GOTCRCE:
X				n = 20;
X				write_sec_to_disk(secbuf,Rxcount);
X				rxbytes += Rxcount;
X				goto nxthdr;
X			}
X		}
X	}
X}	/* end of rzfile */
X
X/*+-------------------------------------------------------------------------
X	rzfiles() - receive file(s) with ZMODEM protocol
X--------------------------------------------------------------------------*/
Xrzfiles()
X{
Xregister c;
X
X	for(;;)
X	{
X		switch(c = rzfile())
X		{
X		case ZEOF:
X		case ZSKIP:
X			switch(tryz())
X			{
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}	/* end of rzfiles */
X
X/*+-------------------------------------------------------------------------
X	close_and_report() - close the received file, set mod time and chmod
X(specifically exclude set uid and gid from chmod)
X--------------------------------------------------------------------------*/
Xclose_and_report()
X{
X	fflush(fout);
X	fstat(fileno(fout),&fout_stat);
X	report_file_byte_io((long)fout_stat.st_size);
X	report_file_close();
X
X	if(fclose(fout)==ERROR)
X		return(ERROR);
X
X	if(Modtime)
X	{
X		timep[0] = time(NULL);
X		timep[1] = Modtime;
X		utime(Pathname,timep);
X	}
X
X	if((Filemode & S_IFMT) == S_IFREG)
X	{
X    	Filemode &= ~(S_ISUID | S_ISGID);
X		chmod(Pathname,(07777 & Filemode));
X	}
X
X	return(OK);
X
X}	/* end of close_and_report */
X
X/*+-------------------------------------------------------------------------
X	send_ZFIN_and_exit() - send ZFIN packet and wait for "OO" ack
X--------------------------------------------------------------------------*/
Xsend_ZFIN_and_exit()
X{
Xregister n;
X
X	Readnum = 1;
X	stohdr(0L);
X	for(n = 0; n < 4; n++)
X	{
X		purgeline();
X		zshhdr(ZFIN,Txhdr);
X		switch(readline(100))
X		{
X		case 'O':
X			readline(1);	/* Discard 2nd 'O' */
X			return;
X		case RCDO:
X			return;
X		case TIMEOUT:
X		default:
X			break;
X		}
X	}
X}	/* end of send_ZFIN_and_exit */
X
X/*+-------------------------------------------------------------------------
X	sys2(shellcmd) - extipte shell command
X
X Strip leading ! if present
X--------------------------------------------------------------------------*/
Xsys2(shellcmd)
Xregister char *shellcmd;
X{
X	if(*shellcmd == '!')
X		++shellcmd;
X	return(system(shellcmd));
X} /* end of sys2 */
X
X/*+-------------------------------------------------------------------------
X	main(argc,argv,envp)
X--------------------------------------------------------------------------*/
Xmain(argc,argv,envp)
Xint argc;
Xchar **argv;
Xchar **envp;
X{
Xregister char *cp;
Xchar **patts;
Xchar *getenv();
Xint exitcode = 0;
Xchar **gargv = argv;
Xint gargc = argc;
X
X	signal(SIGINT,bye_bye);
X	signal(SIGTERM,bye_bye);
X
X	get_curr_dir(curr_dir,sizeof(curr_dir));
X
X	Rxtimeout = 100;
X
X	npats = 0;
X	while(--argc)
X	{
X		cp = *++argv;
X		if(*cp == '-')
X		{
X			while( *++cp)
X			{
X				switch(*cp)
X				{
X				case 'X':
X					required_type = 1;
X					Batch = 0;
X					break;
X				case 'Y':
X					required_type = 1;
X					Nozmodem = 1;
X					Batch = 1;
X					break;
X				case 'Z':
X					required_type = 1;
X					Nozmodem = 0;
X					Batch = 1;
X					break;
X				case '+':
X					Lzmanag = ZMAPND;
X					break;
X				case 'a':
X					Rxascii=1;
X					break;
X				case 'b':
X					Rxbinary=1;
X					break;
X				case 'c':
X					Crcflg=1;
X					break;
X				case 'e':
X					Zctlesc = 1;
X					break;
X				case 'p':
X					Lzmanag = ZMPROT;
X					break;
X				case ',':
X					log_packets = 1;
X					break;
X				case '.':
X					if(--argc < 1)
X					{
X						usage("no iofd after -.");
X					}
X					iofd = atoi(*++argv);
X					break;
X				case 't':
X					if(--argc < 1)
X					{
X						usage("no rcvr timeout after -t");
X					}
X					Rxtimeout = atoi(*++argv);
X					if(Rxtimeout<10 || Rxtimeout>1000)
X						usage("illegal timeout: must be 10 <= t <= 1000");
X					break;
X				case 'w':
X					if(--argc < 1)
X					{
X						usage("no Zrwindow after -w");
X					}
X					Zrwindow = atoi(*++argv);
X					break;
X				case 'C':
X					if(--argc < 1)
X						usage("no label after -C");
X					bottom_label = *++argv;
X					break;
X				case 'u':
X					MakeLCPathname=0;
X					break;
X				case 'y':
X					Rxclob=1;
X					break;
X				default:
X					sprintf(s128,"Unknown switch -%c",*cp);
X					usage(s128);
X				}
X			}
X		}
X		else if( !npats && argc>0)
X		{
X			if(argv[0][0])
X			{
X				npats=argc;
X				patts=argv;
X			}
X		}
X	}
X
X	if(!required_type || !iofd)
X	{
X		printf("can only be run by tip\n");
X		exit(255);
X	}
X
X	if(log_packets)
X	{
X		char log_packets_name[64];
X		FILE *ftmp;
X		int iargv;
X		sprintf(log_packets_name,"/tmp/rz%05d.plog",getpid());
X		unlink(log_packets_name);
X		ftmp = fopen(log_packets_name,"w");
X		fclose(ftmp);
X		log_packets = open(log_packets_name,O_WRONLY,0644);
X		if(log_packets < 0)
X			log_packets = 0;
X		else
X		{
X			write(log_packets,"exec: ",6);
X			for(iargv = 0; iargv < gargc; iargv++)
X			{
X				write(log_packets,gargv[iargv],strlen(gargv[iargv]));
X				write(log_packets," ",1);
X			}
X			write(log_packets,"\n",1);
X		}
X	}
X
X
X	if(Batch && npats)
X		usage("Cannot specify batch receive and filename");
X	if(npats > 1)
X		usage("only one filename allowed");
X	sprintf(s128,"%s",numeric_revision);
X	report_init(s128);
X	mode(1);
X	signal(SIGINT,cancel_transaction);
X	signal(SIGTERM,cancel_transaction);
X	signal(SIGQUIT,cancel_transaction);
X	if(wcreceive(npats,patts)==ERROR)
X	{
X		exitcode=0200;
X		send_cancel();
X	}
X	mode(0);
X	if(exitcode && !Zmodem)	/* bellow again with all thy might. */
X		send_cancel();
X	report_uninit(0);
X	exit(exitcode);
X}
X
X/* vi: set tabstop=4 shiftwidth=4: */
X/* end of tiprz.c */
SHAR_EOF
$TOUCH -am 0521180090 xfer/tiprz.c &&
chmod 0644 xfer/tiprz.c ||
echo "restore of xfer/tiprz.c failed"
set `wc -c xfer/tiprz.c`;Wc_c=$1
if test "$Wc_c" != "39641"; then
	echo original size 39641, current size $Wc_c
fi
echo "End of part 2, continue with part 3"
exit 0

------------------------------------------------------------------
Warren Tucker, Tridom Corporation      ...!gatech!emory!tridom!wht
home address:                                 ...!gatech!n4hgf!wht