This is zmodem.c in view mode; [Download] [Up]
/*+------------------------------------------------------------------------- zmodem.c - ZMODEM protocol primitives based on code by Chuck Forsberg tip adaptation by wht%n4hgf@emory.mathcs.emory.edu Entry point Functions: zsbhdr(len,type,hdr) send binary header zshhdr(type,hdr) send hex header zgethdr(hdr,eflag) receive header - binary or hex zsdata(buf,len,frameend) send data zrdata(buf,len) receive data stohdr(pos) store position data in Txhdr long rclhdr(hdr) recover position offset from header Defined functions: noxrd7() rclhdr(hdr) stohdr(pos) zdlread() zgeth1() zgethdr(hdr,eflag) zgethex() zputhex(c) zrbhdr(hdr) zrbhdr32(hdr) zrdat32(buf,length) zrdata(buf,length) zrhhdr(hdr) zsbh32(hdr,type) zsbhdr(len,type,hdr) zsda32(buf,length,frameend) zsdata(buf,length,frameend) zsendline(c) zshhdr(type,hdr) --------------------------------------------------------------------------*/ /*+:EDITS:*/ /*:05-21-1990-16:00-wht@tridom-adapt ecu xfer protocols for tipwht */ #include "zmodem.h" /* wht */ #include "zlint.h" extern char s128[]; /* wht */ extern int Zctlesc; /* wht */ extern int Zmodem; /* wht */ extern long cr3tab[]; /* wht */ extern unsigned Baudrate; /* wht */ extern unsigned short crctab[]; /* wht */ int Rxtimeout = 100; /* Tenths of seconds to wait for something */ #if !defined(UNSL) #define UNSL #endif /* Globals used by ZMODEM functions */ int Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame */ int Rxtype; /* Type of header received */ int Rxhlen; /* Length of header received */ int Rxcount; /* Count of data bytes received */ char Rxhdr[ZMAXHLEN]; /* Received header */ char Txhdr[ZMAXHLEN]; /* Transmitted header */ long Rxpos; /* Received file position */ long Txpos; /* Transmitted file position */ int Txfcs32; /* TURE means send binary frames with 32 bit FCS */ int Crc32t; /* Controls 32 bit CRC being sent */ /* 1 == CRC32, 2 == CRC32 + RLE */ int Crc32r; /* Indicates/controls 32 bit CRC being received */ /* 0 == CRC16, 1 == CRC32, 2 == CRC32 + RLE */ int Usevhdrs; /* Use variable length headers */ int Znulls; /* Number of nulls to send at beginning of ZDATA hdr */ char Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */ char *Altcan; /* Alternate canit string */ static lastsent; /* Last char we sent */ static Not8bit; /* Seven bits seen on header */ char *frametypes[] = { "No Response to Error Correction Request", /* -4 */ "Carrier Lost", /* -3 */ "TIMEOUT", /* -2 */ "ERROR", /* -1 */ /* #define FTOFFSET 3 moved to zmodem.h */ "ZRQINIT", "ZRINIT", "ZSINIT", "ZACK ", "ZFILE", "ZSKIP", "ZNAK ", "ZABORT", "ZFIN ", "ZRPOS", "ZDATA", "ZEOF ", "ZFERR", "ZCRC ", "ZCHALLENGE", "ZCOMPL", "ZCAN ", "ZFREECNT", "ZCOMMAND", "ZSTDERR", "xxxxx" #define FRTYPES 22 /* Total number of frame types in this array */ /* not including psuedo negative entries */ }; static char masked[] = "8 bit transparent path required"; static char badcrc[] = "Bad CRC"; /* Send ZMODEM binary header hdr of type type */ zsbhdr(len, type, hdr) register unsigned char *hdr; { register int n; register unsigned crc; report_tx_ind(1); sprintf(s128,"hdr %s %ld",frametypes[type+FTOFFSET],rclhdr(hdr)); report_last_txhdr(s128,0); xsendline(ZPAD); xsendline(ZDLE); switch (Crc32t=Txfcs32) { case 2: zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32); flushline(); break; case 1: zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32); break; default: if (Usevhdrs) { xsendline(ZVBIN); zsendline(len); } else xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0); for (n=len; --n >= 0; ++hdr) { zsendline(*hdr); crc = updcrc((0377& *hdr), crc); } crc = updcrc(0,updcrc(0,crc)); zsendline(crc>>8); zsendline(crc); } if (type != ZDATA) flushline(); report_tx_ind(0); } /* Send ZMODEM binary header hdr of type type */ zsbh32(len, hdr, type, flavour) register char *hdr; { register int n; register UNSL long crc; report_tx_ind(1); xsendline(flavour); if (Usevhdrs) zsendline(len); zsendline(type); crc = 0xFFFFFFFFL; crc = UPDC32(type,crc); for(n=len; --n >= 0; ++hdr) { crc = UPDC32((0377 & *hdr),crc); zsendline(*hdr); } crc = ~crc; for(n=len; --n >= 0;) { zsendline((int)crc); crc >>= 8; } report_tx_ind(0); } /* Send ZMODEM HEX header hdr of type type */ zshhdr(len,type,hdr) register unsigned char *hdr; { register int n; register unsigned short crc; report_tx_ind(1); sprintf(s128,"hdr %s %ld",frametypes[type+FTOFFSET],rclhdr(hdr)); report_last_txhdr(s128,0); sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); if (Usevhdrs) { sendline(ZVHEX); zputhex(len); } else sendline(ZHEX); zputhex(type); Crc32t = 0; crc = updcrc(type,0); for(n=len; --n >= 0; ++hdr) { zputhex(*hdr); crc = updcrc(*hdr,crc); /* crc = updcrc((0377 & *hdr),crc); original - wht */ } crc = updcrc(0,updcrc(0,crc)); zputhex(crc>>8); zputhex(crc); /* Make it printable on remote machine */ sendline(015); sendline(0212); /* * Uncork the remote in case a fake XOFF has stopped data flow */ if(type != ZFIN && type != ZACK) sendline(021); flushline(); report_tx_ind(0); } /* * Send binary array buf of length length,with ending ZDLE sequence frameend */ static char *Zendnames[] = { "ZCRCE","ZCRCG","ZCRCQ","ZCRCW"}; zsdata(buf,length,frameend) register unsigned char *buf; { register unsigned short crc; report_tx_ind(1); sprintf(s128,"data %s %d bytes",Zendnames[frameend-ZCRCE&3],length); report_last_txhdr(s128,0); switch (Crc32t) { case 1: zsda32(buf, length, frameend); break; case 2: zsdar32(buf, length, frameend); break; default: crc = 0; for(;--length >= 0; ++buf) { zsendline(*buf); crc = updcrc(*buf,crc); } xsendline(ZDLE); xsendline(frameend); crc = updcrc(frameend,crc); crc = updcrc(0,updcrc(0,crc)); zsendline(crc>>8); zsendline(crc); } if(frameend == ZCRCW) { xsendline(XON); flushline(); } report_tx_ind(0); } zsda32(buf,length,frameend) register char *buf; { register int c; register UNSL long crc; report_tx_ind(1); crc = 0xFFFFFFFFL; for(;--length >= 0; ++buf) { c = *buf & 0377; if(c & 0140) xsendline(lastsent = c); else zsendline(c); crc = UPDC32(c,crc); } xsendline(ZDLE); xsendline(frameend); crc = UPDC32(frameend,crc); crc = ~crc; for(c=4; --c >= 0;) { zsendline((int)crc); crc >>= 8; } report_tx_ind(0); } /* * Receive array buf of max length with ending ZDLE sequence * and CRC. Returns the ending character or error code. * NB: On errors may store length+1 bytes! */ zrdata(buf,length) register char *buf; { register int c; register unsigned short crc; register char *end; register int d; report_rx_ind(1); switch (Crc32r) { case 1: return zrdat32(buf, length); case 2: return zrdatr32(buf, length); } crc = Rxcount = 0; end = buf + length; while(buf <= end) { if((c = zdlread()) & ~0377) { crcfoo: switch(c) { case GOTCRCE: case GOTCRCG: case GOTCRCQ: case GOTCRCW: crc = updcrc(((d=c)&0377),crc); if((c = zdlread()) & ~0377) goto crcfoo; crc = updcrc(c,crc); if((c = zdlread()) & ~0377) goto crcfoo; crc = updcrc(c,crc); if(crc & 0xFFFF) { report_str(badcrc,0); report_rx_ind(0); return(ERROR); } Rxcount = length - (end - buf); report_rxblklen(Rxcount); sprintf(s128,"data %s %d bytes", Zendnames[d-GOTCRCE&3],Rxcount); report_last_rxhdr(s128,0); report_rx_ind(0); return(d); case GOTCAN: report_str("Sender Cancelled",1); report_rx_ind(0); return(ZCAN); case TIMEOUT: report_str("TIMEOUT",1); report_rx_ind(0); return(c); default: report_str("Bad data subpacket",1); report_rx_ind(0); return(c); } } *buf++ = c; crc = updcrc(c,crc); } report_str("Data subpacket too long",1); report_rx_ind(0); return(ERROR); } zrdat32(buf,length) register char *buf; { register int c; register UNSL long crc; register char *end; register int d; report_rx_ind(1); crc = 0xFFFFFFFFL; Rxcount = 0; end = buf + length; while(buf <= end) { if((c = zdlread()) & ~0377) { crcfoo: switch(c) { case GOTCRCE: case GOTCRCG: case GOTCRCQ: case GOTCRCW: d = c; c &= 0377; crc = UPDC32(c,crc); if((c = zdlread()) & ~0377) goto crcfoo; crc = UPDC32(c,crc); if((c = zdlread()) & ~0377) goto crcfoo; crc = UPDC32(c,crc); if((c = zdlread()) & ~0377) goto crcfoo; crc = UPDC32(c,crc); if((c = zdlread()) & ~0377) goto crcfoo; crc = UPDC32(c,crc); if(crc != 0xDEBB20E3) { report_str(badcrc,0); report_rx_ind(0); return(ERROR); } Rxcount = length - (end - buf); report_rxblklen(Rxcount); sprintf(s128,"data %s %d bytes", Zendnames[d-GOTCRCE&3],Rxcount); report_last_rxhdr(s128,0); report_rx_ind(0); return(d); case GOTCAN: report_str("Sender Canceled",1); report_rx_ind(0); return(ZCAN); case TIMEOUT: report_str("TIMEOUT",1); report_rx_ind(0); return(c); default: report_str("Bad data subpacket",1); report_rx_ind(0); return(c); } } *buf++ = c; crc = UPDC32(c,crc); } report_str("Data subpacket too long",1); report_rx_ind(0); return(ERROR); } /* * Read a ZMODEM header to hdr,either binary or hex. * eflag controls local display of non zmodem characters: * 0: no display * 1: display printing characters only * 2: display all non ZMODEM characters * On success,set Zmodem to 1,set Rxpos and return type of header. * Otherwise return negative on error. * Return ERROR instantly if ZCRCW sequence,for fast error recovery. */ extern int Zrwindow; zgethdr(hdr,eflag) char *hdr; { register int c,n,cancount; report_rx_ind(1); n = Zrwindow + Baudrate; /* Max bytes before start of frame */ Rxframeind = Rxtype = 0; startover: cancount = 5; again: /* Return immediate ERROR if ZCRCW sequence seen */ switch(c = readline(Rxtimeout)) { case RCDO: case TIMEOUT: goto fifi; case CAN: gotcan: if(--cancount <= 0) { c = ZCAN; goto fifi; } switch(c = readline(1)) { case TIMEOUT: goto again; case ZCRCW: c = ERROR; /* **** FALL THRU TO **** */ case RCDO: goto fifi; default: break; case CAN: if(--cancount <= 0) { c = ZCAN; goto fifi; } goto again; } /* **** FALL THRU TO **** */ default: agn2: if( --n == 0) { report_str("Garbage count exceeded",1); report_last_rxhdr("Noise",0); report_rx_ind(0); /* return(ERROR); */ goto fifi; } goto startover; case ZPAD|0200: /* This is what we want. */ Not8bit = c; case ZPAD: /* This is what we want. */ /* Not8bit = c & 0200; */ break; } cancount = 5; splat: switch(c = noxrd7()) { case ZPAD: goto splat; case RCDO: case TIMEOUT: goto fifi; default: goto agn2; case ZDLE: /* This is what we want. */ break; } Rxhlen = 4; /* Set default length */ Rxframeind = c = noxrd7(); switch (c) { case ZVBIN32: if ((Rxhlen = c = zdlread()) < 0) goto fifi; if (c > ZMAXHLEN) goto agn2; Crc32r = 1; c = zrbhdr32(hdr); break; case ZBIN32: if (Usevhdrs) goto agn2; Crc32r = 1; c = zrbhdr32(hdr); break; case ZVBINR32: if ((Rxhlen = c = zdlread()) < 0) goto fifi; if (c > ZMAXHLEN) goto agn2; Crc32r = 2; c = zrbhdr32(hdr); break; case ZBINR32: if (Usevhdrs) goto agn2; Crc32r = 2; c = zrbhdr32(hdr); break; case RCDO: case TIMEOUT: goto fifi; case ZVBIN: if ((Rxhlen = c = zdlread()) < 0) goto fifi; if (c > ZMAXHLEN) goto agn2; Crc32r = 0; c = zrbhdr(hdr); break; case ZBIN: if (Usevhdrs) goto agn2; Crc32r = 0; c = zrbhdr(hdr); break; case ZVHEX: if ((Rxhlen = c = zgethex()) < 0) goto fifi; if (c > ZMAXHLEN) goto agn2; Crc32r = 0; c = zrhhdr(hdr); break; case ZHEX: if (Usevhdrs) goto agn2; Crc32r = 0; c = zrhhdr(hdr); break; case CAN: goto gotcan; default: goto agn2; } Rxpos = hdr[ZP3] & 0377; Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377); Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377); Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377); fifi: switch(c) { case GOTCAN: c = ZCAN; /* **** FALL THRU TO **** */ case ZNAK: case ZCAN: case ERROR: case TIMEOUT: case RCDO: sprintf(s128,"Got %s",frametypes[c+FTOFFSET]); report_str(s128,1); /* **** FALL THRU TO **** */ default: if(c >= -4 && c <= FRTYPES) sprintf(s128,"hdr %c %d %s %ld", Rxframeind, Rxhlen, frametypes[c+FTOFFSET], Rxpos); else sprintf(s128,"hdr %c 0x%02x? %ld",Rxframeind,c,Rxpos); report_last_rxhdr(s128,0); } report_rx_ind(0); /* Use variable length headers if we got one */ if (c >= 0 && c <= FRTYPES && Rxframeind & 040) Usevhdrs = 1; return(c); } /* Receive a binary style header (type and position) */ zrbhdr(hdr) register char *hdr; { register int c,n; register unsigned short crc; if((c = zdlread()) & ~0377) return(c); Rxtype = c; crc = updcrc(c,0); for(n=Rxhlen; --n >= 0; ++hdr) { if((c = zdlread()) & ~0377) return(c); crc = updcrc(c,crc); *hdr = c; } if((c = zdlread()) & ~0377) return(c); crc = updcrc(c,crc); if((c = zdlread()) & ~0377) return(c); crc = updcrc(c,crc); if(crc & 0xFFFF) { if(Not8bit) report_str(masked,1); report_str(badcrc,0); return(ERROR); } #if defined(ZMODEM) Protocol = ZMODEM; #endif Zmodem = 1; return(Rxtype); } /* Receive a binary style header (type and position) with 32 bit FCS */ zrbhdr32(hdr) register char *hdr; { register int c,n; register UNSL long crc; if((c = zdlread()) & ~0377) return(c); Rxtype = c; crc = 0xFFFFFFFFL; crc = UPDC32(c,crc); for(n=Rxhlen; --n >= 0; ++hdr) { if((c = zdlread()) & ~0377) return(c); crc = UPDC32(c,crc); *hdr = c; } for(n=4; --n >= 0;) { if((c = zdlread()) & ~0377) return(c); crc = UPDC32(c,crc); } if(crc != 0xDEBB20E3) { if(Not8bit) report_str(masked,1); report_str(badcrc,0); return(ERROR); } #if defined(ZMODEM) Protocol = ZMODEM; #endif Zmodem = 1; return(Rxtype); } /* Receive a hex style header (type and position) */ zrhhdr(hdr) char *hdr; { register int c; register unsigned short crc; register int n; if((c = zgethex()) < 0) return(c); Rxtype = c; crc = updcrc(c,0); for(n=Rxhlen; --n >= 0; ++hdr) { if((c = zgethex()) < 0) return(c); crc = updcrc(c,crc); *hdr = c; } if((c = zgethex()) < 0) return(c); crc = updcrc(c,crc); if((c = zgethex()) < 0) return(c); crc = updcrc(c,crc); if(crc & 0xFFFF) { report_str(badcrc,0); return(ERROR); } switch ( c = readline(2)) { case 0215: Not8bit = c; /* **** FALL THRU TO **** */ case 015: /* Throw away possible cr/lf */ switch (c = readline(2)) { case 012: Not8bit |= c; } } #if defined(ZMODEM) Protocol = ZMODEM; #endif Zmodem = 1; return(Rxtype); } /* Send a byte as two hex digits */ zputhex(c) register int c; { static char digits[] = "0123456789abcdef"; sendline(digits[(c&0xF0)>>4]); sendline(digits[(c)&0xF]); } /* * Send character c with ZMODEM escape sequence encoding. * Escape XON,XOFF. Escape CR following @ (Telenet net escape) */ zsendline(c) { /* Quick check for non control characters */ if(c & 0140) xsendline(lastsent = c); else { switch(c &= 0377) { case ZDLE: xsendline(ZDLE); xsendline(lastsent = (c ^= 0100)); break; case 015: case 0215: if(!Zctlesc && (lastsent & 0177) != '@') goto sendit; /* **** FALL THRU TO **** */ case 020: case 021: case 023: case 0220: case 0221: case 0223: xsendline(ZDLE); c ^= 0100; sendit: xsendline(lastsent = c); break; default: if(Zctlesc && ! (c & 0140)) { xsendline(ZDLE); c ^= 0100; } xsendline(lastsent = c); } } } /* Decode two lower case hex digits into an 8 bit byte value */ zgethex() { register int c; c = zgeth1(); return(c); } zgeth1() { register int c,n; if((c = noxrd7()) < 0) return(c); n = c - '0'; if(n > 9) n -= ('a' - ':'); if(n & ~0xF) return(ERROR); if((c = noxrd7()) < 0) return(c); c -= '0'; if(c > 9) c -= ('a' - ':'); if(c & ~0xF) return(ERROR); c += (n<<4); return(c); } /* * Read a byte,checking for ZMODEM escape encoding * including CAN*5 which represents a quick abort */ zdlread() { register int c; again: /* Quick check for non control characters */ if((c = readline(Rxtimeout)) & 0140) return(c); switch(c) { case ZDLE: break; case 023: case 0223: case 021: case 0221: goto again; default: if(Zctlesc && !(c & 0140)) { goto again; } return(c); } again2: if((c = readline(Rxtimeout)) < 0) return(c); if(c == CAN && (c = readline(Rxtimeout)) < 0) return(c); if(c == CAN && (c = readline(Rxtimeout)) < 0) return(c); if(c == CAN && (c = readline(Rxtimeout)) < 0) return(c); switch(c) { case CAN: return(GOTCAN); case ZCRCE: case ZCRCG: case ZCRCQ: case ZCRCW: return(c | GOTOR); case ZRUB0: return(0177); case ZRUB1: return(0377); case 023: case 0223: case 021: case 0221: goto again2; default: if(Zctlesc && ! (c & 0140)) { goto again2; } if((c & 0140) == 0100) return(c ^ 0100); break; } sprintf(s128,"Bad escape sequence %x",c); report_str(s128,1); return(ERROR); } /* * Read a character from the modem line with timeout. * Eat parity,XON and XOFF characters. */ noxrd7() { register int c; for(;;) { if((c = readline(Rxtimeout)) < 0) return(c); switch(c &= 0177) { case XON: case XOFF: continue; default: if(Zctlesc && !(c & 0140)) continue; case '\r': case '\n': case ZDLE: return(c); } } } /* Store long integer pos in Txhdr */ stohdr(pos) long pos; { Txhdr[ZP0] = pos; Txhdr[ZP1] = pos>>8; Txhdr[ZP2] = pos>>16; Txhdr[ZP3] = pos>>24; } /* Recover a long integer from a header */ long rclhdr(hdr) register char *hdr; { register long l; l = (hdr[ZP3] & 0377); l = (l << 8) | (hdr[ZP2] & 0377); l = (l << 8) | (hdr[ZP1] & 0377); l = (l << 8) | (hdr[ZP0] & 0377); return(l); } /* * File: zmr.c 07-30-1989 * Copyright 1988, 1989 Omen Technology Inc All Rights Reserved * * * * This module implements ZMODEM Run Length Encoding, an * extension that was not funded by the original Telenet * development contract. * * This software may be freely used for non commercial and * educational (didactic only) purposes. This software may also * be freely used to support file transfer operations to or from * licensed Omen Technology products. Any programs which use * part or all of this software must be provided in source form * with this notice intact except by written permission from Omen * Technology Incorporated. * * Use of this software for commercial or administrative purposes * except when exclusively limited to interfacing Omen Technology * products requires a per port license payment of $20.00 US per * port (less in quantity). Use of this code by inclusion, * decompilation, reverse engineering or any other means * constitutes agreement to these conditions and acceptance of * liability to license the materials and payment of reasonable * legal costs necessary to enforce this license agreement. * * * Omen Technology Inc FAX: 503-621-3745 * Post Office Box 4681 * Portland OR 97208 * * This code is made available in the hope it will be useful, * BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY * DAMAGES OF ANY KIND. * * ZMODEM RLE compression and decompression functions */ /* Send data subpacket RLE encoded with 32 bit FCS */ zsdar32(buf, length, frameend) char *buf; { register int c, l, n; register UNSL long crc; crc = 0xFFFFFFFFL; l = *buf++ & 0377; if (length == 1) { zsendline(l); crc = UPDC32(l, crc); if (l == ZRESC) { zsendline(1); crc = UPDC32(1, crc); } } else { for (n = 0; --length >= 0; ++buf) { if ((c = *buf & 0377) == l && n < 126 && length>0) { ++n; continue; } switch (n) { case 0: zsendline(l); crc = UPDC32(l, crc); if (l == ZRESC) { zsendline(0100); crc = UPDC32(0100, crc); } l = c; break; case 1: if (l != ZRESC) { zsendline(l); zsendline(l); crc = UPDC32(l, crc); crc = UPDC32(l, crc); n = 0; l = c; break; } /* **** FALL THRU TO **** */ default: zsendline(ZRESC); crc = UPDC32(ZRESC, crc); if (l == 040 && n < 34) { n += 036; zsendline(n); crc = UPDC32(n, crc); } else { n += 0101; zsendline(n); crc = UPDC32(n, crc); zsendline(l); crc = UPDC32(l, crc); } n = 0; l = c; break; } } } xsendline(ZDLE); xsendline(frameend); crc = UPDC32(frameend, crc); crc = ~crc; for (length=4; --length >= 0;) { zsendline((int)crc); crc >>= 8; } } /* Receive data subpacket RLE encoded with 32 bit FCS */ zrdatr32(buf, length) register char *buf; { register int c; register UNSL long crc; register char *end; register int d; crc = 0xFFFFFFFFL; Rxcount = 0; end = buf + length; d = 0; /* Use for RLE decoder state */ while (buf <= end) { if ((c = zdlread()) & ~0377) { crcfoo: switch (c) { case GOTCRCE: case GOTCRCG: case GOTCRCQ: case GOTCRCW: d = c; c &= 0377; crc = UPDC32(c, crc); if ((c = zdlread()) & ~0377) goto crcfoo; crc = UPDC32(c, crc); if ((c = zdlread()) & ~0377) goto crcfoo; crc = UPDC32(c, crc); if ((c = zdlread()) & ~0377) goto crcfoo; crc = UPDC32(c, crc); if ((c = zdlread()) & ~0377) goto crcfoo; crc = UPDC32(c, crc); if (crc != 0xDEBB20E3) { report_str(badcrc,0); report_rx_ind(0); return ERROR; } Rxcount = length - (end - buf); #ifndef DSZ sprintf(s128, "data %s %d bytes", Zendnames[d-GOTCRCE&3], Rxcount); report_last_rxhdr(s128,0); report_rx_ind(0); #endif return d; case GOTCAN: report_str("Sender Cancelled",1); report_rx_ind(0); return ZCAN; case TIMEOUT: report_str("TIMEOUT",1); report_rx_ind(0); return c; default: report_str("Bad data subpacket",1); report_rx_ind(0); return c; } } crc = UPDC32(c, crc); switch (d) { case 0: if (c == ZRESC) { d = -1; continue; } *buf++ = c; continue; case -1: if (c >= 040 && c < 0100) { d = c - 035; c = 040; goto spaces; } if (c == 0100) { d = 0; *buf++ = ZRESC; continue; } d = c; continue; default: d -= 0100; if (d < 1) goto badpkt; spaces: if ((buf + d) > end) goto badpkt; while ( --d >= 0) *buf++ = c; d = 0; continue; } } badpkt: report_str("Data subpacket too long",1); report_rx_ind(0); return ERROR; } /* end of zmodem.c */ /* vi: set tabstop=4 shiftwidth=4: */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.