home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / MODEMS / ZMODEM / ZMP-SRC.LBR / ZMXFER2.CZ / ZMXFER2.C
Text File  |  2000-06-30  |  10KB  |  454 lines

  1. /************************ START OF XFER MODULE 2 ****************************/
  2.  
  3. /* sz.c By Chuck Forsberg modified for cp/m by Hal Maney */
  4.  
  5.  
  6. #include "zmp.h"
  7. #include "zmodem.h"
  8.  
  9. #ifdef   AZTEC_C
  10. #include "libc.h"
  11. #else
  12. #include <stdio.h>
  13. #endif
  14.  
  15. /*
  16.  * Attention string to be executed by receiver to interrupt streaming data
  17.  *  when an error is detected.  A pause (0336) may be needed before the
  18.  *  ^C (03) or after it. 0337 causes a break to be sent.
  19.  */
  20.  
  21. #define SLEEP 0336
  22.  
  23. char *ltoa(), *alloc(), *grabmem();
  24. char Myattn[] = { CTRLC,SLEEP,0 };
  25.  
  26. unsigned Txwindow = 0;    /* Control the size of the transmitted window */
  27. unsigned Txwspac;          /* Spacing between zcrcq requests */
  28. unsigned Txwcnt;          /* Counter used to space ack requests */
  29. int Noeofseen;
  30. int Totsecs;              /* total number of sectors this file */
  31. char *Txbuf;
  32. int Filcnt;               /* count of number of files opened */
  33. unsigned Rxbuflen = 16384;    /* Receiver's max buffer length */
  34. int Rxflags = 0;
  35. long Bytcnt;
  36. long Lastread;              /* Beginning offset of last buffer read */
  37. int Lastn;                 /* Count of last buffer read or -1 */
  38. int Dontread;              /* Don't read the buffer, it's still there */
  39. long Lastsync;              /* Last offset to which we got a ZRPOS */
  40. int Beenhereb4;           /* How many times we've been ZRPOS'd same place */
  41. int Incnt;              /* count for chars not read from the Cpmbuf */
  42.  
  43. wcsend(argc, argp)
  44. int argc;                     /* nr of files to send */
  45. char *argp[];                 /* list of file names */
  46. {
  47.     int n, status;
  48.  
  49.     slabel();
  50.     Zctlesc = 0;
  51.     Incnt = 0;
  52.     Baudrate = Baudtable[Current.cbaudindex];
  53.     Filcnt = Errors = 0;
  54.  
  55. #ifdef AZTEC_C
  56.     Fd = 0;
  57. #else
  58.     Fd = -1;
  59. #endif
  60.  
  61.     Txbuf = alloc(KSIZE);
  62.     if (allocerror(Txbuf))
  63.         return NERROR;      
  64.     Cpmbuf = grabmem(&Cpbufsize);
  65.     if (allocerror(Cpmbuf))
  66.         return NERROR;
  67.     Cpindex = 0;                        /* just in case */
  68.     Crcflag  = FALSE;
  69.     Firstsec = TRUE;
  70.     Bytcnt = -1;
  71.     Rxtimeout = 600;   
  72.     savecurs();
  73.     hidecurs();
  74.     box();
  75.     status = NERROR;
  76.     report(PROTOCOL,Xmodem?"XMODEM Send":Zmodem?"ZMODEM Send":"YMODEM Send");
  77.     if (Zmodem) {
  78.         stohdr(0L);
  79.         zshhdr(ZRQINIT, Txhdr);
  80.     if (getzrxinit()==NERROR)
  81.         goto badreturn;
  82.     }
  83.     for (n=0; n<argc; ++n) {
  84.         clrreports();
  85.         Totsecs = 0;
  86.         if (opabort() || wcs(argp[n]) == NERROR)
  87.             goto badreturn;
  88.         tfclose();
  89.     }
  90.     Totsecs = 0;
  91.     if (Filcnt==0) {    /* we couldn't open ANY files */
  92.         canit();
  93.         goto badreturn;
  94.     }
  95.     zperr("Complete",FALSE);
  96.     if (Zmodem)
  97.         saybibi();
  98.     else if (!Xmodem)
  99.         wctxpn("");
  100.     status = OK;
  101.  
  102. badreturn:
  103.     free(Cpmbuf);
  104.     free(Txbuf);
  105.     showcurs();
  106.     restcurs();
  107.     if (status == NERROR)
  108.         tfclose();
  109.     return status;
  110. }
  111.  
  112. wcs(oname)
  113. char *oname;
  114. {
  115.     unsigned length;
  116.     long flen;
  117.  
  118. #ifdef AZTEC_C
  119.     if ((Fd=fopen(oname,"rb"))==BUFIOT) {
  120. #else
  121.     if ((Fd=open(oname,0))==UBIOT) {
  122. #endif
  123.  
  124.     zperr("Can't open file",TRUE);
  125.     wait(2);
  126.         return OK;    /* pass over it, there may be others */
  127.     }
  128.     ++Noeofseen;  
  129.     Lastread = 0L;  
  130.     Lastn = -1; 
  131.     Dontread = FALSE;
  132.     ++Filcnt;
  133.     fstat(oname,&Fs);
  134.     switch (wctxpn(oname)) {    /* transmit path name */
  135.         case NERROR:
  136.             if (Zmodem)
  137.                 canit();    /* Send CAN */
  138.             return NERROR;
  139.  
  140.         case ZSKIP:
  141.             return OK;
  142.     }
  143.     length = Fs.records;
  144.     flen = (long)length * 128;
  145.     if (!Zmodem && wctx(flen)==NERROR)
  146.         return NERROR;
  147.     return 0;
  148. }
  149.  
  150. /*
  151.  * generate and transmit pathname block consisting of
  152.  *  pathname (null terminated),
  153.  *  file length, mode time (null) and file mode (null)
  154.  *  in octal.
  155.  *  N.B.: modifies the passed name, may extend it!
  156.  */
  157. wctxpn(name)
  158. char *name;
  159. {
  160.     static char *p;
  161.     char buf[20];
  162.     static unsigned length;
  163.     static long nrbytes;
  164.  
  165.     memset(Txbuf,'\0',KSIZE);
  166.     length = Fs.records;
  167.     nrbytes = (long)length * 128;
  168.     report(PATHNAME,name);
  169.     lreport(FILESIZE,nrbytes);
  170.     dreport(FBLOCKS,length);
  171.     report(SENDTIME,ttime(nrbytes));   
  172.     if (Xmodem)                 /* xmodem, don't send path name */
  173.         return OK;
  174.     if (!Zmodem) {
  175.         Blklen = KSIZE;
  176.         if (getnak())
  177.         return NERROR;
  178.     }
  179.     strcpy(Txbuf,name);
  180.     deldrive(Txbuf);        /* remove drive ind if any */
  181.     p = Txbuf + strlen(Txbuf);
  182.     ++p;
  183.     strcpy(p,ltoa(nrbytes,buf));
  184.     if (Zmodem)
  185.         return zsendfile(Txbuf, 1+strlen(p)+(p-Txbuf));
  186.     if (wcputsec(Txbuf, 0, SECSIZ)==NERROR)
  187.         return NERROR;
  188.     return OK;
  189. }
  190.  
  191. /* itoa - convert n to characters in s. */
  192. char *itoa(n, s)
  193. char s[];
  194. short n;
  195. {
  196.     static short c, k;
  197.     static char *p, *q;
  198.  
  199.     if ((k = n) < 0)    /* record sign */
  200.         n = -n;     /* make n positive */
  201.     q = p = s;
  202.     do {        /* generate digits in reverse order */
  203.         *p++ = n % 10 + '0';  /* get next digit */
  204.     } while ((n /= 10) > 0);    /* delete it */
  205.     if (k < 0) *p++ = '-';
  206.     *p = 0;
  207. /* reverse string in place */
  208.     while (q < --p) {
  209.         c = *q; *q++ = *p; *p = c; }
  210.     return (s);
  211. }
  212.  
  213. /* ltoa - convert n to characters in s. */
  214. char *ltoa(n, s)
  215. char s[];
  216. long n;
  217. {
  218.     static long c, k;
  219.     static char *p, *q;
  220.  
  221.     if ((k = n) < 0)    /* record sign */
  222.         n = -n;     /* make n positive */
  223.     q = p = s;
  224.     do {        /* generate digits in reverse order */
  225.         *p++ = n % 10 + '0';  /* get next digit */
  226.     } while ((n /= 10) > 0);    /* delete it */
  227.     if (k < 0) *p++ = '-';
  228.     *p = 0;
  229. /* reverse string in place */
  230.     while (q < --p) {
  231.         c = *q; *q++ = *p; *p = c; }
  232.     return (s);
  233. }
  234.  
  235. getnak()
  236. {
  237.     static int firstch;
  238.  
  239.     Lastrx = 0;
  240.     for (;;) {
  241.         if (opabort())
  242.             return NERROR;
  243.         switch (firstch = readock(800,1)) {
  244.         case ZPAD:
  245.             if (getzrxinit())
  246.                 return NERROR;
  247.             return FALSE;
  248.         case TIMEOUT:
  249.             zperr("Timeout on PName",TRUE);
  250.             return TRUE;
  251.         case WANTCRC:
  252.             Crcflag = TRUE;
  253.         case NAK:
  254.             return FALSE;
  255.         case CAN:
  256.             if ((firstch = readock(20,1)) == CAN && Lastrx == CAN)
  257.                 return TRUE;
  258.         default:
  259.             break;
  260.         }
  261.         Lastrx = firstch;
  262.     }
  263.     report(BLKCHECK,Crcflag?"CRC":"Checksum");
  264. }
  265.  
  266. wctx(flen)
  267. long flen;
  268. {
  269.     static int thisblklen, i;
  270.     static unsigned sectnum, attempts, firstch;
  271.     static long charssent;
  272.  
  273.     charssent = 0L;  
  274.     Firstsec = TRUE;  
  275.     thisblklen = Blklen;
  276.     i = 0;
  277.  
  278.     while ((firstch=readock(1,2)) != NAK 
  279.             && firstch != WANTCRC
  280.             && firstch != CAN
  281.             && !opabort()
  282.             && ++i < Rxtimeout)
  283.         ;
  284.     if (QuitFlag)
  285.         return NERROR;
  286.     if (firstch==CAN) {
  287.         zperr("Rcvr CANcelled",TRUE);
  288.         return NERROR;
  289.     }
  290.     if (firstch==WANTCRC)
  291.         Crcflag=TRUE;
  292.     report(BLKCHECK,Crcflag?"CRC":"Checksum");
  293.     sectnum=0;
  294.     for (;;) {
  295.         if (opabort())
  296.             return NERROR;
  297.         if (flen <= (charssent + 896L))
  298.             Blklen = thisblklen = 128;
  299.         if ( !filbuf(Txbuf, thisblklen))
  300.             break;
  301.         purgeline();    /* ignore anything got while loading */
  302.         if (wcputsec(Txbuf, ++sectnum, thisblklen)==NERROR)
  303.             return NERROR;
  304.         charssent += thisblklen;
  305.               sreport(sectnum,charssent);
  306.     }
  307.     attempts=0;
  308.     do {
  309.         dreport(ERRORS,attempts);
  310.         purgeline();
  311.         mcharout(EOT);
  312.         ++attempts;
  313.     }
  314.     while ((firstch=(readock(Rxtimeout, 1)) != ACK) 
  315.             && attempts < RETRYMAX
  316.             && !opabort() );
  317.     if (attempts == RETRYMAX) {
  318.         zperr("No ACK on EOT",TRUE);
  319.         return NERROR;
  320.     }
  321.     else if (QuitFlag)  /* from opabort */
  322.         return NERROR;
  323.     else
  324.         return OK;
  325. }
  326.  
  327. wcputsec(buf, sectnum, cseclen)
  328. char *buf;
  329. int sectnum;
  330. int cseclen;    /* data length of this sector to send */
  331. {
  332.     static unsigned checksum;
  333.     static char *cp;
  334.     static unsigned oldcrc;
  335.     static int wcj;
  336.     static int firstch;
  337.     static int attempts;
  338.  
  339.     firstch=0;    /* part of logic to detect CAN CAN */
  340.  
  341.     dreport(ERRORS,0);
  342.     for (attempts=0; attempts <= RETRYMAX; attempts++) {
  343.         if (opabort())
  344.             return NERROR;
  345.         if (attempts)
  346.             dreport(ERRORS,attempts);
  347.         Lastrx= firstch;
  348.         mcharout(cseclen==KSIZE?STX:SOH);
  349.         mcharout(sectnum);
  350.         mcharout(~sectnum);
  351.         oldcrc=checksum=0;
  352.         for (wcj=cseclen,cp=buf; --wcj>=0; ) {
  353.             mcharout(*cp);
  354.             oldcrc=updcrc((0377& *cp), oldcrc);
  355.             checksum += *cp++;
  356.         }
  357.         if (Crcflag) {
  358.             oldcrc=updcrc(0,updcrc(0,oldcrc));
  359.             mcharout((int)oldcrc>>8);
  360.             mcharout((int)oldcrc);
  361.         }
  362.         else
  363.             mcharout(checksum);
  364.  
  365.         firstch = readock(Rxtimeout, (Noeofseen&§num) ? 2:1);
  366. gotnak:
  367.         switch (firstch) {
  368.         case CAN:
  369.             if(Lastrx == CAN) {
  370. cancan:
  371.                 zperr("Rcvr CANcelled",TRUE);  
  372.                 return NERROR;
  373.             }
  374.             break;
  375.         case TIMEOUT:
  376.             zperr("Timeout on ACK",TRUE); 
  377.             continue;
  378.         case WANTCRC:
  379.             if (Firstsec)
  380.                 Crcflag = TRUE;
  381.             report(BLKCHECK,Crcflag?"CRC":"Checksum");
  382.         case NAK:
  383.             zperr("NAK on sector",TRUE); 
  384.             continue;
  385.         case ACK: 
  386.             Firstsec=FALSE;
  387.             Totsecs += (cseclen>>7);
  388.             return OK;
  389.         case NERROR:
  390.             zperr("Got burst",TRUE); 
  391.             break;
  392.         default:
  393.             zperr("Bad sector ACK",TRUE);
  394.             break;
  395.         }
  396.         for (;;) {
  397.             if (opabort())
  398.                 return NERROR;
  399.             Lastrx = firstch;
  400.             if ((firstch = readock(Rxtimeout, 2)) == TIMEOUT)
  401.                 break;
  402.             if (firstch == NAK || firstch == WANTCRC)
  403.                 goto gotnak;
  404.             if (firstch == CAN && Lastrx == CAN)
  405.                 goto cancan;
  406.         }
  407.     }
  408.     zperr("Retry Exceeded",TRUE);
  409.     return NERROR;
  410. }
  411.  
  412. /* fill buf with count chars padding with ^Z for CPM */
  413.  
  414. filbuf(buf, count)
  415. char *buf;
  416. int count;
  417. {
  418.     static int c, m;
  419.  
  420.     c = m = newload(buf, count);
  421.     if (m <= 0)
  422.         return 0;
  423.     while (m < count)
  424.         buf[m++] = CTRLZ;
  425.     return c;
  426. }
  427.  
  428. newload(buf, count)
  429. int count;
  430. char *buf;
  431. {
  432.     static int j;
  433.  
  434.     j = 0;
  435.     while (count--) {
  436.         if (Incnt <= 0) {
  437.  
  438. #ifdef AZTEC_C
  439.             Incnt = fread( Cpmbuf, 1, Cpbufsize, Fd);
  440. #else
  441.             Incnt = read( Fd, Cpmbuf, Cpbufsize );
  442. #endif
  443.  
  444.             Cpindex = 0;      
  445.             if (Incnt <= 0)
  446.                 break;
  447.         }
  448.         buf[j++] = Cpmbuf[Cpindex++];
  449.         --Incnt;
  450.     }
  451.     return (j ? j : -1);
  452. }
  453. /************************** END OF MODULE 7 *********************************/
  454.