ecu - SCO XENIX V/{2,3}86 Extended CU part 30/47
Warren Tucker
wht at tridom.uucp
Wed Oct 11 05:42:23 AEST 1989
---- Cut Here and unpack ----
#!/bin/sh
# this is part 30 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file z/zcommon.c continued
#
CurArch=30
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/zcommon.c"
sed 's/^X//' << 'SHAR_EOF' >> z/zcommon.c
X\----> need M_XENIX or pyr defined
X#endif
X fprintf(stderr," using '%s'\r\n",home_dir);
X }
X else
X strcpy(home_dir,cptr); /* home directory to string */
X
X if( (strlen(home_dir) == 1) && (*home_dir == '/')) /* root is home */
X *home_dir = 0; /* use null for home dir of root */
X
X} /* end of get_home_dir */
X
X/* end of zcommon.c */
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
echo "File z/zcommon.c is complete"
chmod 0644 z/zcommon.c || echo "restore of z/zcommon.c fails"
echo "x - extracting sea/Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > sea/Makefile &&
X# CHK=0x5649
X#+----------------------------------------------------------
X# Makefile for ecusea
X#-----------------------------------------------------------
X#+:EDITS:*/
X#:07-03-1989-22:58-wht------------- ecu 2.00 ----------------
X
X
XCFLAGS = -i -Ox -K -DLINT_ARGS
XLFLAGS = -lx -lcurses -ltermcap
X
XSRC = \
X ecusea.c\
X scurses.c
X
XOBJ = \
X ecusea.o\
X scurses.o\
X ../ecudump.o
X
Xecusea: $(OBJ) Makefile
X cc $(CFLAGS) $(LFLAGS) $(OBJ) -o ecusea
X
Xecusea.fls: $(SRC)
X ls $(SRC) >ecusea.fls
X
Xlint: ecusea.fls
X echo > lint_args.h
X csh ../zgcc ecusea.fls lint_args.h $(CFLAGS)
X fcrc -u Makefile *.c *.h
X
SHAR_EOF
chmod 0644 sea/Makefile || echo "restore of sea/Makefile fails"
echo "x - extracting sea/ecusea.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > sea/ecusea.c &&
X/* CHK=0x76B7 */
Xchar *revision = "1.0"; /* cannot be longer than 7 chars (blk0.sender) */
X/* #define TABLE_CRC16 */
X/*+-------------------------------------------------------------------------
X ecusea.c - SEAlink - Sliding window file transfer protocol
X
X Defined functions:
X crc_update(c,crc)
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_utime_1980(filename,secs_since_1980)
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/*:07-03-1989-22:58-wht------------- ecu 2.00 ---------------- */
X/*:05-26-1989-20:25-wht-was clobberring CBAUD part of c_cflag */
X/*:05-26-1989-20:10-wht-add cancel_transaction */
X/*:05-24-1989-23:10-wht-add table lookup crc */
X/*:05-24-1989-19:06-wht-adoption of pd source with SERIOUS hardening */
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(M_I386)
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; /* 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];
X
Xstruct termio tio;
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 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(M_I286)
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(M_I286)
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(M_I286)
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_seconds_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--------------------------------------------------------------------------*/
Xvoid
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_NAKW));
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,1);
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} /* 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{FILE *dfp= fopen("egad.log","a");
Xfprintf(dfp,"------ blknum %d ---------\n",blknum);
Xhex_dump_fp(dfp,s3,3,"",1);
Xhex_dump_fp(dfp,blk,128,"",1);
Xfclose(dfp);
X}
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 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 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 nap(500L);
X tx_char_count++;
X }
X sf_blknum++;
X }
X
X wait_for_rcvr_response();
X
X if(sf_nakquan > 10)
X goto CANCEL_TRANSFER;
X }
X
X if(endblk)
X fclose(fp);
X return(1); /* exit with good status */
X
XCANCEL_TRANSFER:
X if(endblk)
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 error_count++;
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 strcpy(outname,blk0.filename);
X report_file_rcv_started(blk0.filename,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)
SHAR_EOF
echo "End of part 30"
echo "File sea/ecusea.c is continued in part 31"
echo "31" > 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.
More information about the Alt.sources
mailing list