home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol158 / yam2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1984-04-29  |  9.5 KB  |  483 lines

  1. /*
  2. >>:yam2.c 9-6-83
  3.  * Ward Christensen Protocol handler for sending and receiving
  4.  * ascii and binary files.  Modified for choice of checksum or crc.
  5.  */
  6.  
  7. #define EXTERN extern
  8. #include "yamc86.h"
  9. #define WCEOT (-10)
  10.  
  11. #ifdef DEFBYTL
  12. long Modtime;        /* Unix style mod time for incoming file */
  13. int Filemode;        /* Unix style mode for incoming file */
  14. #endif
  15.  
  16. wcsend(argc, argp)
  17. char **argp;
  18. {
  19.     int wcs();
  20.  
  21.     Crcflg=FALSE;
  22.     firstsec=TRUE;
  23.     if (Batch) {
  24. #ifdef XMODEM
  25.         printf("Sending in Batch Mode\n");
  26. #endif
  27.         if (expand(wcs, argc, argp)==ERROR)
  28.             goto fubar;
  29.         if (wctxpn("")==ERROR)
  30.             goto fubar;
  31.     }
  32.     else {
  33.         for (; --argc>=0;) {
  34.             if (opentx(*argp++)==ERROR)
  35.                 goto fubar;
  36.             if (wctx()==ERROR)
  37.                 goto fubar;
  38.         }
  39.     }
  40.     return OK;
  41. fubar:
  42.     closetx(TRUE);
  43.     canit();
  44.     return ERROR;
  45. }
  46.  
  47. wcs(name)
  48. char *name;
  49. {
  50.     if (opentx(name)==ERROR)
  51.         return OK;        /* skip over inaccessible files */
  52.     if (wctxpn(name)== ERROR)
  53.         return ERROR;
  54.     if (wctx()==ERROR)
  55.         return ERROR;
  56.     return OK;
  57. }
  58.  
  59.  
  60. wcreceive(argc, argp)
  61. char **argp;
  62. {
  63.     if (Batch || argc==0) {
  64.         printf("Receiving in Batch Mode\n");
  65.         for (;;) {
  66.             if (wcrxpn(Utility.ubuf)== ERROR)
  67.                 goto fubar;
  68.             if (Utility.ubuf[0]==0)
  69.                 return OK;
  70.             procheader(Utility.ubuf);
  71.             if (wcrx(Utility.ubuf)==ERROR)
  72.                 goto fubar;
  73.         }
  74.     }
  75.     else
  76.         for (; --argc>=0;) {
  77. #ifdef DEFBYTL
  78.             procheader(0);
  79. #endif
  80. #ifdef XMODEM
  81.             printf("Receive:'%s' FILE OPEN\n", *argp);
  82. #endif
  83.             if (wcrx(*argp++)==ERROR)
  84.                 goto fubar;
  85.         }
  86.     return OK;
  87. fubar:
  88.     canit(); closerx(TRUE); return ERROR;
  89. }
  90. /*
  91.  * Fetch a pathname from the other end as a C ctyle ASCIZ string.
  92.  * Length is indeterminate as long as less than blklen
  93.  * a null string represents no more files
  94.  */
  95. wcrxpn(rpn)
  96. char *rpn;    /* receive a pathname */
  97. {
  98.     purgeline(); Crcflg = (Wcsmask==0377);
  99.     firstsec=TRUE;
  100. #ifdef STATLINE
  101.     lpstat("Fetching pathname");
  102. #else
  103.     lprintf("Fetching pathname ");
  104. #endif
  105.     totsecs = -1;
  106.     if (wcgetsec(rpn, 100, Crcflg?WANTCRC:NAK) != 0)
  107.         return ERROR;
  108.     sendline(ACK);
  109. #ifndef STATLINE
  110.     lprintf("\r                   \r");
  111. #endif
  112.     return OK;
  113. }
  114.  
  115. wctxpn(name)
  116. char *name;
  117. {
  118.     char *p, *q;
  119.  
  120.     totsecs = -1;
  121. #ifdef STATLINE
  122.     pstat("Awaiting pathname NAK");
  123. #else
  124.     lprintf("Awaiting pathname NAK ");
  125. #endif
  126.     if ((firstch=readline(400))==TIMEOUT)
  127.         return ERROR;
  128.     if (firstch==WANTCRC)
  129.         Crcflg=TRUE;
  130.     /* don't send drive specification */
  131.     for(p=name, q=Utility.ubuf; *p; )
  132.         if((*q++ = *p++) == ':')
  133.             q = Utility.ubuf;
  134.     while(q < Utility.ubuf + KSIZE)
  135.         *q++ = 0;
  136.     if (wcputsec(Utility.ubuf, 0, SECSIZ)==ERROR) {
  137.         lprintf("Can't send pathname %s\n", name);
  138.         return ERROR;
  139.     }
  140. #ifndef STATLINE
  141.     lprintf("\r                               \r");
  142. #endif
  143.     return OK;
  144. }
  145.  
  146. /*
  147.  * Adapted from CMODEM13.C, written by
  148.  * Jack M. Wierda and Roderick W. Hart
  149.  */
  150.  
  151. wcrx(name)
  152. char *name;
  153. {
  154.     int sendchar, sectnum, sectcurr;
  155. #ifdef DEFBYTL
  156.     int cblklen;            /* bytes to dump this block */
  157. #endif
  158.  
  159.     if (openrx(name)==ERROR)
  160.         return ERROR;
  161.     firstsec=TRUE; totsecs=sectnum=0; sendchar=Crcflg?WANTCRC:NAK;
  162.  
  163.     for (;;) {
  164. #ifdef STATLINE
  165.         if (!Quiet)
  166.             pstat("Sector %3d %2dk", totsecs, totsecs/8 );
  167. #else
  168.         if (!Quiet && !View)
  169.             lprintf("\rSector %3d %2dk ", totsecs, totsecs/8 );
  170. #endif
  171.         purgeline();
  172.         sectcurr=wcgetsec(Utility.ubuf, (sectnum&0177)?70:130,
  173.           sendchar);
  174.         if (sectcurr==(sectnum+1 &Wcsmask)) {
  175.  
  176.             sectnum++;
  177. /*
  178.  * if the compiler supports longs && the o/s records the
  179.  *  exact length of files then and only then use the file length
  180.  *  info (if transmitted).
  181.  */
  182. #ifdef DEFBYTL
  183. #ifdef BYTEFLENGTH
  184.             wcj = cblklen = Bytesleft>blklen ? blklen:Bytesleft;
  185. #else
  186.             wcj = cblklen = blklen;
  187. #endif
  188. #else
  189.             wcj = blklen;
  190. #endif
  191.             for (cp=Utility.ubuf; --wcj>=0; )
  192.                 if (fputc(*cp++, fout)==ERROR) {
  193.                     lprintf("\nDisk Full\n");
  194.                     return ERROR;
  195.                 }
  196. #ifndef XMODEM
  197.             if (View) {
  198. #ifdef DEFBYTL
  199.                 wcj = cblklen;
  200. #else
  201.                 wcj = blklen;
  202. #endif
  203.                 for (cp=Utility.ubuf;--wcj>=0;)
  204.                     putchar(*cp++);
  205.             }
  206. #endif
  207. #ifdef DEFBYTL
  208.             if ((Bytesleft -= cblklen) < 0)
  209.                 Bytesleft = 0;
  210. #endif
  211.             totsecs += blklen/128; sendchar=ACK;
  212.         }
  213.         else if (sectcurr==sectnum) {
  214.             wcperr("received dup Sector\n");
  215.             sendchar=ACK;
  216.         }
  217.         else if (sectcurr==WCEOT) {
  218.             sendline(ACK);
  219.             /* don't pad the file any more than it already is */
  220.             closerx(FALSE);
  221.             return OK;
  222.         }
  223.         else if (sectcurr==ERROR)
  224.             return ERROR;
  225.         else {
  226.             lprintf(" Sync Error: got %d\n", sectcurr);
  227.             return ERROR;
  228.         }
  229.     }
  230. }
  231.  
  232. /*
  233.  * wcgetsec fetches a Ward Christensen type sector.
  234.  * Returns sector number encountered or ERROR if valid sector not received,
  235.  * or CAN CAN received
  236.  * or WCEOT if eot sector
  237.  * time is timeout for first char, set to 4 seconds thereafter
  238.  ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
  239.  *    (Caller must do that when he is good and ready to get next sector)
  240.  */
  241.  
  242. wcgetsec(rxbuf, time, sendchar)
  243. char *rxbuf;
  244. int time;
  245. {
  246.     int sectcurr;
  247.  
  248.     for (Lastrx=errors=0; errors<RETRYMAX; ++errors, ++toterrs) {
  249.         if(CIREADY && getcty()==CAN)
  250.             return ERROR;
  251.  
  252.         sendline(sendchar);    /* send it now, we're ready! */
  253.         purgeline();
  254.  
  255.         if ((firstch=readline(time))==STX) {
  256.             blklen=KSIZE; goto get2;
  257.         }
  258.         if (firstch==SOH) {
  259.             blklen=SECSIZ;
  260. get2:
  261.             sectcurr=readline(50);
  262.             if ((sectcurr+readline(50))==Wcsmask) {
  263.                 oldcrc=checksum=0;
  264.                 for (cp=rxbuf,wcj=blklen; --wcj>=0; ) {
  265.                     if ((firstch=readline(50)) < 0)
  266.                         goto bilge;
  267.                     oldcrc=updcrc(firstch, oldcrc);
  268.                     checksum += (*cp++ = firstch);
  269.                 }
  270.                 if ((firstch=readline(50)) < 0)
  271.                     goto bilge;
  272.                 if (Crcflg) {
  273.                     oldcrc=updcrc(firstch, oldcrc);
  274.                     if ((firstch=readline(50)) < 0)
  275.                         goto bilge;
  276.                     oldcrc=updcrc(firstch, oldcrc);
  277.                     if (oldcrc)
  278.                         wcperr("Bad CRC=0%o\n",
  279.                           oldcrc);
  280.                     else {
  281.                         firstsec=FALSE;
  282.                         return sectcurr;
  283.                     }
  284.                 }
  285.                 else if (((checksum-firstch)&Wcsmask)==0) {
  286.                     firstsec=FALSE;
  287.                     return sectcurr;
  288.                 }
  289.                 else
  290.                     wcperr("Checksum Bad rx=0%o cx=0%o\n",
  291.                      firstch, checksum);
  292.             }
  293.             else
  294.                 wcperr("Sector number garbled\n");
  295.         }
  296.         /* make sure eot really is eot and not just mixmash */
  297.         else if (firstch==EOT && readline(2)==TIMEOUT)
  298.             return WCEOT;
  299.         else if (firstch==CAN) {
  300.             if (Lastrx==CAN) {
  301.                 wcperr("Sender CANcelled\n");
  302.                 return ERROR;
  303.             } else {
  304.                 Lastrx=CAN;
  305.                 continue;
  306.             }
  307.         }
  308.         else if (firstch==TIMEOUT) {
  309. bilge:
  310.             wcperr("Timeout\n");
  311.         }
  312.         else if (firstch==ERROR)
  313.             wcperr("Modem SR=0%o\n", Mstatus);
  314.         else
  315.             wcperr("Got 0%o sector header\n", firstch);
  316.         Lastrx=0;
  317.         while (readline(2)!=TIMEOUT)
  318.             ;
  319.         if (firstsec)
  320.             sendchar = Crcflg?WANTCRC:NAK;
  321.         else {
  322.             time=40;
  323.             sendchar = NAK;
  324.         }
  325.     }
  326.     /* try to stop the bubble machine. */
  327.     canit(); return ERROR;
  328. }
  329.  
  330. /*VARAGRS*/
  331. wcperr(s,p)
  332. char *s, *p;
  333. {
  334.     lprintf("Sector %3d error %d: ", totsecs, errors);
  335.     lprintf(s, p);
  336. }
  337.  
  338. wctx()
  339. {
  340.     int sectnum;
  341.  
  342.     firstsec=TRUE; totsecs=0;
  343. #ifdef STATLINE
  344.     pstat("Awaiting initial NAK");
  345. #else
  346.     lprintf("Awaiting NAK");
  347. #endif
  348.     while ((firstch=readline(400))!=TIMEOUT && firstch != WANTCRC
  349.       && firstch!=NAK && firstch!=CAN)
  350.         lprintf("%c", firstch);    /* let user see it if strange char */
  351.     if (firstch==CAN)
  352.         return ERROR;
  353.     if (firstch==WANTCRC)
  354.         Crcflg=TRUE;
  355.     sectnum=1;
  356.     while (filbuf(Utility.ubuf, blklen)) {
  357.         totsecs += (blklen/128);
  358.         if (!Quiet
  359. #ifdef STATLINE
  360.         )
  361.             pstat("Sector %3d %2dk", totsecs, totsecs/8 );
  362. #else
  363.         && !View)
  364.             lprintf("\rSector %3d %2dk ", totsecs, totsecs/8 );
  365. #endif
  366.         if (wcputsec(Utility.ubuf, sectnum, blklen)==ERROR) {
  367.             return ERROR;
  368.         } else {
  369.             if (View)    /* View can't be set in xyam */
  370.                 for (cp=Utility.ubuf,wcj=blklen;--wcj>=0;)
  371.                     putchar(*cp++);
  372.             sectnum++;
  373.         }
  374.     }
  375.     closetx(FALSE);
  376.     for (errors=0; ++errors<RETRYMAX; ) {
  377.         sendline(EOT);
  378.         purgeline();
  379.         if(readline(100) == ACK)
  380.             return OK;
  381.     }
  382.     wcperr("No ACK on EOT\n");
  383.     return ERROR;
  384. }
  385.  
  386. wcputsec(txbuf, sectnum, cseclen)
  387. char *txbuf;
  388. int sectnum;
  389. int cseclen;    /* data length of this sector to send */
  390. {
  391.     firstch=0;    /* part of logic to detect CAN CAN */
  392.  
  393.     for (errors=0; errors <= RETRYMAX; ++errors, ++toterrs) {
  394.         Lastrx= firstch;
  395.         sendline(cseclen==KSIZE?STX:SOH);
  396.         sendline(sectnum);
  397.         sendline(-sectnum-1);
  398.         oldcrc=checksum=0;
  399.         for (wcj=cseclen,cp=txbuf; --wcj>=0; ) {
  400.             sendline(*cp);
  401.             oldcrc=updcrc(*cp, oldcrc);
  402.             checksum += *cp++;
  403.         }
  404.         if (Crcflg) {
  405.             oldcrc=updcrc(0,updcrc(0,oldcrc));
  406.             sendline(oldcrc>>8);sendline(oldcrc);
  407.         }
  408.         else
  409.             sendline(checksum);
  410.         if(CIREADY && getcty()==CAN)
  411.             goto cancan;
  412.         purgeline();
  413.  
  414.         /* ignore bullshit line noise, esp. braces from 212's */
  415.         switch(firstch=readline(100)) {
  416.         case CAN:
  417.             if(Lastrx==CAN) {
  418. cancan:
  419.                 lprintf("\nReceiver CANcelled\n");
  420.                 return ERROR;
  421.             }
  422.             break;
  423.         case ACK|0200: 
  424.         case ACK: 
  425.             firstsec=FALSE;
  426.             return OK;
  427.         case TIMEOUT:
  428.             wcperr("Timeout on sector ACK\n"); break;
  429.         case WANTCRC:
  430.             if (firstsec)
  431.                 Crcflg=TRUE;
  432.         case NAK:
  433.             wcperr("NAK on sector\n"); break;
  434.         default:
  435.             wcperr("Got 0%o for sector ACK\n", firstch); break;
  436.         }
  437.         for (;;) {
  438.             Lastrx=firstch;
  439.             if ((firstch=readline(3))==TIMEOUT)
  440.                 break;
  441.             if (firstch==CAN && Lastrx==CAN)
  442.                 goto cancan;
  443.             /* let user see it if strange char */
  444.             lprintf("%c", firstch);
  445.         }
  446.     }
  447.     wcperr("No ACK on sector; Abort\n");
  448.     return ERROR;
  449.  
  450. }
  451. /* send 10 CAN's to try to get the other end to shut up */
  452. canit()
  453. {
  454.     for (wcj=10; --wcj>=0; )
  455.         sendline(CAN);
  456. }
  457.  
  458. /*
  459.  * process incoming header
  460.  */
  461. procheader(name)
  462. char *name;
  463. {
  464.     register char *p;
  465.  
  466. #ifdef DEFBYTL
  467.     /* set default parameters */
  468.     Bytesleft = DEFBYTL; Filemode = 0666; Modtime = 0L;
  469. #endif
  470.  
  471.     if (name) {
  472.         p = name + 1 + strlen(name);
  473.         if (*p) {     /* file coming from Unix type system */
  474. #ifdef DEFBYTL
  475.             sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
  476. #else
  477.             lprintf("%s ", p);
  478. #endif
  479.         }
  480.     }
  481.     return OK;
  482. }
  483.