home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / perkinelmeridris / pe7ptb.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  17KB  |  807 lines

  1. /* pe7ptb.c */
  2. /* include external declarations */
  3. #include "pe7inc.h"
  4.  
  5. /*
  6.  *    g n x t f l
  7.  *
  8.  *    Get next file in a file group
  9.  *
  10.  */
  11.  
  12. gnxtfl()
  13. {
  14.     if (filecount-- == 0)
  15.         return (FALSE); /* If no more, fail */
  16.     if (debug) printf("Gnxtfl 1: filelist = \"%s\"\n",*filelist);
  17.     filnam = *(filelist++);
  18.     return (TRUE);
  19. }
  20.  
  21. /*
  22.  * d o s t a t s
  23.  *
  24.  * Gather various statistics
  25.  *
  26.  */
  27. dostat(type)
  28.     int type;
  29. {
  30.     ULONG time();
  31.     switch(type)
  32.     {
  33.     case 1:                    /* Init Overall totals */
  34.         total.files = 0;
  35.         total.fc = 0;
  36.         total.pli = 0;
  37.         total.plo = 0;
  38.         total.cli = 0;
  39.         total.clo = 0;
  40.         total.time = 0;
  41.         break;
  42.     case 2:                    /* Init File totals */
  43.         file.fc = 0;
  44.         file.pli = 0;
  45.         file.plo = 0;
  46.         file.cli = 0;
  47.         file.clo = 0;
  48.         file.time = time();
  49.         break;
  50.     case 3:                    /* Accumulate Overall totals */
  51.         file.time = time()-file.time;
  52.         if (vflg)
  53.         {
  54.             printf("%d Bytes   %d Seconds   %d/%d Packets",
  55.                 file.fc, file.time, file.plo, file.pli);
  56.             printf("   %d/%d Characters\n", file.clo, file.cli);
  57.         }
  58.         total.fc += file.fc;
  59.         total.pli += file.pli;
  60.         total.plo += file.plo;
  61.         total.cli += file.cli;
  62.         total.clo += file.clo;
  63.         total.time += file.time;
  64.         break;
  65.     case 4:                    /* Count total files */
  66.         total.files++;
  67.     }
  68. }
  69. /*
  70.  *  d o p a r
  71.  *
  72.  *  Set parity bit
  73.  *
  74.  */
  75.  
  76. dopar(ch)
  77. TEXT ch;
  78. {
  79.     TEXT a;
  80.  
  81.     a=ch;
  82.     if (pflg)                    /* True = generate parity */
  83.     {
  84.         a &= 0177;                /* Strip top bit */
  85.         switch (pflg)
  86.         {
  87.         case 'o':            /* Odd parity */
  88.             a |= 0200;        /* Set bit then do even */
  89.         case 'e':            /* Even parity */
  90.             a = (a & 15) ^ ((a >> 4) & 15);
  91.             a = (a &  3) ^ ((a >> 2) &  3);
  92.             a = (a &  1) ^ ((a >> 1) &  1);
  93.             a = ch & 0177 | (a << 7);
  94.         case 's':            /* Space parity */
  95.         default:            /* No parity */
  96.             break;
  97.         case 'm':            /* Mark parity */
  98.             a |= 0200;
  99.         }
  100.     }
  101.     return (a);
  102. }
  103.  
  104. /*
  105.  *  c h k c h a r
  106.  *
  107.  * Check range of input and return the character or FALSE
  108.  *
  109.  */
  110.  
  111. TEXT chkchar(c)
  112. TEXT c;
  113. {
  114.     return ((c < 33) || (c > 62 && c < 96) || (c > 126) ? FALSE : c);
  115. }
  116. /*
  117.  *    f l u s h i n p u t
  118.  *
  119.  *    Dump all pending input to clear stacked up NACK's.
  120.  *    (Implemented only for Berkeley Unix at this time).
  121.  *
  122.  */
  123.  
  124. flushinput()        /* Null version for non-Berkeley Unix */
  125. {
  126.     estty(ttyfd,&ttymode);        /* This flushes the input buffer */
  127. }
  128.  
  129. /*
  130.  *    Kermit printing routines:
  131.  *
  132.  *    printmsg -    like printf with "Kermit: " prepended
  133.  *    error - like printmsg if local kermit; sends a error packet if remote
  134.  *    prerrpkt - print contents of error packet received from remote host
  135.  */
  136. /*
  137.  * U s a g e
  138.  *
  139.  * Like printmsg but will exit after printing the message
  140.  *
  141.  */
  142.  
  143. Usage(message,a1,a2,a3,a4,a5)
  144. TEXT *message;
  145. {
  146.     TEXT
  147.         cp[BUFSIZE];
  148.     cpystr(&cp, "Kermit usage: ", message, "\n", NULL);
  149.     printf(&cp, a1, a2, a3, a4, a5);
  150.     if (ttyfd > 0)
  151.       estty (ttyfd,&savemode);    /* Restore the tty to what it was */
  152.     exit(NO);
  153. }
  154. /*
  155.  *    p r i n t m s g
  156.  *
  157.  *    Print message on standard output if not remote.
  158.  *
  159.  */
  160.  
  161. printmsg(fmt, a1, a2, a3, a4, a5)
  162. TEXT *fmt;
  163. {
  164.     TEXT cp[BUFSIZE];
  165.     cpystr(&cp, "Kermit: ", fmt, "\n", NULL);
  166.     printf(&cp, a1, a2, a3, a4, a5);
  167. }
  168. /*
  169.  *    e r r o r
  170.  *
  171.  *    Print error message.
  172.  *
  173.  *    If remote, send an error packet with the message.
  174.  *
  175.  */
  176.  
  177. error(fmt, a1, a2, a3, a4, a5)
  178. TEXT *fmt;
  179. {
  180.     TEXT cp[MAXPACKSIZ], msg[80];    /* Some arrays for the strings */
  181.     int len;    /* The length of these arrays */
  182.  
  183.     convert(&cp, fmt);        /* Convert the format string */
  184.     len = decode(msg, 80, &cp, a1, a2, a3, a4, a5);
  185.     spack('E',n,len,msg);    /* Send the error packet */
  186.     return;
  187. }
  188. /*
  189.  *    c o n v e r t
  190.  *
  191.  *    Convert the UNIX format string to an IDRIS format string
  192.  *
  193.  */
  194.  
  195. convert(out, in)
  196. TEXT *out, *in;
  197. {
  198.     TEXT    t,
  199.     *cpp;
  200.  
  201.     cpp = out;            /* Init the buffer pointer */
  202.  
  203.     while ((t = *cpp++ = *in++) != NULL)
  204.         if (t == '%')
  205.             switch (t = *in++)
  206.             {
  207.             case 'c':
  208.                 *cpp++ = 'a';
  209.                 *cpp++ = 'c';
  210.                 break;
  211.             case 'x':
  212.                 *cpp++ = 'h';
  213.             case 'd':
  214.                 *cpp++ = 'i';
  215.                 break;
  216.             case 's':
  217.                 *cpp++ = 'p';
  218.                 break;
  219.             case '\0':
  220.                 --in;
  221.                 break;
  222.             default:
  223.                 *cpp++ = t;
  224.             }
  225. }
  226. /*
  227.  *    p r e r r p k t
  228.  *
  229.  *    Print contents of error packet received from remote host.
  230.  *
  231.  */
  232.  
  233. prerrpkt(msg)
  234. TEXT *msg;
  235. {
  236.     putstr(STDERR,\
  237.         "Kermit: Abort with error from remote host:\n",\
  238.         "        ",msg,"\n",NULL);
  239.     return;
  240. }
  241. /*
  242.  * p r i n t f
  243.  *
  244.  * Print formatted output. Convert from UNIX to IDRIS
  245.  *
  246.  */
  247.  
  248. printf(msg, a1, a2, a3, a4, a5)
  249. TEXT *msg;
  250. {
  251.     TEXT
  252.         cp[MAXPACKSIZ]; /* Line pointer for the reformatted string */
  253.  
  254.     convert(&cp, msg);    /* Convert the string */
  255.     putfmt(&cp, a1, a2, a3, a4, a5);
  256. }
  257. /*
  258.  * i n l i n e
  259.  *
  260.  * Input a line (up to break char) from communications line
  261.  *
  262.  */
  263. inline(data)
  264.     TEXT *data;
  265. {
  266.     TEXT t;
  267.     int len, t1;
  268.  
  269.     t1 = tflg ? XON : MYEOL;
  270.     len = 0;
  271.     do
  272.     {
  273.         if (ioread(&t) <= 0)
  274.         {
  275.             data[len]=MYEOL;
  276.             return(len);
  277.         }
  278.         else
  279.             if (t)
  280.             {
  281.                 if (t == SOH)    /* Resync on SOH */
  282.                     len = 0;
  283.                 else
  284.                     data[len++] = t;
  285.             }
  286.     }
  287.     while ((t != t1) && (len < MAXPACKSIZ));
  288.  
  289.     file.cli += len + 1;
  290.     data[len] = '\0';        /* Terminate input string */
  291.  
  292.     if (tflg)                    /* Turn around flag on? */
  293.         do
  294.             if (ioread(&t) < 0) break;
  295.         while (t != XON);
  296.  
  297.     return (len);
  298. }
  299. /*
  300.  *    i o r e a d
  301.  *
  302.  *    Read a character from the i/o channel
  303.  *
  304.  */
  305.  
  306. ioread(t)
  307. TEXT *t;
  308. {
  309.     ULONG time_end,
  310.     time();
  311.     int result;
  312.  
  313.     if (timint > 0)
  314.     {
  315.         time_end = time() + timint;
  316.         do
  317.             if ((result = read(ttyfd, t, 1)) > 0) break;
  318.         while (time_end >= time());
  319.     }
  320.     else
  321.         result = read(ttyfd, t, 1);
  322.     if (pflg)
  323.         *t &= 0177;                /* Handle parity */
  324.     return (result);
  325. }
  326.  
  327. /*
  328.  *    x f i l e
  329.  *
  330.  *    Fetch file and send file header
  331.  *
  332.  */
  333.  
  334. TEXT xfile()
  335. {
  336.     TEXT filnam1[MAXFNAME];        /* A buffer for the file name */
  337.     TEXT *newfilnam;        /* A pointer into the filename */
  338.     TEXT *cp;                /* char pointer */
  339.     int num, len;            /* Packet number, length */
  340.     ULONG time();
  341.  
  342.     if (numtry++ > MAXTRY) return ('A'); /* If too many tries, give up */
  343.     
  344.     if (fd == NULL)            /* If not already open, */
  345.     {
  346.  
  347.         /* cpystr(filnam1, filnam, NULL); /* */
  348.         btobemp(filnam1, filnam, MAXFNAME);
  349.         if (filnamcnv)        /* Convert upper case to lower */
  350.             for (cp = &filnam1; *cp != '\0'; cp++)
  351.                 *cp = tolower(*cp);
  352.  
  353.         newfilnam = cp = filnam;
  354.  
  355.         while (*cp != '\0')    /* Strip leading directories */
  356.             if (*cp++ == '/')
  357.                 newfilnam = cp;
  358.         len = cp - newfilnam;    /* Compute length of filename */
  359.  
  360.         if (debug) printf("Xfile 1: Opening %s for sending.\n",&filnam1);
  361.         /* Open file to be sent */
  362.         if ((fd = fopen(&pfio, filnam1, READ)) == NULL)
  363.         {                        /* If bad file pointer, give up */
  364.             error("Cannot open file %s",filnam);
  365.             return ('C');        /* Go back to idle mode */
  366.         }
  367.  
  368.         if (vflg)
  369.             printmsg("Sending %s as %s", filnam1, newfilnam);
  370.     }
  371.     dostat(2);
  372.     spack('F',n,len,newfilnam); /* Send an F packet */
  373.     switch(rpack(&len,&num,recpkt)) /* What was the reply? */
  374.     {
  375.     case 'N':            /* NAK, just stay in this state, */
  376.         num = (--num<0 ? 63 : num);/* unless it's NAK for next packet */
  377.     case 'Y':
  378.         if (n != num)        /* which is just like an ACK for */ 
  379.         {                    /* Wrong packet number */
  380.     case FALSE:                /* Receive failure, stay in F state */
  381.             nxi++;
  382.             return (state);
  383.         }
  384.         nxtpkt();
  385.         dostat(4);
  386.         repeat_count = 0;    /* Reset repeat character counter */
  387.         empty[1-pknum] = 0;    /* Make other buffer empty */
  388.         if ((empty[pknum] = size[pknum] = bufill (packet[pknum])) != EOF)
  389.             return ('E');    /* Switch to data state */
  390.         return ('Z');        /* Must be end of file */
  391.  
  392.     case 'E':                /* Error packet received */
  393.         prerrpkt(recpkt);    /* Print it out and */
  394.     default:
  395.         return ('A');        /* Something else, just "abort" */
  396.     }
  397. }
  398.  
  399. /*
  400.  *    s d a t a
  401.  *
  402.  *    Send File Data
  403.  *
  404.  */
  405.  
  406. TEXT sdata()
  407. {
  408.     int num, len;        /* Packet number, length */
  409.  
  410.     if (numtry++ > MAXTRY) return ('A'); /* If too many tries, give up */
  411.  
  412.     /* If the packet has not been acked then do not fill it
  413.         We may need to retransmit it again */
  414.     spack('D',n,size[pknum],packet[pknum]);    /* Send a D packet */
  415.     if (!empty[1-pknum])
  416.         empty[1-pknum] = size[1-pknum] = bufill(packet[1-pknum]);
  417.     switch(rpack(&len,&num,recpkt)) /* What was the reply? */
  418.     {
  419.     case 'N':            /* NAK, just stay in this state, */
  420.         num = (--num<0 ? 63 : num);/* unless it's NAK for next packet */
  421.     case 'Y':
  422.         if (n != num)        /* which is just like an ACK for */ 
  423.         {                    /* Wrong packet number */
  424.     case FALSE:                /* Receive failure, stay in D */
  425.             nxi++;
  426.             return (state);
  427.         }
  428.         empty[pknum] = 0;    /* Empty this buffer */
  429.         nxtpkt();
  430.         if (size[pknum] == EOF)
  431.             return ('Z');    /* Send eof packet */
  432.         return ('E');        /* Got data, stay in state E */
  433.  
  434.     case 'E':                /* Error packet received */
  435.         prerrpkt(recpkt);    /* Print it out and */
  436.     default:
  437.         return ('A');        /* Anything else, "abort" */
  438.     }
  439. }
  440.  
  441. /*
  442.  *    r d a t a
  443.  *
  444.  *    Receive Data
  445.  *
  446.  */
  447.  
  448. TEXT rdata()
  449. {
  450.     int num, len;            /* Packet number, length */
  451.     ULONG time();
  452.  
  453.     if (numtry++ > MAXTRY) return ('A'); /* "abort" if too many tries */
  454.  
  455.     switch(rpack(&len,&num,recpkt)) /* Get packet */
  456.     {
  457.     case 'D':            /* Got Data packet */
  458.         if (num != n)        /* Right packet? */
  459.         {
  460.             /* No */
  461.             if (oldtry++ > MAXTRY) return ('A'); /* If too many tries, abort */
  462.             if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */
  463.             {
  464.                 /* Previous packet again? */
  465.                 spack('Y',num,0,0); /* Yes, re-ACK it */
  466.                 numtry = 0; /* Reset try counter */
  467.                 return (state);    /* Don't write out data! */
  468.             }
  469.             else return ('A');    /* sorry, wrong number */
  470.         }
  471.             /* Got data with right packet number */
  472.         spack('Y',n,0,0);    /* Acknowledge the packet */
  473.         bufemp(recpkt,len); /* Write the data to the file */
  474.         oldtry = numtry;    /* Reset the try counters */
  475.         nxtpkt();
  476.         return ('D');        /* Remain in data state */
  477.  
  478.     case 'F':            /* Got a File Header */
  479.         if (oldtry++ > MAXTRY)
  480.             return ('A');     /* If too many tries, "abort" */
  481.         if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */
  482.         {
  483.             /* It was the previous one */
  484.             spack('Y',num,0,0);/* ACK it again */
  485.             numtry = 0;         /* Reset try counter */
  486.             return (state);    /* Stay in Data state */
  487.         }
  488.         else return ('A');    /* Not previous packet, "abort" */
  489.  
  490.     case 'Z':                /* End-Of-File */
  491.         if (num != n)
  492.             return ('A');    /* Must have right packet number */
  493.         spack('Y',n,0,0);    /* OK, ACK it. */
  494.         fclose(&pfio);        /* Close the file */
  495.         fd = NULL;            /* Say the file is closed */
  496.         nxtpkt();
  497.         dostat(3);
  498.         return ('F');        /* Go back to Receive File state */
  499.  
  500.     case FALSE:                /* Didn't get packet */
  501.         nxi++;
  502.         spack('N',n,0,0);    /* Return a NAK */
  503.         return (state);        /* Keep trying */
  504.  
  505.     case 'E':                /* Error packet received */
  506.         prerrpkt(recpkt);    /* Print it out and */
  507.     default:
  508.         return ('A');        /* Some other packet, "abort" */
  509.     }
  510. }
  511.  
  512. /*
  513.  *    s e o f
  514.  *
  515.  *    Send End-Of-File.
  516.  *
  517.  */
  518.  
  519. TEXT seof()
  520. {
  521.     int num, len;        /* Packet number, length */
  522.     ULONG time();
  523.  
  524.     if (numtry++ > MAXTRY) return ('A'); /* If too many tries, "abort" */
  525.  
  526.     spack('Z',n,0,0);        /* Send a 'Z' packet */
  527.     switch(rpack(&len,&num,recpkt)) /* What was the reply? */
  528.     {
  529.     case 'N':            /* NAK, just stay in this state, */
  530.         num = (--num<0 ? 63 : num);/* unless it's NAK for next packet, */
  531.     case 'Y':
  532.         if (n != num)        /* which is just like an ACK for */ 
  533.         {                    /* Wrong packet number */
  534.     case FALSE:                /* Receive failure, stay in Z */
  535.             nxi++;
  536.             return (state);
  537.         }
  538.         nxtpkt();
  539.         dostat(3);
  540.         if (debug) printf("Seof 1: Closing input file %s\n",filnam);
  541.         fclose(&pfio);        /* Close the file */
  542.         fd = NULL;            /* Set flag indicating no file open */ 
  543.  
  544.         if (debug) printf("Seof 2: Looking for next file...\n");
  545.         if (gnxtfl() == FALSE)    /* No more files go? */
  546.             return ('B');    /* if not, break, EOT, all done */
  547.         if (debug) printf("Seof 3: New file is %s\n",filnam);
  548.         return ('T');        /* More files, switch state to T */
  549.  
  550.     case 'E':                /* Error packet received */
  551.         prerrpkt(recpkt);    /* Print it out and */
  552.     default:
  553.         return ('A');        /* Something else, "abort" */
  554.     }
  555. }
  556.  
  557. /*
  558.  *    s b r e a k
  559.  *
  560.  *    Send Break (EOT)
  561.  *
  562.  */
  563.  
  564. TEXT sbreak()
  565. {
  566.     int num, len;            /* Packet number, length */
  567.     ULONG time();
  568.  
  569.     if (numtry++ > MAXTRY) return ('A'); /* If too many tries "abort" */
  570.  
  571.     spack('B',n,0,0);        /* Send a B packet */
  572.     switch(rpack(&len,&num,recpkt)) /* What was the reply? */
  573.     {
  574.     case 'N':                /* NAK, just stay in this state, */
  575.         num = (--num<0 ? 63 : num);/* unless NAK for previous packet, */
  576.     case 'Y':
  577.         if (n != num)        /* Which is just like an ACK for */ 
  578.         {                    /* Wrong packet number */
  579.     case FALSE:                /* Receive failure, stay in B */
  580.             nxi++;
  581.             return (state);
  582.         }
  583.         nxtpkt();
  584.         return ('C');        /* Switch state to Complete */
  585.  
  586.     case 'E':                /* Error packet received */
  587.         prerrpkt(recpkt);    /* Print it out and */
  588.     default:
  589.         return ('A');        /* Other, "abort" */
  590.     }
  591. }
  592. /*
  593.  *    s f i n i s h
  594.  *
  595.  *    Send Finish (LOGOUT)
  596.  *
  597.  */
  598.  
  599. TEXT sfinish()
  600. {
  601.     int num, len;            /* Packet number, length */
  602.  
  603.     if (numtry++ > MAXTRY) return ('A'); /* If too many tries "abort" */
  604.  
  605.     spack('G',n,1,"F");        /* Send a GF packet */
  606.     switch(rpack(&len,&num,recpkt)) /* What was the reply? */
  607.     {
  608.     case 'N':                /* NAK, just stay in this state, */
  609.         num = (--num<0 ? 63 : num);/* unless NAK for previous packet, */
  610.     case 'Y':
  611.         if (n != num)        /* which is just like an ACK for */ 
  612.         {                    /* Wrong packet number */
  613.     case FALSE:                /* Receive failure, stay in B */
  614.             nxi++;
  615.             return (state);
  616.         }
  617.         nxtpkt();
  618.         return ('C');        /* Switch state to Complete */
  619.  
  620.     case 'E':                /* Error packet received */
  621.         prerrpkt(recpkt);    /* Print it out and */
  622.     default:
  623.         return ('A');        /* Other, "abort" */
  624.     }
  625. }
  626.  
  627. /*
  628.  *    KERMIT utilities.
  629.  *
  630.  */
  631.  
  632. /*
  633.  *    s p a c k
  634.  *
  635.  *    Send a Packet
  636.  *
  637.  */
  638.  
  639. spack(type,num,len,data)
  640. TEXT type, *data;
  641. int num, len;
  642. {
  643.     register int i;            /* Character loop counter */
  644.     register TEXT *bufp;    /* Buffer pointer */
  645.     TEXT buffer[100];        /* Packet buffer */
  646.     TEXT temp[12];            /* A buffer for a status message */
  647.     int checksum;
  648.  
  649.     data[len] = '\0';        /* Null-terminate data to print it */
  650.     if (debug>1)            /* Display outgoing packet */
  651.     {
  652.         printf("Spack 1: type: %c\n",type);
  653.         printf("         num: %d\n",num);
  654.         printf("         len: %d\n",len);
  655.         if (len != 0)
  656.             printf("         data: \"%s\"\n",data);
  657.     }
  658.     
  659.     bufp = buffer;            /* Set up buffer pointer */
  660.     for (i=1; i<=pad; i++)
  661.         write(ttyfd,&padchar,1); /* Issue any padding */
  662.  
  663.     *bufp++ = dopar(SOH);    /* Packet marker, ASCII 1 (SOH) */
  664.     /* Send character count and set up checksum */
  665.     *bufp++ = dopar(tochar(len + chkt - '0' + 2));
  666.     *bufp++ = dopar(tochar(num));    /* Packet number */
  667.     *bufp++ = dopar(type);    /* Packet type */
  668.  
  669.     for (i=0; i<len; i++)    /* Loop for all data characters */
  670.         *bufp++ = dopar(data[i]);    /* Get a character */
  671.     *bufp = '\0';            /* Mark end for block check */
  672.     switch (chkt)
  673.     {
  674.     case '1':
  675.         *bufp++ = dopar(tochar(chk1(buffer+1)));
  676.         break;
  677.     case '2':
  678.         checksum = chk2(buffer+1);
  679.         *bufp++ = dopar(tochar((checksum & 07700) >> 6));
  680.         *bufp++ = dopar(tochar(checksum & 077));
  681.         break;
  682.     case '3':
  683.         checksum = chk3(buffer+1);
  684.         *bufp++ = dopar(tochar((checksum & 0170000) >> 12));
  685.         *bufp++ = dopar(tochar((checksum & 07700) >> 6));
  686.         *bufp++ = dopar(tochar(checksum & 077));
  687.         break;
  688.     }
  689.  
  690.     if (eol)
  691.         *bufp++ = dopar(eol);    /* Extra-packet line terminator */
  692.     *bufp = '\0';
  693.  
  694.     i = bufp - buffer;
  695.     write(ttyfd, buffer, i); /* Send the packet */
  696.     file.plo++;
  697.     file.clo += i;
  698.  
  699.     if (vflg)
  700.     {
  701.         if (nxi == nxs)
  702.             write(STDERR,&temp,decode(&temp,12,"%5i/\r",nxo++));
  703.         else
  704.             write(STDERR,&temp,decode(&temp,12,"%5i/%5i\r",
  705.                 nxo++, nxs = nxi));
  706.     }
  707. }
  708.  
  709. /*
  710.  *    r p a c k
  711.  *
  712.  *    Read a Packet
  713.  *
  714.  */
  715.  
  716. rpack(len,num,data)
  717. int *len, *num;                /* Packet length, number */
  718. TEXT *data;                    /* Packet data */
  719. {
  720.     int chksum, i, j, len1, pbl;
  721.     TEXT t,                    /* Current input character */
  722.     type,                    /* Packet type */
  723.     cchksum[4],                /* Our (computed) checksum */
  724.     rchksum[4],                /* Checksum received from other host */
  725.     rpacket[MAXPACKSIZ];    /* Receive packet */
  726.  
  727.     if(!(len1=inline(&rpacket))) return (FALSE);
  728.  
  729.     i = 0;
  730.     if ((t = rpacket[i++]) == MYEOL) return (FALSE);
  731.     *len = unchar(t);     /* Character count */
  732.  
  733.     if ((t = rpacket[i++]) == MYEOL) return (FALSE);
  734.     *num = unchar(t);    /* Packet number */
  735.  
  736.     if ((type = rpacket[i++]) == MYEOL) return (FALSE);
  737.  
  738.     pbl = ((type == 'S') || (type == 'I')) ? 1 : type == 'N' ?
  739.         *len - 2 : chkt - '0';
  740.     *len -= pbl + 2;        /* Data length */
  741.  
  742.     for (j=0; j < *len;)    /* The data itself, if any */
  743.         if ((data[j++] = rpacket[i++]) == MYEOL) return (FALSE);
  744.     data[*len] = '\0';        /* Mark the end of the data */
  745.  
  746.     /* Fetch the checksum */
  747.     cchksum[0] = '\0';
  748.     cchksum[1] = '\0';
  749.     cchksum[2] = '\0';
  750.     cchksum[3] = '\0';
  751.     rchksum[0] = '\0';
  752.     rchksum[1] = '\0';
  753.     rchksum[2] = '\0';
  754.     rchksum[3] = '\0';
  755.     for (j=0; j < pbl;)    /* The checksum */
  756.     {
  757.         if ((rchksum[j++] = rpacket[i]) == MYEOL) return (FALSE);
  758.         rpacket[i++] = '\0';
  759.     }
  760.  
  761.     if (debug > 1)            /* Display incoming packet */
  762.     {
  763.         printf("Rpack 2: type: %c\n",type);
  764.         printf("         num: %d\n",*num);
  765.         printf("         len: %d\n",*len);
  766.         if (*len != 0)
  767.             printf("         data: \"%s\"\n",data);
  768.     }
  769.     switch (pbl)
  770.     {
  771.     case 1:
  772.         cchksum[0] = tochar(chk1(&rpacket));
  773.         break;
  774.     case 2:
  775.         chksum = chk2(&rpacket);
  776.         cchksum[0] = tochar((chksum & 07700) >> 6);
  777.         cchksum[1] = tochar(chksum & 077);
  778.         break;
  779.     case 3:
  780.         chksum = chk3(&rpacket);
  781.         cchksum[0] = tochar((chksum & 0170000) >> 12);
  782.         cchksum[1] = tochar((chksum & 07700) >> 6);
  783.         cchksum[2] = tochar(chksum & 077);
  784.     }
  785.     if (!cmpstr(cchksum, rchksum))
  786.       type = FALSE;
  787.  
  788.     file.pli++;
  789.     flushinput();
  790.     return (type);            /* All OK, return packet type */
  791. }
  792.  
  793. /*
  794.  *  n e x t p k
  795.  *
  796.  *  Increment packet number to the next one.  Reset retry counter.
  797.  *
  798.  */
  799.  
  800. nxtpkt()
  801. {
  802.     pknum = 1 & (n = (n+1)%64);    /* Bump packet count */
  803.     numtry = 0;                    /* Start a new counter */
  804. }
  805.  
  806. /* pe7ptb.c End-of-file */
  807.