home *** CD-ROM | disk | FTP | other *** search
- /************************ START OF RZMP MODULE 3 ****************************/
-
- /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */
- /* Further modified rjm to remove xmodem/ymodem stuff for rzmp */
-
- #define RZMP
-
- #include "zmp.h"
- #include "zmodem.h"
-
- #ifdef AZTEC_C
- #include "libc.h"
- #else
- #include <stdio.h>
- #endif
-
- #include <setjmp.h>
- jmp_buf jb_stop;
-
-
- /*
- * 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(), *alloc(), *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();
- QuitFlag = FALSE;
- Zctlesc = 0;
- Incnt = 0;
- Baudrate = Baudtable[Current.cbaudindex];
- Filcnt = Errors = 0;
-
- #ifdef AZTEC_C
- Fd = 0;
- #else
- Fd = -1;
- #endif
-
- Txbuf = alloc(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,"ZMODEM Send");
- stohdr(0L);
- zshhdr(ZRQINIT, Txhdr);
- if (getzrxinit()==NERROR)
- goto badreturn;
- for (n=0; n<argc; ++n) {
- strcpy(Pathname,argp[n]);
- if (Private) {
- deldrive(Pathname); /* remove any du: */
- addu(Pathname,Dprivdrive,Dprivuser);
- }
- if (checkname(Pathname))
- continue; /* bad filetype */
- clrreports();
- Totsecs = 0;
- if (opabort() || wcs(Pathname) == NERROR)
- goto badreturn;
- tfclose();
- (*Downloads)++; /* only bump count if successful */
- savelog(Pathname); /* and write to disk */
- }
- Totsecs = 0;
- if (Filcnt==0) { /* we couldn't open ANY files */
- canit();
- goto badreturn;
- }
- zperr("Complete",FALSE);
- saybibi();
- status = OK;
-
- badreturn:
- free(Cpmbuf);
- free(Txbuf);
- showcurs();
- restcurs();
- if (status == NERROR)
- tfclose();
- return status;
- }
-
- wcs(oname)
- char *oname;
- {
- unsigned length;
- long flen;
-
- #ifdef AZTEC_C
- if ((Fd=fopen(oname,"rb"))==BUFIOT) {
- #else
- if ((Fd=open(oname,0))==UBIOT) {
- #endif
-
- zperr("Can't open file",TRUE);
- wait(2);
- return OK; /* pass over it, there may be others */
- }
- ++Noeofseen;
- Lastread = 0L;
- Lastn = -1;
- Dontread = FALSE;
- ++Filcnt;
- fstat(oname,&Fs);
- switch (wctxpn(oname)) { /* transmit path name */
- case NERROR:
- canit(); /* Send CAN */
- return NERROR;
-
- case ZSKIP:
- return OK;
- }
- length = Fs.records;
- flen = (long)length * 128;
- return 0;
- }
-
- /*
- * generate and transmit pathname block consisting of
- * pathname (null terminated),
- * file length, mode time (null) and file mode (null)
- * in octal.
- * N.B.: modifies the passed name, may extend it!
- */
- wctxpn(name)
- char *name;
- {
- static char *p;
- char buf[20];
- static unsigned length;
- static long nrbytes;
-
- memset(Txbuf,'\0',KSIZE);
- length = Fs.records;
- nrbytes = (long)length * 128;
- report(PATHNAME,name);
- lreport(FILESIZE,nrbytes);
- dreport(FBLOCKS,length);
- report(SENDTIME,ttime(nrbytes));
- strcpy(Txbuf,name);
- deldrive(Txbuf); /* remove drive ind if any */
- p = Txbuf + strlen(Txbuf);
- ++p;
- strcpy(p,ltoa(nrbytes,buf));
- return zsendfile(Txbuf, 1+strlen(p)+(p-Txbuf));
- }
-
- /* itoa - convert n to characters in s. */
- char *itoa(n, s)
- char s[];
- short n;
- {
- static short 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);
- }
-
- /* 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);
- }
-
- /* 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);
- }
-
- /*
- * Get the receiver's init parameters
- */
-
- getzrxinit()
- {
- static int n;
-
- for (n=10; --n>=0; ) {
- if (opabort())
- return NERROR;
- switch (zgethdr(Rxhdr, 1)) {
- case ZCHALLENGE: /* Echo receiver's challenge numbr */
- stohdr(Rxpos);
- zshhdr(ZACK, Txhdr);
- continue;
- case ZCOMMAND: /* They didn't see out ZRQINIT */
- stohdr(0L);
- zshhdr(ZRQINIT, Txhdr);
- continue;
- case ZRINIT:
- Rxflags = 0377 & Rxhdr[ZF0];
- Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
- Zctlesc |= Rxflags & TESCCTL;
- Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
- return (sendzsinit());
- case ZCAN:
- case TIMEOUT:
- return NERROR;
- case ZRQINIT:
- if (Rxhdr[ZF0] == ZCOMMAND)
- continue;
- default:
- zshhdr(ZNAK, Txhdr);
- continue;
- }
- }
- return NERROR;
- }
-
- /* Send send-init information */
-
- sendzsinit()
- {
- int tries;
-
- stohdr(0L); /* All flags are undefined */
- strcpy(Txbuf,Myattn); /* Copy Attn string */
- for (tries = 0; tries < 20; tries++)
- {
- if (opabort())
- return NERROR;
- zsbhdr(ZSINIT,Txhdr); /* Send binary header */
- zsdata(Txbuf,strlen(Txbuf) + 1,ZCRCW); /* Send string */
- if (zgethdr(Rxhdr,0) == ZACK)
- return OK;
- zperr("Bad ACK: ZSINIT",FALSE);
- }
- return NERROR;
- }
-
- /* Send file name and related info */
-
- zsendfile(buf, blen)
- char *buf;
- int blen;
- {
- static int c;
-
- for (;;) {
- if (opabort())
- return NERROR;
- Txhdr[ZF0] = 0; /* file conversion request */
- Txhdr[ZF1] = 0; /* file management request */
- Txhdr[ZF2] = 0; /* file transport request */
- Txhdr[ZF3] = 0;
- zsbhdr(ZFILE, Txhdr);
- zsdata(buf, blen, ZCRCW);
- again:
- c = zgethdr(Rxhdr, 1);
- switch (c) {
- case ZRINIT:
- while ((c = readline(INTRATIME)) > 0)
- if (c == ZPAD) {
- goto again;
- }
- /* **** FALL THRU TO **** */
- default:
- continue;
- case ZCAN:
- case TIMEOUT:
- case ZABORT:
- case ZFIN:
- return NERROR;
- case ZSKIP:
- return c;
- case ZRPOS:
- /*
- * Suppress zcrcw request otherwise triggered by
- * lastyunc==Bytcnt
- */
- Lastsync = (Bytcnt = Txpos = Rxpos) -1L;
-
- #ifdef AZTEC_C
- fseek(Fd, Rxpos, 0); /* absolute offset */
- #else
- lseek(Fd, Rxpos, 0); /* absolute offset */
- #endif
-
- clrline(KBYTES);
- Incnt = 0;
- Dontread = FALSE;
- c = zsndfdata();
- Sending = FALSE;
- return c;
- }
- }
- }
-
- /* Send the data in the file */
-
- zsndfdata()
- {
- static int c, e, n;
- static int newcnt;
- static long tcount;
- static int junkcount; /* Counts garbage chars received by TX */
-
- tcount = 0L;
- Blklen = 128;
- if (Baudrate > 300)
- Blklen = 256;
- if (Baudrate > 1200)
- Blklen = 512;
- if (Baudrate > 2400)
- Blklen = KSIZE;
- if (Rxbuflen && Blklen>Rxbuflen)
- Blklen = Rxbuflen;
- Lrxpos = 0L;
- junkcount = 0;
- Beenhereb4 = FALSE;
- Sending = Firstsec = TRUE;
- somemore:
- if (NULL) {
- waitack:
- junkcount = 0;
- c = getinsync(0);
- if (QuitFlag)
- return NERROR;
- gotack:
- if (setjmp(jb_stop)) { /* come here if rx stops us */
- rxint:
- c = getinsync(1);
- }
-
- switch (c) {
- default:
- case ZCAN:
- return NERROR;
- case ZSKIP:
- return c;
- case ZACK:
- case ZRPOS:
- break;
- case ZRINIT:
- return OK;
- }
- /*
- * If the reverse channel can be tested for data,
- * this logic may be used to detect error packets
- * sent by the receiver, in place of setjmp/longjmp
- * minprdy() returns non 0 if a character is available
- */
- while (minprdy()) {
- if (QuitFlag)
- return NERROR;
- switch (readline(1)) {
- case CTRLC:
- case CAN:
- case ZPAD:
- goto rxint;
- case XOFF: /* Wait a while for an XON */
- case XOFF|0200:
- readline(100);
- }
- }
- }
-
- if (setjmp(jb_stop)) { /* rx interrupt */
- c = getinsync(1);
- if (c == ZACK)
- goto gotanother;
- purgeline();
- /* zcrce - dinna wanna starta ping-pong game */
- zsdata(Txbuf, 0, ZCRCE);
- goto gotack;
- }
-
- newcnt = Rxbuflen;
- Txwcnt = 0;
- stohdr(Txpos);
- zsbhdr(ZDATA, Txhdr);
- do {
- if (QuitFlag)
- return NERROR;
- if (Dontread) {
- n = Lastn;
- }
- else {
- n = filbuf(Txbuf, Blklen);
- Lastread = Txpos;
- Lastn = n;
- }
- Dontread = FALSE;
- if (n < Blklen)
- e = ZCRCE;
- else if (junkcount > 3)
- e = ZCRCW;
- else if (Bytcnt == Lastsync)
- e = ZCRCW;
- else if (Rxbuflen && (newcnt -= n) <= 0)
- e = ZCRCW;
- else if (Txwindow && (Txwcnt += n) >= Txwspac) {
- Txwcnt = 0;
- e = ZCRCQ;
- }
- else
- e = ZCRCG;
- zsdata(Txbuf, n, e);
- Txpos += (long)n;
- Bytcnt = Txpos;
- crcrept(Crc32t); /* praps report crc mode */
- lreport(KBYTES,Bytcnt);
- if (e == ZCRCW)
- goto waitack;
-
- /*
- * If the reverse channel can be tested for data,
- * this logic may be used to detect error packets
- * sent by the receiver, in place of setjmp/longjmp
- * minprdy() returns non 0 if a character is available
- */
-
- while (minprdy()) {
- if (QuitFlag)
- return NERROR;
- switch (readline(1)) {
- case CAN:
- case CTRLC:
- case ZPAD:
- c = getinsync(1);
- if (c == ZACK)
- break;
- purgeline();
- /* zcrce - dinna wanna starta ping-pong game */
- zsdata(Txbuf, 0, ZCRCE);
- goto gotack;
- case XOFF: /* Wait a while for an XON */
- case XOFF|0200:
- readline(100);
- default:
- ++junkcount;
-
- }
- gotanother:;
- }
- if (Txwindow) {
- while ((tcount = Txpos - Lrxpos) >= Txwindow) {
- if (QuitFlag)
- return NERROR;
- if (e != ZCRCQ)
- zsdata(Txbuf, 0, e = ZCRCQ);
- c = getinsync(1);
- if (c != ZACK) {
- purgeline();
- zsdata(Txbuf, 0, ZCRCE);
- goto gotack;
- }
- }
- }
- }
- while (n == Blklen);
-
- for (;;) {
- if (QuitFlag)
- return NERROR;
- stohdr(Txpos);
- zsbhdr(ZEOF, Txhdr);
- switch (getinsync(0)) {
- case ZACK:
- continue;
- case ZRPOS:
- goto somemore;
- case ZRINIT:
- return OK;
- case ZSKIP:
- return c;
- default:
- return NERROR;
- }
- }
- }
-
- /*
- * Respond to receiver's complaint, get back in sync with receiver
- */
-
- getinsync(flag) /* flag means that there was an error */
- int flag;
- {
- static int c;
- unsigned u;
-
- for (;;) {
- if (opabort())
- return NERROR;
- c = zgethdr(Rxhdr, 0);
- c = c < FRTYPES ? c : FRTYPES-1;
- sprintf(Buf,"Got %s", frametypes[c+FTOFFSET]);
- zperr(Buf,flag);
- switch (c) {
- case ZCAN:
- case ZABORT:
- case ZFIN:
- case TIMEOUT:
- return NERROR;
- case ZRPOS:
- /* ************************************* */
- /* If sending to a modem beuufer, you */
- /* might send a break at this point to */
- /* dump the modem's buffer. */
-
- if (Lastn >= 0 && Lastread == Rxpos) {
- Dontread = TRUE;
- }
- else {
-
- #ifdef AZTEC_C
- u = fseek(Fd, Rxpos, 0); /* absolute offset */
- if (u != EOF)
- uneof(Fd); /* Reset EOF flag */
- #else
- u = lseek(Fd, Rxpos, 0); /* absolute offset */
- #endif
-
- clrline(KBYTES);
- Incnt = 0;
- }
- Bytcnt = Lrxpos = Txpos = Rxpos;
- if (Lastsync == Rxpos) {
- if (++Beenhereb4 > 4)
- if (Blklen > 256)
- Blklen /= 2;
- }
- Lastsync = Rxpos;
- return c;
- case ZACK:
- Lrxpos = Rxpos;
- if (flag || Txpos == Rxpos)
- return ZACK;
- continue;
- case ZRINIT:
- case ZSKIP:
- return c;
- case NERROR:
- default:
- zsbhdr(ZNAK, Txhdr);
- continue;
- }
- }
- }
-
- /* Say "bibi" to the receiver, try to do it cleanly */
-
- saybibi()
- {
- for (;;) {
- stohdr(0L); /* CAF Was zsbhdr - minor change */
- zshhdr(ZFIN, Txhdr); /* to make debugging easier */
- switch (zgethdr(Rxhdr, 0)) {
- case ZFIN:
- xmchout('O');
- xmchout('O');
- case ZCAN:
- case TIMEOUT:
- return;
- }
- }
- }
-
- char *
- ttime(fsize)
- long fsize;
- {
- static int efficiency, cps, seconds;
- static char buffer[10];
-
- efficiency = 9;
- cps = (Baudrate/100) * efficiency;
- seconds = (int)(fsize/cps);
- sprintf(buffer,"%d:%02d",seconds/60,seconds%60);
- return buffer;
- }
-
- tfclose() /* close file if still open */
- {
- #ifdef AZTEC_C
- if (Fd)
- fclose(Fd);
- Fd = 0;
- #else
- if (Fd >= 0)
- close(Fd);
- Fd = -1;
- #endif
- }
-
- /* output a character to the modem and test the receive channel */
- xmchout(c)
- char c;
- {
- testrxc(200); /* test receive channel in case xoff */
- mcharout(c); /* then send it */
- }
-
- /* Test receive channel for xon/xoff and interrupt while sending */
- testrxc(timeout)
- short timeout; /* timeout in seconds */
- {
- static char c;
-
- c = minprdy() ? mcharinp() : '\0'; /* get a character if any */
- if (c) {
- if (c == CTRLS) {
- while (((c = readline(10)) != CTRLQ) && timeout--);
- if (c < 1)
- c = CTRLC; /* timeout */
- }
- StopFlag = ((c == CTRLC) || (c == CTRLX) || (c == '*'));
- if (StopFlag && Sending)
- longjmp(jb_stop,c); /* zmodem transmit interrupt */
- }
- }
-
- /* print send mode label */
- slabel()
- {
- putlabel("SEND FILE mode: Press ESC to Abort...");
- }
-
- /************************** END OF MODULE 3 *********************************/
-