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

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

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

---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is part 23 of ecu3
if touch 2>&1 | fgrep 'amc' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= sea/ecusea.c ==============
if test ! -d 'sea'; then
    echo 'x - creating directory sea'
    mkdir 'sea'
fi
echo 'x - extracting sea/ecusea.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'sea/ecusea.c' &&
X
Xchar *revision = "1.10";	/* cannot be longer than 7 chars (blk0.sender) */
X
X/* #define TABLE_CRC16 */
X#ifdef M_XENIX
X#define NO_SELECT
X#endif
X
X/*+-------------------------------------------------------------------------
X	ecusea.c - SEAlink - Sliding window file transfer protocol
X
X  Defined functions:
X	arg_token(parsestr,termchars)
X	cancel_transaction(sig)
X	crc_update(c,crc)
X	fname_split(cmd,arg,arg_max_quan,narg_rtn)
X	fname_too_long(fname)
X	fname_truncated()
X	getspeed(code)
X	lgetc_timeout(tenths)
X	lgetc_timeout_SIGALRM()
X	main(argc,argv,envp)
X	receive_block(buf)
X	receive_file()
X	send_comm_block(blk,blknum)
X	send_file(name)
X	send_file_block(fp,blknum)
X	set_sf_state(place,new_state)
X	set_utime_1980(filename,secs_since_1980)
X	sf_state_text(state)
X	wait_for_rcvr_response()
X	xmit_ack(blknum)
X	xmit_cancel()
X	xmit_nak(blknum)
X
Xecu adaptation by W. Tucker
Xmodelled after MSDOS sealink.c, which carried the following proviso:
X
X              MS-DOS Version 1.20, created on 08/05/87
X              at 17:51:40 (C) COPYRIGHT 1986,87 by
X              System Enhancement Associates; ALL RIGHTS
X              RESERVED By: Thom Henderson
X
X              You are granted a license to use this
X              code in your programs, and to adapt it to
X              your particular situation and needs,
X              subject only to the following conditions:
X              1) You must refer to it as the SEAlink
X              protocol, and you must give credit to
X              System Enhancement Associates.  2) If you
X              modify it in such a way that your version
X              cannot converse with the original code as
X              supplied by us, then you should refer to
X              it as "SEAlink derived", or as a
X              "variation of SEAlink", or words to that
X              effect.  In short, we're not asking for
X              any money, but we'd like to get some
X              credit for our work.
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
X
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <fcntl.h>
X#include <termio.h>
X#include <sys/ioctl.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <time.h>
X#include <sys/timeb.h>
X#include <memory.h>
X#if !defined(NO_SELECT)
X#include <sys/select.h>
X#endif
X
X#include "lint_args.h"
X
X/* Various system constants */
X#define WINDOW		6					/* maximum size of window */
X#define TIMEOUT	0x0FFF
X#define OFFSET_1980	(time_t)315547200	/* time offset for 1970 <-> 1980 */
X
X/*
X * The section of code that is compiled when NAKEOT is defined is in the
X * original MS-DOS version 1.16 routine.  Its purpose is to send a NAK when
X * an EOT is received during receive_file(), apparently to confirm that this is
X * indeed the end of file.  However, in certain (apparently non - standard)
X * versions of the protocol, it is possible that the program will report an
X * error when in fact there isn't one.  Comment this out at your discretion.
X */
X#define NAKEOT
X
X/* SEAlink block zero data structure */
Xtypedef struct blk0
X{
X	long length;			/* length */
X	time_t secs_since_1980;	/* creation/last mod in secs since 1/1/80 */
X	char filename[17];		/* file name */
X	char sender[15];		/* sending program */
X	char send_no_acks;		/* true if rcvr need not ack */
X	char filler[87];		/* fill to 128 bytes */
X}	BLK0;
X
X/* protocol characters */
X#define SOH	0x01
X#define EOT	0x04
X#define ACK	0x06
X#define NAK	0x15
X#define CAN	0x18
X
X/*  send_file state (sf_state) values */
X#define SFS_GND		0	/* Ground state, ACK or NAK expected */
X#define SFS_ACK		1	/* ACK received */
X#define SFS_NAK		2	/* NAK received */
X#define SFS_ACKW	3	/* ACK, block# received */
X#define SFS_NAKW	4	/* NAK, block# received */
X#define SFS_RGND	5	/* Returning to ground state */
Xint sf_state;
X
Xint allow_slide = 1;	/* sliding windows allowed */
Xint crc_in_use;			/* check type, 1 = CRC, 0 = checksum */
Xchar *dfile = "/tmp/ecuSEA.log";
Xint error_count = 0;	/* total number of errors */
Xint iofd = 0;			/* file descriptor to use */
Xint no_ack_mode = 1;	/* true of ACKs not required */
Xint rf_done = 0;		/* receive file done */
Xint sf_ackw_count;		/* count of sliding ACKs seen */
Xint sf_ackblk;			/* number of last block ACKed */
Xint sf_blknum;			/* number of next block to send */
Xint sf_lastnum;			/* number of last block sent */
Xint sf_nakquan;			/* number of sequential NAKs */
Xint sf_slide;			/* true if sliding window */
X
Xint sending_flag = -1;		/* send == 1, receive == 0, bad usage == -1 */
Xint log_packets = 0;
Xlong rx_char_count = 0;
Xlong tx_char_count = 0;
Xint Filcnt = 0;
Xint npaths = 0;
Xchar curr_dir[256];
Xchar s128[128];
Xunsigned baud_rate;
Xint exit_code;
Xint sent_EOT = 0;
X
Xstruct termio tio;
Xstruct termio tio0;
X
Xjmp_buf	lgetc_timeout_setjmp;
X
X/* CRC16 routine; finish CRC calculation for compare */
X
X#ifdef TABLE_CRC16
X
X/* crctab calculated by Mark G. Mendel,Network Systems Corporation */
Xunsigned short crctab[256] = 
X{
X	0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
X	0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
X	0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
X	0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
X	0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
X	0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
X	0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
X	0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
X	0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
X	0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
X	0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
X	0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
X	0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
X	0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
X	0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
X	0xFF9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
X	0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
X	0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
X	0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
X	0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
X	0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
X	0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
X	0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
X	0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
X	0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
X	0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
X	0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
X	0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
X	0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
X	0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
X	0xef1f,0xFF3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
X	0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
X};
X
X/*+-------------------------------------------------------------------------
X  updcrc macro derived from article Copyright (C) 1986 Stephen Satchell. 
X  NOTE: First argument must be in range 0 to 255.
X        Second argument is referenced twice.
X  Programmers may incorporate any or all code into their programs, giving
X  proper credit within the source.  Publication of the source routines is
X  permitted so long as proper credit is given to Stephen Satchell,
X  Satchell Evaluations and Chuck Forsberg, Omen Technology.
X--------------------------------------------------------------------------*/
X#define crc_update(ch,crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ ch)
X
X#else /* calculated crc */
X
X/*+-------------------------------------------------------------------------
X	crc_update(c,crc)
X--------------------------------------------------------------------------*/
Xunsigned short
Xcrc_update(c,crc)
Xregister c;
Xregister unsigned crc;
X{
Xregister count;
X
X	for(count = 8; --count >= 0;)
X	{
X		if(crc & 0x8000)
X		{
X			crc <<= 1;
X			crc += (((c <<= 1) & 0400) != 0);
X			crc ^= 0x1021;
X		}
X		else 
X		{
X			crc <<= 1;
X			crc += (((c <<= 1) & 0400) != 0);
X		}
X	}
X	return(crc);
X}	/* end of crc_update */
X#endif /* crc calc selection */
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	xmit_cancel()
X--------------------------------------------------------------------------*/
Xvoid
Xxmit_cancel()
X{
Xchar *cancel_msg = "\030\030\030\030\030\030\030\030\b\b\b\b\b\b\b\b";
X
X	ioctl(iofd,TCFLSH,(char *)1);
X	write(iofd,cancel_msg,16);
X	tx_char_count += 16;
X	report_str("CANCELling transfer",1);
X	report_last_txhdr("CAN",0);
X
X}	/* end of xmit_cancel */
X
X/*+-------------------------------------------------------------------------
X	xmit_ack(blknum)
X--------------------------------------------------------------------------*/
Xvoid
Xxmit_ack(blknum)
Xregister int blknum;			/* block number */
X{
Xchar s16[16];
X
X	sprintf(s16,"ACK %3d",blknum);
X	report_last_txhdr(s16,0);
X
X	s16[0] = ACK;
X	s16[1] = blknum;			/* block number */
X	s16[2] = blknum ^ 0xFF;	/* block number check */
X	write(iofd,s16,3);
X	tx_char_count += 3;
X}	/* end of xmit_ack */
X
X/*+-------------------------------------------------------------------------
X	xmit_nak(blknum)
X--------------------------------------------------------------------------*/
Xvoid
Xxmit_nak(blknum)
Xregister int blknum;			/* block number */
X{
Xchar s16[16];
X
X	sprintf(s16,"NAK %d",blknum);
X	report_last_txhdr(s16,1);
X
X	if(crc_in_use)
X		s16[0] = 'C';
X	else
X		s16[0] = NAK;
X
X	s16[1] = blknum;			/* block number */
X	s16[2] = blknum ^ 0xFF;	/* block number check */
X	write(iofd,s16,3);
X	tx_char_count += 3;
X
X}	/* end of xmit_nak */
X
X/*+-------------------------------------------------------------------------
X	lgetc_timeout_SIGALRM() - called when alarm is caught by lgetc_timeout
X--------------------------------------------------------------------------*/
X#if defined(NO_SELECT)
Xvoid
Xlgetc_timeout_SIGALRM()
X{
X	longjmp(lgetc_timeout_setjmp,TIMEOUT);
X}	/* end of lgetc_timeout_SIGALRM */
X#endif
X
X/*+-------------------------------------------------------------------------
X	lgetc_timeout(tenths)
X
X reads one character from line unless timeout in tenths passes
X with no receipt.
X--------------------------------------------------------------------------*/
Xunsigned int
Xlgetc_timeout(tenths)
Xint tenths;
X{
X#if defined(NO_SELECT)
Xunsigned char rdchar;
Xlong msec;
Xint seconds;
Xlong nap(long);
X#else
Xint fdmask;
Xstruct timeval tval;
Xunsigned char rdchar;
X#endif
X
X	if(!tenths)
X	{
X		if(!rdchk(iofd))
X			return(TIMEOUT);
X		else
X		{
X			read(iofd,&rdchar,1);
X			rx_char_count++;
X			return((unsigned int)rdchar);
X		}
X	}
X
X#if defined(NO_SELECT)
X
X/* there is a timeout ... if less than 2 secs, nap it out */
X	if(tenths <= 20)
X	{
X		msec = (tenths < 6) ? 60L : (long)tenths * 10;
X		while(msec)
X		{
X			msec -= nap(20L);
X			if(rdchk(iofd))
X			{
X				read(iofd,&rdchar,1);
X				rx_char_count++;
X				return((unsigned int)rdchar);
X			}
X		}
X		report_last_rxhdr("TIMEOUT",0);
X		return(TIMEOUT);
X	}
X
X/* timeout is > 2 seconds use sleep */
X
X	seconds = (tenths / 10) + 1;
X
X	if(setjmp(lgetc_timeout_setjmp))
X	{
X		report_last_rxhdr("TIMEOUT",0);
X		return(TIMEOUT);
X	}
X
X	signal(SIGALRM,lgetc_timeout_SIGALRM);
X	alarm(seconds);
X	while(read(iofd,&rdchar,1) != 1)
X		;
X	alarm(0);
X	signal(SIGALRM,SIG_DFL);
X
X#else
X
X	if(tenths < 6)
X		tenths = 6;
X	tval.tv_sec = tenths / 10L;
X	tval.tv_usec = (tenths % 10L) * 100000L;
X	fdmask = 1 << iofd;
X	if(select(32,&fdmask,(int *)0,(int *)0,&tval) != 1)
X	{
X		report_last_rxhdr("TIMEOUT",0);
X		return(TIMEOUT);
X	}
X	if((!rdchk(iofd)) || (read(iofd,&rdchar,1) < 0))
X	{
X		report_last_rxhdr("TIMEOUT",0);
X		return(TIMEOUT);
X	}
X
X#endif
X
X	rx_char_count++;
X	return((unsigned int)rdchar);
X
X}	/* end of lgetc_timeout */
X
X/*+-------------------------------------------------------------------------
X	sf_state_text(state)
X--------------------------------------------------------------------------*/
Xchar *
Xsf_state_text(state)
Xregister state;
X{
Xchar unrecog[16];
X
X	switch(state)
X	{
X		case SFS_GND:	return("GND");
X		case SFS_ACK:	return("ACK");
X		case SFS_NAK:	return("NAK");
X		case SFS_ACKW:	return("ACKW");
X		case SFS_NAKW:	return("NAKW");
X		case SFS_RGND:	return("RGND");
X		default:
X			sprintf(unrecog,"SFS_%d",state);
X			return(unrecog);
X	}
X
X}	/* end of sf_state_text */
X
X/*+-------------------------------------------------------------------------
X	set_sf_state(place,new_state)
X--------------------------------------------------------------------------*/
Xvoid
Xset_sf_state(place,new_state)
Xint place;
Xint new_state;
X{
X	if(log_packets)
X	{
X		sprintf(s128,"state from %s to %s (%d)",
X			sf_state_text(sf_state),sf_state_text(new_state),place);
X		report_str(s128,0);
X	}
X	sf_state = new_state;
X}	/* end of set_sf_state */
X
X/*+-------------------------------------------------------------------------
X	wait_for_rcvr_response() - check for ACK or NAK
X sets 'sf_state' to SFS_... value depending on response from file rcvr
X returns 1 if TIMEOUT at state other than ground, else 0
X--------------------------------------------------------------------------*/
Xint
Xwait_for_rcvr_response()
X{
Xint c;						/* one byte of data */
Xstatic int rawblk = 0;		/* raw block number */
X
X	while((c = lgetc_timeout((sf_state == SFS_GND) ? 0 : 6)) != TIMEOUT)
X	{
X		if(c == CAN)
X		{									/* CANcel received? */
X			if((c = lgetc_timeout(20)) == CAN)
X			{
X				sf_nakquan = 11;
X				report_last_rxhdr("CAN",0);	/* error counted at cancel time */
X			}
X			break;
X		}
X		if(sf_state == SFS_ACKW || sf_state == SFS_NAKW)	/* windowed */
X		{
X			sf_slide = 0;						/* assume this will fail */
X			/* see if we believe the number */
X			if(rawblk == (c ^ 0xFF))
X			{
X				rawblk = sf_blknum - ((sf_blknum - rawblk) & 0xFF);
X				if((rawblk >= 0) && (rawblk <= sf_blknum) &&
X					(rawblk > (sf_blknum - 128)))
X				{				/* we have sliding window! */
X					if(sf_state == SFS_ACKW)
X					{
X						sf_ackblk = (sf_ackblk > rawblk) ? sf_ackblk : rawblk;
X						sf_slide = 1;
X						if(no_ack_mode && (++sf_ackw_count > 10))
X						{
X							no_ack_mode = 0;
X							report_str("Overdrive disengaged",0);
X						}
X					}
X					else 
X					{
X						sf_blknum = (rawblk < 0) ? 0 : rawblk;
X						sf_slide = (sf_nakquan < 4);
X					}
X					sprintf(s128,"%s %5d",
X						(sf_state == SFS_ACKW) ? "ACKW" : "NAKW",rawblk);
X					report_last_rxhdr(s128,(sf_state != SFS_ACKW) && rawblk);
X				}
X			}
X			set_sf_state(1,SFS_RGND);	/* return to ground state */
X		}
X
X		if(sf_state == SFS_ACK || sf_state == SFS_NAK)
X		{
X			rawblk = c;
X			if(sf_state == SFS_ACK)
X				set_sf_state(2,SFS_ACKW);
X			else
X				set_sf_state(3,SFS_NAKW);
X		}
X
X		if(!sf_slide || sf_state == SFS_GND)
X		{
X			if(c == ACK)
X			{
X				if(!sf_slide)
X				{
X					sprintf(s128,"ACK %3d",sf_ackblk);
X					report_last_rxhdr(s128,0);
X					sf_ackblk++;
X				}
X				set_sf_state(4,SFS_ACK);
X				sf_nakquan = 0;
X			}
X			else if(c == 'C' || c == NAK)
X			{
X				/* if method not determined yet */
X				if(crc_in_use > 1)	/* then do what rcvr wants */
X				{
X					crc_in_use = (c == 'C');
X					report_protocol_crc_type(crc_in_use ? "/CRC16" : "/CHK");
X				}
X				ioctl(iofd,TCFLSH,(char *)1);
X				if(!sf_slide)
X				{
X					sf_blknum = sf_ackblk + 1;
X					sprintf(s128,"NAK %3d",sf_blknum);
X					report_last_rxhdr(s128,(!!sf_blknum));
X				}
X				set_sf_state(5,SFS_NAK);
X				sf_nakquan++;
X				if(sf_lastnum)
X					error_count++;
X			}
X		}
X
X		if(sf_state == SFS_RGND)
X			set_sf_state(6,SFS_GND);
X	}
X	return((sf_state != SFS_GND) && (c == TIMEOUT));
X}	/* end of wait_for_rcvr_response */
X
X/*+-------------------------------------------------------------------------
X	send_comm_block(blk,blknum) - format and transmit block
X--------------------------------------------------------------------------*/
Xint
Xsend_comm_block(blk,blknum)
Xchar *blk;				/* data to be shipped */
Xint blknum;				/* number of block */
X{
Xregister unsigned short rUINT16 = 0;
Xregister int itmp;
Xunsigned char chksum;
Xchar *cptr = blk;
Xchar s3[3];
X
X	s3[0] = SOH;				/* block header */
X	s3[1] = blknum;				/* block number */
X	s3[2] = blknum ^ 0xFF;		/* block number check value */
X
X/* calculate the crc or checksum */
X	itmp = 128;
X	if(crc_in_use)
X	{
X		while(itmp--)
X		{
X			rUINT16 = crc_update(*cptr,rUINT16);
X			cptr++;
X		}
X		rUINT16 = crc_update(0,rUINT16);
X		rUINT16 = crc_update(0,rUINT16);
X	}
X	else 
X	{
X		while(itmp--)
X			rUINT16 += *cptr++;
X	}
X
X/* write the block */
X
X	write(iofd,s3,3);						/* the header */
X	write(iofd,blk,128);					/* the block */
X	if(crc_in_use)							/* the crc or checksum */
X	{
X		s3[0] = rUINT16 >> 8;
X		s3[1] = rUINT16 & 0xFF;
X		write(iofd,s3,2);
X		tx_char_count += 133;
X	}
X	else
X	{
X		chksum = rUINT16;
X		write(iofd,&chksum,1);
X		tx_char_count += 132;
X	}
X
X	return(1);
X}	/* end of send_comm_block */
X
X/*+-------------------------------------------------------------------------
X	send_file_block(fp,blknum) - read a block from file and send it
X--------------------------------------------------------------------------*/
Xvoid
Xsend_file_block(fp,blknum)
XFILE *fp;
Xint blknum;
X{
Xlong fileaddr;
Xchar buf[128];
X
X	fileaddr = (long)(blknum - 1) * 128L;
X	if(blknum != sf_lastnum + 1)
X		fseek(fp,fileaddr,0);	/* move where to */
X	sf_lastnum = blknum;
X	report_txpos(fileaddr);
X
X	memset(buf,0x1A,sizeof(buf));	/* fill buffer with control Zs */
X	fread(buf,1,sizeof(buf),fp);	/* read in some data */
X	send_comm_block(buf,blknum);	/* pump it out to the receiver */
X}	/* end of send_file_block */
X
X/*+-------------------------------------------------------------------------
X	send_file(name) - transmit a file
X--------------------------------------------------------------------------*/
Xint
Xsend_file(name)
Xchar *name;
X{
Xregister int endblk;	/* block number of EOT */
XFILE *fp;				/* file to send */
Xstruct stat fst;
XBLK0 blk0;
Xchar *basename;			/* base filename */
Xchar eot = EOT;
X
X	Filcnt++;
X	if(name && *name)			/* if sending a file */
X	{
X		if((fp = fopen(name,"r")) == NULL)
X		{
X			sprintf(s128,"Cannot open %s",name);
X			report_str(s128,1);
X			exit_code = 253;
X			return(0);
X		}
X
X		memset((char *)&blk0,0,sizeof(blk0)); /* clear out data block */
X
X		stat(name,&fst);	/* get file statistics */
X		blk0.length = (long)fst.st_size;
X
X		/* cnvt time from 1970 base to 1980 */
X		if((blk0.secs_since_1980 = fst.st_mtime-OFFSET_1980) < 0L)
X			blk0.secs_since_1980 = 0;
X
X		if((basename = strrchr(name,'/')) == NULL) /* find basename */
X			strcpy(blk0.filename,name);
X		else 
X		{
X			basename++;
X			strcpy(blk0.filename,basename);
X		}
X
X		strcpy(blk0.sender,"ecusea ");
X		strcat(blk0.sender,revision);
X		blk0.send_no_acks = no_ack_mode;
X
X		endblk = (int)((blk0.length + 127L) / 128L) + 1;
X		report_file_send_open(name,&fst);
X	}
X	else 
X	{
X		endblk = 0;						/* fake for no file */
X		report_str("sending EOT indication",-1);
X		report_txpos(blk0.length);
X	}
X
X
X	sf_blknum = 1;						/* set starting state */
X	sf_ackblk = -1;
X	sf_state = SFS_GND;
X	sf_lastnum = 0;
X	sf_slide = 0;
X	sf_nakquan = 0;
X	error_count = 0;
X	sf_ackw_count = 0;
X	crc_in_use = 2;						/* undetermined */
X
X	while(sf_ackblk < endblk)			/* while not all there yet */
X	{
X		sent_EOT = 0;
X		if(sf_blknum <= sf_ackblk + ((sf_slide && allow_slide) ? WINDOW : 1))
X		{
X			if(sf_blknum < endblk)
X			{
X				if(sf_blknum > 0)
X				{
X					sprintf(s128,"sending block %d",sf_blknum);
X					report_last_txhdr(s128,0);
X					send_file_block(fp,sf_blknum);
X				}
X				else
X				{
X					sprintf(s128,"sending filename",sf_blknum);
X					report_last_txhdr(s128,0);
X					send_comm_block((char *)&blk0,0);
X					report_txpos(0L);
X				}
X				if(no_ack_mode && sf_slide && allow_slide)
X					sf_ackblk = sf_blknum;
X			}
X			else if(sf_blknum == endblk)
X			{
X				report_last_txhdr("EOT",0);
X				write(iofd,&eot,1);
X				sent_EOT = 1;
X				nap(500L);
X				tx_char_count++;
X			}
X			sf_blknum++;
X		}
X
X		if(wait_for_rcvr_response() && sent_EOT)
X		{
X			report_str("Receiver did not ACK our EOT",-1);
X			break;
X		}
X
X		if(sf_nakquan > 10)
X			goto CANCEL_TRANSFER;
X	}
X
X	if(endblk)	/* if sending file, not EOT */
X		fclose(fp);
X	return(1);							/* exit with good status */
X
XCANCEL_TRANSFER:
X	if(endblk)	/* if sending file, not EOT */
X		fclose(fp);
X	xmit_cancel();
X	return(0);                          /* exit with bad status */
X}	/* end of send_file */
X
X/*+-------------------------------------------------------------------------
X	set_utime_1980(filename,secs_since_1980)
X--------------------------------------------------------------------------*/
Xvoid
Xset_utime_1980(filename,secs_since_1980)
Xchar *filename;						/* file to set stamp on */
Xlong secs_since_1980;
X{
Xtime_t times[2];
Xtime_t time();
X
X	times[0] = time((long *) 0);				/* accessed */
X	times[1] = secs_since_1980 + OFFSET_1980;	/* modified (convert time) */
X	utime(filename,times);
X}	/* end of set_utime_1980 */
X
X/*+-------------------------------------------------------------------------
X	receive_block(buf) - get block from line
Xreturn 0 if good chk/CRC, 1 if bad
X--------------------------------------------------------------------------*/
Xint
Xreceive_block(buf)
Xchar *buf;				/* data buffer */
X{
Xregister unsigned int rdchar;	
Xregister unsigned short rUINT16 = 0;	/* calculated CRC or check value */
Xint itmp;
Xint timeout = no_ack_mode ? 200 : 5;	/* short block timeout */
Xunsigned short rcvd_crc;				/* received CRC or check value */
X
X	itmp = 128;
X	while(itmp--)
X	{
X		if((rdchar = lgetc_timeout(timeout)) == TIMEOUT)
X			return(1);
X		if(crc_in_use)
X			rUINT16 = crc_update(rdchar,rUINT16);
X		else
X			rUINT16 += rdchar;
X		*buf++ = rdchar;
X	}
X
X	if(crc_in_use)
X	{
X		rUINT16 = crc_update(0,rUINT16);
X		rUINT16 = crc_update(0,rUINT16);
X		rdchar = lgetc_timeout(timeout);
X		rcvd_crc = (rdchar << 8) | lgetc_timeout(timeout);
X	}
X	else 
X	{
X		rUINT16 &= 0xFF;
X		rcvd_crc = lgetc_timeout(timeout) & 0xFF;
X	}
X
X	if(rUINT16 != rcvd_crc)
X	{
X		sprintf(s128,"bad %s calc=%04x rcvd=%04x",
X			crc_in_use ? "CRC" : "checksum",rcvd_crc,rUINT16);
X		report_str(s128,-1);
X	}
X	return(rUINT16 != rcvd_crc);
X}	/* end of receive_block */
X
X/*+-------------------------------------------------------------------------
X	receive_file()
X--------------------------------------------------------------------------*/
Xchar *
Xreceive_file()
X{
Xint rdchar;			/* received character */
Xint tries;			/* retry counter */
Xint blknum;			/* desired block number */
Xint inblk;			/* this block number */
XFILE *fp;
Xchar buf[128];		/* data buffer */
Xchar tmpname[100];		/* name of temporary file */
Xstatic char outname[100];	/* name of final file */
XBLK0 blk0;		/* file header data storage */
Xint endblk;			/* block number of EOT, if known */
Xlong left;			/* bytes left to output */
Xint itmp;				/* index */
Xint cnvrt;			/* flag -- convert filename? */
Xchar *onp;			/* use to convert filename to l / rdchar */
Xchar *basename;		/* base filename */
Xlong ftell();
X
X	*outname = '\0';		/* get name from transmitter */
X	cnvrt = 1;		/* convert to local is necessary */
X	sprintf(tmpname,"./SEA%05d.tmp",getpid());	/* use a unique temp filename */
X
X	if(!(fp = fopen(tmpname,"w")))
X	{	/* open temporary file */
X		sprintf(s128,"Cannot create temp file %s\n",tmpname);
X		report_str(s128,0);
X		xmit_cancel();
X		return(NULL);
X	}
X
X	blknum = 0;
X	tries = -10;				/* kludge for first time around */
X	crc_in_use = 1;				/* try for CRC error checking */
X	error_count = 0;			/* no errors yet */
X	endblk = 0;					/* we don't know the size yet */
X	no_ack_mode = 0;			/* we don't know about this yet */
X	memset((char *)&blk0,0,sizeof(blk0));	/* or much of anything else */
X	report_protocol_crc_type("/CRC16");
X
XSEND_NAK:				/* we got a bad block */
X	if(blknum > 1)
X	{
X		error_count++;
X		report_str("bad block",1);
X	}
X	if(++tries > 10)
X		goto CANCEL_TRANSFER;
X	if(tries == 0)			/* if CRC isn't going */
X	{
X		crc_in_use = 0;		/* then give checksum a try */
X		report_protocol_crc_type("/CHK");
X	}
X
X	xmit_nak(blknum);		/* send the NAK */
X	if(no_ack_mode && error_count > 20)
X	{	/* if no_ack_mode mode isn't working */
X		no_ack_mode = 0;		/* then shut it off */
X		report_str("Overdrive disengaged",0);
X	}
X
XRECEIVE_NEXT_BLOCK:				/* start of "get a block" */
X	report_rxpos(ftell(fp));
X	while((rdchar = lgetc_timeout(30)) != TIMEOUT)
X	{
X		if(rdchar == CAN)
X		{
X			if((rdchar = lgetc_timeout(30)) == CAN)
X			{
X				xmit_cancel();
X				return(NULL);
X			}
X			break;
X		}
X		if(rdchar == EOT)
X		{
X			if(!endblk || endblk == blknum)
X				goto RECEIVE_EOT_SEEN;
X		}
X		else if(rdchar == SOH)
X		{
X			if((inblk = lgetc_timeout(5)) == TIMEOUT)
X				goto SEND_NAK;
X			if(lgetc_timeout(5) == (inblk ^ 0xFF))
X			{
X				sprintf(s128,"receiving %d",inblk);
X				report_last_rxhdr(s128,0);
X				goto GOT_START_OF_BLOCK;	/* we found a start */
X			}
X		}
X	}
X	goto SEND_NAK;
X
XGOT_START_OF_BLOCK:				/* start of block detected */
X	rdchar = blknum & 0xFF;
X	if(inblk == 0 && blknum <= 1)
X	{	/* if this is the header */
X		if(receive_block((char *)&blk0))
X			goto SEND_NAK;		/* bad header block */
X		else 
X		{
X			xmit_ack(inblk);	/* ack the header */
X
X#if defined(M_UNIX)
X			if(fname_too_long(blk0.filename))
X			{
X				strcpy(s128,"truncated: ");
X				strncat(s128,blk0.filename,sizeof(s128) - 12);
X				report_str(s128,-1);
X				strcpy(outname,fname_truncated());
X			}
X			else
X#endif
X				strcpy(outname,blk0.filename);
X			report_file_rcv_started(outname,blk0.length,
X				blk0.secs_since_1980 + OFFSET_1980);
X			if(left = blk0.length)	/* length to transfer */
X				endblk=(int)((left + 127L)/128L)+1;
X			if(no_ack_mode != blk0.send_no_acks)
X			{
X				sprintf(s128,"Overdrive %sengaged",
X					(blk0.send_no_acks) ? "" : "dis");
X				report_str(s128,0);
X			}
X			no_ack_mode = blk0.send_no_acks;
X			blknum = 1;	/* now we want first data block */
X			goto RECEIVE_NEXT_BLOCK;
X		}
X	}
X
X	if(inblk == rdchar)
X	{			/* if this is the one we want */
X		if(!receive_block(buf))
X		{		/* else if we get it okay */
X			if(!no_ack_mode)		/* if we're sending ACKs */
X				xmit_ack(inblk);	/* then ACK the data */
X			for(itmp = 0; itmp < 128; itmp++)
X			{
X				if(endblk)
X				{	/* limit file size if known */
X					if(!left)
X						break;
X					left--;
X				}
X				if(fputc(buf[itmp],fp) == EOF)
X				{
X					report_str("FILE WRITE ERROR",0);
X					goto CANCEL_TRANSFER;
X				}
X			}
X			tries = 0;		/* reset try count */
X			blknum++;		/* we want the next block */
X			goto RECEIVE_NEXT_BLOCK;
X		}
X		goto SEND_NAK;		/* ask for a resend */
X	}
X
X	if(inblk < rdchar || inblk > rdchar + 100)
X	{	/* if resending what we have */
X		receive_block(buf);			/* ignore it */
X		xmit_ack(inblk);			/* but ack it */
X	}
X	goto RECEIVE_NEXT_BLOCK;		/* else if running ahead */
X
XRECEIVE_EOT_SEEN:
X#ifdef NAKEOT
X	xmit_nak(blknum);				/* NAK the EOT, make sure */
X	if(lgetc_timeout(20) != EOT)	/* we're all done */
X		goto SEND_NAK;
X#endif /* NAKEOT */
X	xmit_ack(blknum);				/* ACK it and clean up */
X	report_last_rxhdr("EOT",0);
X	if(blknum > 1)
X	{				/* if we really got anything */
X		fclose(fp);
X		unlink(outname);		/* rename temp to proper name */
X		for(onp = outname;cnvrt && *onp;onp++)
X			/* find out if there's lower- */
X			if(islower(*onp))	/* case letters filename */
X				cnvrt = 0;	/*  there are, don't convert */
X		if(cnvrt)			/* if there aren't, make all */
X			for(onp = outname;*onp;onp++)	/* into uppercase */
X				*onp = tolower(*onp);
X		if(link(tmpname,outname) == 0)
X			unlink(tmpname);
X		if(blk0.secs_since_1980)		/* set stamp, if known */
X			set_utime_1980(outname,blk0.secs_since_1980);
X		return(outname);
X	}
X	else 
X	{				/* else no real file */
X		fclose(fp);
X		unlink(tmpname);		/* discard empty file */
X		report_str("end of transfer",0);
X		rf_done = 1;
X		return(NULL);
X	}
X
XCANCEL_TRANSFER:
X	fclose(fp);
X	xmit_cancel();
X	rf_done = 2;
X	return(NULL);
X}	/* end of receive_file */
X
X/*+-------------------------------------------------------------------------
X	cancel_transaction(sig)
X--------------------------------------------------------------------------*/
Xcancel_transaction(sig)
Xint sig;
X{
X	xmit_cancel();
X	sprintf(s128,"signal %d ... exiting",sig);
X	report_str(s128,1);
X/*
X	report_rx_ind(0);
X	report_tx_ind(0);
X*/
X	report_uninit();
X	if(sig == SIGQUIT)
X		abort();
X	exit(128+sig);
X}	/* end of cancel_transaction */
X
X/*+-------------------------------------------------------------------------
X	getspeed(code)
X--------------------------------------------------------------------------*/
Xstruct B_to_baud { unsigned baud; int B_code; };
Xunsigned
Xgetspeed(code)
Xint code;
X{
Xregister itmp;
Xstatic struct B_to_baud speeds[] = 
X{
X 50, B50, 75, B75, 110, B110, 300, B300, 600, B600, 1200, B1200,
X 2400, B2400, 4800, B4800, 9600, B9600, 19200, EXTA, 38400, EXTB, 0
X};
X
X	code &= CBAUD;
X	for(itmp = 0; speeds[itmp].baud; itmp++)
X		if(speeds[itmp].B_code == code)
X			return(speeds[itmp].baud);
X	return(38400);	/* Assume fifo if ioctl failed */
X}	/* end of getspeed */
X
X/*+-------------------------------------------------------------------------
X	main(argc,argv,envp)
X--------------------------------------------------------------------------*/
Xmain(argc,argv,envp)
Xint argc;
Xchar **argv;
Xchar **envp;
X{
Xint ipaths;
Xint ok;
X#define MAX_PATHS 512
Xchar *paths[MAX_PATHS];
Xchar **ppaths = paths;
Xchar *cptr;
Xchar **gargv = argv;
Xint gargc = argc;
X
X	exit_code = 254;
X	while(--argc)
X	{
X		cptr = *++argv;
X		if(*cptr == '-')
X		{
X			cptr++;
X			switch(*cptr++)
X			{
X			case ',':
X				log_packets = 1;
X				break;
X			case '/':
X				if(--argc < 1)
X					exit(255);
X				strcpy(curr_dir,*++argv);
X				break;
X			case '.':
X				if(--argc < 1)
X					exit(255);
X				iofd = atoi(*++argv);
X				break;
X			case 'r':
X				sending_flag = 0;
X				break;
X			case 's':
X				sending_flag = 1;
X			}
X		}
X		else if(argc > 0)
X		{
X			if(npaths < MAX_PATHS)
X			{
X				*ppaths++ = cptr;
X				npaths++;
X			}
X			else
X			{
X				printf("too many filenames to send\n");
X				exit(255);
X			}
X		}
X	}
X
X	if(sending_flag == -1)
X	{
X		printf("no -r or -s\n");
X		exit(255);
X	}
X
X	if((npaths < 1) && sending_flag)
X		exit(253);
X
X	if(npaths && !sending_flag)
X		exit(255);
X
X	if(log_packets)
X	{
X	char log_packets_name[64];
X	FILE *ftmp;
X	int iargv;
X		sprintf(log_packets_name,"/tmp/sea%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	sprintf(s128,"ecusea %s",revision);
X	report_init(s128);
X	signal(SIGHUP,cancel_transaction);
X	signal(SIGQUIT,cancel_transaction);
X	signal(SIGINT,cancel_transaction);
X	signal(SIGTERM,cancel_transaction);
X
X	ioctl(iofd,TCGETA,&tio0);
X	tio = tio0;
X
X	tio.c_oflag = 0;
X	tio.c_cflag &= ~PARENB;
X	tio.c_cflag &= ~CSIZE;
X	tio.c_cflag |= CS8;
X
X	baud_rate = getspeed(tio.c_cflag);
X	ioctl(iofd,TCSETA,&tio);
X	report_line(baud_rate,"RAW");
X
X	switch(sending_flag)
X	{
X		case 0:				/* receive files */
X			while(receive_file() != NULL)
X				nap(1000L);
X			ok = (rf_done == 1);
X			break;
X
X		case 1:				/* send files */
X			ipaths = 0;
X			while(ipaths < npaths)
X			{
X				if(!(ok = send_file(paths[ipaths])))
X					break;
X				nap(1000L);
X				ipaths++;
X			}
X			if(ok)		/* no errors, send end marker */
X				send_file("");
X			report_str("end of transfer",0);
X			break;
X	}
X
X	ioctl(iofd,TCSETA,&tio0);
X	report_line(baud_rate,"NORMAL");
X	report_uninit();
X	exit(ok ? 0 : exit_code);	/* and return error status */
X
X}	/* end of main */
X
SHAR_EOF
$TOUCH -am 0814204290 'sea/ecusea.c' &&
chmod 0644 sea/ecusea.c ||
echo 'restore of sea/ecusea.c failed'
Wc_c="`wc -c < 'sea/ecusea.c'`"
test 35194 -eq "$Wc_c" ||
	echo 'sea/ecusea.c: original size 35194, current size' "$Wc_c"
# ============= sea/lint_args.h ==============
echo 'x - extracting sea/lint_args.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'sea/lint_args.h' &&
X/*+-----------------------------------------------------------------------
X	lint_args.h
X------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:08-14-1990-21:03-afterlint-creation */
X
X#ifndef BUILDING_LINT_ARGS
X#ifdef LINT_ARGS
X
X/* ecusea.c */
X/* void send_file_block(struct UNNAMED *fp,int blknum); */
Xchar *arg_token(char *,char *);
Xchar *fname_truncated(void );
Xchar *receive_file(void );
Xchar *sf_state_text(int );
Xint cancel_transaction(int );
Xint fname_too_long(char *);
Xint main(int ,char **,char **);
Xint receive_block(char *);
Xint send_comm_block(char *,int );
Xint send_file(char *);
Xint wait_for_rcvr_response(void );
Xunsigned int getspeed(int );
Xunsigned int lgetc_timeout(int );
Xunsigned short crc_update(int ,unsigned int );
Xvoid fname_split(char *,char **,int ,int *);
Xvoid lgetc_timeout_SIGALRM(void );
Xvoid set_sf_state(int ,int );
Xvoid set_utime_1980(char *,long );
Xvoid xmit_ack(int );
Xvoid xmit_cancel(void );
Xvoid xmit_nak(int );
X/* scurses.c */
Xchar *get_elapsed_time(long );
Xchar *get_tod(int ,char *);
Xint clear_area(struct _win_st *,int ,int ,int );
Xint clear_area_char(struct _win_st *,int ,int ,int ,char );
Xint report_error_count(void );
Xint report_file_byte_io(long );
Xint report_file_open_length(long );
Xint report_file_rcv_started(char *,long ,long );
Xint report_protocol_crc_type(char *);
Xint report_rx_tx_count(void );
Xvoid report_file_close(void );
Xvoid report_file_open_tod(void );
Xvoid report_file_send_open(char *,struct stat *);
Xvoid report_init(char *);
Xvoid report_last_rxhdr(char *,int );
Xvoid report_last_txhdr(char *,int );
Xvoid report_line(unsigned int ,char *);
Xvoid report_rx_ind(int );
Xvoid report_rxpos(long );
Xvoid report_str(char *,int );
Xvoid report_top_line(char *);
Xvoid report_transaction(char *);
Xvoid report_tx_ind(int );
Xvoid report_txpos(long );
Xvoid report_uninit(void );
X
X#else		/* compiler doesn't know about prototyping */
X
X/* ecusea.c */
X/* void send_file_block();
Xchar *arg_token();
Xchar *fname_truncated();
Xchar *receive_file();
Xchar *sf_state_text();
Xunsigned int getspeed();
Xunsigned int lgetc_timeout();
Xunsigned short crc_update();
Xvoid fname_split();
Xvoid lgetc_timeout_SIGALRM();
Xvoid set_sf_state();
Xvoid set_utime_1980();
Xvoid xmit_ack();
Xvoid xmit_cancel();
Xvoid xmit_nak();
X/* scurses.c */
Xchar *get_elapsed_time();
Xchar *get_tod();
Xvoid report_file_close();
Xvoid report_file_open_tod();
Xvoid report_file_send_open();
Xvoid report_init();
Xvoid report_last_rxhdr();
Xvoid report_last_txhdr();
Xvoid report_line();
Xvoid report_rx_ind();
Xvoid report_rxpos();
Xvoid report_str();
Xvoid report_top_line();
Xvoid report_transaction();
Xvoid report_tx_ind();
Xvoid report_txpos();
Xvoid report_uninit();
X
X#endif /* LINT_ARGS */
X#endif /* BUILDING_LINT_ARGS */
X
X/* end of lint_args.h */
SHAR_EOF
$TOUCH -am 0919224990 'sea/lint_args.h' &&
chmod 0644 sea/lint_args.h ||
echo 'restore of sea/lint_args.h failed'
Wc_c="`wc -c < 'sea/lint_args.h'`"
test 2779 -eq "$Wc_c" ||
	echo 'sea/lint_args.h: original size 2779, current size' "$Wc_c"
true || echo 'restore of sea/scurses.c failed'
echo End of part 23, continue with part 24
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.