/********************** START OF XFER MODULE 4 ******************************/ /* rz.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 int Tryzhdrtype; /* Header type to send corresponding to Last rx close */ char *Rxptr, *malloc(); long lseek(); wcreceive(filename) char *filename; { char *grabmem(); static int c; rlabel(); QuitFlag = FALSE; Zctlesc = 0; Baudrate = Baudtable[Current.cbaudindex]; Tryzhdrtype = ZRINIT; Secbuf = malloc(KSIZE + 1); if (allocerror(Secbuf)) return NERROR; Cpmbuf = grabmem(&Cpbufsize); if (allocerror(Cpmbuf)) return NERROR; Cpindex = 0; /* just in case */ Rxptr = Cpmbuf; /* ditto */ Fd = UBIOT; /* ditto ditto */ Rxtimeout = 100; /* 10 seconds */ Errors = 0; #ifdef DEBUG printf("\nbuffer size = %u\n",Cpbufsize); wait(5); #endif savecurs(); hidecurs(); box(); if (filename == (char *) 0) { /* batch transfer */ Crcflag=(Wcsmask==0377); if (c=tryz()) { /* zmodem transfer */ report(PROTOCOL,"ZMODEM Receive"); if (c == ZCOMPL) goto good; if (c == NERROR) goto fubar; c = rzmfile(); if (c) goto fubar; } else { /* ymodem batch transfer */ report(PROTOCOL,"YMODEM Receive"); report(BLKCHECK,Crcflag?"CRC":"Checksum"); for (;;) { if (opabort()) goto fubar; if (wcrxpn(Secbuf)== NERROR) goto fubar; if (Secbuf[0]==0) goto good; if (procheader(Secbuf) == NERROR) goto fubar; if (wcrx()==NERROR) goto fubar; } } } else { report(PROTOCOL,"XMODEM Receive"); strcpy(Pathname,filename); checkpath(Pathname); testexist(Pathname); Fd = creat(Pathname,0); if (openerror(Fd,Pathname,UBIOT)) goto fubar1; if (wcrx()==NERROR) /* xmodem */ goto fubar; } good: free(Cpmbuf); free(Secbuf); showcurs(); restcurs(); return OK; fubar: canit(); if (Fd >= 0) { if (Zmodem && askuser("Save partial file? \007") && !closeit()) goto good; /* user might try again */ else unlink(Pathname); /* erase incomplete file */ } fubar1: free(Cpmbuf); free(Secbuf); showcurs(); restcurs(); return NERROR; } /* * 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) */ wcrxpn(rpn) char *rpn; /* receive a pathname */ { static int c; purgeline(); et_tu: Firstsec=TRUE; Eofseen=FALSE; mcharout(Crcflag?WANTCRC:NAK); while ((c = wcgetsec(rpn, 100)) != 0) { if (QuitFlag) return NERROR; if (c == WCEOT) { mcharout(ACK); readline(INTRATIME); goto et_tu; } return NERROR; } mcharout(ACK); return OK; } /* * Adapted from CMODEM13.C, written by * Jack M. Wierda and Roderick W. Hart */ wcrx() { static int sectnum, sectcurr; static unsigned totsecs; static char sendchar; static int cblklen; /* bytes to dump this block */ long charsgot; Firstsec=TRUE; sectnum = totsecs = 0; charsgot = 0L; Eofseen=FALSE; sendchar=Crcflag?WANTCRC:NAK; report(BLKCHECK,Crcflag?"CRC":"Checksum"); for (;;) { if (opabort()) return NERROR; mcharout(sendchar); /* send it now, we're ready! */ sectcurr = wcgetsec(Rxptr, Firstsec || (sectnum&0177) ? 50 : 130); if (sectcurr==(sectnum+1 &Wcsmask)) { sectnum++; totsecs += Blklen / 128; charsgot += Blklen; sreport(totsecs, charsgot); cblklen = Blklen; if (putsec(cblklen,FALSE)==NERROR) return NERROR; sendchar=ACK; } else if (sectcurr==(sectnum&Wcsmask)) { zperr("Duplicate Sector",TRUE); sendchar=ACK; } else if (sectcurr==WCEOT) { if (closeit()) return NERROR; mcharout(ACK); return OK; } else if (sectcurr==NERROR) return NERROR; else { zperr( "Sync Error",TRUE); return NERROR; } } } /* * Wcgetsec fetches a Ward Christensen type sector. * Returns sector number encountered or NERROR if valid sector not received, * or CAN CAN received * or WCEOT if eot sector * time is timeout for first char, set to 4 seconds thereafter ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK ************** * (Caller must do that when he is good and ready to get next sector) */ wcgetsec(rxbuf, maxtime) char *rxbuf; int maxtime; { static int checksum, wcj, firstch; static unsigned oldcrc; static char *p; static int sectcurr; for (Lastrx=Errors=0; Errors < RETRYMAX; ) { /* errors incr by zperr */ if (opabort()) return NERROR; if ((firstch=readline(maxtime))==STX) { Blklen=KSIZE; goto get2; } if (firstch==SOH) { Blklen=SECSIZ; get2: sectcurr=readline(INTRATIME); if ((sectcurr+(oldcrc=readline(INTRATIME)))==Wcsmask) { oldcrc=checksum=0; for (p=rxbuf,wcj=Blklen; --wcj>=0; ) { if ((firstch=readline(INTRATIME)) < 0) goto bilge; oldcrc=updcrc(firstch, oldcrc); checksum += (*p++ = firstch); } if ((firstch=readline(INTRATIME)) < 0) goto bilge; if (Crcflag) { oldcrc=updcrc(firstch, oldcrc); if ((firstch=readline(INTRATIME)) < 0) goto bilge; oldcrc=updcrc(firstch, oldcrc); if (oldcrc & 0xFFFF) zperr( "CRC Error",TRUE); else { Firstsec=FALSE; return sectcurr; } } else if (((checksum-firstch)&Wcsmask)==0) { Firstsec=FALSE; return sectcurr; } else zperr("Checksum error",TRUE); } else zperr("Block nr garbled",TRUE); } /* make sure eot really is eot and not just mixmash */ else if (firstch==EOT && readline(10)==TIMEOUT) return WCEOT; else if (firstch==CAN) { if (Lastrx==CAN) { zperr( "Sender CANcelled",TRUE); return NERROR; } else { Lastrx=CAN; continue; } } else if (firstch==TIMEOUT) { if (Firstsec) { zperr( "TIMEOUT",TRUE); goto humbug; } bilge: zperr( "TIMEOUT",TRUE); } else zperr( "Bad header",TRUE); humbug: Lastrx=0; while(readline(50) != TIMEOUT) if (QuitFlag) return NERROR; if (Firstsec) { if (Xmodem && (Errors == RETRYMAX/2)) Crcflag = !Crcflag; report(BLKCHECK,Crcflag?"CRC":"Checksum"); mcharout(Crcflag?WANTCRC:NAK); } else { maxtime=40; mcharout(NAK); } } /* try to stop the bubble machine. */ canit(); return NERROR; } /* * Process incoming file information header */ procheader(name) char *name; { long atol(); static char *p, *ap, c; /* * Process YMODEM,ZMODEM remote file management requests */ clrreports(); p = name + 1 + strlen(name); if (*p) { /* file coming from Unix or DOS system */ ap = p; while ((c = *p) && (c != ' ')) /* find first space or null */ ++p; if (c) *p = '\0'; /* ap now points to a long integer in ascii */ report(FILESIZE,ap); report(SENDTIME,ttime(atol(ap))); } strcpy(Pathname, name); checkpath(Pathname); if (testexist(Pathname)) { Fd = open(Pathname,2); /* append to existing file */ Lrxpos = lseek(Fd, 0L, 2); /* zmodem only */ } else { Fd = creat(Pathname, 0); /* new file */ Lrxpos = 0L; } if (openerror(Fd,Pathname,UBIOT)) return NERROR; return OK; } /* * substr(string, token) searches for token in string s * returns pointer to token within string if found, NULL otherwise */ char * substr(s, t) char *s,*t; { static int i; if ((i=stindex(s,t)) != -1) return s+i; else return NULL; } /* send cancel string to get the other end to shut up */ canit() { static char canistr[] = { 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 }; mstrout(canistr,FALSE); purgeline(); } clrreports() { static int i; for (i=4; i<14; i++) clrline(i); } /************************** END OF MODULE 8 *********************************/