[alt.sources] ecu - SCO XENIX V/{2,3}86 Extended CU part 25/47

wht@tridom.uucp (Warren Tucker) (10/10/89)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 25 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file z/ecurz.c continued
#
CurArch=25
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
echo "x - Continuing file z/ecurz.c"
sed 's/^X//' << 'SHAR_EOF' >> z/ecurz.c
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)
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			return(ERROR);
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#ifndef bad_problem
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#else
Xint rtnv;
X
X	if(--Lleft >= 0)
X	{
X		rtnv = *cdq++;
X		goto LOG_AND_RETURN;
X	}
X
X	n = timeout/10;
X	if(n < 2)
X		n = 3;
X	if(setjmp(tohere))
X	{
X		Lleft = 0;
X		rtnv = *cdq++;
X		goto LOG_AND_RETURN;
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	{
X		rtnv = TIMEOUT;
X		goto LOG_AND_RETURN;
X	}
X	--Lleft;
X	rtnv = *cdq++;
X
XLOG_AND_RETURN:
X	if(log_packets)
X	{
X		sprintf(s128,"rl: l=%3d ch=%x\n",Lleft,rtnv);
X		write(log_packets,s128,strlen(s128));
X	}
X	return(rtnv);
X
X#endif
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{
X	int cpid,status;
X	struct 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))
X		{	/* Try to create it as a dir */
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
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	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#ifdef LOG_XFER
X					ecu_log_event(s128);
X#endif
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#ifdef LOG_XFER
X			ecu_log_event(s128);
X#endif
X			return(ERROR);
X		}
X
X		if(Filemode & UNIXFILE)
X			++Thisbinary;
X		++Filcnt;
X		if(Bytesleft != DEFBYTL)
X			report_file_rcv_started( name,Bytesleft,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		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	}
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 defined(LOG_XFER)
X	sprintf(s256,"RECEIVE success: %s",Pathname);
X	ecu_log_event(s256);
X#endif
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) - execute 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;
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	{
SHAR_EOF
echo "End of part 25"
echo "File z/ecurz.c is continued in part 26"
echo "26" > s2_seq_.tmp
exit 0
-- 
-------------------------------------------------------------------
Warren Tucker, Tridom Corporation       ...!gatech!emory!tridom!wht 
Ker-au'-lo-phon.  An 8-foot partial flue-stop, having metal pipes
surmounted by adjustable rings, and with a hole bored near the top
of each pipe, producing a soft and "reedy" tone.