/* Send ZMODEM binary header hdr of type type */ void zsbhdr(int type, char *hdr) { register int n; register unsigned short crc; if (type == ZDATA) for (n = Znulls; --n >= 0;) xsendline(0); xsendline(ZPAD); xsendline(ZDLE); Crc32t = Txfcs32; if (Crc32t) zsbh32(hdr, type); else { xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0); for (n = 4; --n >= 0; ++hdr) { zsendline(*hdr); crc = updcrc((0377 & *hdr), crc); } crc = updcrc(0, updcrc(0, crc)); zsendline(crc >> 8); zsendline(crc); } if (type != ZDATA) flushmo(); }
void zsda32(const char *buf, size_t length, int frameend) { int c; unsigned long crc; int i; crc = 0xFFFFFFFFL; zsendline_s(buf, length); for (; length; length--) { c = *buf & 0377; crc = UPDC32(c, crc); buf++; } xsendline(ZDLE); xsendline(frameend); crc = UPDC32(frameend, crc); crc = ~crc; for (i = 4; --i >= 0;) { c = (int) crc; if (c & 0140) xsendline(lastsent = c); else zsendline(c); crc >>= 8; } if (frameend == ZCRCW) { xsendline(XON); flushmo(); } }
/* Send ZMODEM binary header hdr of type type */ void zsbhdr(int type, char *hdr) { vfile(F("zsbhdr: %s %lx"), frametypes[type+FTOFFSET], rclhdr(hdr)); /* if (type == ZDATA) for (n = Znulls; --n >=0; ) xsendline(0); */ xsendline(ZPAD); xsendline(ZDLE); //Pete (El Supremo) This looks wrong but it is correct - the code fails if == is used if ((Crc32t = Txfcs32)) { int n; UNSL long crc; xsendline(ZBIN32); zsendline(type); crc = 0xFFFFFFFFL; crc = UPDC32(type, crc); for (n=4; --n >= 0; ++hdr) { crc = UPDC32((0377 & *hdr), crc); zsendline(*hdr); } crc = ~crc; for (n=4; --n >= 0;) { zsendline((int)crc); crc >>= 8; } } else {
static int wcrx(void) { int sectnum, sectcurr; char sendchar; int cblklen; /* bytes to dump this block */ Firstsec = TRUE; sectnum = 0; Eofseen = FALSE; sendchar = Crcflg ? WANTCRC : NAK; for (;;) { xsendline(sendchar); /* send it now, we're ready! */ Lleft = 0; /* Do read next time ... */ sectcurr = wcgetsec(secbuf, (sectnum & 0177) ? 50 : 130); report(sectcurr); if (sectcurr == ((sectnum + 1) & 0377)) { sectnum++; cblklen = Bytesleft > Blklen ? Blklen : Bytesleft; if (putsec(secbuf, cblklen) == ERROR) return ERROR; if ((Bytesleft -= cblklen) < 0) Bytesleft = 0; sendchar = ACK; } else if (sectcurr == (sectnum & 0377)) { zperr("Received dup Sector"); sendchar = ACK; } else if (sectcurr == WCEOT) { if (closeit()) return ERROR; xsendline(ACK); Lleft = 0; /* Do read next time ... */ return OK; } else if (sectcurr == ERROR) return ERROR; else { zperr("Sync Error"); return ERROR; } } }
/* * Send binary array buf of length length, with ending ZDLE sequence frameend */ void zsdata(const char *buf, size_t length, int frameend) { register unsigned short crc; crc = 0; do { zsendline(*buf); crc = updcrc((0377 & *buf), crc); buf++; } while (--length > 0); xsendline(ZDLE); xsendline(frameend); crc = updcrc(frameend, crc); crc = updcrc(0, updcrc(0, crc)); zsendline(crc >> 8); zsendline(crc); if (frameend == ZCRCW) { xsendline(XON); flushmo(); } }
/* * Fetch a pathname from the other end as a C ctyle ASCIZ string. * Length is indeterminate as long as less than Blklen * A null string represents no more files (YMODEM) */ static int wcrxpn(char *rpn) { int c; readline(1); et_tu: Firstsec = TRUE; Eofseen = FALSE; xsendline(Crcflg ? WANTCRC : NAK); Lleft = 0; /* Do read next time ... */ while ((c = wcgetsec(rpn, 100)) != 0) { if (c == WCEOT) { zperr("Pathname fetch returned %d", c); xsendline(ACK); Lleft = 0; /* Do read next time ... */ readline(1); goto et_tu; } return ERROR; } xsendline(ACK); return OK; }
/* Send ZMODEM binary header hdr of type type */ static void zsbh32(char *hdr, int type) { register int n; register unsigned long crc; xsendline(ZBIN32); zsendline(type); crc = 0xFFFFFFFFL; crc = UPDC32(type, crc); for (n = 4; --n >= 0; ++hdr) { crc = UPDC32((0377 & *hdr), crc); zsendline(*hdr); } crc = ~crc; for (n = 4; --n >= 0;) { zsendline((int) crc); crc >>= 8; } }
static inline void zsendline_s(const char *s, size_t count) { const char *end = s + count; while (s != end) { int last_esc = 0; const char *t = s; while (t != end) { last_esc = zsendline_tab[(unsigned) ((*t) & 0377)]; if (last_esc) break; t++; } if (t != s) { raw_write(0, s, (t - s)); lastsent = t[-1]; s = t; } if (last_esc) { int c = *s; switch (last_esc) { case 0: xsendline(lastsent = c); break; case 1: xsendline(ZDLE); c ^= 0100; xsendline(lastsent = c); break; case 2: if ((lastsent & 0177) != '@') { xsendline(lastsent = c); } else { xsendline(ZDLE); c ^= 0100; xsendline(lastsent = c); } break; } s++; } } }
/* * Send character c with ZMODEM escape sequence encoding. * Escape XON, XOFF. Escape CR following @ (Telenet net escape) */ inline void zsendline(int c) { switch (zsendline_tab[(unsigned) (c &= 0377)]) { case 0: xsendline(lastsent = c); break; case 1: xsendline(ZDLE); c ^= 0100; xsendline(lastsent = c); break; case 2: if ((lastsent & 0177) != '@') { xsendline(lastsent = c); } else { xsendline(ZDLE); c ^= 0100; xsendline(lastsent = c); } break; } }
/* * Receive a file with ZMODEM protocol * Assumes file name frame is in secbuf */ static int rzfile(void) { int c, n; long last_rxbytes = 0; long not_printed = 0; last_bps = 0; Eofseen = FALSE; n = 20; rxbytes = 0l; if (procheader(secbuf) == ERROR) { return (tryzhdrtype = ZSKIP); } for (;;) { stohdr(rxbytes); zshhdr(ZRPOS, Txhdr); nxthdr: switch (c = zgethdr(Rxhdr, 0)) { default: vfile("lrzfile: zgethdr returned %d", c); return ERROR; case ZNAK: case TIMEOUT: if (--n < 0) { vfile("lrzfile: zgethdr returned %d", c); return ERROR; } case ZFILE: zrdata(secbuf, MAX_BLOCK); continue; case ZEOF: if (rclhdr(Rxhdr) != rxbytes) { /* * Ignore eof if it's at wrong place - force * a timeout because the eof might have gone * out before we sent our zrpos. */ errors = 0; goto nxthdr; } if (Verbose > 1) { int minleft = 0; int secleft = 0; last_bps = (rxbytes / timing(0)); if (last_bps > 0) { minleft = (Bytesleft - rxbytes) / last_bps / 60; secleft = ((Bytesleft - rxbytes) / last_bps) % 60; } fprintf(stderr, "\rBytes Received: %7ld/%7ld BPS:%-6d \r\n", rxbytes, Bytesleft, last_bps); } closeok = 1; if (closeit()) { tryzhdrtype = ZFERR; vfile("lrzfile: closeit returned <> 0"); return ERROR; } vfile("lrzfile: normal EOF"); return c; case ERROR: /* Too much garbage in header search error */ if (--n < 0) { vfile("lrzfile: zgethdr returned %d", c); return ERROR; } zmputs(Attn); continue; case ZSKIP: closeit(); vfile("lrzfile: Sender SKIPPED file"); return c; case ZDATA: if (rclhdr(Rxhdr) != rxbytes) { if (--n < 0) { return ERROR; } zmputs(Attn); continue; } moredata: if (Verbose > 1 && (not_printed > 7 || rxbytes > last_bps / 2 + last_rxbytes)) { int minleft = 0; int secleft = 0; last_bps = (rxbytes / timing(0)); if (last_bps > 0) { minleft = (Bytesleft - rxbytes) / last_bps / 60; secleft = ((Bytesleft - rxbytes) / last_bps) % 60; } fprintf(stderr, "\rBytes Received: %7ld/%7ld BPS:%-6d ETA %02d:%02d ", rxbytes, Bytesleft, last_bps, minleft, secleft); last_rxbytes = rxbytes; not_printed = 0; if (nodeinf != -1 && ((time(0) - lup) > 5)) { lseek(nodeinf, 0, SEEK_SET); nin.ddn_bpsrate = last_bps; sprintf(nin.ddn_activity, "UL: %-34.34s", myname); write(nodeinf, &nin, sizeof(struct DayDream_NodeInfo)); lup = time(0); } } else if (Verbose) not_printed++; switch (c = zrdata(secbuf, MAX_BLOCK)) { case ZCAN: vfile("lrzfile: zgethdr returned %d", c); return ERROR; case ERROR: /* CRC error */ if (--n < 0) { vfile ("lrzfile: zgethdr returned %d", c); return ERROR; } zmputs(Attn); continue; case TIMEOUT: if (--n < 0) { vfile ("lrzfile: zgethdr returned %d", c); return ERROR; } continue; case GOTCRCW: n = 20; putsec(secbuf, Rxcount); rxbytes += Rxcount; stohdr(rxbytes); zshhdr(ZACK, Txhdr); xsendline(XON); goto nxthdr; case GOTCRCQ: n = 20; putsec(secbuf, Rxcount); rxbytes += Rxcount; stohdr(rxbytes); zshhdr(ZACK, Txhdr); goto moredata; case GOTCRCG: n = 20; putsec(secbuf, Rxcount); rxbytes += Rxcount; goto moredata; case GOTCRCE: n = 20; putsec(secbuf, Rxcount); rxbytes += Rxcount; goto nxthdr; } } } }
static int wcgetsec(char *rxbuf, int maxtime) { int checksum, wcj, firstch; unsigned short oldcrc; char *p; int sectcurr; for (Lastrx = errors = 0; errors < RETRYMAX; errors++) { if ((firstch = readline(maxtime)) == STX) { Blklen = 1024; goto get2; } if (firstch == SOH) { Blklen = 128; get2: sectcurr = readline(1); if ((sectcurr + (oldcrc = readline(1))) == 0377) { oldcrc = checksum = 0; for (p = rxbuf, wcj = Blklen; --wcj >= 0;) { if ((firstch = readline(1)) < 0) goto bilge; oldcrc = updcrc(firstch, oldcrc); checksum += (*p++ = firstch); } if ((firstch = readline(1)) < 0) goto bilge; if (Crcflg) { oldcrc = updcrc(firstch, oldcrc); if ((firstch = readline(1)) < 0) goto bilge; oldcrc = updcrc(firstch, oldcrc); if (oldcrc & 0xFFFF) zperr("CRC"); else { Firstsec = FALSE; return sectcurr; } } else if (((checksum - firstch) & 0377) == 0) { Firstsec = FALSE; return sectcurr; } else zperr("Checksum"); } else zperr("Sector number garbled"); } /* make sure eot really is eot and not just mixmash */ else if (firstch == EOT && readline(1) == TIMEOUT) return WCEOT; else if (firstch == CAN) { if (Lastrx == CAN) { zperr("Sender CANcelled"); return ERROR; } else { Lastrx = CAN; continue; } } else if (firstch == TIMEOUT) { if (Firstsec) goto humbug; bilge: zperr("TIMEOUT"); } else zperr("Got 0%o sector header", firstch); humbug: Lastrx = 0; while (readline(1) != TIMEOUT); if (Firstsec) { xsendline(Crcflg ? WANTCRC : NAK); Lleft = 0; /* Do read next time ... */ } else { maxtime = 40; xsendline(NAK); Lleft = 0; /* Do read next time ... */ } } /* try to stop the bubble machine. */ canit(); return ERROR; }