/************************ START OF XFER MODULE 2 ****************************/ /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */ #include "zmp.h" #include "zmodem.h" #ifdef AZTEC_C #include "libc.h" #else #include #endif /* * Attention string to be executed by receiver to interrupt streaming data * when an error is detected. A pause (0336) may be needed before the * ^C (03) or after it. 0337 causes a break to be sent. */ #define SLEEP 0336 char *ltoa(), *grabmem(); char Myattn[] = { CTRLC,SLEEP,0 }; unsigned Txwindow = 0; /* Control the size of the transmitted window */ unsigned Txwspac; /* Spacing between zcrcq requests */ unsigned Txwcnt; /* Counter used to space ack requests */ int Noeofseen; int Totsecs; /* total number of sectors this file */ char *Txbuf; int Filcnt; /* count of number of files opened */ unsigned Rxbuflen = 16384; /* Receiver's max buffer length */ int Rxflags = 0; long Bytcnt; long Lastread; /* Beginning offset of last buffer read */ int Lastn; /* Count of last buffer read or -1 */ int Dontread; /* Don't read the buffer, it's still there */ long Lastsync; /* Last offset to which we got a ZRPOS */ int Beenhereb4; /* How many times we've been ZRPOS'd same place */ int Incnt; /* count for chars not read from the Cpmbuf */ wcsend(argc, argp) int argc; /* nr of files to send */ char *argp[]; /* list of file names */ { int n, status; slabel(); Zctlesc = 0; Incnt = 0; Baudrate = Baudtable[Current.cbaudindex]; Filcnt = Errors = 0; #ifdef AZTEC_C Fd = 0; #else Fd = -1; #endif Txbuf = malloc(KSIZE); if (allocerror(Txbuf)) return NERROR; Cpmbuf = grabmem(&Cpbufsize); if (allocerror(Cpmbuf)) return NERROR; Cpindex = 0; /* just in case */ Crcflag = FALSE; Firstsec = TRUE; Bytcnt = -1; Rxtimeout = 600; savecurs(); hidecurs(); box(); status = NERROR; report(PROTOCOL,Xmodem?"XMODEM Send":Zmodem?"ZMODEM Send":"YMODEM Send"); if (Zmodem) { stohdr(0L); zshhdr(ZRQINIT, Txhdr); if (getzrxinit()==NERROR) goto badreturn; } for (n=0; n 0); /* delete it */ if (k < 0) *p++ = '-'; *p = 0; /* reverse string in place */ while (q < --p) { c = *q; *q++ = *p; *p = c; } return (s); } /* ltoa - convert n to characters in s. */ char *ltoa(n, s) char s[]; long n; { static long c, k; static char *p, *q; if ((k = n) < 0) /* record sign */ n = -n; /* make n positive */ q = p = s; do { /* generate digits in reverse order */ *p++ = n % 10 + '0'; /* get next digit */ } while ((n /= 10) > 0); /* delete it */ if (k < 0) *p++ = '-'; *p = 0; /* reverse string in place */ while (q < --p) { c = *q; *q++ = *p; *p = c; } return (s); } getnak() { static int firstch; Lastrx = 0; for (;;) { if (opabort()) return NERROR; switch (firstch = readock(800,1)) { case ZPAD: if (getzrxinit()) return NERROR; return FALSE; case TIMEOUT: zperr("Timeout on PName",TRUE); return TRUE; case WANTCRC: Crcflag = TRUE; case NAK: return FALSE; case CAN: if ((firstch = readock(20,1)) == CAN && Lastrx == CAN) return TRUE; default: break; } Lastrx = firstch; } report(BLKCHECK,Crcflag?"CRC":"Checksum"); } wctx(flen) long flen; { static int thisblklen, i; static unsigned sectnum, attempts, firstch, totsecs; static long charssent; charssent = 0L; Firstsec = TRUE; thisblklen = Blklen; i = 0; while ((firstch=readock(1,2)) != NAK && firstch != WANTCRC && firstch != CAN && !opabort() && ++i < Rxtimeout) ; if (QuitFlag) return NERROR; if (firstch==CAN) { zperr("Rcvr CANcelled",TRUE); return NERROR; } if (firstch==WANTCRC) Crcflag=TRUE; report(BLKCHECK,Crcflag?"CRC":"Checksum"); sectnum = totsecs = 0; for (;;) { if (opabort()) return NERROR; if (flen <= (charssent + 896L)) Blklen = thisblklen = 128; if ( !filbuf(Txbuf, thisblklen)) break; purgeline(); /* ignore anything got while loading */ if (wcputsec(Txbuf, ++sectnum, thisblklen)==NERROR) return NERROR; charssent += thisblklen; totsecs += thisblklen / 128; sreport(totsecs, charssent); } attempts=0; do { dreport(ERRORS,attempts); purgeline(); mcharout(EOT); ++attempts; } while ((firstch=(readock(Rxtimeout, 1)) != ACK) && attempts < RETRYMAX && !opabort() ); if (attempts == RETRYMAX) { zperr("No ACK on EOT",TRUE); return NERROR; } else if (QuitFlag) /* from opabort */ return NERROR; else return OK; } wcputsec(buf, sectnum, cseclen) char *buf; int sectnum; int cseclen; /* data length of this sector to send */ { static unsigned checksum; static char *cp; static unsigned oldcrc; static int wcj; static int firstch; static int attempts; firstch=0; /* part of logic to detect CAN CAN */ dreport(ERRORS,0); for (attempts=0; attempts <= RETRYMAX; attempts++) { if (opabort()) return NERROR; if (attempts) dreport(ERRORS,attempts); Lastrx= firstch; mcharout(cseclen==KSIZE?STX:SOH); mcharout(sectnum); mcharout(~sectnum); oldcrc=checksum=0; for (wcj=cseclen,cp=buf; --wcj>=0; ) { mcharout(*cp); oldcrc=updcrc((0377& *cp), oldcrc); checksum += *cp++; } if (Crcflag) { oldcrc=updcrc(0,updcrc(0,oldcrc)); mcharout((int)oldcrc>>8); mcharout((int)oldcrc); } else mcharout(checksum); firstch = readock(Rxtimeout, (Noeofseen&§num) ? 2:1); gotnak: switch (firstch) { case CAN: if(Lastrx == CAN) { cancan: zperr("Rcvr CANcelled",TRUE); return NERROR; } break; case TIMEOUT: zperr("Timeout on ACK",TRUE); continue; case WANTCRC: if (Firstsec) Crcflag = TRUE; report(BLKCHECK,Crcflag?"CRC":"Checksum"); case NAK: zperr("NAK on sector",TRUE); continue; case ACK: Firstsec=FALSE; Totsecs += (cseclen>>7); return OK; case NERROR: zperr("Got burst",TRUE); break; default: zperr("Bad sector ACK",TRUE); break; } for (;;) { if (opabort()) return NERROR; Lastrx = firstch; if ((firstch = readock(Rxtimeout, 2)) == TIMEOUT) break; if (firstch == NAK || firstch == WANTCRC) goto gotnak; if (firstch == CAN && Lastrx == CAN) goto cancan; } } zperr("Retry Exceeded",TRUE); return NERROR; } /* fill buf with count chars padding with ^Z for CPM */ filbuf(buf, count) char *buf; int count; { static int c, m; c = m = newload(buf, count); if (m <= 0) return 0; while (m < count) buf[m++] = CTRLZ; return c; } newload(buf, count) int count; char *buf; { static int j; j = 0; while (count--) { if (Incnt <= 0) { #ifdef AZTEC_C Incnt = fread( Cpmbuf, 1, Cpbufsize, Fd); #else Incnt = read( Fd, Cpmbuf, Cpbufsize ); #endif Cpindex = 0; if (Incnt <= 0) break; } buf[j++] = Cpmbuf[Cpindex++]; --Incnt; } return (j ? j : -1); } /************************** END OF MODULE 7 *********************************/