home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / sinclairqla / qlkfns.c < prev    next >
C/C++ Source or Header  |  1987-05-07  |  17KB  |  432 lines

  1. /*
  2.     FNS_C - QL-Kermit protocol functions
  3.  
  4.     Based on ckcfns.c, (C) Columbia University
  5. */
  6.  
  7.  
  8. /* Include files */
  9.  
  10. #include "ram1_ker_h"                            /* Kermit definitions */
  11.  
  12.  
  13. /* External variables */
  14.  
  15. extern int slen;                                 /* Maximum send packet size */
  16. extern int rlen;                                 /* Maximum receive packet size */
  17. extern int tslen;                                /* Send packet size in use */
  18. extern int stmo;                                 /* Timeout remote is to use */
  19. extern int rtmo;                                 /* Timeout we will use */
  20. extern int n;                                    /* Packet number */
  21. extern int ttyfd;                                /* FD of TTY for I/O, 0 if remote */
  22. extern int ttychid;                              /* Channel ID for ttyfd */
  23. extern int tvalue;                               /* Current timeout value */
  24. extern int debug;                                /* Level of debugging output */
  25. extern int parity;                               /* Current parity setting */
  26. extern int npad;                                 /* Amount of padding remote needs */
  27. extern int tnpad;                                /* Padding count in use */
  28. extern int xfertyp;                              /* File transfer mode */
  29.  
  30. extern long filein;                              /* File bytes received */
  31. extern long fileout;                             /* File bytes sent */
  32. extern long totin;                               /* Total bytes received */
  33. extern long totout;                              /* Total bytes sent */
  34.  
  35. extern bool timer;                               /* Timer enabled */
  36. extern bool cxseen;                              /* File interruption flag */
  37. extern bool czseen;                              /* Group interruption flag */
  38. extern bool toscr;                               /* Screen data flag */
  39. extern bool ebqflg;                              /* 8-bit quoting being done */
  40.  
  41. extern char ssop;                                /* SOP remote needs */
  42. extern char rsop;                                /* SOP I need */
  43. extern char seol;                                /* EOL for sending packets */
  44. extern char reol;                                /* EOL for receiving packets */
  45. extern char tseol;                               /* Sending EOL in use */
  46. extern char quote;                               /* Sending control quote */
  47. extern char pebq;                                /* 8-bit quote prefix */
  48. extern char tquote;                              /* Receiving control quote */
  49. extern char ebq;                                 /* 8-bit quote in use */
  50.  
  51. extern unsigned char padch;                      /* Pad character remote needs */
  52. extern unsigned char tpadc;                      /* Pad character in use */
  53.  
  54. extern char *ttyname;                            /* Name of TTY for transfer */
  55.  
  56. extern int fp;                                   /* Local file for data transfer */
  57.  
  58. extern int _oserr;                               /* QDOS error code */
  59. extern int oserr;                                /* Copy of above */
  60.  
  61. extern bool warn8;                               /* Lost 8th bit warning given */
  62.  
  63. extern int state;                                /* Current switcher state */
  64.  
  65.  
  66. /* External functions */
  67.  
  68. extern bool chkquote();                          /* Check for valid quote character */
  69. extern bool tfput();                             /* Put a byte to transfer file */
  70. extern int tfget();                              /* Get a byte from transfer file */
  71.  
  72.  
  73. /* Local variables */
  74.  
  75. static int length;                               /* Length of last packet read */
  76.  
  77.  
  78. /* TINIT - Initialise transaction */
  79.  
  80. tinit()
  81. {
  82.     tseol = seol;                                /* Initialise sending EOL, */
  83.     tslen = slen;                                /* packet length */
  84.     tvalue = 50*rtmo;                            /* and timeout */
  85.     czseen = FALSE;                              /* Clear interrupt flags */
  86.     cxseen = FALSE;
  87.     tnpad = npad;                                /* Initialise padding */
  88.     tpadc = padch;
  89.     tquote = quote;                              /* and quote characters */
  90.     ebq = 0;
  91.     ebqflg = FALSE;                              /* Reset 8-bit quote flag */
  92.     totin = totout = 0;                          /* Clear character counts */
  93. }
  94.  
  95.  
  96. /* SPACK - Send a packet */
  97.  
  98. spack(type,num,len,data)
  99. char type;
  100. int num,len;
  101. char *data;
  102. {
  103.     int i;                                       /* Character loop counter */
  104.     char chksum;                                 /* Checksum */
  105.     char buffer[110];                            /* Packet buffer */
  106.     char *bufp;                                  /* Buffer pointer */
  107.  
  108.     if (debfull)                                 /* Display outgoing packet? */
  109.     {
  110.          if (data!=NULL) data[len] = '\0';       /* Null-terminate data for printing */
  111.          printf("spack: type=%c, num=%d, len=%d\n",type,num,len);
  112.          if (data!=NULL) printf(" data=\"%s\"\n",data);
  113.     }
  114.  
  115.     bufp = buffer;                               /* Set up buffer pointer */
  116.  
  117.     *bufp++ = ssop;                              /* Packet marker (SOH) */
  118.  
  119.     chksum = *bufp++ = tochar(len+3);            /* Character count */
  120.  
  121.     *bufp++ = tochar(num);                       /* Packet number */
  122.     chksum += tochar(num);                       /* Update checksum */
  123.  
  124.     *bufp++ = type;                              /* Packet type */
  125.     chksum += type;                              /* Update checksum */
  126.  
  127.     for (i=0; i<len; i++)                        /* Loop for all data characters */
  128.     {
  129.          *bufp++ = data[i];                      /* Put a character */
  130.          chksum += data[i];                      /* Update checksum */
  131.     }
  132.  
  133.     chksum = (((chksum&0300)>>6)+chksum)&077;    /* Compute final checksum */
  134.     *bufp++ = tochar(chksum);                    /* Put it in the packet */
  135.     *bufp = tseol;                               /* Add packet line terminator */
  136.     write(ttyfd,buffer,bufp-buffer+1);           /* and send the packet */
  137.  
  138.     for (i = 0; i<tnpad; i++)
  139.          write(ttyfd,&tpadc,1);                  /* Put out any padding needed */
  140. }
  141.  
  142.  
  143. /* RPACK - Read a packet */
  144.  
  145. int rpack(len,num,data)
  146. int *len,*num;
  147. char *data;
  148. {
  149.     int i;                                       /* Loop counter */
  150.     bool done;                                   /* Loop exit */
  151.     char type;                                   /* Packet type */
  152.     int t;                                       /* Current input character */
  153.     char ccsum;                                  /* Our (computed) checksum */
  154.     char rcsum;                                  /* Checksum received from host */
  155.  
  156.     done = FALSE;                                /* Start to look for a packet */
  157.     do
  158.     {
  159.          if ((t = tread())<0) return(t);         /* Error */
  160.     } while (t!=rsop);                           /* Look for start of packet */
  161.  
  162.     while (!done)                                /* Got SOP, loop to get packet */
  163.     {
  164.          if ((t = tread())<0) return(t);         /* Error */
  165.          if (t==rsop) continue;                  /* Aborted packet */
  166.          ccsum = t;                              /* Start the checksum */
  167.          *len = unchar(t)-3;                     /* Character count */
  168.  
  169.          if ((t = tread())<0) return(t);         /* Error */
  170.          if (t==rsop) continue;                  /* Aborted packet */
  171.          ccsum += t;                             /* Update checksum */
  172.          *num = unchar(t);                       /* Packet number */
  173.  
  174.          if ((t = tread())<0) return(t);         /* Error */
  175.          if (t==rsop) continue;                  /* Aborted packet */
  176.          ccsum += t;                             /* Update checksum */
  177.          type = t;                               /* Packet type */
  178.  
  179.          for (i=0; i<*len; i++)                  /* Loop for data */
  180.          {
  181.               if ((t = tread())<0) return(t);    /* Error */
  182.               if (t==rsop) goto xx;              /* Aborted packet */
  183.               ccsum += t;                        /* Update checksum */
  184.               data[i] = t;                       /* Put it in the data buffer */
  185.          }
  186.          data[*len] = '\0';                      /* Mark the end of the data */
  187.  
  188.          if ((t = tread())<0) return(t);         /* Error */
  189. xx:      if (t==rsop) continue;                  /* Aborted packet */
  190.          rcsum = unchar(t);                      /* Convert checksum to numeric */
  191.  
  192.          done = TRUE;                            /* Got checksum, done */
  193.          length = *len;                          /* Save length for rpar() */
  194.     }
  195.  
  196.     if (debfull)                                 /* Display incoming packet */
  197.     {
  198.          if (data!=NULL) data[*len] = '\0';      /* Null-terminate data for printing */
  199.          printf("rpack type: %c, num: %d, len: %d\n",type,*num,*len);
  200.          if (data!=NULL) printf(" data: \"%s\"\n",data);
  201.     }
  202.  
  203.                                                  /* Fold in bits 7,8 to */
  204.     ccsum = (((ccsum&0300)>>6)+ccsum)&077;       /* compute final checksum */
  205.  
  206.     if (ccsum!=rcsum)                            /* Checksum correct? */
  207.     {
  208.          if (debon) printf("Received bad checksum\n");
  209.          return(BAD);
  210.     }
  211.     return((int) type);                          /* All OK, return packet type */
  212. }
  213.  
  214.  
  215. /* BUFILL - Get a bufferful of data from the file that's being sent and
  216.    encode it for transmission.
  217. */
  218.  
  219. int bufill(buff)
  220. char buff[];
  221. {
  222.     int i;                                       /* Loop index */
  223.     char t;                                      /* Character read from file */
  224.     int tt;                                      /* For testing EOF */
  225.     int a7,b8;                                   /* Split-up versions of above */
  226.  
  227.     i = 0;                                       /* Set up data buffer pointer */
  228.     while ((tt = tfget())!=EOF)                  /* Get the next character */
  229.     {
  230.          fileout++;                              /* Count it */
  231.  
  232.          t = (char) tt;
  233.          a7 = t&0177;                            /* Get lower 7 bits */
  234.          b8 = t&0200;                            /* and 8th bit */
  235.  
  236.          if (a7!=t && !warn8 && !ebqflg && parity!=PYNONE)
  237.          {                                       /* Check for data loss */
  238.               printf("Warning: 8th bits lost\n");
  239.               warn8 = TRUE;
  240.          }
  241.  
  242.          if (ebqflg && b8!=0)                    /* EBQ required? */
  243.          {
  244.               buff[i++] = ebq;                   /* Yes, put out prefix */
  245.               t = a7;                            /* and work on 7-bit character */
  246.          }
  247.  
  248.          if (a7<SP || a7==DEL)                   /* Control quote required? */
  249.          {
  250.               buff[i++] = quote;                 /* Yes, output prefix */
  251.               if (t==LF && xfertyp==FTASC)       /* EOL in ASCII mode */
  252.               {
  253.                    buff[i++] = 'M';              /* Standard Kermit EOL sequence */
  254.                    buff[i++] = quote;
  255.                    t = 'J';
  256.               }
  257.               else t = ctl(t);                   /* Uncontrollify */
  258.          }
  259.  
  260.          if (a7==quote || (a7==ebq && ebqflg))
  261.          {
  262.               buff[i++] = quote;                 /* Quote control prefix or EBQ */
  263.          }
  264.  
  265.          buff[i++] = t;                          /* Finally output the character */
  266.  
  267.          if (i>=tslen-9) return(i);              /* Conservative length check */
  268.     }
  269.     if (i==0) return(EOF);                       /* Here only on EOF */
  270.     return(i);                                   /* Handle partial buffer */
  271. }
  272.  
  273.  
  274. /* BUFEMP - Put data from an incoming packet into a file */
  275.  
  276. bool bufemp(buff,len)
  277. char buff[];
  278. int len;
  279. {
  280.     int i;                                       /* Counter */
  281.     char t;                                      /* Character holder */
  282.     int a,a7,b8;                                 /* Component parts of above */
  283.     char fbuf[MAXPACK];                          /* File data buffer */
  284.     int fbufp = 0;                               /* Index into above */
  285.  
  286.     for (i=0; i<len; i++)                        /* Loop through the data */
  287.     {
  288.          a = buff[i];                            /* Get character */
  289.          b8 = 0;                                 /* Clear high bit flag */
  290.  
  291.          if (ebqflg && a==ebq)                   /* An 8-bit prefixed sequence? */
  292.          {
  293.               b8 = 0200;                         /* Set 8th bit for later */
  294.               a = buff[++i];                     /* and get prefixed character */
  295.          }
  296.  
  297.          if (a==tquote)                          /* Control quote? */
  298.          {
  299.               a = buff[++i];                     /* Yes, get what it prefixes */
  300.               a7 = a&0177;                       /* Split off lower 7 bits */
  301.               if ((a7>=0100 && a7<=0137) || a7=='?')
  302.                    a = ctl(a);                   /* Uncontrollify */
  303.          }
  304.  
  305.          t = (char) a | b8;                      /* Add in 8th bit */
  306.  
  307.          if (toscr && t!=CR) putch(t);           /* Screen output */
  308.          else if (!(t==CR && xfertyp==FTASC))    /* File output */
  309.               fbuf[fbufp++] = t;
  310.          filein++;                               /* Count the character */
  311.     }
  312.  
  313.     if (!toscr)                                  /* File output */
  314.     {
  315.          if (write(fp,fbuf,fbufp)!=fbufp)        /* Write to file */
  316.          {
  317.               oserr = _oserr;                    /* Save error code */
  318.               return(FALSE);
  319.          }
  320.     }
  321.     else if (n==1) putch('\n');                  /* Set screen for DO results */
  322.     return(TRUE);
  323. }
  324.  
  325.  
  326. /* SPAR - Fill the data array with my Send-Init parameters */
  327.  
  328. int spar(data)
  329. char data[];
  330. {
  331.     data[0] = tochar(rlen);                      /* Biggest packet I can receive */
  332.     data[1] = tochar(stmo);                      /* When I want to be timed out */
  333.     data[2] = tochar(0);                         /* How much padding I need */
  334.     data[3] = ctl('\0');                         /* Padding character I need */
  335.     data[4] = tochar(reol);                      /* End-Of-Line character I need */
  336.     data[5] = quote;                             /* Quote character I send */
  337.  
  338.     if (parity!=PYNONE || ebqflg)                /* 8-bit quoting required? */
  339.     {
  340.          data[6] = pebq;                         /* Ask for what we have SET */
  341.          if (chkquote(ebq) || ebq=='Y')
  342.               ebqflg = TRUE;                     /* If valid reply, set flag */
  343.     }
  344.     else data[6] = 'Y';                          /* Not required, just say we're willing */
  345.  
  346.     data[7] = '1';                               /* Checksum type 1 */
  347.     data[8] = ' ';                               /* No repeat count capability */
  348.  
  349.     return(9);                                   /* Return the length */
  350. }
  351.  
  352.  
  353. /* RPAR - Get and analyse the remote's Send-Init parameters */
  354.  
  355. #define IFP        if (length-->0)               /* If field is present */
  356.  
  357. rpar(data)
  358. char data[];
  359. {
  360.     IFP tslen = min(unchar(data[0]),tslen);      /* Maximum send packet size */
  361.     IFP tvalue = max(50*unchar(data[1]),tvalue); /* When I should time out */
  362.     IFP tnpad = max(unchar(data[2]),tnpad);      /* Padding required */
  363.     IFP tpadc = ctl(data[3]);                    /* Padding character */
  364.     IFP tseol = unchar(data[4]);                 /* EOL character I must send */
  365.     IFP tquote = data[5];                        /* Incoming data quote character */
  366.  
  367.     IFP
  368.     {
  369.          ebq = data[6];                          /* EBQ remote will use */
  370.  
  371.          if (chkquote(ebq)) ebqflg = TRUE;       /* If acceptable, we will too */
  372.          else if ((parity!=PYNONE || ebqflg) && ebq=='Y')
  373.          {                                       /* We need it, remote says OK */
  374.               ebqflg = TRUE;
  375.               ebq = pebq;                        /* Use what we have SET */
  376.          }
  377.          else if (ebq=='N')
  378.          {
  379.               ebqflg = FALSE;                    /* We need it, remote can't do */
  380.          }
  381.          else ebqflg = FALSE;                    /* Some other reply */
  382.     }
  383.     else ebqflg = FALSE;                         /* No reply */
  384.  
  385.     if (tseol==0) tseol = '\r';                  /* Check and set defaults */
  386.     if (tquote==0) tquote = quote;
  387.     if (tslen<10) tslen = 10;
  388.  
  389.     if (debon)
  390.     {
  391.          printf("rpar:  timeout=%d, length=%d, EOL=%d\n",tvalue/50,tslen,tseol);
  392.          printf("       npad=%d, padchar=0%o, quote=%c\n",tnpad,tpadc,tquote);
  393.          printf("       8-bit quoting %s",(ebqflg ? "yes" : "no"));
  394.          if (ebqflg) printf(", with %c",ebq);
  395.          printf("\n");
  396.     }
  397. }
  398.  
  399.  
  400. /* ACK - Send an acknowledgement with no data */
  401.  
  402. ack()
  403. {
  404.      spack('Y',n,0,0);
  405. }
  406.  
  407.  
  408. /* ACK1 - Send an acknowledgement with 1 character of data */
  409.  
  410. ack1(s)
  411. char *s;
  412. {
  413.      spack('Y',n,1,s);
  414. }
  415.  
  416.  
  417. /* ACKN - Acknowledge a specific packet number */
  418.  
  419. ackn(num)
  420. int num;
  421. {
  422.      spack('Y',num,0,0);
  423. }
  424.  
  425.  
  426. /* NAK - Send a negative acknowledegement */
  427.  
  428. nak()
  429. {
  430.      spack('N',n,0,0);
  431. }
  432.