wht@tridom.uucp (Warren Tucker) (10/11/89)
---- Cut Here and unpack ---- #!/bin/sh # this is part 27 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file z/ecusz.c continued # CurArch=27 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/ecusz.c" sed 's/^X//' << 'SHAR_EOF' >> z/ecusz.c 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/* fill buf with count chars */ Xzbuf_build(buf,count) Xregister char *buf; X{ X register 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} X X XSIGALRM_handler() X{ X#if defined(M_XENIX) X report_rx_ind(0); X report_tx_ind(0); X#endif X longjmp(tohere,-1); X} X X X/* X * readock(timeout,count) X * timeout is in tenths of seconds X * reads character(s) from file descriptor 'fd' X * read 'count' characters, (1 <= count <= 3) X * if more than one received, return ERROR unless all are CAN X * normal response is NAK, ACK, CAN, G or C X */ Xreadock(timeout,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} X Xreadline(n) X{ X return(readock(n,1)); X} X X Xpurgeline() X{ X#if defined(M_XENIX) X ioctl(iofd,TCFLSH,0); X#else X lseek(iofd,0L,2); X#endif X} X X/* send cancel string to get the other end to shut up */ Xsend_cancel() 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",1); X while(*cptr) X sendline(*cptr++); X flushline(); X} X X/* X * substr(string,token) searches for token in string s X * returns pointer to token within string if found,NULL otherwise X */ Xchar * Xsubstr(s,t) Xregister char *s,*t; X{ X register char *ss,*tt; X /* search for first char of token */ X for(ss=s; *s; s++) X if(*s == *t) X /* compare token with substring */ X for(ss=s,tt=t; ;) X { X if(*tt == 0) X return(s); X if(*ss++ != *tt++) X break; X } X return(NULL); X} X X Xusage() X{ X exit(255); X} X X/* X * 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_XENIX) 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} X X/* Send send-init information */ 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} X X/* Send file name and related info */ Xzsendfile(buf,blen) Xchar *buf; X{ X register c; X X for(;;) X { X blklen = blklen_original; 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} X X/* Send the data in the file */ 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 blklen *= 2; 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(s128); /* always log this */ X report_str(s128 + 5,1); X if(FileRejectCount < 127) X FileRejectCount++; X report_file_byte_io(this_file_length); X report_file_close(); X fclose(in); X return(ERROR); X } X } X} X X/* X * Respond to receiver's complaint, 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 blklen /= 2; /* wht - original code */ X } /* wht */ X } /* wht - original code */ X Lastsync = Rxpos; X report_send_stats(Txpos); X return(c); X case ZACK: X Lrxpos = Rxpos; X if(flag || Txpos == Rxpos) X return(ZACK); X continue; X X case ZRINIT: X#if defined(LOG_XFER) X sprintf(s256,"SEND success: %s",Pathname); X ecu_log_event(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",1); X zsbhdr(ZNAK,Txhdr); X continue; X } X } X} X X X/* Say "cancel_transaction" to the receiver,try to do it cleanly */ 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} 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} X X/* vi: set tabstop=4 shiftwidth=4: */ SHAR_EOF echo "File z/ecusz.c is complete" chmod 0644 z/ecusz.c || echo "restore of z/ecusz.c fails" echo "x - extracting z/zmodem.c (Text)" sed 's/^X//' << 'SHAR_EOF' > z/zmodem.c && X/* CHK=0x2976 */ X/*+------------------------------------------------------------------------- X zmodem.c - ZMODEM protocol primitives X based on code by Chuck Forsberg X X Entry point Functions: X zsbhdr(type,hdr) send binary header X zshhdr(type,hdr) send hex header X zgethdr(hdr,eflag) receive header - binary or hex X zsdata(buf,len,frameend) send data X zrdata(buf,len) receive data X stohdr(pos) store position data in Txhdr X long rclhdr(hdr) recover position offset from header X X Defined functions: X noxrd7() X rclhdr(hdr) X stohdr(pos) X zdlread() X zgeth1() X zgethdr(hdr,eflag) X zgethex() X zputhex(c) X zrbhdr(hdr) X zrbhdr32(hdr) X zrdat32(buf,length) X zrdata(buf,length) X zrhhdr(hdr) X zsbh32(hdr,type) X zsbhdr(type,hdr) X zsda32(buf,length,frameend) X zsdata(buf,length,frameend) X zsendline(c) X zshhdr(type,hdr) X X--------------------------------------------------------------------------*/ X/*+:EDITS:*/ X/*:07-03-1989-22:58-wht------------- ecu 2.00 ---------------- */ X/*:06-24-1989-16:51-wht-flush edits --- ecu 1.95 */ X X#include "zmodem.h" /* wht */ X#include "zlint.h" X Xextern char s128[]; /* wht */ Xextern int Zctlesc; /* wht */ Xextern int Zmodem; /* wht */ Xextern long cr3tab[]; /* wht */ Xextern unsigned Baudrate; /* wht */ Xextern unsigned short crctab[]; /* wht */ X Xint Rxtimeout = 100; /* Tenths of seconds to wait for something */ X X#if !defined(UNSL) X#define UNSL X#endif X X X Xstatic lastsent; /* Last char we sent */ Xstatic evenp; /* Even parity seen on header */ X X/* Globals used by ZMODEM functions */ Xchar Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */ Xchar Rxhdr[4]; /* Received header */ Xchar Txhdr[4]; /* Transmitted header */ Xint Crc32; /* Display flag indicating 32 bit CRC being received */ Xint Crc32t; /* Display flag indicating 32 bit CRC being sent */ Xint Rxcount; /* Count of data bytes received */ Xint Rxframeind; /* ZBIN ZBIN32,or ZHEX type of frame received */ Xint Rxtimeout; /* Tenths of seconds to wait for something */ Xint Rxtype; /* Type of header received */ Xint Txfcs32; /* TURE means send binary frames with 32 bit FCS */ Xint Zrwindow; /* RX window size (controls garbage count) */ Xlong Rxpos; /* Received file position */ Xlong Txpos; /* Transmitted file position */ X Xchar *frametypes[] = X{ X "Carrier Lost", /* -3 */ X "TIMEOUT", /* -2 */ X "ERROR", /* -1 */ X/* #define FTOFFSET 3 moved to zmodem.h */ X "ZRQINIT", X "ZRINIT", X "ZSINIT", X "ZACK ", X "ZFILE", X "ZSKIP", X "ZNAK ", X "ZABORT", X "ZFIN ", X "ZRPOS", X "ZDATA", X "ZEOF ", X "ZFERR", X "ZCRC ", X "ZCHALLENGE", X "ZCOMPL", X "ZCAN ", X "ZFREECNT", X "ZCOMMAND", X "ZSTDERR", X "xxxxx" X#define FRTYPES 22 /* Total number of frame types in this array */ X /* not including psuedo negative entries */ X}; X Xstatic char masked[] = "8 bit transparent path required"; Xstatic char badcrc[] = "Bad CRC"; X X/* Send ZMODEM binary header hdr of type type */ Xzsbhdr(type,hdr) Xregister unsigned char *hdr; X{ X register int n; X register unsigned crc; X X report_tx_ind(1); X sprintf(s128,"hdr %s %08lx",frametypes[type+FTOFFSET],rclhdr(hdr)); X report_last_txhdr(s128,0); X X xsendline(ZPAD); X xsendline(ZDLE); X X if(Crc32t=Txfcs32) X zsbh32(hdr,type); X else X { X xsendline(ZBIN); X zsendline(type); X crc = updcrc(type,0); X X for(n=4; --n >= 0; ++hdr) X { X zsendline(*hdr); X crc = updcrc(*hdr,crc); X } X crc = updcrc(0,updcrc(0,crc)); X zsendline(crc>>8); X zsendline(crc); X } X if(type != ZDATA) X flushline(); X report_tx_ind(0); X} X X X/* Send ZMODEM binary header hdr of type type */ Xzsbh32(hdr,type) Xregister char *hdr; X{ X register int n; X register UNSL long crc; X X report_tx_ind(1); X xsendline(ZBIN32); X zsendline(type); X crc = 0xFFFFFFFFL; X crc = UPDC32(type,crc); X X for(n=4; --n >= 0; ++hdr) X { X crc = UPDC32((0377 & *hdr),crc); X zsendline(*hdr); X } X crc = ~crc; X for(n=4; --n >= 0;) X { X zsendline((int)crc); X crc >>= 8; X } X report_tx_ind(0); X} X X/* Send ZMODEM HEX header hdr of type type */ Xzshhdr(type,hdr) Xregister unsigned char *hdr; X{ X register int n; X register unsigned short crc; X X report_tx_ind(1); X X sprintf(s128,"hdr %s %08lx",frametypes[type+FTOFFSET],rclhdr(hdr)); X report_last_txhdr(s128,0); X sendline(ZPAD); X sendline(ZPAD); X sendline(ZDLE); X sendline(ZHEX); X zputhex(type); X Crc32t = 0; X X crc = updcrc(type,0); X for(n=4; --n >= 0; ++hdr) X { X zputhex(*hdr); X crc = updcrc(*hdr,crc); X/* crc = updcrc((0377 & *hdr),crc); original - wht */ X } X crc = updcrc(0,updcrc(0,crc)); X zputhex(crc>>8); X zputhex(crc); X X /* Make it printable on remote machine */ X sendline(015); X sendline(012); X /* X * Uncork the remote in case a fake XOFF has stopped data flow X */ X if(type != ZFIN && type != ZACK) X sendline(021); X flushline(); X report_tx_ind(0); X} X X/* X * Send binary array buf of length length,with ending ZDLE sequence frameend X */ Xstatic char *Zendnames[] = { "ZCRCE","ZCRCG","ZCRCQ","ZCRCW"}; X Xzsdata(buf,length,frameend) Xregister unsigned char *buf; X{ X register unsigned short crc; X X report_tx_ind(1); X X sprintf(s128,"data %s %d bytes",Zendnames[frameend-ZCRCE&3],length); X report_last_txhdr(s128,0); X if(Crc32t) X zsda32(buf,length,frameend); X else X { X crc = 0; X for(;--length >= 0; ++buf) X { X zsendline(*buf); X crc = updcrc(*buf,crc); X } X xsendline(ZDLE); X xsendline(frameend); X crc = updcrc(frameend,crc); X X crc = updcrc(0,updcrc(0,crc)); X zsendline(crc>>8); X zsendline(crc); X } X if(frameend == ZCRCW) X { X xsendline(XON); X flushline(); X } X report_tx_ind(0); X X} X Xzsda32(buf,length,frameend) Xregister char *buf; X{ X register int c; X register UNSL long crc; X X report_tx_ind(1); X X crc = 0xFFFFFFFFL; X for(;--length >= 0; ++buf) X { X c = *buf & 0377; X if(c & 0140) X xsendline(lastsent = c); X else X zsendline(c); X crc = UPDC32(c,crc); X } X xsendline(ZDLE); X xsendline(frameend); X crc = UPDC32(frameend,crc); X X crc = ~crc; X for(length=4; --length >= 0;) X { X zsendline((int)crc); X crc >>= 8; X } X report_tx_ind(0); X} X X/* X * Receive array buf of max length with ending ZDLE sequence X * and CRC. Returns the ending character or error code. X * NB: On errors may store length+1 bytes! X */ Xzrdata(buf,length) Xregister char *buf; X{ X register int c; X register unsigned short crc; X register char *end; X register int d; X X report_rx_ind(1); X X if(Rxframeind == ZBIN32) X { X report_rx_ind(0); X return(zrdat32(buf,length)); X } X X crc = Rxcount = 0; X end = buf + length; X while(buf <= end) X { X if((c = zdlread()) & ~0377) X { Xcrcfoo: X switch(c) X { X case GOTCRCE: X case GOTCRCG: X case GOTCRCQ: X case GOTCRCW: X crc = updcrc(((d=c)&0377),crc); X if((c = zdlread()) & ~0377) X goto crcfoo; X crc = updcrc(c,crc); X if((c = zdlread()) & ~0377) X goto crcfoo; X crc = updcrc(c,crc); X if(crc & 0xFFFF) X { X report_str(badcrc,1); X report_rx_ind(0); X return(ERROR); X } X Rxcount = length - (end - buf); X report_rxblklen(Rxcount); X sprintf(s128,"data %s %d bytes", X Zendnames[d-GOTCRCE&3],Rxcount); X report_last_rxhdr(s128,0); X report_rx_ind(0); X return(d); X case GOTCAN: X report_str("Sender Cancelled",1); X report_rx_ind(0); X return(ZCAN); X case TIMEOUT: X report_str("TIMEOUT",1); X report_rx_ind(0); X return(c); X default: X report_str("Bad data subpacket",1); X report_rx_ind(0); X return(c); X } X } X *buf++ = c; X crc = updcrc(c,crc); X } X report_str("Data subpacket too long",1); X report_rx_ind(0); X return(ERROR); X} X Xzrdat32(buf,length) Xregister char *buf; X{ X register int c; X register UNSL long crc; X register char *end; X register int d; X X report_rx_ind(1); X crc = 0xFFFFFFFFL; X Rxcount = 0; X end = buf + length; X while(buf <= end) X { X if((c = zdlread()) & ~0377) X { Xcrcfoo: X switch(c) X { X case GOTCRCE: X case GOTCRCG: X case GOTCRCQ: X case GOTCRCW: X d = c; X c &= 0377; X crc = UPDC32(c,crc); X if((c = zdlread()) & ~0377) X goto crcfoo; X crc = UPDC32(c,crc); X if((c = zdlread()) & ~0377) X goto crcfoo; X crc = UPDC32(c,crc); X if((c = zdlread()) & ~0377) X goto crcfoo; X crc = UPDC32(c,crc); X if((c = zdlread()) & ~0377) X goto crcfoo; X crc = UPDC32(c,crc); X if(crc != 0xDEBB20E3) X { X report_str(badcrc,1); X report_rx_ind(0); X return(ERROR); X } X Rxcount = length - (end - buf); X report_rxblklen(Rxcount); X sprintf(s128,"data %s %d bytes", X Zendnames[d-GOTCRCE&3],Rxcount); X report_last_rxhdr(s128,0); X report_rx_ind(0); X return(d); X case GOTCAN: X report_str("Sender Canceled",1); X report_rx_ind(0); X return(ZCAN); X case TIMEOUT: X report_str("TIMEOUT",1); X report_rx_ind(0); X return(c); X default: X report_str("Bad data subpacket",1); X report_rx_ind(0); X return(c); X } X } X *buf++ = c; X crc = UPDC32(c,crc); X } X report_str("Data subpacket too long",1); X report_rx_ind(0); X return(ERROR); X} X X X/* X * Read a ZMODEM header to hdr,either binary or hex. X * eflag controls local display of non zmodem characters: X * 0: no display X * 1: display printing characters only X * 2: display all non ZMODEM characters X * On success,set Zmodem to 1,set Rxpos and return type of header. X * Otherwise return negative on error. X * Return ERROR instantly if ZCRCW sequence,for fast error recovery. X */ Xzgethdr(hdr,eflag) Xchar *hdr; X{ Xregister int c,n,cancount; X X report_rx_ind(1); X n = Zrwindow + Baudrate; /* Max bytes before start of frame */ X Rxframeind = Rxtype = 0; X Xstartover: X cancount = 5; Xagain: X /* Return immediate ERROR if ZCRCW sequence seen */ X switch(c = readline(Rxtimeout)) X { X case RCDO: X case TIMEOUT: X goto fifi; X case CAN: Xgotcan: X if(--cancount <= 0) X { X c = ZCAN; X goto fifi; X } X switch(c = readline(1)) X { X case TIMEOUT: X goto again; X case ZCRCW: X c = ERROR; X /* **** FALL THRU TO **** */ X case RCDO: X goto fifi; X default: X break; X case CAN: X if(--cancount <= 0) X { X c = ZCAN; X goto fifi; X } X goto again; X } X /* **** FALL THRU TO **** */ X default: Xagn2: X if( --n == 0) X { X report_str("Garbage count exceeded",1); X report_last_rxhdr("Noise",0); X report_rx_ind(0); X return(ERROR); X } X goto startover; X case ZPAD|0200: /* This is what we want. */ X case ZPAD: /* This is what we want. */ X evenp = c & 0200; X break; X } X cancount = 5; Xsplat: X switch(c = noxrd7()) X { X case ZPAD: X goto splat; X case RCDO: X case TIMEOUT: X goto fifi; X default: X goto agn2; X case ZDLE: /* This is what we want. */ X break; X } X X switch(c = noxrd7()) X { X case RCDO: X case TIMEOUT: X goto fifi; X case ZBIN: X Rxframeind = ZBIN; X Crc32 = FALSE; X c = zrbhdr(hdr); X break; X case ZBIN32: X Crc32 = Rxframeind = ZBIN32; X c = zrbhdr32(hdr); X break; X case ZHEX: X Rxframeind = ZHEX; X Crc32 = FALSE; X c = zrhhdr(hdr); X break; X case CAN: X goto gotcan; X default: X goto agn2; X } X Rxpos = hdr[ZP3] & 0377; X Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377); X Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377); X Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377); Xfifi: X switch(c) X { X case GOTCAN: X c = ZCAN; X /* **** FALL THRU TO **** */ X case ZNAK: X case ZCAN: X case ERROR: X case TIMEOUT: X case RCDO: X sprintf(s128,"Got %s",frametypes[c+FTOFFSET]); X report_str(s128,1); X /* **** FALL THRU TO **** */ X default: X if(c >= -3 && c <= FRTYPES) X sprintf(s128,"hdr %s %08lx",frametypes[c+FTOFFSET],Rxpos); X else X sprintf(s128,"hdr 0x%02x? %08lx",c,Rxpos); X report_last_rxhdr(s128,0); X } X report_rx_ind(0); X return(c); X} X X/* Receive a binary style header (type and position) */ Xzrbhdr(hdr) Xregister char *hdr; X{ X register int c,n; X register unsigned short crc; X X if((c = zdlread()) & ~0377) X return(c); X Rxtype = c; X crc = updcrc(c,0); X X for(n=4; --n >= 0; ++hdr) X { X if((c = zdlread()) & ~0377) X return(c); X crc = updcrc(c,crc); X *hdr = c; X } X if((c = zdlread()) & ~0377) X return(c); X crc = updcrc(c,crc); X if((c = zdlread()) & ~0377) X return(c); X crc = updcrc(c,crc); X if(crc & 0xFFFF) X { X if(evenp) X report_str(masked,1); X report_str(badcrc,1); X return(ERROR); X } X#if defined(ZMODEM) X Protocol = ZMODEM; X#endif X Zmodem = 1; X return(Rxtype); X} X X/* Receive a binary style header (type and position) with 32 bit FCS */ Xzrbhdr32(hdr) Xregister char *hdr; X{ X register int c,n; X register UNSL long crc; X X if((c = zdlread()) & ~0377) X return(c); X Rxtype = c; X crc = 0xFFFFFFFFL; X crc = UPDC32(c,crc); X X for(n=4; --n >= 0; ++hdr) X { X if((c = zdlread()) & ~0377) X return(c); X crc = UPDC32(c,crc); X *hdr = c; X } X for(n=4; --n >= 0;) X { X if((c = zdlread()) & ~0377) X return(c); X crc = UPDC32(c,crc); X } X if(crc != 0xDEBB20E3) X { X if(evenp) X report_str(masked,1); X report_str(badcrc,1); X return(ERROR); X } X#if defined(ZMODEM) X Protocol = ZMODEM; X#endif X Zmodem = 1; X return(Rxtype); X} X X X/* Receive a hex style header (type and position) */ Xzrhhdr(hdr) Xchar *hdr; X{ X register int c; X register unsigned short crc; X register int n; X X if((c = zgethex()) < 0) X return(c); X Rxtype = c; X crc = updcrc(c,0); X X for(n=4; --n >= 0; ++hdr) X { X if((c = zgethex()) < 0) X return(c); X crc = updcrc(c,crc); X *hdr = c; X } X if((c = zgethex()) < 0) X return(c); X crc = updcrc(c,crc); X if((c = zgethex()) < 0) X return(c); X crc = updcrc(c,crc); X if(crc & 0xFFFF) X { X report_str(badcrc,1); X return(ERROR); X } X if(readline(1) == '\r') /* Throw away possible cr/lf */ X readline(1); X#if defined(ZMODEM) X Protocol = ZMODEM; X#endif X Zmodem = 1; X return(Rxtype); X} X X/* Send a byte as two hex digits */ Xzputhex(c) Xregister int c; X{ X static char digits[] = "0123456789abcdef"; X X sendline(digits[(c&0xF0)>>4]); X sendline(digits[(c)&0xF]); X} X X/* X * Send character c with ZMODEM escape sequence encoding. X * Escape XON,XOFF. Escape CR following @ (Telenet net escape) X */ Xzsendline(c) X{ X X /* Quick check for non control characters */ X if(c & 0140) X xsendline(lastsent = c); X else X { X switch(c &= 0377) X { X case ZDLE: X xsendline(ZDLE); X xsendline(lastsent = (c ^= 0100)); X break; X case 015: X case 0215: X if(!Zctlesc && (lastsent & 0177) != '@') X goto sendit; X /* **** FALL THRU TO **** */ X case 020: X case 021: X case 023: X case 0220: X case 0221: X case 0223: SHAR_EOF echo "End of part 27" echo "File z/zmodem.c is continued in part 28" echo "28" > 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.