[comp.sources.misc] v16i044: ECU async comm package rev 3.0, Part20/35

wht@n4hgf.uucp (Warren Tucker) (01/06/91)

Submitted-by: wht@n4hgf.uucp (Warren Tucker)
Posting-number: Volume 16, Issue 44
Archive-name: ecu3/part20

---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is part 20 of ecu3
if touch 2>&1 | fgrep 'amc' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= z/ecusz.c ==============
if test ! -d 'z'; then
    echo 'x - creating directory z'
    mkdir 'z'
fi
echo 'x - extracting z/ecusz.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'z/ecusz.c' &&
Xchar *numeric_revision = "ecusz 3.04";
X#define BUFFERED_WRITE
X/*+-------------------------------------------------------------------------
X	ecusz.c - X/Y/ZMODEM send program
X  Derived from public domain source by Chuck Forsberg, Omen Technologies
X  Adaptation for ecu 1989 wht@n4hgf.Mt-Park.GA.US
X
X	Usage:	ecusz [-X -Y -Z] [-12+abdefkLlNnquvwy] [-] file ...
X		(Y) = Option applies to YMODEM only
X		(Z) = Option applies to ZMODEM only
X		a (ASCII) change NL to CR/LF
X		b Binary file transfer override
X		f send Full pathname (Y/Z)
X		k Send 1024 byte packets (Y)
X		L N Limit subpacket length to N bytes (Z)
X		l N Limit frame length to N bytes (l>=L) (Z)
X		n send file if source newer (Z)
X		N send file if source newer or longer (Z)
X		o Use 16 bit CRC instead of 32 bit CRC (Z)
X		p Protect existing destination file (Z)
X		r Resume/Recover interrupted file transfer (Z)
X		q Quiet (no progress reports)
X		u Unlink file after transmission
X		w N Window is N bytes (Z)
X		y Yes,overwrite existing file (Z)
X		@file reads a list of filenames from 'file'
X
X  Defined functions:
X	SIGALRM_handler()
X	bye_bye(sig)
X	cancel_transaction(sig)
X	determine_transaction_time()
X	flushline()
X	get_file_list_name(namep)
X	getinsync(flag)
X	getnak()
X	getzrxinit()
X	log_packet_buffer(buf,len)
X	main(argc,argv)
X	onintr()
X	purgeline()
X	readline(n)
X	readock(timeout,count)
X	report_rcvr_cancelled(place_happened)
X	report_rcvr_skipped()
X	report_send_stats(filepos)
X	report_send_transaction()
X	rewind_file_list()
X	saybibi()
X	send_cancel(error)
X	sendline(ch)
X	sendzsinit()
X	set_file_list(pathc,pathv)
X	substr(s,t)
X	usage()
X	wcputsec(buf,sectnum,cseclen)
X	wcs(oname)
X	wcsend()
X	wctx(flen)
X	wctxpn(name)
X	xbuf_build(buf,count)
X	xsendline(ch)
X	zbuf_build(buf,count)
X	zsendfdata()
X	zsendfile(buf,blen)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:12-18-1990-21:26-wht@n4hgf-better output control */
X/*:09-19-1990-19:36-wht@n4hgf-ecu_log_event now gets pid for log from caller */
X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
X
X/*
X  Error return conditions
X	255:     usage
X	254:     protocol failed (bad line conditions,brain dead remote)
X	253:     could not open any files
X	128-192: process terminated with signal==code-128 (64 signals allowed for)
X             signal 0 == program logic error (see cancel_transaction)
X	127:     127 or more files not transmitted (see ~/.ecu/log)
X	1-126:   count of files not transmitted (see ~/.ecu/log)
X	0:       file transfer completely successful
X*/
X
Xchar *substr(),*getenv();
X
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <ctype.h>
X#include <fcntl.h>
X#include "zmodem.h"
X#include "zlint.h"
X
Xextern char *sys_errlist[];
Xextern unsigned short crctab[];	/* wht */
Xextern unsigned long total_data_chars_xfered; /* zcurses.c */
Xextern int errno;
Xextern int show_window;
Xextern int Rxtimeout;	/* Tenths of seconds to wait for something */
Xextern char Rxhdr[4];	/* Received header */
Xextern char Txhdr[4];	/* Transmitted header */
Xextern int Txfcs32;		/* TURE means send binary frames with 32 bit FCS */
Xextern long Rxpos;	/* Received file position */
Xextern long Txpos;	/* Transmitted file position */
Xextern char *frametypes[];
Xextern char Attn[];		/* Attention string rx sends to tx on err */
Xextern char s256[];
X
X#define RETRYMAX 10		/* non-zmodem retry count on block send */
X#define VMIN_COUNT 2	/* must not exceed 255 */
Xunsigned char vmin_count = VMIN_COUNT;
Xint iofd = 0;		/* line io fd */
X#ifdef BUFFERED_WRITE
XFILE *iofp;
X#endif
X
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#if defined(READCHECK)
Xchar Myattn[] = { 0 };
X#else
X#if defined(M_SYS5)
Xchar Myattn[] = { 03,0336,0 };
X#else
Xchar Myattn[] = { 0 };
X#endif
X#endif
X
XFILE *in;
X
Xchar *Cmdstr;		/* Pointer to the command string */
Xchar *bottom_label = (char *)0;
Xchar Crcflg;
Xchar Lastrx;
Xchar Lzconv;		/* Local ZMODEM file conversion request */
Xchar Lzmanag;		/* Local ZMODEM file management request */
Xchar Lztrans;
Xchar Pathname[PATHLEN];
Xchar curr_dir[256];
Xchar s128[128];
Xchar txbuf[1024];
Xchar zconv;				/* ZMODEM file conversion request */
Xchar zmanag;			/* ZMODEM file management request */
Xchar ztrans;			/* ZMODEM file transport request */
Xint Ascii=0;			/* Add CR's for brain damaged programs */
Xint Cmdack1;			/* Rx ACKs command,then do it */
Xint Cmdtries = 11;
Xint Command = 0;		/* Send a command,then exit. */
Xint Dontread;			/* Don't read the buffer,it's still there */
Xint Dottoslash=0;		/* Change foo.bar.baz to foo/bar/baz */
Xint Exitcode = 0;
Xint Filcnt=0;			/* count of number of files opened */
Xint FilesTotal;
Xint Filesleft;
Xint Fullname=0;			/* transmit full pathname */
Xint Lastn;				/* Count of last buffer read or -1 */
Xint Lfseen=0;
Xint Noeofseen;
Xint Nozmodem = 0;
Xint Optiong;			/* no wait for block ACK's */
Xint Quiet=0;			/* overrides logic that would otherwise set verbose */
Xint Rxflags = 0;
Xint SameZrposAgain=0;	/* How many times we've been ZRPOS'd same place (wht) */
Xint Tframlen = 0;		/* Override for tx frame length */
Xint Totsecs;			/* total number of blocks this file */
Xint Twostop = 0;		/* use two stop bits */
Xint Unlinkafter=0;		/* Unlink file after it is sent */
Xint Wantfcs32 = TRUE;	/* want to send 32 bit FCS */
Xint Xmodem=0;			/* XMODEM Protocol - don't send pathnames */
Xint Zctlesc;			/* Encode control characters */
Xint Zmodem=0;			/* ZMODEM protocol requested by receiver */
Xint Zrwindow = 1400;	/* RX window size (controls garbage count) */
Xint blklen=128;			/* length of transmitted records */
Xint blklen_original;
Xint blkopt=0;			/* Override value for zmodem blklen */
Xint ecusz_flag = 1;
Xint force_no_curses = 0;
Xint skip_count = 0;		/* skipped files */
Xint errors;
Xint firstsec;
Xint log_packets = 0;
Xint no_files = 0;
Xint npats = 0;
Xlong Lastread;		/* Beginning offset of last buffer read */
Xlong Lastsync;		/* Last offset to which we got a ZRPOS */
Xlong Lrxpos;			/* Receiver's last reported offset */
Xlong TotalLeft;
Xlong TotalToSend;
Xlong bytcnt;
Xlong rx_char_count = 0L;
Xlong this_file_length;
Xlong tx_char_count = 0L;
Xunsigned Baudrate;
Xunsigned Rxbuflen = 16384;	/* Receiver's max buffer length */
Xunsigned Txwcnt;		/* Counter used to space ack requests */
Xunsigned Txwindow;		/* Control the size of the transmitted window */
Xunsigned Txwspac;		/* Spacing between zcrcq requests */
Xunsigned int bad_condx_blklen = 0;	/* if <>0,blklen has been reduced (wht) */
Xunsigned int bad_condx_frame_count = 0;	/* frame # last SameZrposAgain (wht) */
Xunsigned int this_file_frame_count;	/* count of frames sent this file (wht) */
X
X#define MAX_PATHS 512
Xchar *paths[MAX_PATHS];
X
Xjmp_buf tohere;		/* For the interrupt on RX timeout */
Xjmp_buf intrjmp;	/* For the interrupt on RX CAN */
X
Xint file_list_pathc;
Xint file_list_path_current;
Xchar **file_list_pathv;
Xint required_type = 0;
XFILE *fpflst = (FILE *)0;
X
X/*+-------------------------------------------------------------------------
X	log_packet_buffer(buf,len)
X--------------------------------------------------------------------------*/
Xvoid
Xlog_packet_buffer(buf,len)
Xregister unsigned char *buf;
Xregister int len;
X{
Xchar xbuf[32];
X
X	while(len--)
X	{
X		sprintf(xbuf,"%02x ",*buf++);
X		write(log_packets,xbuf,strlen(xbuf));
X	}
X	write(log_packets,"\n",1);
X
X}	/* end of log_packet_buffer */
X
X/*+-------------------------------------------------------------------------
X	rewind_file_list()
X--------------------------------------------------------------------------*/
Xvoid
Xrewind_file_list()
X{
X	file_list_path_current = 0;
X	if(fpflst)
X	{
X		fclose(fpflst);
X		fpflst = (FILE *)0;
X	}
X}	/* end of rewind_file_list */
X
X/*+-------------------------------------------------------------------------
X	set_file_list(pathc,pathv)
X--------------------------------------------------------------------------*/
Xvoid
Xset_file_list(pathc,pathv)
Xint pathc;
Xchar **pathv;
X{
X
X	file_list_pathc = pathc;
X	file_list_pathv = pathv;
X	rewind_file_list();
X}	/* end of set_file_list */
X
X/*+-------------------------------------------------------------------------
X	get_file_list_name(namep)
X--------------------------------------------------------------------------*/
Xget_file_list_name(namep)
Xchar **namep;
X{
Xregister char *cptr;
Xstatic char name[256];
X
Xtry_fpflst:
X	if(fpflst)
X	{
X		if(fgets(name,sizeof(name),fpflst) != NULL)
X		{
X			name[strlen(name) - 1] = 0;
X			*namep = name;
X			return(1);
X		}
X		fclose(fpflst);
X		fpflst = (FILE *)0;
X	}
X
Xnext_arg:
X	if(file_list_path_current == file_list_pathc)
X		return(0);
X	cptr = file_list_pathv[file_list_path_current++];
X	if(*cptr != '@')
X	{
X		*namep = cptr;
X		return(1);
X	}
X	cptr++;
X	if((fpflst = fopen(cptr,"r")) == NULL)
X		goto next_arg;
X	goto try_fpflst;
X
X}	/* end of get_file_list_name */
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(1);
X	mode(0);
X	if(sig >= 0)
X	{
X		sprintf(s128,"ecusz 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/* Called when ZMODEM gets an interrupt (^X) */
Xonintr()
X{
X	signal(SIGINT,SIG_IGN);
X#if defined(M_SYS5)
X	report_rx_ind(0);
X	report_tx_ind(0);
X#endif
X	longjmp(intrjmp,-1);
X}
X
X
X/*+-------------------------------------------------------------------------
X	report_send_transaction()
X--------------------------------------------------------------------------*/
Xvoid
Xreport_send_transaction()
X{
X	if(Xmodem)
X	{
X		long blocks = (TotalToSend >> 7) + ((TotalToSend % 128) != 0);
X		long secs = 7		/* slightly worse than average first nak delay */
X			+ (blocks / 5L)				/* assume .2 sec ack time */
X			+ ((blocks * (128L + 16L)) / (Baudrate / 10));
X		if(!secs)
X			secs = 10L;
X		sprintf(s128,"Sending %ld blocks time ~= %ld:%02ld",
X		    blocks,secs/60,secs % 60);
X	}
X	else
X	{
X		long min_100 =
X			(FilesTotal * 2L) + (((TotalToSend * 11L)) * 10L) / (Baudrate * 6L);
X		if(!min_100)
X			min_100 = 4L;
X#if defined(M_I286)	/* slower */
X		else if(Baudrate > 4800)
X		{
X			min_100 *= 13;
X			min_100 /= 9;	/* yech ... empirical */
X		}
X#endif
X		sprintf(s128,
X			"Total transaction %ld bytes (xfer time ~= %2lu:%02lu)",
X		    TotalToSend,min_100 / 100,((min_100 % 100) * 60L) / 100L);
X	}
X	report_transaction(s128);
X
X}	/* end of report_send_transaction */
X
X/*+-------------------------------------------------------------------------
X	report_send_stats(filepos)
X--------------------------------------------------------------------------*/
Xvoid
Xreport_send_stats(filepos)
Xlong filepos;
X{
X
X	if(Xmodem)
X		sprintf(s128,"File %d%% complete",
X		    (this_file_length == 0) ? (int)100 :
X		    (int)((filepos * 100L) / this_file_length));
X	else
X		sprintf(s128,"This file %d%%, transaction %d%% complete",
X		    (this_file_length == 0) ? (int)100 :
X				    (int)((filepos * 100L)/this_file_length),
X		    (TotalToSend == 0) ? (int)100 :
X		    		(int)(((total_data_chars_xfered + filepos) * 100L)
X						/ TotalToSend));
X	report_str(s128,0);
X	report_txpos(filepos);
X
X}	/* end of report_send_stats */
X
X/*+-------------------------------------------------------------------------
X	report_rcvr_cancelled(place_happened)
X--------------------------------------------------------------------------*/
Xvoid
Xreport_rcvr_cancelled(place_happened)
Xchar *place_happened;
X{
X	strcpy(s128,"SEND CANCELLED");
X	report_str(s128 + 5,1);
X#if defined(LOG_XFER)
X	strcat(s128," (");
X	strcat(s128,place_happened);
X	strcat(s128,")");
X	ecu_log_event(getppid(),s128);
X#endif
X	skip_count++;
X	report_error_count();
X}	/* end of report_rcvr_cancelled */
X
X/*+-------------------------------------------------------------------------
X	report_rcvr_skipped()
X--------------------------------------------------------------------------*/
Xvoid
Xreport_rcvr_skipped()
X{
X	sprintf(s128,"SEND skipped: %s",Pathname);
X	report_str(s128 + 5,-1);
X#if defined(LOG_SKIP)
X	ecu_log_event(getppid(),s128);
X#endif
X	skip_count++;
X	report_error_count();
X	TotalToSend -= this_file_length;
X	report_send_transaction();
X}	/* end of report_rcvr_skipped */
X
X
X/*+-------------------------------------------------------------------------
X	xsendline(ch)
X--------------------------------------------------------------------------*/
Xxsendline(ch)
Xchar ch;
X{
X#ifdef BUFFERED_WRITE
X	fputc(ch,iofp);
X#else
X	write(iofd,&ch,1);
X#endif
X	++tx_char_count;
X}	/* end of xsendline */
X
X/*+-------------------------------------------------------------------------
X	sendline(ch)
X--------------------------------------------------------------------------*/
Xsendline(ch)
Xchar ch;
X{
X	xsendline(ch);
X}	/* end of sendline */
X
Xflushline()
X{
X#ifdef BUFFERED_WRITE
X	fflush(iofp);
X#endif
X}
X
Xmain(argc,argv)
Xchar *argv[];
X{
Xregister char *cp;
Xlong min_100;
Xchar **patts = paths;
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 = 600;
X	npats=0;
X	if(argc<2)
X		usage();
X	while(--argc)
X	{
X		cp = *++argv;
X		if(*cp == '-')
X		{
X			cp++;
X			switch(*cp++)
X			{
X			case 'X':
X				required_type = 1;
X				Xmodem = TRUE;
X				break;
X			case 'Y':
X				required_type = 1;
X				Nozmodem = TRUE;
X				blklen=1024;
X				break;
X			case 'Z':
X				show_window = 1;
X				required_type = 1;
X				break;
X
X			case '+':
X				Lzmanag = ZMAPND;
X				break;
X			case 'a':
X				Lzconv = ZCNL;
X				Ascii = TRUE;
X				break;
X			case 'b':
X				Lzconv = ZCBIN;
X				break;
X			case 'd':
X				++Dottoslash;
X				/* **** FALL THROUGH TO **** */
X			case 'f':
X				Fullname=TRUE;
X				break;
X			case ',':
X				log_packets = 1;
X				break;
X			case '@':
X				force_no_curses = 1;
X				break;
X			case '/':
X				if(--argc < 1)
X					usage();
X				strcpy(curr_dir,*++argv);
X				break;
X			case '.':
X				if(--argc < 1)
X					usage();
X				iofd = 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 'e':
X				Zctlesc = 1;
X				break;
X			case 'k':
X				blklen=1024;
X				break;
X			case 'L':
X				if(--argc < 1)
X				{
X					usage();
X				}
X				blkopt = atoi(*++argv);
X				if(blkopt<24 || blkopt>1024)
X						usage();
X				break;
X			case 'l':
X				if(--argc < 1)
X				{
X					usage();
X				}
X				Tframlen = atoi(*++argv);
X				if(Tframlen<32 || Tframlen>1024)
X					usage();
X				break;
X			case 'N':
X				Lzmanag = ZMNEWL;
X				break;
X			case 'n':
X				Lzmanag = ZMNEW;
X				break;
X			case 'o':
X				Wantfcs32 = FALSE;
X				break;
X			case 'p':
X					Lzmanag = ZMPROT;
X					break;
X			case 'r':
X				Lzconv = ZCRESUM;
X			case 't':
X				if(--argc < 1)
X				{
X					usage();
X				}
X				Rxtimeout = atoi(*++argv);
X				if(Rxtimeout<10 || Rxtimeout>1000)
X					usage();
X				break;
X			case 'u':
X				++Unlinkafter;
X				break;
X			case 'w':
X				if(--argc < 1)
X				{
X					usage();
X				}
X				Txwindow = atoi(*++argv);
X				if(Txwindow < 256)
X					Txwindow = 256;
X				Txwindow = (Txwindow/64) * 64;
X				Txwspac = Txwindow/4;
X				if(blkopt > Txwspac || (!blkopt && Txwspac < 1024))
X					blkopt = Txwspac;
X				break;
X			case 'y':
X				Lzmanag = ZMCLOB;
X				break;
X			default:
X				usage();
X			}
X		}
X		else if(argc > 0)
X		{
X			if(npats < MAX_PATHS)
X			{
X				npats++;
X				*patts++ = cp;
X			}
X			else
X			{
X				printf("too many filenames to send\n");
X				exit(255);
X			}
X		}
X	}
X	if(!required_type || !iofd)
X	{
X		printf("can only be run by ecu\n");
X		exit(255);
X	}
X
X	if(determine_output_mode())
X	{
X		setbuf(stdout,NULL);
X		setbuf(stderr,NULL);
X	}
X
X	if(npats < 1 && !Command)
X		usage();
X
X	set_file_list(npats,paths);
X	sprintf(s128,"%s",numeric_revision);
X
X	if(log_packets)
X	{
X	char log_packets_name[64];
X	FILE *ftmp;
X	int iargv;
X		sprintf(log_packets_name,"/tmp/sz%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	report_init(s128);
X	mode(1);
X
X	if(signal(SIGINT,cancel_transaction) == SIG_IGN)
X		signal(SIGINT,SIG_IGN);
X	else
X		signal(SIGINT,cancel_transaction);
X	signal(SIGTERM,cancel_transaction);
X
X	report_str("calculating transaction time",-1);
X	determine_transaction_time();
X#ifdef BUFFERED_WRITE
X	iofp = fdopen(iofd,"w");
X#endif
X	if(!Xmodem)
X	{
X		TotalToSend = TotalLeft;
X		report_send_transaction();
X		report_str("starting remote receiver",-1);
X		report_last_txhdr("begin transfer",0);
X		if(!Nozmodem)
X			write(iofd,"rz\r",3);
X		else	/* wht -- why not? */
X			write(iofd,"rb\r",3);		/* wht */
X		nap(2000L);
X		report_str("",-1);
X		if(!Nozmodem)
X		{
X			stohdr(0L);
X			zshhdr(ZRQINIT,Txhdr);
X		}
X	}
X	else
X	{
X		report_str("",-1);
X		report_last_txhdr("begin transfer",0);
X	}
X
X	if(wcsend()==ERROR)
X	{
X		Exitcode=254;		/*wht was 0200 */
X		send_cancel(1);
X	}
X	mode(0);
X	report_uninit(0);
X	if(no_files)
X		Exitcode = 253;
X	exit(Exitcode ? Exitcode : (skip_count > 127) ? 127 : skip_count);
X	/*NOTREACHED*/
X}
X
X/*+-------------------------------------------------------------------------
X	wcsend(argc,argp) -- send group of files
X--------------------------------------------------------------------------*/
Xwcsend()
X{
X	register n;
X	char *name;
X
X	Crcflg=FALSE;
X	firstsec=TRUE;
X	bytcnt = -1;
X	rewind_file_list();
X	while(get_file_list_name(&name))
X	{
X		Totsecs = 0;
X		if(wcs(name)==ERROR)
X			return(ERROR);
X	}
X	Totsecs = 0;
X	if(Filcnt==0)
X	{	/* bitch if we couldn't open ANY files */
X		send_cancel(1);
X		strcpy(s128,"SEND cannot open any requested files");
X		report_str(s128 + 5,1);
X#if defined(LOG_XFER)
X		ecu_log_event(getppid(),s128);
X#endif
X		sleep(2);		/* allow time for other rz to get ready */
X		no_files = 1;
X		return(ERROR);	/* ... then cancel */
X	}
X	if(Zmodem)
X		saybibi();
X	else if(!Xmodem)
X		wctxpn("");
X	return(OK);
X}
X
X/*+-------------------------------------------------------------------------
X	wcs(oname) -- send a file
X--------------------------------------------------------------------------*/
Xwcs(oname)
Xchar *oname;
X{
Xregister c;
Xregister char *p;
Xstruct stat f;
X
X	strcpy(Pathname,oname);	/* global copy of name */
X
X	if((in=fopen(oname,"r"))==NULL)
X	{
X		sprintf(s128,"SEND %s: %s",sys_errlist[errno],oname);
X#if defined(LOG_XFER)
X		ecu_log_event(getppid(),s128);
X#endif
X		report_str(s128 + 5,1);
X		skip_count++;
X		report_error_count();
X		return(OK);	/* pass over it,there may be others */
X	}
X	++Noeofseen;
X	Lastread = 0;
X	Lastn = -1;
X	Dontread = FALSE;
X	/* Check for directory or block special files */
X	fstat(fileno(in),&f);
X	c = f.st_mode & S_IFMT;
X	if(c == S_IFDIR || c == S_IFBLK)
X	{
X		sprintf(s128,"SEND %s: %s",
X		    (c == S_IFDIR) ? "directory" : "block device",oname);
X		report_str(s128 + 5,1);
X#if defined(LOG_SKIP)
X		ecu_log_event(getppid(),s128);
X#endif
X		skip_count++;
X		report_error_count();
X		fclose(in);
X		return(OK);
X	}
X    f.st_mode &= ~(S_ISUID | S_ISGID);
X	Filcnt++;
X	report_file_send_open(oname,&f);
X	this_file_length = f.st_size;
X	report_send_stats(0L);
X	switch(wctxpn(Pathname))
X	{
X	case ERROR:
X		sprintf(s128,"SEND protocol failure: %s",oname);
X		report_str(s128 + 5,1);
X#if defined(LOG_XFER)
X		ecu_log_event(getppid(),s128);
X#endif
X		skip_count++;
X		report_error_count();
X		report_file_close();
X		fclose(in);
X		return(ERROR);
X	case ZSKIP:
X		report_rcvr_skipped();
X		return(OK);
X	}
X	if(!Zmodem && wctx(f.st_size)==ERROR)
X		return(ERROR);
X	if(Unlinkafter)
X		unlink(oname);
X	return(0);
X}
X
X/*
X * generate and transmit pathname block consisting of
X *  pathname (null terminated),
X *  file length,mode time and file mode in octal
X *  as provided by the Unix fstat call.
X *  N.B.: modifies the passed name,may extend it!
X */
Xwctxpn(name)
Xchar *name;
X{
X	register char *p,*q;
X	char name2[PATHLEN];
X	struct stat f;
X
X	if(Xmodem)
X	{
X		if((in!=stdin) && *name && fstat(fileno(in),&f)!= -1)
X		{
X			TotalToSend = f.st_size;
X			report_protocol_type("XMODEM");
X			report_send_transaction();
X			report_xfer_mode((Ascii) ? "ASCII" : "BINARY");
X			report_last_txhdr("Waiting on NAK",0);
X		}
X		return(OK);
X	}
X	if(!Zmodem)
X	{
X		report_last_txhdr("START PENDING",0);
X		if(getnak())
X		{
X			report_str("Timeout on pathname nak",1);
X			return(ERROR);
X		}
X	}
X
X	q = (char *) 0;
X	if(Dottoslash)
X	{		/* change . to . */
X		for(p=name; *p; ++p)
X		{
X			if(*p == '/')
X				q = p;
X			else if(*p == '.')
X				*(q=p) = '/';
X		}
X		if(q && strlen(++q) > 8)
X		{	/* If name>8 chars */
X			q += 8;			/*   make it .ext */
X			strcpy(name2,q);	/* save excess of name */
X			*q = '.';
X			strcpy(++q,name2);	/* add it back */
X		}
X	}
X
X	for(p=name,q=txbuf ; *p; )
X		if((*q++ = *p++) == '/' && !Fullname)
X			q = txbuf;
X	*q++ = 0;
X	p=q;
X	while(q < (txbuf + 1024))
X		*q++ = 0;
X	if(!Ascii && (in != stdin) && *name && !fstat(fileno(in),&f))
X		sprintf(p,"%lu %lo %o 0 %d %ld",f.st_size,f.st_mtime,
X		    f.st_mode &= ~(S_ISUID | S_ISGID),
X			Filesleft,TotalLeft);
X	report_xfer_mode((Lzconv == ZCNL) ? "ASCII" : "BINARY");
X	TotalLeft -= f.st_size;
X	if(--Filesleft <= 0)
X		TotalLeft = 0;
X	if(TotalLeft < 0)
X		TotalLeft = 0;
X
X	/* force 1k blocks if name won't fit in 128 byte block */
X	if(txbuf[125])
X		blklen=1024;
X	else
X	{		/* A little goodie for IMP/KMD */
X		txbuf[127] = (f.st_size + 127) >>7;
X		txbuf[126] = (f.st_size + 127) >>15;
X	}
X	if(Zmodem)
X		return(zsendfile(txbuf,1+strlen(p)+(p-txbuf)));
X	report_protocol_type("YMODEM");
X	if(wcputsec(txbuf,0,128)==ERROR)
X		return(ERROR);
X	return(OK);
X}
X
Xgetnak()
X{
X	register firstch;
X
X	Lastrx = 0;
X	for(;;)
X	{
X		switch(firstch = readock(50,1))		/* 50 was 800 (80 secs!!) wht */
X		{
X		case ZPAD:
X			if(getzrxinit())
X				return(ERROR);
X			Ascii = 0;	/* Receiver does the conversion */
X			return(FALSE);
X		case TIMEOUT:
X			report_str("Timeout",1);
X			return(TRUE);
X		case WANTG:
X#if defined(MODE2OK)
X			mode(2);	/* Set cbreak,XON/XOFF,etc. */
X#endif
X			Optiong = TRUE;
X			blklen=1024;
X		case WANTCRC:
X			Crcflg = TRUE;
X		case NAK:
X			return(FALSE);
X		case CAN:
X			if((firstch = readock(20,1)) == CAN && Lastrx == CAN)
X				return(TRUE);
X		default:
X			break;
X		}
X		Lastrx = firstch;
X	}
X}
X
X/*+-------------------------------------------------------------------------
X	wctx(flen)
X--------------------------------------------------------------------------*/
Xwctx(flen)
Xlong flen;
X{
Xregister int thisblklen;
Xregister int firstch;
Xregister int sectnum;
Xregister int attempts;
Xlong charssent;
X
X	charssent = 0;
X	firstsec=TRUE;
X	thisblklen = blklen;
X	report_txblklen(blklen);
X
X	attempts = 8;
X	while(((firstch = readock(Rxtimeout,2)) != NAK) &&
X		(firstch  !=  WANTCRC) && (firstch  !=  WANTG) &&
X		(firstch != TIMEOUT) && (firstch != CAN))
X	{
X		if(!--attempts)
X		{
X			report_str("bad start stimulus",1);
X			send_cancel(1);
X			return(ERROR);
X		}
X	}
X
X	if(firstch==CAN)
X	{
X		report_str("receiver CAN",1);
X		return(ERROR);
X	}
X
X	if((firstch==WANTCRC) || (firstch==WANTG))
X		Crcflg=TRUE;
X
X	report_protocol_crc_type((Crcflg)
X			? ((firstch== WANTG) ? "/CRC-g" : "/CRC")
X			: "/CHK");
X
X	sectnum=0;
X	for(;;)
X	{
X		if(flen <= (charssent + 896L))
X		{
X			thisblklen = 128;
X			report_txblklen(thisblklen);
X		}
X		if(!xbuf_build(txbuf,thisblklen))
X			break;
X		if(wcputsec(txbuf,++sectnum,thisblklen)==ERROR)
X			return(ERROR);
X		charssent += thisblklen;
X	}
X
X	/* file transfer completed */
X	report_file_byte_io(this_file_length);
X	report_file_close();
X	fclose(in);
X
X#if defined(LOG_XFER)
X	sprintf(s256,"SEND success: %s",Pathname);
X	ecu_log_event(getppid(),s256);
X#endif
X
X	attempts=0;
X	do
X	{
X		purgeline();
X		sendline(EOT);
X		flushline();
X		report_last_txhdr("EOT",0);
X		++attempts;
X	}	while((firstch=(readock(Rxtimeout,1)) != ACK) && attempts < RETRYMAX);
X	if(attempts == RETRYMAX)
X	{
X		report_str("No ACK on EOT",1);
X		return(ERROR);
X	}
X	else
X		return(OK);
X}
X
Xwcputsec(buf,sectnum,cseclen)
Xchar *buf;
Xint sectnum;
Xint cseclen;	/* data length of this block to send */
X{
X	register int checksum;
X	register int wcj;
X	register unsigned char *cp;
X	unsigned short oldcrc;
X	int firstch;
X	int attempts;
X
X	firstch=0;	/* part of logic to detect CAN CAN */
X
X	sprintf(s128,"Sending block %d",sectnum);
X	report_last_txhdr(s128,0);
X	if(log_packets)
X	{
X		log_packet_buffer(buf,cseclen);
X	}
X
X	for(attempts=0; attempts <= RETRYMAX; attempts++)
X	{
X		Lastrx= firstch;
X		sendline(cseclen == 1024 ? STX : SOH);
X		sendline(sectnum);
X		sendline(-sectnum - 1);
X		oldcrc=checksum=0;
X
X		for(wcj = cseclen,cp = buf; --wcj >= 0; )
X		{
X			sendline(*cp);
X			oldcrc=updcrc(*cp,oldcrc);
X			checksum += *cp++;
X		}
X		if(Crcflg)
X		{
X			oldcrc=updcrc(0,updcrc(0,oldcrc));
X			sendline((int)(oldcrc >> 8));
X			sendline((int)(oldcrc & 0xFF));
X		}
X		else
X			sendline(checksum);
X		flushline();
X
X		if(Optiong)
X		{
X			firstsec = FALSE;
X			return(OK);
X		}
X		firstch = readock(Rxtimeout,(Noeofseen&&sectnum) ? 2:1);
Xgotnak:
X		switch(firstch)
X		{
X		case CAN:
X			if(Lastrx == CAN)
X			{
Xcancan:
X				report_last_rxhdr("CAN",1);
X				return(ERROR);
X			}
X			break;
X		case TIMEOUT:
X			report_last_rxhdr("Timeout",1);
X			continue;
X		case WANTCRC:
X			if(firstsec)
X				Crcflg = TRUE;
X		case NAK:
X			report_last_rxhdr("NAK",1);
X			continue;
X		case ACK:
X			report_last_rxhdr("ACK",0);
X			firstsec=FALSE;
X			Totsecs += (cseclen>>7);
X			return(OK);
X		case ERROR:
X			report_last_rxhdr("Noise",0);
X			break;
X		default:
X			sprintf(s128,"0x%02x ???",firstch);
X			report_last_rxhdr(s128,1);
X			break;
X		}
X		for(;;)
X		{
X			Lastrx = firstch;
X			if((firstch = readock(Rxtimeout,2)) == TIMEOUT)
X				break;
X			if(firstch == NAK || firstch == WANTCRC)
X				goto gotnak;
X			if(firstch == CAN && Lastrx == CAN)
X				goto cancan;
X		}
X	}
X	report_str("retry count exceeded",1);
X	return(ERROR);
X}
X
X/* fill buf with count chars padding with ^Z for CPM */
Xxbuf_build(buf,count)
Xregister char *buf;
X{
Xregister c,m;
Xlong lseek();
Xlong X_txpos = lseek(fileno(in),0L,1);
Xchar diag_str[64];
X
X	report_send_stats(X_txpos);
X	if( !Ascii)
X	{
X		m = read(fileno(in),buf,count);
X		if(log_packets)
X		{
X			sprintf(diag_str,"read rtnd %d of %d",m,count);
X			report_str(diag_str,1);
X		}
X		if(m <= 0)
X			return(0);
X		while(m < count)
X			buf[m++] = 032;
X		return(count);
X	}
X	m=count;
X	if(Lfseen)
X	{
X		*buf++ = 012;
X		--m;
X		Lfseen = 0;
X	}
X	while((c=getc(in))!=EOF)
X	{
X		if(c == 012)
X		{
X			*buf++ = 015;
X			if(--m == 0)
X			{
X				Lfseen = TRUE;
X				break;
X			}
X		}
X		*buf++ =c;
X		if(--m == 0)
X			break;
X	}
X	if(m==count)
X		return(0);
X	else
X		while(--m>=0)
X			*buf++ = CPMEOF;
X	return(count);
X}
X
X/*+-------------------------------------------------------------------------
X	zbuf_build(buf,count) - fill buf with count chars 
X--------------------------------------------------------------------------*/
Xzbuf_build(buf,count)
Xregister char *buf;
Xint count;
X{
Xregister c,m;
X
X	m=count;
X	while((c=getc(in))!=EOF)
X	{
X		*buf++ =c;
X		if(--m == 0)
X			break;
X	}
X	return(count - m);
X}	/* end of zbuf_build */
X
X/*+-------------------------------------------------------------------------
X	SIGALRM_handler()
X--------------------------------------------------------------------------*/
XSIGALRM_handler()
X{
X#if defined(M_SYS5)
X	report_rx_ind(0);
X	report_tx_ind(0);
X#endif
X	longjmp(tohere,-1);
X}	/* end of SIGALRM_handler */
X
X/*+-------------------------------------------------------------------------
X	readock(timeout,count)
Xtimeout is in tenths of seconds reads character(s) from file
Xdescriptor 'fd' read 'count' characters, (1 <= count <= 3) if more than
Xone received, return ERROR unless all are CAN normal response is NAK,
XACK, CAN, G or C
X--------------------------------------------------------------------------*/
Xreadock(timeout,count)
Xint timeout;
Xint count;
X{
X	register int c;
X	static char byt[5];
X
X	if(setjmp(tohere))
X	{
X		report_str("TIMEOUT",1);
X		return(TIMEOUT);
X	}
X	c = timeout/10;
X	if(c<2)
X		c = 2;
X	signal(SIGALRM,SIGALRM_handler);
X	alarm(c);
X#if defined(ONEREAD)
X	c=read(iofd,byt,1);		/* regulus raw read is unique */
X#else
X	c=read(iofd,byt,count);
X#endif
X	rx_char_count += c;
X	alarm(0);
X	if(c<1)
X		return(TIMEOUT);
X	if(c==1)
X		return(byt[0]&0377);
X	else
X		while(c)
X			if(byt[--c] != CAN)
X				return(ERROR);
X	return(CAN);
X}	/* end of readock */
X
X
X/*+-------------------------------------------------------------------------
X	readline(n)
X--------------------------------------------------------------------------*/
Xreadline(n)
Xint n;
X{
X	return(readock(n,1));
X}	/* end of readline */
X
X
X
X/*+-------------------------------------------------------------------------
X	purgeline()
X--------------------------------------------------------------------------*/
Xpurgeline()
X{
X#if defined(M_SYS5)
X	ioctl(iofd,TCFLSH,0);
X#else
X	lseek(iofd,0L,2);
X#endif
X}	/* end of purgeline */
X
X
X/*+-------------------------------------------------------------------------
X	send_cancel(error) - send cancel to remote
X--------------------------------------------------------------------------*/
Xsend_cancel(error)
Xint error;
X{
X	static 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	};
X	register char *cptr = canistr;
X
X	report_last_txhdr("^X CAN",!!error);
X	while(*cptr)
X		sendline(*cptr++);
X	flushline();
X}	/* end of send_cancel */
X
X
X/*+-------------------------------------------------------------------------
X	substr(str,substr) - searches for substr in string str
X--------------------------------------------------------------------------*/
Xchar *
Xsubstr(str,substr)
Xregister char *str,*substr;
X{
Xregister char *sptr;
Xregister char *ssptr;
X
X	for(sptr = str; *str; str++)
X	{
X		if(*str == *substr)
X		{
X			sptr = str;
X			ssptr = substr;
X			while(1)
X			{
X				if(*ssptr == 0)
X					return(str);
X				if(*sptr++ != *ssptr++)
X					break;
X			}
X		}
X	}
X	return(NULL);
X}	/* end of substr */
X
X/*+-------------------------------------------------------------------------
X	usage()
X--------------------------------------------------------------------------*/
Xusage()
X{
X	exit(255);
X}	/* end of usage */
X
X/*+-------------------------------------------------------------------------
X	getzrxinit() - Get the receiver's init parameters
X--------------------------------------------------------------------------*/
Xgetzrxinit()
X{
X	register n;
X	struct stat f;
X
X	for(n=10; --n>=0; )
X	{
X		switch(zgethdr(Rxhdr,1))
X		{
X		case ZCHALLENGE:	/* Echo receiver's challenge numbr */
X			stohdr(Rxpos);
X			zshhdr(ZACK,Txhdr);
X			continue;
X		case ZCOMMAND:		/* They didn't see out ZRQINIT */
X			stohdr(0L);
X			zshhdr(ZRQINIT,Txhdr);
X			continue;
X		case ZRINIT:
X			Rxflags = 0377 & Rxhdr[ZF0];
X			Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
X			report_protocol_type("ZMODEM");
X			report_protocol_crc_type((Txfcs32) ? "/CRC32" : "/CRC16");
X			Zctlesc |= Rxflags & TESCCTL;
X			Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
X			if( !(Rxflags & CANFDX))
X				Txwindow = 0;
X#if defined(MODE2OK)
X			mode(2);	/* Set cbreak,XON/XOFF,etc. */
X#endif
X#if !defined(READCHECK)
X#if !defined(M_SYS5)
X			/* Use 1024 byte frames if no sample/interrupt */
X			if(Rxbuflen < 32 || Rxbuflen > 1024)
X			{
X				Rxbuflen = 1024;
X			}
X#endif
X#endif
X			/* Override to force shorter frame length */
X			if(Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
X				Rxbuflen = Tframlen;
X			if( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
X				Rxbuflen = Tframlen;
X
X			/* If using a pipe for testing set lower buf len */
X			fstat(iofd,&f);
X			if((f.st_mode & S_IFMT) != S_IFCHR
X			    && (Rxbuflen == 0 || Rxbuflen > 4096))
X				Rxbuflen = 4096;
X			sprintf(s128,"Remote: CRC32 %c  duplex %c",
X			    (Rxflags & CANFC32) ? 'y' : 'n',
X			    (Rxflags & CANFDX)  ? 'y' : 'n');
X			if(Rxbuflen)
X				sprintf(&s128[strlen(s128)],"  buflen %u",Rxbuflen);
X			else
X				strcat(s128,"  continuous stream y");
X			report_str(s128,2);
X			/*
X			 * If input is not a regular file,force ACK's each 1024
X			 *  (A smarter strategey could be used here ...)
X			 */
X			if( !Command)
X			{
X				fstat(fileno(in),&f);
X				if(((f.st_mode & S_IFMT) != S_IFREG)
X				    && (Rxbuflen == 0 || Rxbuflen > 1024))
X					Rxbuflen = 1024;
X			}
X
X			if(Baudrate > 300)	/* Set initial subpacket len */
X				blklen = 256;
X			if(Baudrate > 1200)
X				blklen = 512;
X			if(Baudrate >= 2400)	/* original code had > 2400 here ****/
X				blklen = 1024;
X			if(Rxbuflen && blklen>Rxbuflen)
X				blklen = Rxbuflen;
X			if(blkopt && blklen > blkopt)
X				blklen = blkopt;
X			blklen_original = blklen;
X			report_txblklen(blklen);
X			return(sendzsinit());
X		case ZCAN:
X		case TIMEOUT:
X			return(ERROR);
X		case ZRQINIT:
X			if(Rxhdr[ZF0] == ZCOMMAND)
X				continue;
X		default:
X			zshhdr(ZNAK,Txhdr);
X			continue;
X		}
X	}
X	return(ERROR);
X}	/* end of getzrxinit */
X
X
X/*+-------------------------------------------------------------------------
X	sendzsinit() - send send-init information
X--------------------------------------------------------------------------*/
Xsendzsinit()
X{
X	register c;
X
X	if(Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
X		return(OK);
X	errors = 0;
X	for(;;)
X	{
X		stohdr(0L);
X		if(Zctlesc)
X		{
X			Txhdr[ZF0] |= TESCCTL;
X			zshhdr(ZSINIT,Txhdr);
X		}
X		else
X			zsbhdr(ZSINIT,Txhdr);
X		zsdata(Myattn,1+strlen(Myattn),ZCRCW);
X		c = zgethdr(Rxhdr,1);
X		switch(c)
X		{
X		case ZCAN:
X			return(ERROR);
X		case ZACK:
X			return(OK);
X		default:
X			if(++errors > 19)
X				return(ERROR);
X			continue;
X		}
X	}
X}	/* end of sendzsinit */
X
X/*+-------------------------------------------------------------------------
X	zsendfile(buf,blen) - send file name & info
X--------------------------------------------------------------------------*/
Xzsendfile(buf,blen)
Xchar *buf;
Xint blen;
X{
X	register c;
X
X	for(;;)
X	{
X		blklen = blklen_original;
X		report_txblklen(blklen);
X		Txhdr[ZF0] = Lzconv;	/* file conversion request */
X		Txhdr[ZF1] = Lzmanag;	/* file management request */
X		Txhdr[ZF2] = Lztrans;	/* file transport request */
X		Txhdr[ZF3] = 0;
X		zsbhdr(ZFILE,Txhdr);
X		zsdata(buf,blen,ZCRCW);
Xagain:
X		c = zgethdr(Rxhdr,1);
X		switch(c)
X		{
X		case ZRINIT:
X			while((c = readline(50)) > 0)
X				if(c == ZPAD)
X				{
X					goto again;
X				}
X			/* **** FALL THRU TO **** */
X		default:
X			continue;
X		case ZCAN:
X		case TIMEOUT:
X		case ZABORT:
X		case ZFIN:
X			return(ERROR);
X		case ZSKIP:
X			report_file_close();
X			fclose(in);
X			return(c);
X		case ZRPOS:
X			/*
X			 * Suppress zcrcw request otherwise triggered by
X			 * lastyunc==bytcnt
X			 */
X			Lastsync = (bytcnt = Txpos = Rxpos) -1;
X			fseek(in,Rxpos,0);
X			Dontread = FALSE;
X			report_send_stats(Txpos);
X			return(zsendfdata());
X		}
X	}
X}	/* end of zsendfile */
X
X/*+-------------------------------------------------------------------------
X	zsendfdata() - send data in the file
X--------------------------------------------------------------------------*/
Xzsendfdata()
X{
Xregister c,e,n;
Xregister newcnt;
Xregister long tcount = 0;
Xint junkcount;		/* Counts garbage chars received by TX */
Xstatic int tleft = 6;	/* Counter for test mode */
Xint err;
X
X	Lrxpos = 0;
X	junkcount = 0;
X	SameZrposAgain = FALSE;		/* variable was named Beenhereb4 (wht) */
X	this_file_frame_count = 0;	/* we've sent no frames (wht) */
Xsomemore:
X	if(setjmp(intrjmp))
X	{
Xwaitack:
X		junkcount = 0;
X		c = getinsync(0);
Xgotack:
X		switch(c)
X		{
X		default:
X		case ZCAN:
X			report_rcvr_cancelled("zfdata-1");
X			report_file_close();
X			fclose(in);
X			return(ERROR);
X		case ZSKIP:
X			report_file_close();
X			fclose(in);
X			return(c);
X		case ZACK:
X		case ZRPOS:
X			break;
X		case ZRINIT:
X			return(OK);
X		}
X#if defined(READCHECK)
X		/*
X		 * If the reverse channel can be tested for data,
X		 *  this logic may be used to detect error packets
X		 *  sent by the receiver,in place of setjmp/longjmp
X		 *  rdchk(fdes) returns non 0 if a character is available
X		 */
X		while(rdchk(iofd))
X		{
X			switch(readline(1))
X			{
X			case CAN:
X			case ZPAD:
X				c = getinsync(1);
X				goto gotack;
X			case XOFF:		/* Wait a while for an XON */
X			case XOFF|0200:
X				readline(100);
X			}
X		}
X#endif
X	}
X
X	newcnt = Rxbuflen;
X	Txwcnt = 0;
X	stohdr(Txpos);
X	zsbhdr(ZDATA,Txhdr);
X
X	do
X	{
X		if(Dontread)
X		{
X			n = Lastn;
X		} else
X		{
X			n = zbuf_build(txbuf,blklen);
X			Lastread = Txpos;
X			Lastn = n;
X		}
X		Dontread = FALSE;
X		if(n < blklen)
X			e = ZCRCE;
X		else if(junkcount > 3)
X			e = ZCRCW;
X		else if(bytcnt == Lastsync)
X			e = ZCRCW;
X		else if(Rxbuflen && (newcnt -= n) <= 0)
X			e = ZCRCW;
X		else if(Txwindow && (Txwcnt += n) >= Txwspac)
X		{
X			Txwcnt = 0;
X			e = ZCRCQ;
X		}
X		else
X			e = ZCRCG;
X		zsdata(txbuf,n,e);
X		this_file_frame_count++;		/* wht */
X		if(bad_condx_blklen)			/* wht */
X		{
X			/* if we have sent four frames since last ZRPOS to same pos (wht)*/
X			if((this_file_frame_count - bad_condx_frame_count) > 4) /*wht*/
X			{
X				if(blklen == bad_condx_blklen)
X					bad_condx_blklen = 0;
X				else
X				{
X					blklen *= 2;
X					report_txblklen(blklen);
X				}
X				SameZrposAgain = 0;
X			}
X		}
X		bytcnt = Txpos += n;
X		report_send_stats(Txpos);
X		if(e == ZCRCW)
X			goto waitack;
X#if defined(READCHECK)
X		/*
X		 * If the reverse channel can be tested for data,
X		 *  this logic may be used to detect error packets
X		 *  sent by the receiver,in place of setjmp/longjmp
X		 *  rdchk(fdes) returns non 0 if a character is available
X		 */
X		while(rdchk(iofd))
X		{
X			switch(readline(1))
X			{
X			case CAN:
X			case ZPAD:
X				c = getinsync(1);
X				if(c == ZACK)
X					break;
X#if defined(TCFLSH)
X				ioctl(iofd,TCFLSH,1);
X#endif
X				/* zcrce - dinna wanna starta ping-pong game */
X				zsdata(txbuf,0,ZCRCE);
X				goto gotack;
X
X			case XOFF:		/* Wait a while for an XON */
X			case XOFF|0200:
X				readline(100);
X
X			default:
X				++junkcount;
X			}
X		}
X#endif	/* READCHECK */
X		if(Txwindow)
X		{
X			while((tcount = Txpos - Lrxpos) >= Txwindow)
X			{
X				if(e != ZCRCQ)
X					zsdata(txbuf,0,e = ZCRCQ);
X				c = getinsync(1);
X				if(c != ZACK)
X				{
X#if defined(TCFLSH)
X					ioctl(iofd,TCFLSH,1);
X#endif
X					zsdata(txbuf,0,ZCRCE);
X					goto gotack;
X				}
X			}
X		}
X	} while(n == blklen);
X
X	for(;;)
X	{
X		stohdr(Txpos);
X		zsbhdr(ZEOF,Txhdr);
X		switch(err = getinsync(0))
X		{
X		case ZACK:
X			continue;
X		case ZRPOS:
X			goto somemore;
X		case ZRINIT:
X			return(OK);
X		case ZSKIP:
X			report_file_close();
X			fclose(in);
X			return(c);
X		default:
X			sprintf(s128,"SEND protocol sync error 0x%04x: %s",err,Pathname);
X			ecu_log_event(getppid(),s128);	/* always log this */
X			report_str(s128 + 5,1);
X			skip_count++;
X			report_error_count();
X			report_file_byte_io(this_file_length);
X			report_file_close();
X			fclose(in);
X			return(ERROR);
X		}
X	}
X}	/* end of zsendfdata */
X
X/*+-------------------------------------------------------------------------
X	getinsync(flag) - get back in sync with receiver
X--------------------------------------------------------------------------*/
Xgetinsync(flag)
X{
X	register c;
X
X	for(;;)
X	{
X		switch(c = zgethdr(Rxhdr,0))
X		{
X		case ZCAN:
X		case ZABORT:
X		case ZFIN:
X		case TIMEOUT:
X			sprintf(s128,"Receiver %s",frametypes[c+FTOFFSET]);
X			report_str(s128,1);
X			return(ERROR);
X		case ZRPOS:
X			report_str("Receiver ZRPOS",1);
X			/* ************************************* */
X			/*  If sending to a modem buffer,you     */
X			/*   might send a break at this point to */
X			/*   dump the modem's buffer.            */
X			/* ************************************* */
X			if(Lastn >= 0 && Lastread == Rxpos)
X			{
X				Dontread = TRUE;
X			} else
X			{
X				clearerr(in);	/* In case file EOF seen */
X				fseek(in,Rxpos,0);
X			}
X			bytcnt = Lrxpos = Txpos = Rxpos;
X			if(Lastsync == Rxpos)					/* wht - original code */
X			{										/* wht - original code */
X				/* save frame count at time of each occurrence (wht) */
X				bad_condx_frame_count = this_file_frame_count;	/* wht */
X				/* save block length at time of error (wht) */
X				if(++SameZrposAgain > 4)			/* wht - original code */
X				{									/* wht */
X					if(bad_condx_blklen == 0)		/* wht */
X						bad_condx_blklen = blklen;	/* wht */
X					if(blklen > 256)				/* wht - 32->256 */
X					{
X						blklen /= 2;				/* wht - original code */
X						report_txblklen(blklen);
X					}
X				}									/* wht */
X			}										/* wht - original code */
X			Lastsync = Rxpos;
X			report_send_stats(Txpos);
X			return(c);
X		case ZACK:
X			report_str("",-1);
X			Lrxpos = Rxpos;
X			if(flag || Txpos == Rxpos)
X				return(ZACK);
X			continue;
X
X		case ZRINIT:
X			report_str("",-1);
X#if defined(LOG_XFER)
X			sprintf(s256,"SEND success: %s",Pathname);
X			ecu_log_event(getppid(),s256);
X#endif
X		case ZSKIP:
X			report_file_byte_io(this_file_length);
X			report_file_close();
X			fclose(in);
X			return(c);
X		case ERROR:
X		default:
X			report_str("Sending ZNAK",0);
X			zsbhdr(ZNAK,Txhdr);
X			continue;
X		}
X	}
X}	/* end of getinsync */
X
X/*+-------------------------------------------------------------------------
X	saybibi() - Say "bibi" to the receiver, try to do it cleanly
X--------------------------------------------------------------------------*/
Xsaybibi()
X{
X	for(;;)
X	{
X		stohdr(0L);		/* CAF Was zsbhdr - minor change */
X		zshhdr(ZFIN,Txhdr);	/*  to make debugging easier */
X		switch(zgethdr(Rxhdr,0))
X		{
X		case ZFIN:
X			sendline('O');
X			sendline('O');
X			flushline();
X		case ZCAN:
X		case TIMEOUT:
X			return;
X		}
X	}
X}	/* end of saybibi */
X
X/*+-------------------------------------------------------------------------
X	determine_transaction_time()
X--------------------------------------------------------------------------*/
Xdetermine_transaction_time()
X{
Xregister c;
Xstruct stat f;
Xchar *name;
X
X	rewind_file_list();
X	TotalLeft = 0;
X	Filesleft = 0;
X	while(get_file_list_name(&name))
X	{
X		f.st_size = -1;
X		if((access(name,04) >= 0) && (stat(name,&f) >= 0))
X		{
X			c = f.st_mode & S_IFMT;
X			if(c != S_IFDIR && c != S_IFBLK)
X			{
X				++Filesleft;
X				TotalLeft += f.st_size;
X			}
X		}
X	}
X	FilesTotal = Filesleft;
X	rewind_file_list();
X}	/* end of determine_transaction_time */
X
X/* vi: set tabstop=4 shiftwidth=4: */
X/* end of ecusz.c */
SHAR_EOF
$TOUCH -am 1220170590 'z/ecusz.c' &&
chmod 0644 z/ecusz.c ||
echo 'restore of z/ecusz.c failed'
Wc_c="`wc -c < 'z/ecusz.c'`"
test 41872 -eq "$Wc_c" ||
	echo 'z/ecusz.c: original size 41872, current size' "$Wc_c"
true || echo 'restore of z/zcommon.c failed'
echo End of part 20, continue with part 21
exit 0
--------------------------------------------------------------------
Warren Tucker, TuckerWare emory!n4hgf!wht or wht@n4hgf.Mt-Park.GA.US
Hacker Extraordinaire  d' async PADs,  pods,  proteins and protocols

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.