home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / os9 / os9utl.c < prev   
C/C++ Source or Header  |  2020-01-01  |  13KB  |  436 lines

  1. /*
  2.  * os9utl.c Packet handling and misc. routines for os9 kermit
  3.  */
  4.  
  5. #include "os9inc.h"
  6.  
  7. /*
  8.  *   KERMIT utilities.
  9.  */
  10.  
  11. static unsigned int timeout;       /* total pauses spent recieving packet */
  12.  
  13. /*
  14.  *  s p a c k
  15.  *
  16.  *  Send a Packet
  17.  */
  18.  
  19. spack(type,num,len,data)
  20. char type, *data;
  21. int num, len;
  22. {
  23.    int i;                          /* Character loop counter */
  24.    char chksum, buffer[100];       /* Checksum, packet buffer */
  25.    register char *bufp;            /* Buffer pointer */
  26.  
  27.    if(type != 'Y' && type != 'N')
  28.       flushinput();                /* dump any leftovers */
  29.    len=len & 0x7f;                 /* Make sure len is not > 127  */
  30.    if (len > MAXPACKSIZ )          /* Make sure not larger than buffer */
  31.       len = MAXPACKSIZ-4;          /* IF so limit it  */
  32.  
  33.    if (debug>1)                    /* Display outgoing packet */
  34.    {
  35.       if (data != NULL)
  36.          data[len] = '\0';          /* Null-terminate data to print it */
  37.       printf("  spack type: %c\n",type);
  38.       printf("         num:  %d\n",num);
  39.       printf("         len:  %d\n",len);
  40.       if (data != NULL)
  41.          printf("       data: \"%s\"\n",data);
  42.    }
  43.  
  44.    bufp = buffer;                  /* Set up buffer pointer */
  45.    for (i=1; i<=pad; i++) write(ttyfd,&padchar,1); /* Issue any padding */
  46.  
  47.    *bufp++ = SOH;                  /* Packet marker, ASCII 1 (SOH) */
  48.    *bufp++ = tochar(len+3);        /* Send the character count */
  49.    chksum  = tochar(len+3);        /* Initialize the checksum */
  50.    *bufp++ = tochar(num);          /* Packet number */
  51.    chksum += tochar(num);          /* Update checksum */
  52.    *bufp++ = type;                 /* Packet type */
  53.    chksum += type;                 /* Update checksum */
  54.  
  55.    for (i=0; i<len; i++)           /* Loop for all data characters */
  56.    {
  57.       *bufp++ = data[i];           /* Get a character */
  58.       chksum += data[i];           /* Update checksum */
  59.    }
  60.    chksum = (((chksum&0300) >> 6)+chksum)&077; /* Compute final checksum */
  61.    *bufp++ = tochar(chksum);       /* Put it in the packet */
  62.    *bufp = eol;                    /* Extra-packet line terminator */
  63.    write(ttyfd, buffer,bufp-buffer+1); /* Send the packet */
  64. }
  65.  
  66. /*
  67.  *  r p a c k
  68.  *
  69.  *  Read a Packet
  70.  */
  71.  
  72. char rpack(len,num,data)
  73. int *len, *num;                    /* Packet length, number */
  74. char *data;                        /* Packet data */
  75. {
  76.    int i,j, done;                  /* Data character number, loop exit */
  77.    int abort;                      /* restart current packet */
  78.    char t,                         /* Current input character */
  79.    type,                           /* Packet type */
  80.    cchksum,                        /* Our (computed) checksum */
  81.    rchksum;                        /* Checksum received from other host */
  82.  
  83.    timeout=0;                      /* start timeout counter */
  84.    do {
  85.       if(readtimed(&t)) return(FALSE);
  86.    } 
  87.    while ((t&127) != SOH);         /* Wait for packet header */
  88.  
  89.    done = FALSE;                   /* Got SOH, init loop */
  90.    while (!done)                   /* Loop to get a packet */
  91.    {
  92.       if(readtimed(&t)) return(FALSE); /* read character, or timeout */
  93.       if (!image) t &= 0177;       /* Handle parity */
  94.       if (t == SOH) continue;      /* Resynchronize if SOH */
  95.       cchksum = t;                 /* Start the checksum */
  96.       *len = unchar(t)-3;          /* Character count */
  97.  
  98.       if(readtimed(&t)) return(FALSE); /* read character, or timeout */
  99.       if (!image) t &= 0177;       /* Handle parity */
  100.       if (t == SOH) continue;      /* Resynchronize if SOH */
  101.       cchksum = cchksum + t;       /* Update checksum */
  102.       *num = unchar(t);            /* Packet number */
  103.  
  104.       if(readtimed(&t)) return(FALSE); /* read character, or timeout */
  105.       if (!image) t &= 0177;       /* Handle parity */
  106.       if (t == SOH) continue;      /* Resynchronize if SOH */
  107.       cchksum = cchksum + t;       /* Update checksum */
  108.       type = t;                    /* Packet type */
  109.       abort=FALSE;
  110.  
  111.       for (i=0; i<*len; i++)       /* The data itself, if any */
  112.       {            /* Loop for character count */
  113.          if(readtimed(&t)) return(FALSE); /* read character, or timeout */
  114.          if (!image) t &= 0177;    /* Handle parity */
  115.          if (t == SOH) {           /* Resynch if SOH */
  116.             abort=TRUE;
  117.             break;
  118.          }
  119.          cchksum = cchksum + t;    /* Update checksum */
  120.          data[i] = t;              /* Put it in the data buffer */
  121.       }
  122.       if(abort)continue;
  123.       data[*len] = 0;              /* Mark the end of the data */
  124.  
  125.       if(readtimed(&t)) return(FALSE); /* read character, or timeout */
  126.       t &= 0177;                   /* do not use parity bit of checksum */
  127.       rchksum = unchar(t);         /* Convert to numeric */
  128.       if (t == SOH) continue;      /* Resynchronize if SOH */
  129.       done = TRUE;                 /* Got checksum, done */
  130.    }
  131.  
  132.    if (debug>1)                    /* Display incoming packet */
  133.    {
  134.       if (data != NULL)
  135.          data[*len] = '\0';        /* Null-terminate data to print it */
  136.       printf("  rpack type: %c\n",type);
  137.       printf("         num:  %d\n",*num);
  138.       printf("         len:  %d\n",*len);
  139.       if (data != NULL)
  140.          printf("        data: \"%s\"\n",data);
  141.    }
  142.    /* Fold in bits 7,8 to compute */
  143.    cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */
  144.  
  145.    if (cchksum != rchksum)
  146.    {
  147.       if(debug >1 ) printf("Rx Checksum Error was %x sb %x\n",rchksum,cchksum);
  148.       return(FALSE);
  149.    }
  150.  
  151.    return(type);                   /* All OK, return packet type */
  152. }
  153.  
  154. /* readtimed: read a character or timeout
  155.  *            timeout is relitive to start of waiting for packet
  156.  */
  157.  
  158. readtimed(c)
  159. char *c;
  160. {
  161.    if(state != 'W'){ /* no timeout in server wait */
  162. #ifdef OSK
  163.       while(getstat(1,ttyfd)<1){
  164. #else
  165.       while(getstat(1,ttyfd)<0){
  166. #endif
  167.          tsleep(ticstosleep);
  168.          /* note that right side of comparison is a constat */
  169.          /* if anything in it is changed to a variable, move the calculation */
  170.          /* out of the readtimed! */
  171.          if(++timeout > (tps*timeoutint/((ticstosleep>1) ? ticstosleep-1 : 1))){
  172.             if(debug)printf("Timed out while waiting for packet\n");
  173.             return(TRUE);
  174.          }
  175.          if(debug>2 && ((timeout & 7)==0))
  176.             printf("Timeout counter at %d pauses\n",timeout);
  177.       }
  178.    }
  179.    read(ttyfd,c,1);
  180.    if(debug>3) printf("Recieved character: %d\n",*c);
  181.    return(FALSE);
  182. }
  183.  
  184. /*
  185.  *  b u f i l l
  186.  *
  187.  *  Get a bufferful of data from the file that's being sent.
  188.  *  Only control-quoting is done; 8-bit & repeat count prefixes are
  189.  *  not handled.
  190.  */
  191.  
  192. bufill(buffer)
  193. char buffer[];                      /* Buffer */
  194. {
  195.    int i,                           /* Loop index */
  196.    t;                               /* Char read from file */
  197.    char t7;                         /* 7-bit version of above */
  198.    char t9;                         /* dup of data char t  */
  199.  
  200.    i = 0;                           /* Init data buffer pointer */
  201.    while((t = getc(fp)) != EOF)     /* Get the next character */
  202.    {
  203.       t9=t;                         /* Keep original pattern */
  204.       t7 = t & 0177;                /* Get low order 7 bits */
  205.  
  206.       if (t7 < SP || t7==DEL || t7==quote) /* Does this char require */
  207.       {                             /* special handling? */
  208. #ifndef OS9
  209.          if (t=='\n' && !image)
  210.          {                          /* Do LF->CRLF mapping if !image */
  211.             buffer[i++] = quote;
  212.             buffer[i++] = ctl('\r');
  213.          }
  214. #endif
  215.          buffer[i++] = quote;       /* Quote the character */
  216.          if (t7 != quote)
  217.          {
  218.             t = ctl(t);             /* and uncontrolify */
  219.             t7 = ctl(t7);
  220.          }
  221.       }
  222.       if (image)
  223.          buffer[i++] = t;           /* Deposit the character itself */
  224.       else
  225.          buffer[i++] = t7;
  226.  
  227. #ifdef OS9
  228.       if ((t9&127)== '\r' && !image)  /* then if this is CR  */
  229.       {
  230.          buffer[i++]=quote;         /* Add LF   */
  231.          buffer[i++]=ctl('\l');
  232.       }
  233. #endif
  234.  
  235.       if (i >= spsiz-8) return(i);  /* Check length */
  236.    }
  237.    if (i==0) return(EOF);           /* Wind up here only on EOF */
  238.    return(i);                       /* Handle partial buffer */
  239. }
  240.  
  241.  
  242. /*
  243.  *   b u f e m p
  244.  *
  245.  *  Put data from an incoming packet into a file.
  246.  */
  247.  
  248. bufemp(buffer,len)
  249. char  buffer[];                     /* Buffer */
  250. int   len;                          /* Length */
  251. {
  252.    int i;                           /* Counter */
  253.    char t;                          /* Character holder */
  254.  
  255.    for (i=0; i<len; i++)            /* Loop thru the data field */
  256.    {
  257.       t = buffer[i];                /* Get character */
  258.       if (t == MYQUOTE)             /* Control quote? */
  259.       {            
  260.          t = buffer[++i];           /* Get the quoted character */
  261.          if ((t & 0177) != MYQUOTE) /* Low order bits match quote char? */
  262.             t = ctl(t);             /* No, uncontrollify it */
  263.       }
  264. #ifndef OS9
  265.       if (t==CR && !image)          /* Don't pass CR if in image mode */
  266.          continue;
  267. #else
  268.       if (t == '\l' && !image)      /* then if t = LF  */
  269.          /*      if (ctl(buffer[i-2]) == '\r')   /* then if last char was CR  */
  270.          continue;                  /* Skip LF, don't put in buffer */
  271. #endif
  272.  
  273.       putc(t,fp);
  274.    }
  275. }
  276.  
  277.  
  278. /*
  279.  *  g n x t f l
  280.  *
  281.  *  Get next file in a file group
  282.  */
  283.  
  284. gnxtfl()
  285. {
  286.    if (server) return(FALSE);      /* If server no multi send   */
  287.    if (debug) printf("     gnxtfl: filelist = \"%s\"\n",*filelist);
  288.    filnam = *(filelist++);
  289.    if (filecount-- == 0) return FALSE; /* If no more, fail */
  290.    else return TRUE;               /* else succeed */
  291. }
  292.  
  293.  
  294. /*
  295.  *  s p a r
  296.  *
  297.  *  Fill the data array with my send-init parameters
  298.  *
  299.  */
  300.  
  301. spar(data)
  302. char data[];
  303. {
  304.    data[0] = tochar(MAXPACKSIZ);  /* Biggest packet I can receive */
  305.    data[1] = tochar(MYTIME);      /* When I want to be timed out */
  306.    data[2] = tochar(MYPAD);       /* How much padding I need */
  307.    data[3] = ctl(MYPCHAR);        /* Padding character I want */
  308.    data[4] = tochar(MYEOL);       /* End-Of-Line character I want */
  309.    data[5] = MYQUOTE;             /* Control-Quote character I send */
  310. }
  311.  
  312.  
  313. /*  r p a r
  314.  *
  315.  *  Get the other host's send-init parameters
  316.  *
  317.  */
  318.  
  319. rpar(data)
  320. char data[];
  321. {
  322.    spsiz = unchar(data[0]);       /* Maximum send packet size */
  323.    timint = unchar(data[1]);      /* When I should time out */
  324.    pad = unchar(data[2]);         /* Number of pads to send */
  325.    padchar = ctl(data[3]);        /* Padding character to send */
  326.    eol = unchar(data[4]);         /* EOL character I must send */
  327.    quote = data[5];               /* Incoming data quote character */
  328. }
  329.  
  330.  
  331. /*
  332.  *  f l u s h i n p u t
  333.  *
  334.  *  Dump all pending input to clear stacked up NACK's.
  335.  */
  336. flushinput()    
  337. {
  338.    /* OS9 Clear receive buffer   */
  339.    char t;
  340. #ifdef OSK
  341.    while(getstat(1,ttyfd) > 0){
  342. #else
  343.    while(getstat(1,ttyfd) >= 0){
  344. #endif
  345.       read(ttyfd,&t,1);
  346.    }
  347.    return;
  348. }
  349.  
  350.  
  351. /*
  352.  *  Kermit printing routines:
  353.  *
  354.  *  usage - print command line options showing proper syntax
  355.  *  printmsg -   like printf with "Kermit: " prepended
  356.  *  error - like printmsg if local kermit; sends a error packet if remote
  357.  *  prerrpkt - print contents of error packet received from remote host
  358.  */
  359.  
  360. /*
  361.  *  u s a g e 
  362.  *
  363.  *  Print summary of usage info and quit
  364.  */
  365.  
  366. usage()
  367. {
  368.    printf("Kermit Program   Version %d    Release %d \n",VERSION,RELEASE);
  369.    printf("Usage:   kermit c[le line esc.char]         (connect mode)\n");
  370.    printf("or:      kermit s[difl line] file ...       (send mode)\n");
  371.    printf("or:      kermit r[difl line]                (receive mode)\n");
  372.    printf("or:      kermit h[difl line]                (Host server mode)\n");
  373.    printf("or:      kermit g[difl line] file ...       (get file from server)\n");
  374.    printf("or:      kermit q[diful line]               (Quit remote Host server\n");
  375.    exit(0);
  376. }
  377.  
  378. /*
  379.  *  p r i n t m s g
  380.  *
  381.  *  Print message on standard output if not remote.
  382.  */
  383.  
  384. /*VARARGS1*/
  385. printmsg(fmt, a1, a2, a3, a4, a5)
  386. char *fmt;
  387. {
  388.    if (!remot)
  389.    {
  390.       printf("Kermit: ");
  391.       printf(fmt,a1,a2,a3,a4,a5);
  392.       printf("\n");
  393.       fflush(stdout);             /* force output (UTS needs it) */
  394.    }
  395. }
  396.  
  397. /*
  398.  *  e r r o r
  399.  *
  400.  *  Print error message.
  401.  *
  402.  *  If local, print error message with printmsg.
  403.  *  If remote, send an error packet with the message.
  404.  */
  405.  
  406. /*VARARGS1*/
  407. error(fmt, a1, a2, a3, a4, a5)
  408. char *fmt;
  409. {
  410.    char msg[80];
  411.    int len;
  412.  
  413.    if (remot || server)
  414.    {
  415.       sprintf(msg,fmt,a1,a2,a3,a4,a5); /* Make it a string */
  416.       len = strlen(msg);
  417.       spack('E',n,len,msg);       /* Send the error packet */
  418.    }
  419.    else
  420.       printmsg(fmt, a1, a2, a3, a4, a5);
  421.  
  422.    return;
  423. }
  424.  
  425. /*
  426.  *  p r e r r p k t
  427.  *
  428.  *  Print contents of error packet received from remote host.
  429.  */
  430. prerrpkt(msg)
  431. char *msg;
  432. {
  433.    printf("Kermit aborting with following error from remote host:\n%s\n",msg);
  434.    return;
  435. }
  436.