home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / honeywellgcosa / hd6pri.c < prev   
C/C++ Source or Header  |  2020-01-01  |  59KB  |  1,523 lines

  1. /************************************************************************
  2.  *
  3.  *       HD6PRI.C     Superkermit protocol modules and primitives.
  4.  *
  5.  ***********************************************************************/  
  6.  
  7. #include "hd6ker.h"
  8.  
  9. /*
  10.  *     r d a t a
  11.  *
  12.  *     Receive data
  13.  *     The receiving of file attribute packets is handled in this module!
  14.  *
  15.  */
  16.  
  17. char rdata()
  18. {
  19.     int num, len;                     /* Packet number, length */
  20.     unsigned int j;
  21.     unsigned int k_size = 0;
  22.     char *bufp, *start, c, d;             /* attribute pointers */
  23.     float byte_size;
  24.     double byte_sz, atof();
  25.     char filnam1[50];                   /* Holds the converted file name */
  26.  
  27.     if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
  28.  
  29.     switch(rpack(&len,&num,packet))     /* Get packet */
  30.     {
  31.  
  32.  /* code added to ACK and use attrib packets if received [FRANK DREANO] */
  33.  
  34.           case 'A':
  35.               if (num != n) {             /* Right packet number or not */
  36.                  if (oldtry++ > MAXTRY)
  37.                     return('A');          /* too many retries, abort */
  38.               if (num == ((n==0) ? 63:n-1))  {  /* duplicate ? */
  39.                  spack('Y',num,0,xnull);   /* Yes, re-ACK it */
  40.                  numtry = 0;              /* Reset try counter */
  41.                  return(state);           /* stay in this state */
  42.                  }
  43.               else return('A');
  44.               }
  45.            /* got the right attrib packet */
  46.               spack('Y',n,0,xnull);       /* ACK the attribute */
  47.               oldtry = numtry;            /* Reset try counters */
  48.               numtry = 0;                 /* Reset try counter */
  49.               n = (n+1)%64;               /* bump packet counter */
  50.  
  51.           bufp = packet;
  52.           while ((*bufp) != '\0') { /* process the attributes */
  53.              switch(*bufp++) {
  54.               case '1':
  55.                     d = *bufp;
  56.                     j = (*bufp) - ' ';
  57.                     *bufp = '+';
  58.                     start = bufp; byte_sz = 0;
  59.                     bufp = ++bufp + j;
  60.                     c = *bufp;
  61.                     *bufp = ' ';   /* terminate flting point string */
  62.                     byte_sz = atof(start);
  63.                     if (debug)
  64.                       fprintf(dfp,"\nThe file size is: %7.f bytes.\n", byte_sz);
  65.                     *bufp = c;
  66.                     *start = d;
  67.                     break;
  68.               case '#':   /* just eat all other non-file size attribs */
  69.               case '.':
  70.                     j = (*bufp++) -  ' ';
  71.                     bufp = bufp + j;
  72.                     break;
  73.               case '!':
  74.                     j = (*bufp++) -  ' ';
  75.                     start = bufp; k_size = 0;
  76.                     bufp = bufp + j;
  77.                     c = *bufp;
  78.                     *bufp  = '\0'; /* terminate integer string */
  79.                     k_size = atoi(start);
  80.           if (debug) fprintf(dfp,"\nThe file size is: %u Kilobytes.\n", k_size);
  81.                     *bufp = c;
  82.                     break;
  83.                default:
  84.                    j = (*bufp++) -  ' ';
  85.                    bufp = bufp + j;
  86.           if (debug) fprintf(dfp,"\nThe attribute is not recognized.");
  87.                    break;
  88.                } /* end switch */
  89.            } /* end while */
  90.  
  91.   /* got the incoming file size lets make contiguous efficient space */
  92.   
  93.               if ((k_size == 0) && (byte_sz != 0)) 
  94.                   k_size = byte_sz / 1000;
  95.               k_size = 32 * ((k_size + 32 - 1)/32); /* round out */    
  96.               k_size = k_size * 2;
  97.               getfiles[49] = 0;
  98.               strcpy(filnam1, getfiles);     /* Copy filename */
  99.               if (k_size > 64) {
  100.                   if (debug) fprintf(dfp,"\nCI growth size is: %u.\n", k_size);
  101.                   fclose(fp);
  102.                   sprintf(cmdstg,">SYSLIB2>MFA %s -GRSZ %u ", filnam1, k_size);
  103.                   if ((cmdstat = system(cmdstg)) != 0)
  104.               fprintf(stderr,"\nCould not modify <%s> growth size.", filnam1);
  105.               if ((fileimage == FOREIGN) || (fileimage == BINARY)) 
  106.                   fp = fopen(filnam1,"ab");
  107.                   else
  108.                     fp = fopen(filnam1, "a");
  109.                   } /* end if */
  110.                  
  111.           if (fileimage == FOREIGN) {  /* stuff the attributes in the files */
  112.                 sprintf(cmdstg,"%s\n",packet);
  113.                 fputs(cmdstg, fp);
  114.                 }  
  115.  
  116.       /* end of attribute decoding and use [FRANK DREANO] */
  117.  
  118.               return('D');                /* stay in this state */
  119.  
  120.           case 'D':                       /* Got Data packet */
  121.               if (num != n)               /* Right packet? */
  122.               {                           /* No */
  123.                     if (oldtry++ > MAXTRY)
  124.                         return('A');        /* If too many tries, abort */
  125.                     if (num == ((n==0) ? 63:n-1)) { /* duplicate?   */
  126.                         spack('Y',num,0,xnull); /* Yes, re-ACK it    */
  127.                         numtry = 0;         /* Reset try counter    */
  128.                         return(state);      /* Don't write out data! */
  129.                     }
  130.                     else return('A');       /* sorry, wrong number */
  131.               }
  132.  
  133.               /* Got data with right packet number */
  134.               if ( (num = decode(packet,len)) != 0 ) {
  135.                     error("Trouble writing file, OS code %xx",num);
  136.                     return('A');
  137.               }
  138.               spack('Y',n,0,xnull);           /* Acknowledge the packet */
  139.               n = (n+1)%64;               /* Bump packet number, mod 64 */
  140.               oldtry = numtry;            /* Reset the try counters */
  141.               numtry = 0;                 /* ... */
  142.               return('D');                /* Remain in data state */
  143.  
  144.           case 'F':                       /* Got a File Header */
  145.               if (oldtry++ > MAXTRY)
  146.                     return('A');            /* If too many tries, "abort" */
  147.               if (num == ((n==0) ? 63:n-1)) /* Else check packet number */
  148.               {                           /* It was the previous one */
  149.                     spack('Y',num,0,xnull);     /* ACK it again */
  150.                     numtry = 0;             /* Reset try counter */
  151.                     return(state);          /* Stay in Data state */
  152.               }
  153.               else return('A');           /* Not previous packet, "abort" */
  154.  
  155.           case 'Z':                       /* End-Of-File */
  156.               if (num != n) return('A');  /* Must have right packet number */
  157.               spack('Y',n,0,xnull);           /* OK, ACK it. */
  158.               fflush(fp);                 /* Flush all buffers */
  159.               fclose(fp);                 /* Close the file */
  160.               fp = NULL;
  161.               
  162.        /* if attributes were used shrink file then reset growth size */
  163.   
  164.             if ((senda) && (sattrib)) {
  165.                   sprintf(cmdstg,">SYSLIB2>SHRINK %s", filnam1);
  166.                   system(cmdstg);
  167.                   sprintf(cmdstg,">SYSLIB2>MFA %s -GRSZ 20", filnam1);
  168.                   if ((cmdstat = system(cmdstg)) != 0)
  169.               fprintf(stderr,"\nCould not reset <%s> growth size.", filnam1);
  170.               }
  171.  
  172.               if (debug) {
  173.                  if ( (len != 0) && (*packet == 'D') )
  174.                 fprintf(dfp, "\nFile <%s> truncated by local Kermit\n",filnam);
  175.                     else
  176.                        fprintf(dfp,"\nFile <%s> received OK\n",filnam1);
  177.                  }
  178.               n = (n+1)%64;               /* Bump packet number */
  179.               return('F');                /* Go back to Receive File state */
  180.  
  181.           case 'E':                       /* Error packet received */
  182.               prerrpkt(packet);           /* Print it out and */
  183.               return('A');                /* abort */
  184.  
  185.           case FALSE:                     /* Didn't get packet */
  186.               spack('N',n,0,xnull);           /* Return a NAK */
  187.               return(state);              /* Keep trying */
  188.  
  189.           default:
  190.               error(badpack,prompt,type);
  191.               return('A');       /* Some other packet, "abort" */
  192.     }
  193. }                       /* End of rdata()               */
  194.  
  195.  
  196. /*
  197.  *     r f i l e
  198.  *
  199.  *     Receive file header
  200.  *
  201.  */
  202.  
  203. char rfile()
  204. {
  205.     int num, len;                       /* Packet number, length */
  206.     char filnam1[50];                   /* Holds the converted file name */
  207.  
  208.     if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
  209.  
  210.     switch(rpack(&len,&num,packet))     /* Get a packet */
  211.     {
  212.  
  213.           case 'S':                       /* Send-Init, maybe our ACK lost */
  214.               if (oldtry++ > MAXTRY) return('A'); /* If too many tries "abort" */
  215.               if (num == ((n==0) ? 63:n-1)) { /* Previous packet, mod 64? */
  216.                     len = spar(packet);           /* our Send-Init parameters */
  217.                     spack('Y',num,len,packet);
  218.                     numtry = 0;             /* Reset try counter */
  219.                     return(state);          /* Stay in this state */
  220.               }
  221.               else return('A');           /* Not previous packet, "abort" */
  222.  
  223.           case 'Z':                       /* End-Of-File */
  224.               if (oldtry++ > MAXTRY) return('A');
  225.               if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */
  226.               {                           /* Yes, ACK it again. */
  227.                     spack('Y',num,0,xnull);
  228.                     numtry = 0;
  229.                     return(state);          /* Stay in this state */
  230.               }
  231.               else return('A');           /* Not previous packet, "abort" */
  232.  
  233.           case 'F':                       /* File Header (just what we want) */
  234.               if (num != n) return('A');  /* The packet number must be right */
  235.               decfil(packet, getfiles, len);  /* 'unrepeat' filename */
  236.               getfiles[49] = 0;              /* terminate the string */
  237.               strcpy(filnam1, getfiles);     /* Copy filename */
  238.  
  239.               if (filnamcnv) {            /* Convert upper case to lower */
  240.                     for (filnam=filnam1; *filnam != '\0'; filnam++)
  241.                         if (*filnam >= 'A' && *filnam <= 'Z')
  242.                               *filnam |= 040;
  243.                     filnam = filnam1;
  244.               } 
  245.       /* should have gotten a file attribute packet instead */
  246.  
  247. /*  if ((fileimage == FOREIGN) && ((senda == FALSE) || (sattrib == FALSE))) {
  248.        error(noattrib, prompt);
  249.        return('A');
  250.        }  */
  251.                for (filnam=filnam1; *filnam != '\0'; filnam++)
  252.                if (*filnam == ',') {
  253.                   *filnam++ = '\0'; 
  254.                    *filnam = '\0'; 
  255.                   break;
  256.                   } /* end for */
  257.                filnam = filnam1;
  258.  
  259.        if ((fileimage == BINARY) || (fileimage == FOREIGN)) {  
  260.  
  261.               /*  create and open binary/foreign type file  */
  262.  
  263.                if (debug) fprintf(dfp,
  264.                              "\nDeleting <%s> if it exists.",filnam1);
  265.                  sprintf(cmdstg,">SYSLIB2>DL %s -BF", filnam1);
  266.  
  267.                if ( ((cmdstat = system(cmdstg)) !=0) && (debug) )
  268.                     fprintf(dfp,
  269.                          "\nFile not deleted; as it did not already exist.");
  270.                cmdstat = 0;
  271.          if (fileimage == BINARY)
  272.       sprintf(cmdstg, ">SYSLIB2>CR %s -F_REL -LRSZ %d -SZ 0", filnam1, lrsz_6);
  273.          if (fileimage == FOREIGN)
  274.       sprintf(cmdstg, ">SYSLIB2>CR %s -SEQ -DATA_CODE BINARY -SZ 0", filnam1);
  275.                  
  276.                if ((cmdstat = system(cmdstg)) != 0) {
  277.                      syserr("system");
  278.                      return('A');
  279.                      } /* end if */
  280.               if (debug) fprintf(dfp,"\nOpening <%s> for receiving.",filnam1);
  281.               fp=fopen(filnam1,"ab");
  282.               } /* end if */
  283.  
  284.               else {         /* open ASCII type file  */
  285.                    if (dlflag) {  /* overwrite existing file if flag set */
  286.                        if (debug) fprintf(dfp,
  287.                                   "\nDeleting <%s> if it exists.",filnam1);
  288.                        sprintf(cmdstg,">SYSLIB2>DL %s ", filnam1);
  289.                        if ( ((cmdstat = system(cmdstg)) !=0) && (debug) )
  290.                fprintf(dfp,"\nFile not deleted; as it did not already exist.");         
  291.                        }  /* end if */
  292.                    if (debug) fprintf(dfp,
  293.                                  "\nOpening <%s> for receiving.",filnam1);
  294.                    fp=fopen(filnam1,"a");
  295.                    } /* end else */
  296.  
  297.               if (fp == NULL) {
  298.                     error("%sCannot create <%s>",prompt,filnam1);
  299.                     return('A');
  300.                     } /* end if */
  301.                     else                        /* OK, give message */
  302.                     if (debug) fprintf(dfp,"\nReceiving %s as %s",packet,filnam1);
  303.                     
  304.   /* stuff dummy attribute in foreign file if the PC didn't send any */
  305.   
  306.   if ((fileimage == FOREIGN) && ((senda == FALSE) || (sattrib == FALSE))) 
  307.               fputs(",I\n", fp);
  308.  
  309.               spack('Y',n,0,xnull);       /* Acknowledge the file header */
  310.               oldtry = numtry;            /* Reset try counters */
  311.               numtry = 0;                 /* ... */
  312.               n = (n+1)%64;               /* Bump packet number, mod 64 */
  313.               return('D');                /* Switch to Data state */
  314.  
  315.           case 'B':                       /* Break transmission (EOT) */
  316.               if (num != n) return ('A'); /* Need right packet number here */
  317.               spack('Y',n,0,xnull);           /* Say OK */
  318.               if (debug) fprintf(dfp,"All files received\n");
  319.               return('C');                /* Go to complete state */
  320.  
  321.           case 'E':                       /* Error packet received */
  322.               prerrpkt(packet);           /* Print it out and */
  323.               return('A');                /* abort */
  324.  
  325.           case FALSE:                     /* Didn't get packet */
  326.               spack('N',n,0,xnull);           /* Return a NAK */
  327.               return(state);              /* Keep trying */
  328.  
  329.           default:
  330.               error(badpack,prompt,type);
  331.               return ('A');       /* Some other packet, "abort" */
  332.     }
  333. }                       /* End rfile()                  */
  334.  
  335. /*
  336.  *     r i n i t
  337.  *
  338.  *     Receive initalization
  339.  *
  340.  */
  341.  
  342. char rinit()
  343. {
  344.     int len, num;                       /* Packet length, number */
  345.     bctu = 1;      /* type-1 blk chk at first */
  346.     if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */
  347.  
  348.     switch(rpack(&len,&num,packet))     /* Get a packet */
  349.     {
  350.           case 'S':                       /* Send-Init */
  351.               rpar(packet,len);
  352.               len = spar(packet);
  353.               spack('Y',n,len,packet);      /* ACK with my parameters */
  354.               oldtry = numtry;            /* Save old try count */
  355.               numtry = 0;                 /* Start a new counter */
  356.               n = (n+1)%64;               /* Bump packet number, mod 64 */
  357.               bctu = bctr;                /* use agreed blk chk type */
  358.               return('F');                /* Enter File-Receive state */
  359.  
  360.           case 'E':                       /* Error packet received */
  361.               prerrpkt(packet);           /* Print it out and */
  362.               return('A');                /* abort */
  363.  
  364.           case 'I':                       /* Init-parameters      */
  365.               rpar(packet,len);
  366.               len = spar(packet);
  367.               spack('Y',n,len,packet); /* ack with our parameters */
  368.               n = (n+1)%64;               /* Bump packet number, mod 64 */
  369.               bctu = bctr;                /* use agreed block check type */
  370.               return(state);              /*  & continue          */
  371.  
  372.           case FALSE:                     /* Didn't get packet */
  373.               spack('N',n,0,xnull);           /* Return a NAK */
  374.               return(state);              /* Keep trying */
  375.  
  376.           default:
  377.               error(badpack,prompt,type);
  378.               return('A');       /* Some other packet type, "abort" */
  379.     }
  380. }                       /* End rinit()                          */
  381.  
  382. /*
  383.  *     r p a c k
  384.  *
  385.  *     Read a packet
  386.  *     Modified for extended packets [FRANK DREANO]
  387.  */
  388.  
  389. rpack(len,num,data)
  390. int *len, *num;                         /* Packet length and number */
  391. char *data;                             /* Packet data */
  392. {
  393.     int j,i,done,k,s;            /* Data character number, loop exit */
  394.     register char *bufp, *datap;            /* 'fast' array indexes */
  395.     int maxlx1, maxlx2;                   /* extended packet length */
  396.     unsigned char pcb[4];                /* block check char array */
  397.     char  t,                               /* Current input character */
  398.           rlongp,                        /* extended packet flag */
  399.           buffer[MAXPACKSIZ + 6];                /* area to do CRC block checks */
  400.  
  401.     timoset(timint);         /* set timeout                     */
  402. /* The way timeouts are handled is that the flag stays clear, indicating
  403.           that a timeout has occurred, until it is set to a value again
  404.           by the next call to timoset().  This means that the effect can
  405.           run up thro' the procedures without using longjmp().    */
  406.  
  407.     rlongp = FALSE;
  408.     t = 0;
  409.     *len = 0;                           /* in case times out    */
  410.     while (t != SOH) {                  /* Wait for packet header */
  411.           t = cread() & (char)0x7f;
  412.     }
  413.     timocan();
  414.     done = FALSE;                       /* Got SOH, init loop */
  415.     while (!done)                       /* Loop to get a packet */
  416.     {
  417.           t = cread();                  /* Get character */
  418.           if (t == SOH) continue;       /* Resynchronize if SOH */
  419.           bufp = buffer;                /* init buffer pointer */
  420.           *bufp++ = t;                  /* Start the checksum */
  421.           *len = unchar(t) - bctu - 2;  /* Character count */
  422.           if (*len == -(bctu+2)) rlongp = TRUE;    /* long packets */
  423.  
  424.           t = cread();                  /* Get character */
  425.           if (t == SOH) continue;       /* Resynchronize if SOH */
  426.           *bufp++ = t;                  /* Update checksum */
  427.           *num = unchar(t);             /* Packet number */
  428.  
  429.           t = cread();                  /* Get character */
  430.           if (t == SOH) continue;       /* Resynchronize if SOH */
  431.           *bufp++ = type = t;           /* Update checksum */
  432. /* extended packet modifications [FRANK DREANO] */
  433.           if (rlongp == TRUE) {
  434.  
  435.              t = cread();
  436.              if (t == SOH) continue;
  437.              *bufp++ = maxlx1 = t;      /* Get extended length */
  438.  
  439.              t = cread();
  440.              if (t == SOH) continue;
  441.              *bufp++ = maxlx2 = t;      /* Get extended length */
  442.  
  443.              t = cread();
  444.              if (t == SOH) continue;
  445. /* got all of extended packet header; do checksum and length computes */
  446.              *bufp = '\0';
  447.              if (t != tochar(chk1(buffer))) {     /* compute hdr sum */
  448.              if (debug)
  449.                 fprintf(dfp,
  450.                     "\nExtended hdr chksum error: rec'd %xx computed %xx;",
  451.                                                t, tochar(chk1(buffer)));
  452.                 return(FALSE);
  453.                 } /* end if */
  454.              *bufp++ = t;
  455.              *len = unchar(maxlx1) * 95 + unchar(maxlx2) - bctu;
  456.              } /* end if */
  457.  
  458.           datap = data;
  459.           for (i=0; i<*len; i++) {           /* The data itself, if any */
  460.               t = cread();                   /* Get character */
  461.               if (t == SOH)
  462.                     break;                   /* Resynch if SOH */
  463.               *bufp++ = *datap++ = t;        /* Update checksum */
  464.           }
  465.           if (t == SOH)
  466.               continue;
  467.           *bufp = *datap = '\0';             /* Terminate the strings */
  468.  
  469. /*  At this point the data for an entire packet should have been read in    */
  470. /*  so print it and do the block checks...type 1, 2, or 3.  [FRANK DREANO]  */
  471.  
  472.     if (debug) fprintf(dfp,"\n Packet %d received; ",*num);
  473.     if (debug>1) {                       /* Display incoming packet */
  474.           fprintf(dfp," type: %c;",type);
  475.           fprintf(dfp," num:  %d;",*num);
  476.           fprintf(dfp," len:  %d.",*len);
  477.           if (*len != 0) {
  478.           j = 0;
  479.               while (j < *len) {
  480.                  fprintf(dfp,"\n  data: <");
  481.                  i=0;
  482.                  while ((i < 60 ) && (j < *len)) {
  483.                        putc(data[j++],dfp);
  484.                        i++;
  485.                        } /* end while */
  486.                  putc('>',dfp);
  487. }   }   }
  488.  
  489.        for (s=0; s<bctu; s++) {   /* get all of the block check characters */
  490.            t = cread();
  491.            if (t == SOH) break;    /* Get out of loop if SOH */
  492.            pcb[s] = t;
  493.            } /* end for */
  494.  
  495.        if (t == SOH) continue;     /* Resynch if SOH */
  496.        pcb[s] = '\0';              /* terminate the string */
  497.        done = TRUE;                /* I have now read EVERYTHING ! */
  498.        } /* end outermost while */
  499.  
  500.        switch (bctu) {
  501.            case 1:
  502.                if (unchar(*pcb) != chk1(buffer)) {
  503.                   if (debug)
  504.                      fprintf(dfp,"\n bad checksum: rec'd %xx computed %xx; ",
  505.                                   unchar(*pcb), chk1(buffer));
  506.                   return(FALSE);
  507.                } /* end if */
  508.                break;
  509.            case 2:
  510.                s = unchar(*pcb) << 6;
  511.                s = s | unchar(pcb[1]);
  512.                if (s != chk2(buffer)) {
  513.                    if (debug)
  514.                      fprintf(dfp,"\n bad checksum: rec'd %xx computed %xx; ",
  515.                                    s, chk2(buffer));
  516.                    return(FALSE);
  517.                } /* end if */
  518.                break;
  519.            case 3:
  520.                s = unchar(*pcb) << 12;
  521.                s = s | unchar(pcb[1]) << 6;
  522.                s = s | unchar(pcb[2]);
  523.                if (s != chk3(buffer)) {
  524.                    if (debug)
  525.                      fprintf(dfp,"\n bad checksum: rec'd %xx computed %xx; ",
  526.                                    s, chk3(buffer));
  527.                   return(FALSE);
  528.                } /* end if */
  529.                break;
  530.            default:
  531.                if (debug)
  532.                   fprintf(dfp,"\n packet format is invalid");
  533.                return(FALSE);
  534.            } /* end switch */
  535.  
  536.     flushinput();
  537.  
  538.     return(type);                       /* All OK, return packet type */
  539. }                               /* End of rpack()                       */
  540.  
  541. /*
  542.  *     r p a r
  543.  *
  544.  *     Get the other side's send-init parameters
  545.  *     Modified for extended packets [FRANK DREANO]
  546.  */
  547.  
  548. rpar(data,len)
  549. char    *data, len;
  550. /* Set up incoming parameters to either what has been received
  551.           or, if nil, to defaults.
  552.   No return-code.                                               */
  553. {
  554.     char        p;
  555.     int         olen,   /* original recv-init packet length */
  556.                 rpsiz;  /* remote's packet length */
  557.  
  558.     olen = len;
  559.     spsiz = 80;                 /* send packet-length 80 chars   */
  560.     timint = MYTIME;            /* timeout as defined           */
  561.     eol = CR;                   /* terminator normally CR       */
  562.     quote = '#';                /* standard control-quote char  */
  563.     rptflg = FALSE;             /*  nor repeat-quoting          */
  564.     sattrib = FALSE;            /* no attribute packets yet     */
  565.  
  566.     while (len-- > 0) {
  567.           p = data[len];
  568.  
  569.           switch (len) {          /* for each parameter           */
  570.  
  571.             case 0:                       /* MAXL                     */
  572.               rpsiz = unchar(p);
  573.     /* loop goes backwards so set spsiz to what was negotiated */
  574.               spsiz = (spsiz < 95) ? rpsiz : spsiz;
  575.               break;
  576.  
  577.             case 1:                       /* TIME                 */
  578.               timint = (unchar(p) < 5) ? 5 : unchar(p);
  579.               break;
  580.  
  581.             case 2:                       /* NPAD                 */
  582.               pad = unchar(p);
  583.               break;
  584.  
  585.             case 3:                       /* PADC                 */
  586.               padchar = ctl(p);
  587.               break;
  588.  
  589.             case 4:                       /* EOL                  */
  590.               eol = unchar(p);
  591.               break;
  592.  
  593.             case 5:                       /* QCTL                 */
  594.               quote = p;
  595.               break;
  596.  
  597.             case 6:                       /* QBIN                 */
  598.               if (image == 2) {
  599.                     if (p == 'Y')
  600.                         qu8 = '&';
  601.                     else if (isalnum(p) == 0) /* provided punctuation */
  602.                         qu8 = p;
  603.                     else
  604.                         image = 0;
  605.                     break;
  606.               }
  607.               break;
  608.  
  609.             case 7:                       /* BLOCK CHECK TYPE */
  610.                bctr = p - '0';
  611.                bctr = (bctr < 1 || bctr > 3) ? 1 : bctr;
  612.                break;
  613.  
  614.             case 8:                       /* REPT                 */
  615.               if (p == '~')
  616.                rptflg = TRUE;
  617.               break;
  618.  
  619.   /* extended packet additions [FRANK DREANO]
  620.      This routine sets 2 variables slongp = TRUE/FALSE for extended
  621.      packets on/off and spsiz = negotiated packet length. */
  622.  
  623.             case 9:
  624.             if (slongp == TRUE) {     /* did user ask for extended packets ? */
  625.               if (((unchar(p) & 0x02)) == 0x02) {
  626.                     spsiz = MAXPACKSIZ;  /* 2000 bytes */
  627.                     rpsiz = 500;   /* set default extended packet length */
  628.                     if (olen > 9)
  629.                           rpsiz = unchar(data[11]) * 95 + unchar(data[12]);
  630.                     /* set final negotiated size no matter what */
  631.                     spsiz = (spsiz < rpsiz) ? spsiz : rpsiz;
  632.                     if (debug)
  633.                        fprintf(dfp,"\nExtended packets used size: %d.", spsiz);
  634.                     } /* end if */
  635.                     else
  636.                        slongp = FALSE; /* turn extended packets off */
  637.                } /* end if */          /* if CAPAS bit not set */
  638.              if (((unchar(p) & 0x08)) == 0x08)  /* user likes attrib packets */
  639.                     sattrib = TRUE;
  640.               break;
  641.  
  642.             default:                      /* CHKT, CAPAS etc.     */
  643.               break;
  644.  
  645.     }   }                       /* end while & outer switch     */
  646.  
  647.     if ( (qu8 == 0) && (image == 2) )   /* invalid tseting      */
  648.           image = 0;
  649.     if (debug) fprintf(dfp,
  650. "\nParms recd in: Fileimage: %d, image: %d, q_char: %c, rptflg: %s, bchk: %d.",
  651. fileimage,image,qu8,logicval[-rptflg],bctr);              
  652. /*
  653. "\nParms rec'd in: 8th-bit tseting is %d, char is %c, reptflag %s, chktype %d.",
  654. image,qu8,logicval[-rptflg],bctr); */
  655.     return;
  656. }                       /* End of rpar()                        */
  657.  
  658. /*
  659.  *     s b r e a k
  660.  *
  661.  *     Send break (EOT)
  662.  *
  663.  */
  664.  
  665. char sbreak()
  666. {
  667.     int num, len;                       /* Packet number, length */
  668.     if (numtry++ > MAXTRY) return('A'); /* If too many tries "abort" */
  669.  
  670.     spack('B',n,0,packet);              /* Send a B packet */
  671.     switch (rpack(&len,&num,recpkt))    /* What was the reply? */
  672.     {
  673.           case 'N':                       /* NAK, just stay in this state, */
  674.               num = (--num<0 ? 63:num);   /* unless NAK for previous packet, */
  675.               if (n != num)               /* which is just like an ACK for */
  676.                     return(state);        /* this packet so fall thru to... */
  677.  
  678.           case 'Y':                       /* ACK */
  679.               if (n != num) return(state); /* If wrong ACK, fail */
  680.               numtry = 0;                 /* Reset try counter */
  681.               n = (n+1)%64;               /* and bump packet count */
  682.               return('C');                /* Switch state to Complete */
  683.  
  684.           case 'E':                       /* Error packet received */
  685.               prerrpkt(recpkt);           /* Print it out and */
  686.               return('A');                /* abort */
  687.  
  688.           case FALSE: return('C');        /* Receive failure, count as OK */
  689. /* If timed out or etc. when completing, likely other end has gone away */
  690.  
  691.           default:
  692.               error(badpack,prompt,type);
  693.               return ('A');       /* Other, "abort" */
  694.    }
  695. }                       /* End sbreak()                         */
  696.  
  697. /*
  698.  *     s d a t a
  699.  *
  700.  *     Send file data
  701.  *
  702.  */
  703.  
  704. char sdata()
  705. {
  706.     int num, len;                       /* Packet number, length */
  707.  
  708.     if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
  709.  
  710.     spack('D',n,size,packet);
  711.     switch(rpack(&len,&num,recpkt))     /* What was the reply? */
  712.     {
  713.           case 'N':                       /* NAK, just stay in this state, */
  714.               num = (--num<0 ? 63:num);   /* unless it's NAK for next packet */
  715.               if (n != num)               /* which is just like an ACK for */
  716.                     return(state);          /* this packet so fall thru to... */
  717.  
  718.           case 'Y':                       /* ACK */
  719.               if (n != num) return(state); /* If wrong ACK, persist */
  720.               numtry = 0;                 /* Reset try counter    */
  721.               n = (n+1)%64;               /* Bump packet count    */
  722.               if (len != 0) switch (*recpkt) {   /* ACK has data */
  723.                 case 'Z':                         /* cancel all   */
  724.                 case 'z':
  725.                     filecount = 0;                 /* no more to go */
  726.                 case 'X':                         /* cancel file  */
  727.                 case 'x':
  728.                     return('Z');
  729.                 default:                          /* invalid      */
  730.                     if (!senda) {               /* Attrib ACK can have data */
  731.                        recpkt[20] = 0;                 /*  truncate    */
  732.                        error("%sLocal Kermit sent ACK with data: <%s> - goodbye!",prompt,recpkt);
  733.                        return('A');
  734.                        } /* end if */
  735.                  } /* end inner switch */
  736.               if ((size = bufill(packet)) != EOF) /* data from file */
  737.                     return('D');            /* Got data, stay in state D */
  738.   /* EOF can mean either really end-of-file or an error         */
  739.               if ( (num = filerr()) != 0 ) {    /* actual error */
  740.                     error("Problem while reading file, OS code %xx",num);
  741.                     return('A');
  742.                     } /* end if */
  743.               return('Z');                /* EOF                  */
  744.  
  745.           case 'E':                       /* Error packet received */
  746.               prerrpkt(recpkt);           /* Print it out and */
  747.               return('A');                /* abort */
  748.  
  749.           case FALSE: return(state);      /* Receive failure, stay in D */
  750.  
  751.           default:
  752.               error(badpack,prompt,type);
  753.               return('A');        /* Anything else, "abort" */
  754.           } /* end outer switch */
  755. }                       /* End sdata()                          */
  756.  
  757. /*
  758.  *     s e o f
  759.  *
  760.  *     Send End-of-File
  761.  *
  762.  */
  763.  
  764. char seof()
  765. {
  766.     int num, len;                       /* Packet number, length */
  767.     if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */
  768.  
  769.     spack('Z',n,0,packet);              /* Send a 'Z' packet */
  770.     switch(rpack(&len,&num,recpkt))     /* What was the reply? */
  771.     {
  772.           case 'N':                       /* NAK, just stay in this state, */
  773.               num = (--num<0 ? 63:num);   /* unless it's NAK for next packet, */
  774.               if (n != num)               /* which is just like an ACK for */
  775.                     return(state);          /* this packet so fall thru to... */
  776.  
  777.           case 'Y':                       /* ACK */
  778.               if (n != num) return(state); /* If wrong ACK, hold out */
  779.               numtry = 0;                 /* Reset try counter */
  780.               n = (n+1)%64;               /* and bump packet count */
  781.               if (debug) fprintf(dfp,"\nClosing input file <%s>, ",filnam);
  782.               fclose(fp);                 /* Close the input file */
  783.               fp = NULL;            /* Set flag indicating no file open */
  784.  
  785.               if (debug) fprintf(dfp,"looking for next file...");
  786.               if (gnxtfl() == FALSE) {     /* No more files go? */
  787.                     if (debug) fprintf(dfp,"\nNo more files to send.");
  788.                     return('B');            /* if not, break, EOT, all done */
  789.               }
  790.               if (debug) fprintf(dfp,"New file is %s\n",filnam);
  791.               senda = TRUE;               /* send attrib pkt if negotiated */
  792.               return('F');                /* More files, switch state to F */
  793.  
  794.           case 'E':                       /* Error packet received */
  795.               prerrpkt(recpkt);           /* Print it out and */
  796.               return('A');                /* abort */
  797.  
  798.           case FALSE: return(state);      /* Receive failure, stay in Z */
  799.  
  800.           default:
  801.               error(badpack,prompt,type);
  802.               return('A');        /* Something else, "abort" */
  803.     }
  804. }                       /* End seof()                           */
  805.  
  806. /*
  807.  *     s f i l e
  808.  *
  809.  *     Send file header
  810.  *
  811.  */
  812.  
  813. char sfile()
  814. {
  815.     int num, len, lenlen;               /* Packet number, length */
  816.     unsigned filesize;
  817.     char filnam1[50],                   /* Converted file name */
  818.           *newfilnam,                     /* Pointer to file name to send */
  819.           *cp;                            /* char pointer */
  820.  
  821.      /*  MUST use attribute packets with foreign file types!!  */ 
  822.  
  823. /*  if ((fileimage == FOREIGN) && ((senda == FALSE) || (sattrib == FALSE))) {
  824.        error(noattrib, prompt);
  825.        return('A');
  826.        }   */
  827.  
  828.     if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
  829.  
  830.     if (fp == NULL) {                   /* If not already open, */
  831.           if (debug) fprintf(dfp,"\nOpening %s for sending.",filnam);
  832.         if ((fileimage == BINARY) || (fileimage == FOREIGN))
  833.           fp = fopen(filnam,"rb");
  834.         else
  835.           fp = fopen(filnam,"r");         /* open the file to be sent */
  836.           if (fp == NULL)                 /* If bad file pointer, give up */
  837.           {
  838.               error("%sCannot open file <%s>",prompt,filnam);
  839.               return('A');
  840.           }
  841.     }
  842.  
  843.     strcpy(filnam1, filnam);            /* Copy file name */
  844.     newfilnam = cp = filnam1;
  845.     while (*cp != '\0')                 /* Strip off all leading directory */
  846.           if (*cp++ == '>')               /* names (ie. up to the last >). */
  847.               newfilnam = cp;
  848.  
  849.     if (filnamcnv)                      /* Convert lower case to upper  */
  850.           for (cp = newfilnam; *cp != '\0'; cp++)
  851.               if (*cp >= 'a' && *cp <= 'z')
  852.                     *cp ^= 040;
  853.  
  854.     len = cp - newfilnam;               /* Compute length of new filename */
  855.  
  856.     if (debug) fprintf(dfp,"\nSending %s as %s",filnam,newfilnam);
  857.  
  858.    if (iflg >= 99)
  859.       spack('X',n,len,newfilnam);   /* Send an X packet if a 'remote' cmd */
  860.       else
  861.          spack('F',n,len,newfilnam);  /* Send an F packet for file xfer */
  862.     switch(rpack(&len,&num,recpkt))     /* What was the reply? */
  863.     {
  864.           case 'N':                       /* NAK, just stay in this state, */
  865.               num = (--num<0 ? 63:num);   /* unless it's NAK for next packet */
  866.           case 'Y':                       /* ACK */
  867.               if (n != num)
  868.                     return(state);          /* If wrong ACK, stay in F state */
  869.               numtry = 0;                 /* Reset try counter */
  870.               n = (n+1)%64;               /* Bump packet count */
  871.  
  872.        /*  if using attributes switch to 'Q' state; else 'D' state */
  873.  
  874.           /*  get the attribute from foreign files  */
  875.           
  876.            if (fileimage == FOREIGN)  
  877.               fgets(attrib, 80, fp);
  878.  
  879.            if ((sattrib) && (senda)) {   
  880.                 /* use attribute packets */
  881.           if ( (fileimage == FOREIGN) && ((strncmp(",I",attrib,2)!=0)) ) {
  882.                 size = strlen(attrib)-1;               /* drop the newline */
  883.                 } else {      /* not 'foreign' so build some attribs */
  884.                   lenlen = 0;
  885.                   while (lenlen < 45) attrib[lenlen++] = 0x0000;
  886.                   /*   compute size in Kilobytes  */
  887.                   if (fileimage == BINARY) 
  888.                      filesize = fsize(filnam,0);
  889.                        else filesize = 0;
  890.                   sprintf(attrib, "%u", filesize);
  891.                   lenlen = strlen(attrib);
  892.          /*   print to string, include computer attrib as well  */
  893.                   sprintf(attrib, ".\042E3!%c%u", tochar(lenlen), filesize);
  894.                   size = strlen(attrib);
  895.                   } /* end else */
  896.               return('Q');
  897.               } else {  /* not using attributes! */
  898.                 if ((size = bufill(packet)) != EOF) /* data from file */
  899.                     return('D');            /* Got data, stay in state D */
  900.   /* EOF can mean either really end-of-file or an error         */
  901.                 if ( (num = filerr()) != 0 ) {    /* actual error */
  902.                     error("Problem while reading file, OS code %xx",num);
  903.                     return('A');
  904.                     }
  905.                 return('Z');                /* EOF (empty file)     */
  906.                 } /* end outer else */
  907.  
  908.           case 'E':                       /* Error packet received */
  909.               prerrpkt(recpkt);           /* Print it out and */
  910.               return('A');                /* abort */
  911.  
  912.           case FALSE: return(state);      /* Receive failure, stay in F state */
  913.  
  914.           default:
  915.               error(badpack,prompt,type);
  916.               return('A');        /* Something else, just "abort" */
  917.     }
  918. }                       /* End sfile()                  */
  919.  
  920.  
  921. /*
  922.  *     s a t t r u
  923.  *
  924.  *     Send file attributes
  925.  *     A separate state is not required to receive file attributes !
  926.  *
  927.  */
  928.  
  929. char sattru()
  930. {
  931.     int num, len, lenlen;        /* Packet number, length */
  932.  
  933.     spack('A',n,size,attrib);             /* Send an A packet for file xfer */
  934.     switch(rpack(&len,&num,recpkt))      /* What was the reply? */
  935.     {
  936.           case 'N':                       /* NAK, just stay in this state, */
  937.               num = (--num<0 ? 63:num);   /* unless it's NAK for next packet */
  938.           case 'Y':                       /* ACK */
  939.               if (n != num)
  940.                     return(state);          /* If wrong ACK, stay in Q state */
  941.               numtry = 0;                 /* Reset try counter */
  942.               n = (n+1)%64;               /* Bump packet count */
  943.               if ((size = bufill(packet)) != EOF) /* data from file */
  944.                     return('D');            /* Got data, stay in state D */
  945.   /* EOF can mean either really end-of-file or an error         */
  946.               if ( (num = filerr()) != 0 ) {    /* actual error */
  947.                     error("Problem while reading file, OS code %xx",num);
  948.                     return('A');
  949.                     }                    
  950.               return('Z');                /* EOF (empty file)     */
  951.  
  952.           case 'E':                       /* Error packet received */
  953.               prerrpkt(recpkt);           /* Print it out and */
  954.               return('A');                /* abort */
  955.  
  956.           case FALSE: return(state);      /* Receive failure, stay in Q state */
  957.  
  958.           default:
  959.               error(badpack,prompt,type);
  960.               return('A');        /* Something else, just "abort" */
  961.     }
  962. }                       /* End sattru()                     */
  963.  
  964.  
  965. /*
  966.  *     s i n i t
  967.  *
  968.  *     Send initialization parameters and receive other side's back
  969.  *
  970.  */
  971.  
  972. char sinit()
  973. {
  974.     int num, len;                       /* Packet number, length */
  975.  
  976.     flushinput();                       /* Flush pending input */
  977.     bctu = 1;                           /* assume type-1 block check */
  978.     if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
  979.     len = spar(packet);                 /* Fill up init info packet */
  980.     spack('S',n,len,packet);              /* Send an S packet */
  981.     switch(rpack(&len,&num,recpkt))     /* What was the reply? */
  982.     {
  983.           case 'N':
  984.               num = (--num<0 ? 63:num);   /* unless it's NAK for next packet */
  985.               if (n != num)               /* which is just like an ACK for */
  986.                     return(state);          /* this packet so fall thru to... */
  987.  
  988.           case 'Y':                       /* ACK */
  989.               if (n != num)               /* If wrong ACK, stay in S state */
  990.                     return(state);          /* and try again */
  991.               rpar(recpkt,len);           /* Get other side's init info */
  992.               numtry = 0;                 /* Reset try counter */
  993.               n = (n+1)%64;               /* Bump packet count */
  994.               bctu = bctr;                /* use agreed upon block check */
  995.               return('F');                /* OK, switch state to F */
  996.  
  997.           case 'E':                       /* Error packet received */
  998.               prerrpkt(recpkt);           /* Print it out and */
  999.               return('A');                /* abort */
  1000.  
  1001.           case 'I':                       /* Init-parameters      */
  1002.               rpar(packet,len);
  1003.               len = spar(packet);
  1004.               spack('Y',n,len,packet); /* ack with our parameters */
  1005.               n = (n+1)%64;               /* Bump packet number, mod 64 */
  1006.               bctu = bctr;                /* use agreed upon block check */
  1007.               return(state);              /*  & continue          */
  1008.  
  1009.           case FALSE: return(state);      /* Receive failure, try again */
  1010.  
  1011.           default:
  1012.               error(badpack,prompt,type);
  1013.               return('A');           /* Anything else, just "abort" */
  1014.     }
  1015. }                       /* End sinit()                          */
  1016.  
  1017. /*
  1018.  *     s p a c k
  1019.  *
  1020.  *     Send a packet
  1021.  *     Modified for extended packets [FRANK DREANO]
  1022.  */
  1023.  
  1024. spack(stype,num,len,d)
  1025. char stype, *d;
  1026. int num, len;
  1027. {
  1028.     int i, j;                             /* Character loop counter */
  1029.     register char *bufp;
  1030.     char chksum, buffer[MAXPACKSIZ + 6], *lp;    /* Checksum, packet buffer */
  1031.  
  1032.     if (debug > 1) {                     /* Display outgoing packet */
  1033.           fprintf(dfp,"\nSending packet;  type: %c;",stype);
  1034.           fprintf(dfp," num: %d;",num);
  1035.           fprintf(dfp," len:  %d;",len);
  1036.           if (len != 0) {
  1037.          j = 0;
  1038.               while (j < len) {
  1039.                  fprintf(dfp,"\n  data: <");
  1040.                  i=0;
  1041.                  while ((i < 60 ) && (j < len)) {
  1042.                        putc(d[j++],dfp);
  1043.                        i++;
  1044.                        } /* end while */
  1045.                  putc('>',dfp);
  1046. }   }   }
  1047.     bufp = buffer;
  1048.     *bufp++ = SOH;                      /* Packet marker, ASCII 1 (SOH) */
  1049.     lp = bufp++;                        /* store LEN pointer for later */
  1050.     *bufp++ = tochar(num);              /* Packet number */
  1051.     *bufp++ = stype;                     /* Packet type */
  1052.     j = len + bctu;      /* packet length plus block check characters */
  1053.       if (j+2 > 94) {
  1054. /*    if (j > 95) {                         long packets */
  1055.        *lp = tochar(0);                  /* init LEN count */
  1056.        *bufp++ = tochar(j / 95);     /* high part */
  1057.        *bufp++ = tochar(j % 95);     /* lo part */
  1058.        *bufp = '\0';                   /* header checksum */
  1059.        *bufp++  = tochar(chk1(lp));
  1060.        } else *lp = tochar(j+2);    /* give normal length */
  1061.  
  1062.     while (len-- > 0) *bufp++ = (*d++);
  1063.       *bufp = '\0';
  1064.  
  1065.     switch (bctu) {
  1066.        case 1:
  1067.            *bufp++ = tochar(chk1(lp));
  1068.            break;
  1069.        case 2:
  1070.            j = chk2(lp);
  1071.            *bufp++ = (unsigned) tochar((j >> 6) & 077);
  1072.            *bufp++ = (unsigned) tochar(j & 077);
  1073.            break;
  1074.        case 3:
  1075.            j = chk3(lp);
  1076.            *bufp++ = tochar(( (unsigned) (j & 0170000)) >> 12);
  1077.            *bufp++ = tochar((j >> 6) & 077);
  1078.            *bufp++ = tochar(j & 077);
  1079.            break;
  1080.        }
  1081.     *bufp++ = eol;
  1082. /*  *bufp = CR;                      CR for network */
  1083.     write(1, buffer, bufp-buffer+1);
  1084.     if (debug) {
  1085.           fprintf(dfp," Packet %d sent;\n",num);
  1086.     }
  1087.     return;
  1088. }                       /* End of spack()                       */
  1089.  
  1090. /*
  1091.  *     s p a r
  1092.  *
  1093.  *     Fill the data array with my send-init parameters
  1094.  *     Returns length of parameter block (6, 7, 9 or 13)
  1095.  *     Modified for extended packets [FRANK DREANO]
  1096.  */
  1097.  
  1098. spar(data)
  1099. char    *data;
  1100. {
  1101.     char        len;
  1102.  
  1103.     data[0] = tochar((spsiz > 94) ? 94 : spsiz);
  1104.     data[1] = tochar(MYTIME);
  1105.     data[2] = tochar(MYPAD);
  1106.     data[3] = ctl(0);
  1107.     data[4] = tochar(MYEOL);
  1108.     data[5] = MYQUOTE;
  1109.     len = 6;
  1110.     if (image == 2) {                   /* 8th-bit prefixing    */
  1111.           if (qu8 == 0)
  1112. /*            data[6] = 'Y';       this means I don't need to quote !!!  */
  1113.               data[6] = '&';
  1114.           else
  1115.               data[6] = qu8;              /*  feed back 8-quote   */
  1116.           len = 7;
  1117.           }
  1118.           else
  1119.              data[6] = 'N';
  1120.     data[7] = bctr + '0';           /*  set checksum type */
  1121.     len = 8;
  1122.     if (rptflg) {
  1123.           data[8] = '~';        /* only ~ for repeating */
  1124.           len = 9;
  1125.           } /* end if */
  1126.  
  1127. /* extended packet modifications  [FRANK DREANO]         */
  1128.        data[9] = tochar(0x08);       /* I can accept attribute packets */
  1129.     if (slongp == TRUE) {
  1130.        data[9] = tochar(0x0a); /* attribs & extended packets can be used */
  1131.        data[10] = tochar(0x00);                /* NO sliding windows! */
  1132.        data[11] = tochar(MAXPACKSIZ / 95);   /* set up for 2000 bytes */
  1133.        data[12] = tochar(MAXPACKSIZ % 95);
  1134.        len = 13;
  1135.        if (debug)
  1136.           fprintf(dfp,"\nExtended packets requested (2000) bytes.");
  1137.        } /* end if */
  1138.  
  1139.     if (debug) fprintf(dfp,
  1140. "\nParms sent out: Fileimage: %d, image: %d, q_char: %c, rptflg: %s, bchk: %d.",
  1141. fileimage,image,qu8,logicval[-rptflg],bctr);              
  1142. /*    
  1143. "\nParms sent out: 8th-bit tseting is %d, char is %c, reptflag %s, chktype %d.",
  1144. image,qu8,logicval[-rptflg],bctr); */
  1145.     return(len);
  1146.  
  1147. }                       /* End of spar()                        */
  1148.  
  1149. /*
  1150.  *     t i m o c a n
  1151.  *
  1152.  *     Cancel a scheduled timeout
  1153.  *
  1154.  */
  1155.  
  1156. timocan()
  1157. {
  1158.     timoset(0);
  1159.     timflag = 0xff;
  1160.     return;
  1161. }                       /* End of timocan()             */
  1162.  
  1163. /*
  1164.  *     t i m e o x
  1165.  *
  1166.  *     Indicate timeout condition
  1167.  *
  1168.  */
  1169.  
  1170. timoex()
  1171. {
  1172.     timflag = 0;                /* clear flag           */
  1173.     if (debug) {
  1174.           fprintf(dfp,"Timeout ...");
  1175.     }
  1176.     return;
  1177. }                       /* End of timoex()              */
  1178.  
  1179.  
  1180. /*
  1181.  *        f s i z e
  1182.  *
  1183.  *        This routine gets the APPROXIMATE size of a file in kilobytes
  1184.  *        so that an 'attribute' packet may be sent during transfers.
  1185.  *        It uses very esoteric code and MOD400 macro calls so if it
  1186.  *        causes trouble, skip sending attribute packets.  
  1187.  *        If the 'func' arg is other than '1' the size is only computed
  1188.  *        for fixed-length record files as variable-length record file 
  1189.  *        size estimates are highly inaccurate.  If the 'func' arg is '1'
  1190.  *        AND the file 'fname' contains variable length records a 0 is
  1191.  *        returned if the DATA_CODE is unknown and a 1 if it is BINARY. 
  1192.  *
  1193.  *                                                   [FRANK DREANO]
  1194.  */
  1195.  
  1196. unsigned
  1197. fsize(fname, func) char *fname; int func;
  1198. {
  1199. #define $GIFIL 0x1060   /* --- get file information       --- */
  1200.  
  1201.       struct mcl_psb {
  1202.           int *reg_b4;
  1203.           int *reg_b3;
  1204.           int *reg_b2;
  1205.           int *reg_b1;
  1206.           int reg_r7;
  1207.           int reg_r6;
  1208.           int reg_r5;
  1209.           int reg_r4;
  1210.           int reg_r3;
  1211.           int reg_r2; } reg;
  1212.  
  1213.        union cvt_adr {int address[3]; int *adrint; char *adrchar;} adrtag;
  1214.  
  1215. struct gifab {
  1216.      int gfa_lrsz;            /* logical record size                  */
  1217.      int gfa_bksz;            /* block size (bytes/CI for disk files) */
  1218.      int gfa_find;            /* field indicators (# of CIs in file)  */
  1219.      int gfa_dsw1;            /* device specific word 1               */
  1220.      int gfa_dsw2;            /* device specific word 2               */
  1221.      int gfa_isw1;            /* init device specific word 1          */
  1222.      int gfa_isw2;            /* init device specific word 2          */
  1223.      int gfa_rfu [9];         /* reserved - must be zero              */
  1224. } fab;
  1225. # define gfa_cisz gfa_bksz
  1226.  
  1227. struct gipsb {
  1228.      int gipsb_lfn;
  1229.      int *gipsb_pthp;
  1230.      int gipsb_dtyp;
  1231.      int gipsb_lrn;
  1232.      char gipsb_ftyp;
  1233.      char gipsb_rtyp;
  1234.      struct gifab *gipsb_fabp;
  1235.      unsigned int gipsb_sdid;
  1236.      int gipsb_resv;
  1237.      int *gipsb_kdp;
  1238.      int gipsb_rdsz;
  1239.      int gipsb_nrf;
  1240. } psb;
  1241.  
  1242.        int i;
  1243.        int hunds, tens, units;
  1244.        int path_name[28];
  1245.        char rec_type;              /* Fixed or variable records */
  1246. /*     float front; */
  1247.        unsigned lrsz, cisz, cinum, bytesize;    /* multiplicative operands */
  1248.  
  1249.               /* load up required parameters in arg block */
  1250.  
  1251.        lrsz = cisz = cinum = bytesize = 0;
  1252. /*     front = 0;  */  i = 0;
  1253.        while (i < 28) path_name[i++] = 0x2020;  /* file name inited to blank */
  1254.        path_name[28] = 0x2020;                  /* terminate name array     */
  1255.        strcpy(path_name, fname);
  1256.        strcat(path_name, " ");      /* $GIFIL macro needs terminating blank */
  1257.        psb.gipsb_lfn = 0x2020;                   /* blank out LFN field      */
  1258.        psb.gipsb_pthp = &path_name[0];           /* load pointer to pathname */
  1259.        psb.gipsb_fabp = &fab;                    /* load ptr to file attribs */
  1260.        psb.gipsb_kdp = 0x000;                    /* load NULL ptr, field N/A */
  1261.  
  1262.                 /* set-up arg-block for the mcl call */
  1263.  
  1264.        adrtag.adrint = &psb;          /* get char pointer to argument block */
  1265.        reg.reg_b4 = adrtag.adrint;    /* 'dirty' conversion of pointer      */
  1266.        adrtag.adrint = ®.reg_b4;   /* get address of B4 register         */
  1267.        i = mcl($GIFIL,adrtag.adrint);
  1268.        if (i != 0) {
  1269.            printf("\n\tERRORCODE: %x\n", i);
  1270.            return(0);
  1271.            } /* end if */
  1272.  
  1273.        rec_type = psb.gipsb_rtyp;
  1274.  /*  if arg = 3 get lrsz for >SYSLIB2>EC to determine operating system  */ 
  1275.        if (func == 3) {
  1276.           lrsz_6 = fab.gfa_lrsz; 
  1277.           if (debug) fprintf(dfp, "BU lrsz size = %d\n", lrsz_6);
  1278.           return(0);
  1279.           }
  1280.        lrsz = fab.gfa_lrsz;
  1281.        cisz = fab.gfa_cisz;  /* put Fixed-relative CI size in var. */
  1282.        cinum = fab.gfa_find;
  1283.  
  1284.    /* determine if a sequential file has DATA_CODE = BINARY attribute */       
  1285.    
  1286. /*     if (debug) 
  1287.           fprintf(dfp,
  1288.          "\nFSIZE(): File: %s, rec_type: %c, function: %d, data_code: %x\n", 
  1289.               fname, rec_type, func, (psb.gipsb_resv & 0x1000));  */
  1290.  
  1291.        if ((rec_type != 'F') && (func == 1)) 
  1292.           return(psb.gipsb_resv & 0x1000);
  1293.        
  1294.    /* recompute the CI size to exclude CI & logical record header info */
  1295.  
  1296.        if (rec_type != 'F')          /* dont try var-length SEQ files */
  1297.           return(0);
  1298.        cisz = cisz - (((cisz / lrsz) * 4) + 8);
  1299.  
  1300.    /* compute file size in kilobytes WITHOUT using floating point ops. */
  1301.  
  1302.        hunds = cisz/100; tens = (cisz - (hunds * 100)) / 10;
  1303.        units = cisz - (hunds * 100) - (tens * 10);
  1304.        hunds = hunds * cinum; tens = tens * cinum; units = units * cinum;
  1305.        bytesize = (hunds + (tens/ 10) + (units / 100)) / 10;
  1306.  
  1307. /*     front = cisz; front = front / 1024; front = front * cinum;
  1308.        bytesize = front; */
  1309.        if (debug ) {
  1310.           fprintf(dfp, "\n\tThe logical record size is: %u.", lrsz);
  1311.           fprintf(dfp, "\n\tThe number of data bytes per CI is: %u.", cisz);
  1312.           fprintf(dfp, "\n\tThe highest numbered file CI is: %u.", cinum);
  1313.           fprintf(dfp,
  1314.               "\n\tThe approximate size in kilobytes is: %u.\n", bytesize);
  1315.           } /* end if */
  1316.        return(bytesize);         /* return size in bytes */
  1317.  
  1318.  
  1319. }  /* end fsize */
  1320.  
  1321.  
  1322. /*
  1323.  *     Kermit checksum routines:
  1324.  *
  1325.  *     The following three routines are in keeping with 'classic'
  1326.  *     Kermit and are presented worst to best below [FRANK DREANO]
  1327.  *
  1328.  */
  1329.  
  1330. /*
  1331.  *      c h k 1 -- compute type-1 Kermit error-checking;
  1332.  *                 a 6-bit checksum.
  1333.  *
  1334.  */
  1335.  
  1336. chk1(pkt) char *pkt; {
  1337.         unsigned int chk;
  1338.         chk = chk2(pkt);
  1339.         chk = (((chk & 0300) >> 6) + chk) & 077;
  1340.         return(chk);
  1341. }       /* end of chk1 */
  1342.  
  1343. /*
  1344.  *      c h k 2 -- compute the numeric sum of all bytes in the packet;
  1345.  *                 a 12-bit checksum.
  1346.  *
  1347.  */
  1348.  
  1349.  unsigned
  1350.  chk2(pkt) unsigned char *pkt; {
  1351.         long chk;
  1352.         for (chk = 0; *pkt != '\0'; pkt++)
  1353.            chk += *pkt;
  1354.         return(chk & 07777);
  1355. }       /* end of chk2 */
  1356.  
  1357. /*
  1358.  *      c h k 3 -- compute type-3 Kermit checksum;
  1359.  *                 a 16-bit cyclic redundancy check.
  1360.  *
  1361.  */
  1362.  
  1363.  chk3(s) char *s; {
  1364.         unsigned int c, q;
  1365.         unsigned long crc = 0;
  1366.  
  1367.         while ((c = *s++) != '\0') {
  1368.            c &= 0177;                   /* strip high bit if any */
  1369.            q = (crc ^ c) & 017;         /* low order nibble */
  1370.            crc = (crc >> 4) ^ (q * 010201);
  1371.            q = (crc ^ (c >> 4)) & 017;  /* hi order nibble */
  1372.            crc = (crc >> 4) ^ (q * 010201);
  1373.            } /* end while */
  1374.         return(crc);
  1375. } /* end chk3 */
  1376.  
  1377. /*
  1378.  *     Kermit printing routines:
  1379.  *
  1380.  *     help - displays command syntax specific to DHS version of Kermit
  1381.  *     usage - print command line options showing proper syntax
  1382.  *     printmsg - like printf with logo prepended
  1383.  *     error - like printmsg if local Kermit; sends error packet if remote
  1384.  *     prerrpkt - print contents of error packet received from remote
  1385.  *
  1386.  */
  1387.  
  1388. /*
  1389.  *     h e l p
  1390.  *
  1391.  *     The next two routines are user help displays for DHS Kermit
  1392.  *
  1393.  */
  1394.  
  1395. help()
  1396. {
  1397.     printf("\nSummary of DPS-6 Superkermit:\n");
  1398.     help1();
  1399.     printf("\t\t\t\t hit CR for more ");
  1400.     timoset(30);
  1401.     while (timflag != 0)
  1402.           if (cread() != 0)
  1403.               break;
  1404.     printf("\nBasic syntax of the \"superkerm\" command is:\n");
  1405.     usage();                    /* exits                */
  1406. }                       /* End of help()                */
  1407. help1()
  1408. {
  1409.  printf("This is a remote receive/send/server Kermit; normally called with\n");
  1410.  printf("  command line arguments, if not, server mode is assumed.\n");
  1411.  printf("CRC error checking is always requested, 7-bit ASCII transfers invoked\n");
  1412.  printf("  by \"a\"-flag, otherwise 8-bit prefixed transfer is the default;\n");
  1413.  printf("  mapping between LFs and CR/LF pairs is only done for ASCII transfers.\n");
  1414.  printf("8-bit image mode is invoked by \"i\"-flag; there is NO Connect facility.\n");
  1415.  printf("Extended packet (up to 2000 bytes) transfers are always available.\n");
  1416.  printf("Incoming text files will be concatenated to via the \"c\"-flag.\n");
  1417.  printf("Server mode supports many advanced server commands...see the files\n");
  1418.  printf("   >SYSLIB1>SUPERKER.DOC and >SYSLIB1>SUPERKER.BWR for details.\n");
  1419.  printf("If your transfer breaks down, go into connect-mode and enter\n");
  1420.  printf("  ESCAPE-C, which will cause Superkermit to quit gracefully;\n");
  1421.  printf("  alternatively enter ESCAPE-H, which will elicit a reassurance.\n");
  1422.  printf("If debug is requested by \"-D\" flag(s) on second parameter, then\n");
  1423.  printf("  debug information is written into a file whose name is \n");
  1424.  printf("  the rest of the second parameter (after last \"D\"); up to three\n");
  1425.  printf("  \"D\" flags may be entered (but only one \"-\"):\n");
  1426.  printf("Debug = 1 gives basic trace of automaton states + error-messages,\n");
  1427.  printf("      = 2 logs packets as sent/received,\n");
  1428.  printf("      = 3 also logs all chars as read from line, in hex.\n");
  1429.     return;
  1430. }                               /* End of help1()                       */
  1431.  
  1432. /*
  1433.  *     u s a g e
  1434.  *
  1435.  *     Tell the user how to invoke Kermit in any mode and quit
  1436.  *
  1437.  */
  1438.  
  1439. usage()
  1440. {
  1441.  cooktty();
  1442. printf
  1443.  ("Usage: superkerm  s[abfic] [-Ddebug-file] file(s) ...    (send mode)\n");
  1444.  printf
  1445.  ("or:    superkerm  r[abfic] [-Ddebug-file]                (receive mode)\n");
  1446.  printf
  1447.  ("or:    superkerm  v[abfic] [-Ddebug-file]                (server mode)\n");
  1448.  printf("  where a  =  ASCII 7-bit file xfer (default),\n");
  1449.  printf("        b  =  BINARY file xfer (usually DPS-6 bound-units),\n");
  1450.  printf("        f  =  FOREIGN (MSDOS/UNIX) file xfer: *.exe, *.com, etc,\n");
  1451.  printf("        i  =  force 8-bit binary-image xfer (no parity allowed!),\n");
  1452.  printf("        c  =  concatenate to ASCII files if they already exist,\n\n");
  1453.  printf("        Wild card xfers (all files ASCII, BINARY or FOREIGN) are legal.\n");
  1454.  printf("        Under the 4.0 operating system Superkermit will work with the\n");
  1455.  printf("        VIP3 Terminal Emulator configured for 7-bit 'other host' Kermit\n");
  1456.  printf("        (NOT Honeywell's Kermit); it can use the ASYNCH1 AP port.\n");
  1457.  printf("        debug-file is preceded by \"-\" and up to 3 \"D\"-flags.\n");
  1458.  printf("or:    superkerm  h                                  (help display).\n");
  1459.  printf(crlf);
  1460.  closeall();
  1461.  exit(0);
  1462. }                       /* End of usage()                       */
  1463.  
  1464. /*
  1465.  *     p r i n t m s g
  1466.  *
  1467.  *     Print message on standard output if not remote
  1468.  *
  1469.  */
  1470.  
  1471. /*VARARGS1*/
  1472. printmsg(fmt, a1, a2, a3, a4, a5)
  1473. char *fmt;
  1474. {
  1475.           printf("Superkermit: ");
  1476.           printf(fmt,a1,a2,a3,a4,a5);
  1477.           printf("\n\r");
  1478.           return;
  1479. }                       /* End of printmsg()                    */
  1480.  
  1481. /*
  1482.  *     e r r o r
  1483.  *
  1484.  *     Print error message
  1485.  *     If remote, send an error packet with the message
  1486.  *
  1487.  */
  1488.  
  1489. /*VARARGS1*/
  1490. error(fmt, a1, a2, a3, a4, a5)
  1491. char *fmt;
  1492. {
  1493.     char msg[100];
  1494.     int len;
  1495.  
  1496.     sprintf(msg,fmt,a1,a2,a3,a4,a5); /* Make it a string */
  1497.     len = strlen(msg);
  1498.     spack('E',n,len,msg);           /* Send the error packet */
  1499.     if (debug) fprintf(dfp,"%s\n",msg);
  1500.     return;
  1501. }                       /* End of error()               */
  1502.  
  1503. /*
  1504.  *     p r e r r p k t
  1505.  *
  1506.  *     Print contents of error packet received from remote Kermit
  1507.  *
  1508.  */
  1509.  
  1510. prerrpkt(msg)
  1511. char *msg;
  1512. {
  1513.     if (debug) {
  1514.        fprintf(dfp,
  1515.        "\nSuperkermit Aborting with following message from local Kermit:");
  1516.        msg[50] = 0;
  1517.        fprintf(dfp,"\n  \"%s\"",msg);
  1518.     }
  1519.     return;
  1520. }                       /* End prerrpkt()               */
  1521.  
  1522. /*********************  END of FILE  hd6pri.c  **************************/
  1523.