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