home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / flex2 / fl2ker.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  144KB  |  4,835 lines

  1. <<< flbuff.c >>>
  2. #include "FLK.H"
  3.  
  4. /*
  5.  *  b u f i l l
  6.  *
  7.  *  Get a bufferful of data from the file that's being sent.
  8.  *  Control-quoting, 8-bit & repeat count prefixes are handled.
  9.  */
  10.  
  11. char  *bptr;                              /* Buffer pointer */
  12.  
  13. bufill(buffer,first_time)
  14. char  buffer[];                           /* Buffer */
  15. char first_time;                          /* Called for the first time */
  16. {
  17.    int   new_char,                        /* Char read from file */
  18.          rpt_count,
  19.          max_data_size,
  20.          bufsize;
  21.    static int old_char;                   /* Previous character */
  22.    static char *savptr,                   /* Must be saved between calls */
  23.                *savbptr,
  24.                savbuf[6];
  25.  
  26.    bptr = buffer;                         /* Init data buffer pointer */
  27.    max_data_size = spsiz - 3 - (block_check_type - 1);
  28.    if (first_time)
  29.    {
  30.       old_char = getc(fp);                /* Pre-read character first time */
  31.       savbptr = savbuf;
  32.    }
  33.    if (savbptr != savbuf)                 /* Data left from previous call */
  34.       for (savptr = savbuf; savptr != savbptr;)
  35.          *bptr++ = *savptr++;             /* Copy old data to buffer */
  36.    savbptr = savbuf;                      /* No more data in save buffer */
  37.    while (old_char != EOF)                /* Do until no more data */
  38.    {
  39.       rpt_count = 1;
  40.       while(((new_char = getc(fp)) != EOF) && (rpt_count < 94)
  41.             && (repeat_quote != 0) && (new_char == old_char)
  42.             && ((new_char != '\n') || image)) /* No repeat for newline */
  43.          rpt_count++;                     /* Count consecutive match */
  44.       if (rpt_count > 1)                  /* We've had more of these */
  45.          if (rpt_count == 2)
  46.             insbuf(old_char);             /* Insert twice if only 2 char's */
  47.          else
  48.          {
  49.             *bptr++ = repeat_quote;       /* Setup repeat quote character */
  50.             *bptr++ = tochar(rpt_count);  /* Send count */
  51.          }
  52.       transmit_chr_count += rpt_count;    /* Counter for total data */
  53.       insbuf(old_char);
  54.       old_char = new_char;                /* Copy next character */
  55.       bufsize = bptr - buffer;            /* Current number of characters */
  56.       if (bufsize > max_data_size)        /* Check length */
  57.       {
  58.          while (savptr != bptr)
  59.             *savbptr++ = *savptr++;       /* Copy excess data */
  60.          return (bufsize - (savbptr - savbuf));
  61.       }
  62.       else if (bufsize == max_data_size)  /* Exact fit */
  63.          return (bufsize);
  64.       savptr = bptr;
  65.    }
  66.    if (bptr == buffer)                    /* Wind up here only on EOF */
  67.       return(EOF);
  68.    return(bptr - buffer);                 /* Handle partial buffer */
  69. }
  70.  
  71.  
  72. insbuf(o_char)
  73. int o_char;
  74. {
  75.    char chr7;
  76.  
  77.    chr7 = o_char & 0177;               /* Get low order 7 bits */
  78.    if ((o_char > 127) && (eight_quote != 0))
  79.       *bptr++ = eight_quote;           /* Eight_bit quoting done */
  80.    if (chr7 < SP || chr7 == DEL || chr7 == quote ||
  81.       chr7 == repeat_quote || chr7 == eight_quote)
  82.    {                                   /* Special handling required ? */
  83.       if (o_char == '\n' && !image)
  84.       {                                /* Do LF->CRLF mapping if !image */
  85.          *bptr++ = quote;
  86.          *bptr++ = ctl('\r');
  87.       }
  88.       *bptr++ = quote;                 /* Quote the character */
  89.       if ((chr7 == 0) || ((chr7 != quote) && 
  90.          (chr7 != repeat_quote) && (chr7 != eight_quote)))
  91.       {
  92.          o_char = ctl(o_char);         /* Uncontrolify it */
  93.          chr7 = ctl(chr7);
  94.       }
  95.    }
  96.    if (image && (eight_quote == 0))
  97.       *bptr++ = o_char;                /* Deposit the character itself */
  98.    else
  99.       *bptr++ = chr7;                  /* Only send the low bits */
  100. }
  101.  
  102. /*
  103.  *      b u f e m p
  104.  *
  105.  *  Put data from an incoming packet into a file.
  106.  *  Control-quoting, 8-bit & repeat count prefixes are handled.
  107.  */
  108.  
  109. bufemp(buffer,len)
  110. char  buffer[];                           /* Buffer */
  111. int   len;                                /* Length */
  112. {
  113.    int   i, j,                            /* Counters */
  114.          rpt_count;                       /* Repeat counter */
  115.    char  t, t7,                           /* Character holder */
  116.          set_bit_eight;                   /* flag to set bit eight */
  117.  
  118.    for (i = 0; i < len; i++)              /* Loop thru the data field */
  119.    {
  120.       t = buffer[i];                      /* Get character */
  121.       if (t == repeat_quote)              /* Repeat quoting ? */
  122.       {
  123.          rpt_count = unchar(buffer[i+1]); /* Get repeat count */
  124.          i++;                    /* Increment here because of compiler bug */
  125.          t = buffer[++i];                 /* Get next character */
  126.       }
  127.       else
  128.          rpt_count = 1;                   /* No repeat quoting, count = 1 */
  129.       if (t == eight_quote)               /* Eight-bit quoting ? */
  130.       {
  131.          set_bit_eight = TRUE;            /* Set bit eight */
  132.          t = buffer[++i];                 /* Get next character */
  133.       }
  134.       else
  135.          set_bit_eight = FALSE;           /* Don't set bit eight */
  136.       if (t == quote)                     /* Control quote? */
  137.       {                                   /* Yes */
  138.          t = buffer[++i];                 /* Get the quoted character */
  139.          t7 = t & 0177;                   /* Character without parity bit */
  140.          if ((t7 >= ctl(DEL)) && (t7 <= ctl(DEL) + 32))
  141.             t = ctl(t);                   /* Undo what others did to it */
  142.       }
  143.       if (set_bit_eight)
  144.          t |= 0x80;                       /* Set bit eight on request */
  145.       transmit_chr_count += rpt_count;    /* Counter for total data */
  146.       for (j = 0; j < rpt_count; j++)
  147.          if (image)
  148.          {
  149.             if (putc(t,fp) == ERROR)      /* send to file if image mode */
  150.                return(ERROR);
  151.          }
  152.          else
  153.          {
  154.             if (t == LF)                  /* strip LF in non-image mode */
  155.                break;
  156.             if (t == TAB)                 /* expand tabs to spaces */
  157.             {
  158.                while (--tabsleft >= 0)
  159.                   if (putc(' ',fp) == ERROR)
  160.                      return(ERROR);
  161.                tabsleft = TABSIZE;        /* reset tabcounter */
  162.             }
  163.             else                          /* pass character */
  164.             {
  165.                if (putc(t,fp) == ERROR)
  166.                   return(ERROR);
  167.                if ((--tabsleft <= 0) || (t == CR))
  168.                   tabsleft = TABSIZE;     /* take care of tabcount */
  169.             }
  170.          }
  171.    }
  172.    return(NULL);
  173. }
  174. <<< flconn.c >>>
  175. #include "FLK.H"
  176.  
  177. /*
  178.  *  c o n n e c t
  179.  *
  180.  *  Establish a virtual terminal connection with the remote host
  181.  *
  182.  */
  183.  
  184. char stop_send;
  185.  
  186. connect()
  187. {
  188.    int   save_port;                       /* Temp port address */
  189.    char  c,
  190.          got_escape;
  191.  
  192.    stop_send = FALSE;                     /* No stop character send yet */
  193.    save_port = ttyfd;                     /* Save old port address */
  194.    if (numprm > 1)
  195.    {
  196.       sscanf(params[1],"%x",&ttyfd);      /* Get hex address */
  197.       if (initport(ttyfd,0) == FALSE)     /* Try to init the port */
  198.       {
  199.          prterr("No such line available");
  200.          if ((ttyfd = save_port) != REMOTE) /* Restore port if not remote */
  201.             initport(ttyfd,0);
  202.          return;                          /* Error in port setting */
  203.       }
  204.       else
  205.          remote = FALSE;
  206.    }
  207.    if (remote)
  208.       prterr("No line to connect to\7");  /* We're remote.... */
  209.    else
  210.    {
  211.       start_remote();                     /* Enable interrupt if any */
  212.       puts("Connected...\n");
  213.       cflg = TRUE;                        /* Put us in "connect mode" */
  214.       purgeline(ttyfd);                   /* eat pending input */
  215.       if (logfileopen)
  216.          logging = TRUE;                  /* if file available, turn log on */
  217.       plog = &logbuf[0];                  /* set pointer to log data area */
  218.       got_escape = FALSE;                 /* no escape char received yet */
  219.       while (cflg)                        /* do as long as we're connected */
  220.       {
  221.          if (instat(consfd))              /* got something from the console */
  222.          {
  223.             c = inchar(consfd) & 0177;    /* get character */
  224.             if ((c == escchr) || (got_escape)) /* check for escape character */
  225.             {
  226.                if (!(got_escape = ~got_escape))
  227.                {
  228.                   if (c == escchr)        /* maybe another one */
  229.                   {
  230.                      outchar(c,ttyfd);    /* yes, echo it */
  231.                      if (!fulldup)
  232.                      {
  233.                         outchar(c,consfd);  /* echo if half duplex */
  234.                         write_log(c,FALSE); /* send to log file as well */
  235.                      }
  236.                   }
  237.                   else
  238.                      switch (tolower(c&0177)) /* special character */
  239.                      {
  240.                         case '0':
  241.                            outchar(NULL,ttyfd); /* send NULL */
  242.                            break;
  243.  
  244.                         case 'b':
  245.                            send_break(ttyfd); /* send BREAK */
  246.                            break;
  247.  
  248.                         case 'c':
  249.                            cflg = FALSE;      /* disconnect */
  250.                            write (consfd,"\r\n",0);
  251.                            break;
  252.  
  253.                         case 'h':
  254.                            write(consfd,"\r\nYes, I'm still here...\r\n",0);
  255.                            break;            /* tell him i'm still available */
  256.  
  257.                         case 'q':
  258.                            if (logfileopen)
  259.                            {
  260.                               logging = FALSE; /* suspend logging */
  261.                               write(consfd,"\r\nLogging suspended\r\n",0);
  262.                            }
  263.                            else
  264.                               write(consfd,"\r\nLog file is not open\r\n",0);
  265.                            break;
  266.  
  267.                         case 'r':
  268.                            if (logfileopen)
  269.                            {
  270.                               logging = TRUE;  /* resume logging */
  271.                               write(consfd,"\r\nLogging resumed\r\n",0);
  272.                            }
  273.                            else
  274.                               write(consfd,"\r\nLog file is not open\r\n",0);
  275.                            break;
  276.  
  277.                         case 's':
  278.                            write(consfd,"\r\nLog file status: ",0);
  279.                            if (logfileopen)
  280.                               write(consfd,"open\r\n",0);
  281.                            else
  282.                               write(consfd,"closed\r\n",0);
  283.                            write(consfd,"Logging status:  ",0);
  284.                            if (logging)
  285.                               write(consfd,"on\r\n",0);
  286.                            else
  287.                               write(consfd,"off\r\n",0);
  288.                            break;
  289.  
  290.                         case '?':         /* display commands */
  291.                            write(consfd,"\r\nArguments available:\r\n\n",0);
  292.                            write(consfd,"? - Show this help message\r\n",0);
  293.                            write(consfd,"0 - Transmit NULL\r\n",0);
  294.                            write(consfd,"B - Transmit 'BREAK'\r\n",0);
  295.                            write(consfd,"C - Close connection\r\n",0);
  296.                            write(consfd,"H - Report availability\r\n",0);
  297.                            write(consfd,"Q - Quit logging (if started)\r\n",0);
  298.                            write(consfd,"R - Resume logging\r\n",0);
  299.                            write(consfd,"S - Show status of connection\r\n",0);
  300.                            break;
  301.  
  302.                         default:
  303.                            beep();             /* unknown, ring the bell */
  304.                            break;
  305.                   }
  306.                }
  307.             }
  308.             else
  309.             {
  310.                outchar(c,ttyfd);               /* write it out */
  311.                if (!fulldup)
  312.                {
  313.                   outchar(c,consfd);           /* to console if half duplex */
  314.                   write_log(c,FALSE);          /* send to logfile */
  315.                }
  316.             }
  317.          }
  318.          else
  319.             if(instat(ttyfd))                  /* see remote keyboard */
  320.             {
  321.                c = inchar(ttyfd);              /* get character */
  322.                outchar(c,consfd);              /* send to local screen */
  323.                write_log(c,FALSE);             /* and to logfile */
  324.                wtcnt = WAITVAL;                /* reset wait counter */
  325.             }
  326.             else if (stop_send)                /* stop sent to remote */
  327.                if (!(--wtcnt))                 /* did remote stop sending? */
  328.                   flushlog();                  /* yes, write buffer to disk */
  329.       }
  330.       write_log(c,TRUE);                       /* write buffer to disk */
  331.       puts("Disconnected.\n");
  332.       finish_remote();                         /* Disable interrupts if any */
  333.       if ((ttyfd = save_port) == REMOTE)       /* Restore port */
  334.          remote = TRUE;
  335.       else
  336.          initport(ttyfd,0);
  337.    }
  338. }
  339.  
  340. /*
  341.  * Write data to log buffer
  342.  */
  343.  
  344. write_log(chr,flush)
  345. char chr;
  346. int  flush;
  347. {
  348.    if (flush)                                /* flush buffer ? */
  349.       flushlog();
  350.    else if (logging && logfileopen && chr != CR)
  351.    {
  352.       if (chr == LF)                         /* convert LF to CR */
  353.          chr = CR;
  354.       if ((chr == BS) || (chr == DEL))       /* backspace or rubout */
  355.       {
  356.          if (plog > &logbuf)                 /* check range of pointer */
  357.          --plog;
  358.       }
  359.       else
  360.          *plog++ = chr;                      /* store char in buffer */
  361.       if (plog == &logbuf[LOGBUFSIZE-132])   /* time for diskwrite ? */
  362.       {
  363.          outchar(dstop, ttyfd);              /* stop remote */
  364.          stop_send = TRUE;                   /* stop signal send to remote */
  365.          wtcnt = WAITVAL;                    /* set counter */
  366.       }
  367.       else if (plog == &logbuf[LOGBUFSIZE])
  368.          --plog;                             /* in case remote won't stop */
  369.    }
  370. }
  371.  
  372. /*
  373.  * Write buffer to disk
  374.  */
  375.  
  376. flushlog()
  377. {
  378.    char *savep = &logbuf[0];                 /* initial pointer */
  379.  
  380.    if (logfileopen)                          /* only if logfile open */
  381.    {
  382.       while (savep != plog)                  /* if not at end of buffer */
  383.          if (putc(*savep++, lfp) == ERROR)   /* write to file */
  384.          {
  385.             prterr("Error writing log file -- logging stopped");
  386.             fclose(lfp);
  387.             logging = logfileopen = FALSE;   /* no more logging */
  388.             logfile[0] = '\0';               /* Zap filename */
  389.             break;
  390.          }
  391.       plog = &logbuf[0];                     /* reset pointer */
  392.       if (stop_send == TRUE)
  393.       {
  394.          stop_send = FALSE;
  395.          outchar(dstart, ttyfd);             /* restart remote */
  396.       }
  397.    }
  398. }
  399. <<< flcutl.c >>>
  400. #include "FLK.H"
  401.  
  402. /*
  403.  *  s p a r
  404.  *
  405.  *  Fill the data array with my send-init parameters
  406.  *
  407.  */
  408.  
  409. spar(data,len)
  410. char  data[],
  411.       *len;
  412. {
  413.    data[0] = tochar(maxpacksiz);          /* Biggest packet I can receive */
  414.    data[1] = tochar(mytime);              /* When I want to be timed out */
  415.    data[2] = tochar(mypad);               /* How much padding I need */
  416.    data[3] = ctl(mypchar);                /* Padding character I want */
  417.    data[4] = tochar(myeol);               /* End-Of-Line character I want */
  418.    data[5] = myquote;                     /* Control-Quote character I send */
  419.    if ((data[6] = eight_quote) == 0)
  420.       data[6] = 'N';                      /* No eight bit quoting */
  421.    else if (config > 3)                   /* 8 bits link */
  422.       data[6] = 'Y';                      /* 8th bit quoting on request */
  423.    data[7] = block_check_type + '0';      /* Type of block check */
  424.    if ((data[8] = repeat_quote) == 0)     /* Repeat count quote character */
  425.       data[8] = ' ';                      /* No repeat quoting done */
  426.    *len = 9;   
  427. }
  428.  
  429.  
  430. /*  r p a r
  431.  *
  432.  *  Get the other host's send-init parameters
  433.  *
  434.  */
  435.  
  436. rpar(data,len)
  437. char  data[],
  438.       len;
  439. {
  440.    char c;
  441.  
  442.    if (len > 0)
  443.       spsiz = unchar(data[0]);            /* Maximum send packet size */
  444.    else
  445.       spsiz = I_MYPACKSIZE;               /* Use default */
  446.    if (len > 1)
  447.       timint = unchar(data[1]);           /* When I should time out */
  448.    else
  449.       timint = I_MYTIME;
  450.    timecount = timint * DELAYVALUE;       /* Setup new timeout counter */
  451.    if (len > 2)
  452.       pad = unchar(data[2]);              /* Number of pads to send */
  453.    else
  454.       pad = I_MYPAD;
  455.    if (len > 3)
  456.       padchar = ctl(data[3]);             /* Padding character to send */
  457.    else
  458.       padchar = I_MYPCHAR;
  459.    if (len > 4)
  460.       eol = unchar(data[4]);              /* EOL character I must send */
  461.    else
  462.       eol = I_MYEOL;
  463.    if (len > 5)
  464.       quote = data[5];                    /* Incoming data quote character */
  465.    else
  466.       quote = I_MYQUOTE;
  467.    if (len > 6)
  468.    {
  469.       if ((c = data[6]) == 'N')
  470.          eight_quote = 0;                 /* Don't use eight_bit quoting */
  471.       else if (c == 'Y')
  472.       {
  473.          if (config <= 3)                 /* 7 bits link */
  474.             eight_quote = myeightquote;   /* Use default */
  475.          else
  476.             eight_quote = 0;              /* Don't use it */
  477.       }
  478.       else
  479.          eight_quote = c;          /* Use this char for eight bit quoting */
  480.    }
  481.    else
  482.       eight_quote = 0;                    /* Don't use it */
  483.    if ((len > 7) && ((c = data[7] - '0') == myblock_check_type))
  484.       block_check_type = c;               /* Setup block check type */
  485.    else
  486.       block_check_type = I_BLOCKCHECKTYPE;/* Set initial value */
  487.    if ((len > 8) && ((c = data[8]) == myrptquote) && (c != ' '))
  488.       repeat_quote = c;                   /* Setup repeat quote character */
  489.    else   
  490.       repeat_quote = 0;                   /* Don't use repeat quoting */
  491. }
  492.  
  493. set_default_comm()
  494. {
  495.    eol = myeol;                           /* EOL for outgoing packets */
  496.    quote = myquote;                       /* Standard control-quote char "#" */
  497.    pad = mypad;                           /* No padding */
  498.    padchar = mypchar;                     /* Use null if any padding wanted */
  499.    timint = mytime;                       /* Timeout value */
  500.    eight_quote = myeightquote;            /* Set eight_bit quote character */
  501.    repeat_quote = myrptquote;             /* Set repeat quote character */
  502.    block_check_type = myblock_check_type; /* Set initial value */
  503. }
  504.  
  505. disp_size_transferred()
  506. {
  507. #ifdef SCREEN
  508.    float xmitted,
  509.          percentage;
  510.  
  511.    if (!remote && (transmit_chr_count != 0))
  512.    {
  513.       xmitted = transmit_chr_count / 1024.; /* Size transferred so far in K */
  514.       posit(18,4);
  515.       printf("%6.2f K", xmitted);
  516.       if (image && sflg)
  517.       {
  518.          percentage = 100. * (transmit_chr_count / (file_size * 252.));
  519.                          /* a FLEX data sector contains 252 bytes of data */
  520.          posit(39,4);
  521.          printf("%3.0f %%", percentage);
  522.       }
  523.    }
  524. #endif
  525. }
  526.  
  527.  
  528. init_xfer()
  529. {
  530.    chr_sent = datachr_sent = chr_rec = datachr_rec = 0; /* zero counters */
  531.    nak_sent = nak_rec = pack_sent = pack_rec = 0;
  532.    data_rate = 0;
  533. #ifdef CLOCK
  534.    start_time = read_clock();
  535. #endif
  536. }
  537.  
  538. fin_xfer()
  539. {
  540.    int numbits;
  541.  
  542.    t_chr_sent += chr_sent;                /* adjust performance counters */
  543.    t_datachr_sent += datachr_sent;
  544.    t_nak_sent += nak_sent;
  545.    t_pack_sent += pack_sent;
  546.    t_chr_rec += chr_rec;
  547.    t_datachr_rec += datachr_rec;
  548.    t_nak_rec += nak_rec;
  549.    t_pack_rec += pack_rec;
  550. #ifdef CLOCK
  551.  
  552.    end_time = read_clock();         /* Get current time */
  553.  
  554.    /* calculate number of bits in transmission */
  555.  
  556.    numbits = (config == 2 || config == 3 || config == 5) ? 10 : 11;
  557.    if (end_time < start_time)
  558.       end_time += 86400;            /* correct for day overflow, */
  559.                                     /* add number of seconds for one day */
  560.    if (rflg)                        /* received data */
  561.       data_rate = (chr_rec / (end_time - start_time)) * (100 / numbits);
  562.    else if (sflg)                   /* transmitted data */
  563.       data_rate = (chr_sent / (end_time - start_time)) * (100 / numbits);
  564.    t_data_rate = (((t_data_rate == 0) ? data_rate : t_data_rate)
  565.                  + data_rate) / 2;
  566. #endif
  567. }
  568.  
  569. #ifdef CLOCK
  570. long int read_clock()
  571. {
  572.    char  *clock,
  573.          c_sec,
  574.          c_min,
  575.          c_hour,
  576.          dummy;
  577.    char  bcdbin();
  578.  
  579.    clock = RTCADR;                        /* point to register 0 */
  580.    clock[15] = 0xaa;                      /* test pattern */
  581.    dummy = 0;                             /* else clock won't be read again */
  582.    if ((clock[13] & 0x80) && (clock[15] == 0xaa))
  583.    {                                      /* clock valid and set */
  584.       while (clock[10] & 0x80);           /* check for update in progress */
  585.       c_sec = clock[0];                   /* copy data */
  586.       c_min = clock[2];
  587.       c_hour = clock[4];
  588.  
  589.       if (!(clock[11] & 0x02))            /* 12 hour format */
  590.          if (c_hour &= 0x80)
  591.             c_hour += 12;
  592.       if (!(clock[11] & 0x04))
  593.       {                                   /* BCD data format */
  594.          c_sec = bcdbin(c_sec);           /* convert BCD to BIN */
  595.          c_min = bcdbin(c_min);
  596.          c_hour = bcdbin(c_hour);
  597.       }
  598.       return (long)c_hour * 3600 + (int)c_min * 60 + c_sec;
  599.    }
  600.    else
  601.       return (NULL);                      /* invalid clock setting */
  602. }
  603.  
  604. /*
  605.  * convert BCD number to binary
  606.  */
  607.  
  608. char bcdbin(value)
  609. char value;
  610. {
  611.    return ((value & 0x0f) + (10 * ((value & 0xf0) >> 4)));
  612. }
  613. #endif
  614. <<< fldir.c >>>
  615. #include "FLK.H"
  616. #include "flex.h"
  617.  
  618. typedef struct fcbc FCB;
  619.  
  620. /*
  621.  *  Get next file in a file group
  622.  */
  623.  
  624. get_file_spec(firsttime)
  625. char firsttime;
  626. {
  627.    char *wild_file_spec(),
  628.         *status;
  629.    static char my_firsttime;
  630.  
  631.    if (firsttime)
  632.    {
  633.       filenum = 1;                        /* First time initial values */
  634.       filecount = numprm - 1;
  635.       my_firsttime = TRUE;
  636.    }
  637.    do 
  638.    {
  639.       if (rflg != 2)
  640.       {
  641.          status = wild_file_spec(params[filenum], my_firsttime);
  642.          my_firsttime = FALSE;
  643.       }
  644.       else
  645.       {
  646.          status = params[filenum++];      /* Don't parse for 'GET' */
  647.          if (filecount-- == 0)
  648.             break;
  649.       }
  650.       if (status == ERROR)
  651.       {
  652.          prterr("Error opening directory");
  653.          break;
  654.       }
  655.       else if (status)                    /* Got valid spec */
  656.       {
  657.          filnam = status;                 /* Setup pointer to spec */
  658.          if (rflg != 2)                   /* Don't convert for 'GET' */
  659.             cvt_case(filnam);             /* Convert filename case */
  660.          return TRUE;
  661.       }
  662.       filenum++;                          /* Next parameter */
  663.       my_firsttime = TRUE;                /* Start new directory search */
  664.    }
  665.    while (--filecount);                   /* More to do */
  666.    return FALSE;                          /* done */
  667. }
  668.  
  669. char *wild_file_spec(mask,first)
  670. char mask[50], first;
  671. {
  672.    static FCB *ptr;
  673.    FCB *diropen();
  674.    static char filename[50];
  675.  
  676.    if (first)
  677.       if ((ptr = diropen(mask)) == ERROR)
  678.          return (ERROR);                  /* Failed to open directory */
  679.    while (dirread(ptr,filename) != ERROR)
  680.       if (mskcmp(filename,mask))          /* Check match */
  681.          return(filename);
  682.    free(ptr);                             /* Release allocated memory */
  683.    return (FALSE);                        /* No more files */
  684. }
  685.  
  686. /*
  687. *** Compare against a mask
  688. *
  689. *  This function compares a given string against a mask and returns
  690. *  a 1 for 'compares' or a 0 for 'does not compare'.
  691. *
  692. *  A mask is a concatenation of the following elements:
  693. *
  694. *  c              literal character
  695. *  ?              any character match except endstring null
  696. *  [..]           character class (all of these characters)
  697. *  [^..]          negated character class (all but these characters)
  698. *  ^c             negated character (all but this character)
  699. *  *              zone (match zero or more occurences)
  700. *
  701. *  A character class consists of zero or more of the following
  702. *  surrounded by [ and ]:
  703. *
  704. *  c1-c2          range of ascii characters
  705. *  c1-c2..c1-c3   multiple ranges
  706. *
  707. */
  708.  
  709. mskcmp(string,m)
  710. char *string,*m;
  711. {
  712.    int k;
  713.    char *sp,*sav,string2[128];
  714.    char *n,msk[128];
  715.  
  716.    strcpy(sp = string2,string);
  717.    cvt_case(sp);
  718.    strcpy(n = msk,m);
  719.    cvt_case(n);
  720.  
  721.    while (*n)
  722.    {
  723.       if (*n == '*')
  724.       {
  725.          sav = sp;
  726.          if (!*++n)
  727.             return (1);
  728.          while (*sp && !mskcmp(sp,n))
  729.             ++sp;
  730.          if (*sp)
  731.             continue;
  732.          sp = sav;
  733.       }
  734.       else
  735.          if (!(k = onecmp(*sp,n)))
  736.             return (0);
  737.          else
  738.             n += k;
  739.       if (*sp)
  740.          ++sp;
  741.    }
  742.    return (!*sp);
  743. }
  744.  
  745. /*
  746. *** Compare only one character (for mskcmp)
  747. */
  748.  
  749. onecmp(s,m)
  750. char s,*m;
  751. {
  752.    char c,setfind,setflag;
  753.    char *mp;
  754.  
  755.    if ((c = *(mp = m)) == '?' && s);         /* Okay as it is */
  756.    else if (c == '[')
  757.    {
  758.       setfind = setflag = 0;
  759.       if (*++mp == '^')
  760.       {
  761.          setflag = 1;
  762.          ++mp;
  763.       }
  764.       for (;(c = *mp) && c != ']'; ++mp)
  765.          if (*mp == '-' && s >= *(mp - 1) &&
  766.             s <= *(mp + 1) && *(mp - 1) <= *(mp + 1))
  767.          {
  768.             /* skip to trailing ']' */
  769.             while ((c = *(mp + 1)) && c != ']')
  770.                ++mp;
  771.             setfind = 1;
  772.          }
  773.          if (setfind == setflag)
  774.             return (0);
  775.          else
  776.             return (mp - m + 1);
  777.       }
  778.    else if (c == '^' && *(mp + 1) != s)
  779.       return (2);
  780.    else if (c != s)
  781.       return (0);
  782.  
  783.    return (1);
  784. }
  785.  
  786. /*
  787. *** Open disk directory
  788. */
  789.  
  790. int drive;
  791.  
  792. FCB *diropen(name)
  793. char *name;
  794. {
  795.    FCB *ptr;
  796.    int len;
  797.    char *malloc();
  798.  
  799.    drive = FLEX_DATA.work_drive;          /* Assume work drive */
  800.    len = strlen(name);
  801.    if (( len == 1) && isdigit(name[0]))
  802.       drive = name[0] - '0';              /* Setup single drive number */
  803.    else
  804.    {
  805.       if ((isdigit(*name)) && (name[1] == '.'))
  806.       {                                   /* Leading drive number */
  807.          drive = name[0] - '0';
  808.          strcpy(name,name + 2);           /* Strip number */
  809.       }
  810.       else if ((isdigit(name[len - 1])) && (name[len - 2] == '.'))
  811.       {                                   /* Trailing drive number */
  812.          drive = name[len - 1] - '0';     /* Setup drive number */
  813.          name[len - 2] = '\0';            /* Strip number */
  814.       }
  815.    }
  816.    if ((ptr = (FCB *) malloc(sizeof(FCB))) == NULL)   /* Allocate space */
  817.       return (ERROR);
  818.    ptr->f.drive = drive;                  /* Insert drive number in FCB */
  819.    ptr->f.function = DR_OPEN;             /* Open directory for read */
  820.    if (_fms(ptr,0) == ERROR)              /* Open directory */
  821.    {
  822.       free(ptr);                          /* Error, return memory */
  823.       return (ERROR);
  824.    }
  825.    else
  826.       return (ptr);
  827. }
  828.  
  829. dirread(ptr,filename)
  830. FCB *ptr;
  831. char *filename;
  832. {
  833.    int i,j;
  834.  
  835.    ptr->f.function = GET_INF;          /* Get info record function code */
  836.    while(_fms(ptr,0) != ERROR)
  837.    {
  838.       for (i = 0;i < 8;++i)
  839.          filename[i] = ptr->f.filename[i];
  840.       filename[8] = '\0';
  841.       if (!*filename)
  842.          return (ERROR);               /* end of directory */
  843.       if (*filename != 0xff)           /* not a deleted file */
  844.       {
  845.          strcat(filename,".");
  846.          j = strlen(filename);
  847.          for (i = 0;i < 3;++i)
  848.             filename[j + i] = ptr->f.extension[i];
  849.          filename[j + 3] = '\0';
  850.          file_size = ptr->f.size;      /* fill in file size */
  851.          transmit_chr_count = 0;       /* start new sequence */
  852.          return (TRUE);
  853.       }
  854.    }
  855.    return (ERROR);
  856. }
  857. <<< flhelp.c >>>
  858. #include "FLK.H"
  859.  
  860. /*
  861.  * Help processing
  862.  */
  863.  
  864. help()
  865. {
  866.    FILE *hlpfp;                  /* Pointer to help file */
  867.    char str[129],                /* Temporary string holder */
  868.         tmpdrv,                  /* Save drive number */
  869.         found,                   /* Found correct record flag */
  870.         match,                   /* One record matched flag */
  871.         quit;                    /* Quit if no match flag */
  872.    int  i,                       /* Counter */
  873.         level,                   /* Help level */
  874.         len1,                    /* String length counters */
  875.         len2,
  876.         cmplen;                  /* Length to compare */
  877.  
  878.    tmpdrv = workdrive;
  879.    workdrive = load_drive;       /* Look for file on drive KERMIT came from */
  880.    if ((hlpfp = fopen(HELPFILE,"r")) == ERROR)
  881.       prterr("No help available.");   /* Can't open help file */
  882.    else
  883.    {
  884.       if (numprm == 1)                    /* No parameters given */
  885.       {
  886.          while ((get_rec(hlpfp,str)) && (str[0] != '0'));/* Find main record */
  887.          disp_rec(hlpfp,str);             /* Show it */
  888.       }
  889.       else
  890.       {
  891.          found = match = quit = FALSE;
  892.          while (!quit && !found && get_rec(hlpfp,str)) /* until found or EOF */
  893.             for (i = 1; i < numprm; i++)  /* Check each parameter */
  894.             {
  895.                make_upper(params[i]);     /* Force equal case */
  896.                make_upper(str);
  897.                len1 = strlen(str) - 2;    /* Correct for number and space */
  898.                len2 = strlen(params[i]);
  899.                cmplen = len2 < len1 ? len2 : len1; /* Find length to match */
  900.                level = atoi(str);         /* Get current level */
  901.                if (match && (level < i))
  902.                {
  903.                   quit = TRUE;            /* New level, quit */
  904.                   break;
  905.                }
  906.                if ((i == level) && (strncmp(&str[1],params[i],cmplen) == 0))
  907.                {                          /* This one is ok */
  908.                   match = TRUE;
  909.                   if (i == numprm - 1)    /* At the end ? */
  910.                      found = TRUE;        /* Done */
  911.                   break;
  912.                }
  913.                if (!match)            /* Stop if first string does'nt match */
  914.                   break;
  915.             }
  916.          if (found)
  917.             disp_rec(hlpfp,str);          /* Show record */
  918.          else
  919.             prterr("No such topic");      /* No match */
  920.       }
  921.       fclose(hlpfp);
  922.       workdrive = tmpdrv;                 /* Restore work drive */
  923.    }
  924. }
  925.  
  926. get_rec(fp,str)
  927. FILE *fp;
  928. char str[];
  929. {
  930.    while (fgets(str,128,fp) != NULL)      /* Until EOF */
  931.       if (isdigit(str[0]))                /* Or no more digits */
  932.          return (TRUE);
  933.    return (FALSE);                        /* End of file */
  934. }
  935.  
  936. disp_rec(fp,topic)
  937. FILE *fp;
  938. char *topic;
  939. {
  940.    char string[129];
  941.  
  942.    printf("\n%s\n",&topic[1]);            /* Print current topic */
  943.    while ((fgets(string,128,fp) != NULL) && (!isdigit(string[0])))
  944.       puts(string);                       /* Print it as long as no digit */
  945.    puts("\n");
  946. }
  947. <<< flio.c >>>
  948. #include "FLK.H"
  949.  
  950. #ifdef VIDIS
  951. int v_speed_6850[] =          /* valid speed settings for VIDIS 6850 */
  952.    {
  953.       75, 0,
  954.       300, 1,
  955.       600, 2,
  956.       1200, 3,
  957.       2400, 4,
  958. #ifdef INTERRUPT
  959.       4800, 5,
  960.       9600, 6,
  961.       19200, 7,
  962. #endif
  963.       0, 0
  964.    };
  965. int v_speed_6551[] =          /* valid speed settings for 6551 acia */
  966.    {
  967.       50, 1,
  968.       75, 2,
  969.       110, 3,
  970.       135, 4,
  971.       150, 5,
  972.       300, 6,
  973.       600, 7,
  974.       1200, 8,
  975.       1800, 9,
  976.       2400, 10,
  977. #ifdef INTERRUPT
  978.       3600, 11,
  979.       4800, 12,
  980.       7200, 13,
  981.       9600, 14,
  982.       19200, 15,
  983. #endif
  984.       0, 0
  985.    };
  986.  
  987. #else
  988. int v_speed_6850[] =       /* valid speed settings for normal 6850 acia */
  989.    {
  990.       300, 2,
  991.       1200, 1,
  992.       0, 0
  993.    };
  994. #endif
  995.  
  996. char port_err,             /* Flag to indicate error in port initialize */
  997.      *old_port,
  998.      lastchar,
  999.      irq_on = FALSE;
  1000.  
  1001. /*
  1002.  * Initialize an acia type port
  1003.  */
  1004.  
  1005. initport(port,first_time)
  1006. char port[];
  1007. char first_time;
  1008. {
  1009.    int  *p;
  1010.  
  1011.    if (!first_time)
  1012.       cleanup();                             /* Reset old port */
  1013. #ifdef INTERRUPT
  1014.    save_vector = -1;                         /* Dummy vector */
  1015. #endif
  1016.    old_port = port;
  1017.    if (!get_acia_type(port))
  1018.       return (FALSE);                        /* no such port available */
  1019. #ifdef INTERRUPT
  1020.    save_nmi = *dmem(NMIVEC);                 /* Save old NMI vector */
  1021.    *dmem(NMIVEC) = &nmihdr;                  /* Setup NMI handler address */
  1022.    inptr = outptr = &input_buffer[0];        /* Setup buffer pointers */
  1023.    setirq_on();                              /* Enable interrupts */
  1024. #endif
  1025. #ifdef VIDIS
  1026.    if (use_6850)
  1027.    {
  1028.       port[0] = RESET_6850;                  /* reset the acia */
  1029. #ifdef INTERRUPT
  1030.       if (irq_on)
  1031.       {
  1032.          save_vector = *dmem(IRQVEC_6850);
  1033.          *dmem(IRQVEC_6850) = &irqprp;       /* Setup interrupt vector */
  1034.          port[0] = (config << 2) | 0x81;     /* clock / 16, irq enable */
  1035.       }
  1036.       else
  1037.          port[0] = (config << 2) | 0x01;     /* clock / 16 */
  1038. #else
  1039.       port[0] = (config << 2) | 0x01;        /* clock / 16 */
  1040. #endif
  1041.       p = v_speed_6850;                      /* point to speed table */
  1042.       while (*p++ != speed)                  /* get valid speed */
  1043.          p++;
  1044.       port[2] = *p;                          /* set hardware */
  1045.    }  
  1046.    else     /* use 6551 */
  1047.    {
  1048.       port[1] = RESET_6551;
  1049. #ifdef INTERRUPT      
  1050.       if (irq_on)
  1051.       {
  1052.          save_vector = *dmem(IRQVEC_6551);
  1053.          *dmem(IRQVEC_6551) = &irqprp;       /* Setup interrupt vector */
  1054.          port[2] = INITCMND_6551 & 0xfd;     /* Enable interrupt */
  1055.       }
  1056.       else
  1057.          port[2] = INITCMND_6551;
  1058. #else 
  1059.       port[2] = INITCMND_6551;
  1060. #endif
  1061.       port[3] = INITCTRL_6551;
  1062.       switch(config)                         /* set configuration */
  1063.       {
  1064.          case 0:
  1065.                   port[2] |= 0x60;
  1066.                   port[3] |= 0xa0;
  1067.                   break;
  1068.          case 1:
  1069.                   port[2] |= 0x20;
  1070.                   port[3] |= 0xa0;
  1071.                   break;
  1072.          case 2:
  1073.                   port[2] |= 0x60;
  1074.                   port[3] |= 0x20;
  1075.                   break;
  1076.          case 3:
  1077.                   port[2] |= 0x20;
  1078.                   port[3] |= 0x20;
  1079.                   break;
  1080.          case 4:
  1081.                   port[3] |= 0x80;
  1082.                   break;
  1083.          case 5:
  1084.                   break;
  1085.          case 6:
  1086.                   port[2] |= 0x60;
  1087.                   break;
  1088.          case 7:
  1089.                   port[2] |= 0x20;
  1090.                   break;
  1091.       }
  1092.       p = v_speed_6551;                   /* point to valid speed table */
  1093.       while (*p++ != speed)               /* get valid speed */
  1094.          p++;
  1095.       port[3] |= *p;                      /* set hardware */
  1096.    }
  1097. #else
  1098.    port[0] = RESET_6850;                  /* reset the acia */
  1099.    p = v_speed_6850;                      /* point to valid speed table */
  1100.    while (*p++ != speed)                  /* get valid speed */
  1101.       p++;
  1102. #ifdef INTERRUPT
  1103.    if (irq_on)
  1104.    {
  1105.       save_vector = *dmem(IRQVEC_6850);
  1106.       *dmem(IRQVEC_6850) = &irqprp;       /* Setup interrupt vector */
  1107.       port[0] = (config << 2) | *p | 0x80;/* set hardware, enable interrupt */
  1108.    }
  1109.    else
  1110.       port[0] = (config << 2) | *p;       /* set hardware */
  1111. #else
  1112.    port[0] = (config << 2) | *p;          /* set hardware */
  1113. #endif
  1114. #endif
  1115.    purgeline(port);                       /* eat old input */
  1116.    return (TRUE);                         /* valid port found */
  1117. }
  1118.  
  1119. /*
  1120.  * get acia type
  1121.  * return TRUE if port found, use_6850 = true if 6850, else 6551
  1122.  */
  1123.  
  1124. get_acia_type(port)
  1125. char port[];
  1126. {
  1127.    int dummy;
  1128.    char savep1, savep2, savep3;
  1129.  
  1130.    savep1 = port[0];                      /* Save memory in case of failure */
  1131.    savep2 = port[1];
  1132.    savep3 = port[3];
  1133.    port_err = FALSE;
  1134.    port[3] = 0;                           /* set initial value */
  1135.    dummy = 0;                             /* else acia won't be read again */
  1136.    if (port[3] != 0)                      /* still zero ? */
  1137.    {
  1138.       port[0] = RESET_6850;               /* no, reset special acia */
  1139.       dummy = 0;                          /* else acia won't be read again */
  1140.       if ((port[0] & 0xf3) == 0)          /* check if 6850 available */
  1141.       {
  1142.          use_6850 = TRUE;                 /* it's there */
  1143.          return (TRUE);
  1144.       }
  1145.    }
  1146. #ifdef VIDIS
  1147.    port[1] = RESET_6551;
  1148.    port[3] = 0;
  1149.    dummy = 0;                             /* else acia won't be read again */
  1150.    if ((port[3] == 0) && (port[1] & 0x10))/* check if 6551 available */
  1151.    {
  1152.       use_6850 = FALSE;                   /* 6551 found */
  1153.       return (TRUE);
  1154.    }
  1155. #endif
  1156.    port[0] = savep1;                   /* Restore memory in case of failure */
  1157.    port[1] = savep2;
  1158.    port[3] = savep3;
  1159.    port_err = TRUE;                       /* Flag port error for cleanup */
  1160.    return (FALSE);                        /* No such port there */
  1161. }
  1162.  
  1163. /*
  1164.  * Setup line for remote connection
  1165.  */
  1166.  
  1167. start_remote()
  1168. {
  1169.    if (remote)
  1170.       ttyfd = consfd;                     /* Must use this port */
  1171.    irq_on = TRUE;
  1172.    initport(ttyfd,0);
  1173.    aborted = FALSE;
  1174. }
  1175.  
  1176. /*
  1177.  * Finish line for remote connection
  1178.  */
  1179.  
  1180. finish_remote()
  1181. {
  1182.    if (remote)
  1183.       ttyfd = REMOTE;                     /* Restore setting */
  1184.    irq_on = FALSE;
  1185.    initport(ttyfd,0);                     /* Re-init old port */
  1186.    if (aborted)
  1187.       puts("\n");
  1188. }
  1189.  
  1190. /*
  1191.  * read data from port
  1192.  */
  1193.  
  1194. read(dev,data,count)
  1195. int   dev,count;
  1196. char  *data;
  1197. {
  1198.    int   i;
  1199.    long int time;
  1200.  
  1201.    for (i = 0; i < count; i++)      /* do it for the requested count */
  1202.    {
  1203.       time = timecount;             /* get timeout value */
  1204.       while (!instat(dev))          /* no response yet */
  1205.          if (--time == 0)
  1206.          {
  1207.             check_abort();          /* check for user abort after timeout */
  1208.             return TIMEOUT;
  1209.          }
  1210.       lastchar = data[i] = inchar(dev); /* get character */
  1211.    }
  1212.    if (rflg || sflg)
  1213.       chr_rec += count;             /* count chars if sending or receiving */
  1214.    return NULL;                     /* normal termination */
  1215. }
  1216.  
  1217. /*
  1218.  * write characters to port
  1219.  */
  1220.  
  1221. write(dev,data,count)
  1222. int   dev,count;
  1223. char  *data;
  1224. {
  1225.    int   i;
  1226.  
  1227.    if (count == 0)                  /* determine count if not given */
  1228.       count = strlen(data);
  1229.    for (i = 0; i < count; i++)
  1230.       outchar(data[i],dev);         /* send to output port */
  1231.    if (rflg || sflg)
  1232.       chr_sent += count;            /* count chars if sending or receiving */
  1233. }
  1234.  
  1235. /*
  1236.  * check for user abort
  1237.  */
  1238.  
  1239. check_abort()
  1240. {
  1241.    char c;
  1242.  
  1243.    if (!cflg && !stopped)                 /* only when connect is inactive */
  1244.    {                                      /* and no stop character is sent */
  1245.       if (instat(consfd))                 /* if character available */
  1246.          c = inchar(consfd);
  1247.       else
  1248.       {
  1249.          if (remote)
  1250.             c = lastchar;                 /* Only check typed character */
  1251.          else                             /* if remote */
  1252.             c = 0;
  1253.       }
  1254.       c &= 0177;                          /* strip parity */
  1255.       lastchar = 0;
  1256.       if ((c == ABORTX) || (c == ABORTZ))
  1257.       {                                   /* and if it's the abort char */
  1258.          aborted = c;                     /* flag abort */
  1259.          return c;
  1260.       }
  1261.       else if (c == TOGDBG)               /* Toggle debug ? */
  1262.       {
  1263.          if (debug)
  1264.          {
  1265.             debug = FALSE;                /* Switch off debug */
  1266.             if (dbgfil != ERROR)
  1267.             {
  1268.                fclose(dbgfil);            /* Close debug output file if open */
  1269.                dbgfil = ERROR;
  1270.             }
  1271.          }
  1272.          else
  1273.             debug = TRUE;                 /* Switch on debug */
  1274.          set_frame();                     /* Make new display frame */
  1275.       }
  1276.       else if (c == dstop)                /* Wait.... */
  1277.          while ((c = inchar(ttyfd) & 0177) != dstart); /* Wait for start */
  1278.    }
  1279.    return NULL;                           /* no abort */
  1280. }
  1281.  
  1282. /*
  1283.  * test for input character
  1284.  */
  1285.  
  1286. instat(port)
  1287. char  port[];
  1288. {
  1289. #ifdef VIDIS
  1290.    if (port_err || ((port == consfd) && !remote))
  1291.       return constat();                   /* buffer status */
  1292. #ifdef INTERRUPT
  1293.    if (irq_on)
  1294.       return (inptr != outptr);
  1295. #endif
  1296.    else if (use_6850)
  1297.       return(port[0] & 0x01);             /* rcv ready bit 6850 */
  1298.    else
  1299.       return(port[1] & 0x08);             /* rcv ready bit 6551 */
  1300. #else
  1301. #ifdef INTERRUPT
  1302.    if (irq_on)
  1303.       return (inptr != outptr);
  1304. #endif
  1305.    return(port[0] & 0x01);                /* rcv ready bit 6850 */
  1306. #endif
  1307. }
  1308.  
  1309. /*
  1310.  * get an input character
  1311.  */
  1312.  
  1313. inchar(port)
  1314. char  port[];
  1315. {
  1316.    char get_in_buf();
  1317.  
  1318.    while (!instat(port));                 /* wait for input */
  1319. #ifdef VIDIS
  1320.    if (port_err || ((port == consfd) && !remote))
  1321.       return inchne();                    /* use FLEX "input no echo" */
  1322. #ifdef INTERRUPT
  1323.    if (irq_on)
  1324.       return (get_in_buf());
  1325. #endif
  1326.    else if (use_6850)
  1327.       return port[1];                     /* get data from 6850 */
  1328.    else
  1329.       return port[0];                     /* get data from 6551 */
  1330. #else
  1331. #ifdef INTERRUPT
  1332.    if (irq_on)
  1333.       return (get_in_buf());
  1334. #endif
  1335.    return port[1];                        /* get data from 6850 */
  1336. #endif
  1337. }
  1338.  
  1339. /*
  1340.  * test for output ready
  1341.  */
  1342.  
  1343. outstat(port)
  1344. char  port[];
  1345. {
  1346.    check_abort();                         /* maybe he's aborting this */
  1347. #ifdef VIDIS
  1348.    if (port_err || ((port == consfd) && !remote))
  1349.       return TRUE;                        /* console always ready in VIDIS */
  1350.    else if (use_6850)
  1351.       return(port[0] & 0x02);             /* xmit ready bit 6850 */
  1352.    else
  1353.       return(port[1] & 0x10);             /* xmit ready bit 6551 */
  1354. #else
  1355.    return (port[0] & 0x02);               /* xmit ready bit 6850 */
  1356. #endif
  1357. }
  1358.  
  1359. /*
  1360.  * send a character
  1361.  */
  1362.  
  1363. outchar(c,port)
  1364. char  c,port[];
  1365. {
  1366.    long int time;
  1367.  
  1368.    time = timecount;
  1369.    while(!outstat(port))                  /* wait for ready */
  1370.       if ((--time == 0) && aborted)       /* Acia not ready ? */
  1371.          return;                          /* return in case of abort */
  1372. #ifdef VIDIS
  1373.    if (port == consfd)
  1374.       _putchr(c);                         /* use FLEX */
  1375.    else if (use_6850)
  1376.       port[1] = c;                        /* send to 6850 */
  1377.    else
  1378.       port[0] = c;                        /* send to 6551 */
  1379. #else 
  1380.    port[1] = c;                           /* send to 6850 */
  1381. #endif
  1382. }
  1383.  
  1384. /*
  1385.  * purge a line of input data
  1386.  */
  1387.  
  1388. purgeline(port)
  1389. char  port[];
  1390. {
  1391.    while(instat(port))              /* eat characters */
  1392.       inchar(port);
  1393. }
  1394.  
  1395. /*
  1396.  * send a break
  1397.  */
  1398.  
  1399. send_break(port)
  1400. char  port[];
  1401. {
  1402. #ifdef VIDIS
  1403.    if (use_6850)
  1404.    {
  1405.       port[0] = 0x60;               /* set line */
  1406.       wait(300);                    /* delay 300 Ms */
  1407.       initport(port,0);             /* re-initialize */
  1408.    }
  1409.    else
  1410.    {
  1411.       port[2] |= 0x0c;              /* set line */
  1412.       wait(300);                    /* delay 300 Ms */
  1413.       initport(port,0);             /* re-initialize */
  1414.    }
  1415. #else
  1416.    port[0] = 0x60;               /* set line */
  1417.    wait(300);                    /* delay 300 Ms */
  1418.    initport(port,0);             /* re-initialize */
  1419. #endif
  1420. }
  1421.  
  1422. /*
  1423.  * delay 'n' Ms
  1424.  */
  1425.  
  1426. wait(delay)
  1427. int delay;
  1428. {
  1429.    long int del_count;
  1430.    
  1431.    if (delay != 0)                                    /* Only if we have to */
  1432.    {
  1433.       del_count = (delay / 1000.) * DELAYVALUE * 3;   /* Calculate value */
  1434.       while (--del_count);                            /* Ordinary wait loop */
  1435.    }
  1436. }
  1437.  
  1438. #ifdef INTERRUPT
  1439. /*
  1440.  * Interrupt handler
  1441.  */
  1442.  
  1443. irqhdr()
  1444. {
  1445.    char status;
  1446.    char *port;
  1447.  
  1448.    port = ttyfd;
  1449.    if (use_6850)
  1450.    {
  1451.       status = port[0];
  1452.       if (status & 0x80)                  /* This port issued interrupt */
  1453.          if (status & 0x01)               /* Data available */
  1454.             put_in_buf(port[1]);
  1455.          else if (status & 0x04)          /* DCD lost interrupt */
  1456.             status = port[1];             /* Dummy read */
  1457.    }
  1458. #ifdef VIDIS
  1459.    else     /* 6551 */
  1460.    {
  1461.       status = port[1];
  1462.       if (status & 0x80)                  /* This port issued interrupt */
  1463.          if (status & 0x08)               /* Data available */
  1464.             put_in_buf(port[0]);
  1465.          else if (status & 0x20)          /* DCD lost interrupt */
  1466.             status = port[0];             /* Dummy read */
  1467.    }
  1468. #endif
  1469. }
  1470.  
  1471. /*
  1472.  * Stuff character in data buffer
  1473.  * Use handshake if buffer becomes full
  1474.  */
  1475.  
  1476. put_in_buf(ch)
  1477. char ch;
  1478. {
  1479.    int numchar;
  1480.  
  1481.    *inptr++ = ch;                         /* Insert character */
  1482.    if (inptr >= &input_buffer[INBUFSIZE]) /* Adjust pointer */
  1483.       inptr = &input_buffer;
  1484.    numchar = calc_bsize(inptr,outptr);    /* Calculate number of characters */
  1485.    if (!stopped && (numchar > FULL_LIMIT)) /* Take care of pending overflow */
  1486.    {
  1487.       stopped = TRUE;                     /* Flag stop character sent */
  1488.       outchar(dstop,ttyfd);               /* Stop remote */
  1489.    }
  1490. }
  1491.  
  1492. /*
  1493.  * Get character from data buffer
  1494.  * Take care of handshake
  1495.  */
  1496.  
  1497. char get_in_buf()
  1498. {
  1499.    int numchar;
  1500.    char ch;
  1501.  
  1502.    ch = *outptr++;                        /* Get character from buffer */
  1503.    if (outptr >= &input_buffer[INBUFSIZE]) /* Adjust buffer pointer */
  1504.       outptr = &input_buffer;
  1505.    numchar = calc_bsize(inptr,outptr);    /* Calculate number of characters */
  1506.    if (stopped && (numchar < EMPTY_LIMIT)) /* Take care of underflow */
  1507.    {
  1508.       outchar(dstart,ttyfd);              /* Re-start remote */
  1509.       stopped = FALSE;                    /* Flag stop character sent */
  1510.    }
  1511.    return ch;
  1512. }
  1513.  
  1514. /*
  1515.  * Calculate number of characters in buffer
  1516.  */
  1517.  
  1518. calc_bsize(i,o)
  1519. char *i,*o;
  1520. {
  1521.    if (i < o)
  1522.       return ((i + INBUFSIZE) - o);
  1523.    else
  1524.       return (i - o);
  1525. }
  1526. #endif
  1527.  
  1528. /*
  1529.  * Cleanup interrupt vectors
  1530.  */
  1531.  
  1532. cleanup()
  1533. {
  1534. #ifdef INTERRUPT
  1535.    char *port;
  1536.    int *p;
  1537.  
  1538.    port = old_port;
  1539.    if (!port_err)                      /* Only restore if no error */
  1540.    {
  1541.       if (use_6850)
  1542.       {
  1543.          port[0] = RESET_6850;         /* reset the acia */
  1544. #ifdef VIDIS
  1545.          port[0] = (config << 2) | 0x01;
  1546. #else
  1547.          p = v_speed_6850;             /* point to valid speed table */
  1548.          while (*p++ != speed)         /* get valid speed */
  1549.             p++;
  1550.          port[0] = (config << 2) | *p; /* set hardware */
  1551. #endif
  1552.          if (save_vector != -1)
  1553.             *dmem(IRQVEC_6850) = save_vector;
  1554.       }
  1555. #ifdef VIDIS
  1556.       else
  1557.       {
  1558.          port[2] |= 0x02;              /* Turn off interrupt enable */
  1559.          if (save_vector != -1)
  1560.             *dmem(IRQVEC_6551) = save_vector;
  1561.       }
  1562. #endif
  1563.    *dmem(NMIVEC) = save_nmi;
  1564.    }
  1565. #endif
  1566. }
  1567. <<< flkerm.c >>>
  1568. /*
  1569.  *  K e r m i t  File Transfer Utility
  1570.  *
  1571.  *  FLEX Kermit...  Adapted from UNIX version by
  1572.  *
  1573.  *    Jur van der Burg
  1574.  *    Nettelhorst 56
  1575.  *    2402 LS Alphen aan den Rijn
  1576.  *    The Netherlands
  1577.  *
  1578.  *    Telephone: (0)1720 - 34057
  1579.  *
  1580.  *    Last update:   12 September 1986
  1581.  *
  1582.  *    This program runs under almost any FLEX-09 version.
  1583.  *    Hardware dependent things are in the files FLK.H and FLIO.C
  1584.  *
  1585.  *    Compiled with INTROL C (c) V 1.5
  1586.  *
  1587.  */
  1588.  
  1589. #include "FLK.H"
  1590.  
  1591. /*
  1592.  * Main command table
  1593.  */
  1594.  
  1595. TABLE  command_table[] =
  1596. {
  1597.    "send", 1,
  1598.    "receive", 2,
  1599.    "connect", 3,
  1600.    "get", 4,
  1601.    "set", 5,
  1602.    "show", 6,
  1603.    "server", 7,
  1604.    "help", 8,
  1605.    "exit", 9,
  1606.    "quit", 10,
  1607.    "bye", 11,
  1608.    "finish", 12,
  1609.    "transmit", 13,
  1610.    "flex", 14,
  1611.    "statistics", 15,
  1612.    "take", 16,
  1613.    "", 0
  1614. };
  1615.  
  1616. /*
  1617.  * Start of main program
  1618.  */
  1619.  
  1620. main(argc,argv)
  1621. int   argc;
  1622. char  **argv;
  1623. {
  1624.    char  input[257],                      /* Command input */
  1625.          *s,                              /* Options pointer */
  1626.          do_startup,                      /* Start file flag */
  1627.          echo;                            /* Echo startup file */
  1628.  
  1629.    do_startup = TRUE;                     /* Use startup command file */
  1630.    echo = FALSE;                          /* Don't echo startup file */
  1631.    while (--argc > 0 && (*++argv)[0] == '-')
  1632.       for (s = argv[0] + 1; *s != '\0'; s++)
  1633.          switch(tolower(*s))
  1634.          {
  1635.             case 'n':
  1636.                      do_startup = FALSE;  /* Don't get commands from file */
  1637.                      break;
  1638.             case 'e':
  1639.                      echo = TRUE;         /* Echo startup file */
  1640.                      break;
  1641.             default:
  1642.                      usage();
  1643.          }
  1644.  
  1645.    init_par(do_startup,echo);             /* Init all parameters */
  1646.    for (;;)                               /* Do this forever */
  1647.    {
  1648.       do
  1649.       {
  1650.          puts(prompt);                    /* Prompt user */
  1651.          if (gets(input,256) == NULL)     /* Get response */
  1652.             kerm_exit();                  /* E O F */
  1653.       }
  1654.       while (!input[0]);                  /* Blank command line */
  1655.       kerm_command(input);                /* Process command */
  1656.    }
  1657. }
  1658.  
  1659. init_par(autostart,echo)
  1660. char autostart, echo;
  1661. {
  1662.    char  data[257];                       /* Command input */
  1663.    FILE  *inifp;
  1664.  
  1665.    /*  Initialize these values and hope the first packet will get across OK */
  1666.  
  1667.    mypackstart = I_MYPACKSTART;           /* Start of packet character */
  1668.    maxpacksiz = I_MAXPACKSIZ;             /* Maximum packet size */
  1669.    maxtry = I_MAXTRY;                     /* Times to retry a packet */
  1670.    myquote = I_MYQUOTE;                   /* Quote character I will use */
  1671.    mypad = I_MYPAD;                       /* Number of padding chars I need */
  1672.    mypchar = I_MYPCHAR;                   /* Padding character I need (NULL) */
  1673.    myeol = I_MYEOL;                       /* End-Of-Line character I need */
  1674.    mytime = I_MYTIME;                     /* My timeout in seconds */
  1675.    myblock_check_type = I_BLOCKCHECKTYPE; /* Block check type */
  1676.    myrptquote = I_MYRPTQUOTE;             /* Repeat count quote character */
  1677.    myeightquote = I_MYEIGHTQUOTE;         /* Eight bit quote character */
  1678.    send_delay = I_SEND_DELAY;             /* Delay before sending */
  1679.  
  1680.    load_drive = system_fcb_drive;         /* Save drive KERMIT came from */
  1681.    strcpy(prompt,DEFPROMPT);              /* Setup prompt */
  1682.    logfile[0] = '\0';                     /* No log filename yet */
  1683.    logfileopen = FALSE;                   /* No logging done yet */
  1684.    speed = 1200;                          /* Default line speed */
  1685.    config = 5;                            /* 8 bits, 1 stop, no parity */
  1686.    image = FALSE;                         /* Translation */
  1687.    save_file = FALSE;                     /* Don't save file on abort */
  1688.    escchr = ESCCHR;                       /* Default escape character */
  1689.    fulldup = TRUE;                        /* Default is full duplex */
  1690.    warning = TRUE;                        /* File conflict warning */
  1691.    t_chr_sent = t_datachr_sent = t_nak_sent = 0; /* reset counters */
  1692.    t_chr_rec = t_datachr_rec = t_nak_rec = 0;
  1693.    dstop = XOFF;                          /* Init handshake characters */
  1694.    dstart = XON;
  1695.    dbgfil = ERROR;                        /* No debug file */
  1696.    remote = FALSE;                        /* No remote line */
  1697.    stopped = FALSE;                       /* Not stopped with handshake */
  1698.    init_crc_table();                      /* Setup table for CRC calculation */
  1699.  
  1700.    consfd = CONSOLE;                      /* Setup console port address */
  1701. #ifdef VIDIS
  1702.    ttyfd = ADDRESS_6850;
  1703.    if (initport(ttyfd,1) == FALSE)        /* Look for a 6850 acia */
  1704.    {
  1705.       ttyfd = ADDRESS_6551;               /* No 6850 present */
  1706.       initport(ttyfd,0);                  /* Use default 6551 acia */
  1707.    }
  1708. #else
  1709.    ttyfd = TTYPORT;                       /* tty is the communications line */
  1710.    initport(ttyfd,1);                     /* Initialize 6850 acia */
  1711. #endif
  1712.  
  1713.    puts(IDENT);                           /* Tell him we're on the air! */
  1714.    puts(VERSION);                         /* With this version */
  1715.    puts("\n\n");
  1716.  
  1717.    if (autostart)                         /* Startup with command file */
  1718.       take(TRUE,echo);
  1719. }
  1720.  
  1721. /*
  1722.  * Process kermit command
  1723.  */
  1724.  
  1725. kerm_command(instrng)
  1726. char *instrng;
  1727. {
  1728.    int funcpoint;
  1729.    char *free();
  1730.    
  1731.    if (split(instrng, params))            /* Split command line */
  1732.    {                                      /* into seperate strings */
  1733.       cflg = sflg = rflg = 0;             /* Turn off all flags */
  1734.       tabsleft = TABSIZE;                 /* Default tab setting */
  1735.       aborted = FALSE;                    /* Not yet aborted */
  1736.       timint = I_MYTIME;                  /* Setup timeout value */
  1737.       timecount = mytime * DELAYVALUE;    /* Setup timeout counter */
  1738.  
  1739.       funcpoint = parse(params[0], command_table);/* Find routine address */
  1740.       if (funcpoint == NULL)              /* Ambiguous */
  1741.          prterr("Ambiguous command");
  1742.       else if (funcpoint == ERROR)        /* Unknown */
  1743.          prterr("Unknown command");
  1744.       else
  1745.          switch(funcpoint)                /* Process command */
  1746.          {
  1747.             case 1:
  1748.                      sendfile();
  1749.                      break;
  1750.             case 2:
  1751.                      recfile();
  1752.                      break;
  1753.             case 3:
  1754.                      connect();
  1755.                      break;
  1756.             case 4:
  1757.                      getfile();
  1758.                      break;
  1759.             case 5:
  1760.                      set();
  1761.                      break;
  1762.             case 6:
  1763.                      show();
  1764.                      break;
  1765.             case 7:
  1766.                      server();
  1767.                      break;
  1768.             case 8:
  1769.                      help();
  1770.                      break;
  1771.             case 9:
  1772.             case 10:
  1773.                      kerm_exit();
  1774.                      break;
  1775.             case 11:
  1776.                      bye();
  1777.                      break;
  1778.             case 12:
  1779.                      finish();
  1780.                      break;
  1781.             case 13:
  1782.                      transmit();
  1783.                      break;
  1784.             case 14:
  1785.                      do_flex();
  1786.                      break;
  1787.             case 15:
  1788.                      statistics();
  1789.                      break;
  1790.             case 16:
  1791.                      take(FALSE,TRUE);
  1792.                      break;
  1793.          }
  1794.       fclose(fp);                         /* Close file if we're aborted */
  1795.       fp = ERROR;                         /* Indicate no file open yet */
  1796.    }
  1797.    while (numprm)
  1798.       free(params[--numprm]);             /* Free command string memory */
  1799. }
  1800.  
  1801. usage()
  1802. {
  1803.    puts("Usage: KERMIT -n  Disable startup command file\n");
  1804.    puts("              -e  Echo startup command file\n");
  1805.    exit();
  1806. }
  1807.  
  1808. kerm_exit()
  1809. {
  1810.    cleanup();                          /* Restore interrupt vectors if any */
  1811.    exit();
  1812. }
  1813. <<< flpack.c >>>
  1814. #include "FLK.H"
  1815.  
  1816. /*
  1817.  *  s p a c k
  1818.  *
  1819.  *  Send a Packet
  1820.  */
  1821.  
  1822. spack(type,num,len,data,check)
  1823. char  type, *data, len,
  1824.       num, check;
  1825. {
  1826.    int   i;                               /* Character loop counter */
  1827.    char  buffer[100];                     /* Packet buffer */
  1828.    int   crc, chksum, ck1, ck2, ck3;      /* CRC value and checksum */
  1829.    register char *bufp;                   /* Buffer pointer */
  1830.  
  1831.    prtdbgf("Packet transmitted: %d, Type: %c, Length: %d\n",num,type,len);
  1832.    if (!remote)
  1833.    {
  1834. #ifdef SCREEN
  1835.       posit(20,7);
  1836.       printf("%d ",num);
  1837. #else
  1838.       printf("Packet transmitted: %d\n",num);
  1839. #endif
  1840.    }
  1841.    if (debug)                       /* Display outgoing packet */
  1842.    {
  1843. #ifdef SCREEN
  1844.       disp(0,12,CLREOL);
  1845.       disp(20,11,CLREOL);
  1846. #endif
  1847.       if ((debug >= 1) && !remote)
  1848.       {
  1849. #ifdef SCREEN
  1850.             posit(33,7);
  1851.             printf("%c",type);
  1852.             posit(45,7);
  1853.             printf("%d ",len);
  1854. #else
  1855.             printf("Type: %c Length: %d\n",type,len);
  1856. #endif
  1857.       }
  1858.       if (len != 0)
  1859.       {
  1860.          data[len] = '\0';          /* Null terminate data to print it */
  1861.          if ((debug >= 1) && !remote)
  1862.          {
  1863. #ifdef SCREEN
  1864.             posit(20,11);
  1865.             putchar('"');
  1866.             puts(data);
  1867.             putchar('"');
  1868. #else
  1869.             printf("Data transmitted: \"%s\"\n",data);
  1870. #endif
  1871.          }
  1872.          prtdbgf("Data transmitted: \"%s\"\n",data);
  1873.       }
  1874.    }
  1875.  
  1876.    pack_sent++;                           /* Count packet */
  1877.    bufp = buffer;                         /* Set up buffer pointer */
  1878.    write(ttyfd,&padchar,pad);             /* Issue any padding */
  1879.  
  1880.    init_crc();                            /* Initialize CRC calculation */
  1881.    *bufp++ = mypackstart;                 /* Packet marker */
  1882.    *bufp++ = tochar(len + check + 2);     /* Send the character count */
  1883.    chksum  = tochar(len + check + 2);     /* Initialize the checksum */
  1884.    calc_crc(tochar(len + check + 2));     /* Calculate CRC */
  1885.    *bufp++ = tochar(num);                 /* Packet number */
  1886.    chksum += tochar(num);                 /* Update checksum */
  1887.    calc_crc(tochar(num));                 /* Calculate CRC */
  1888.    *bufp++ = type;                        /* Packet type */
  1889.    chksum += type;                        /* Update checksum */
  1890.    crc = calc_crc(type);                  /* Calculate CRC */
  1891.    if (type == 'N')
  1892.       nak_sent++;                         /* Count nak */
  1893.  
  1894.    for (i=0; i<len; i++)                  /* Loop for all data characters */
  1895.    {
  1896.       *bufp++ = data[i];                  /* Get a character */
  1897.       chksum += data[i];                  /* Update checksum */
  1898.       crc = calc_crc(data[i]);            /* Calculate CRC */
  1899.    }
  1900.    if (check == 1)                        /* One character checksum */
  1901.    {
  1902.       chksum = (((chksum & 0300) >> 6) + chksum) & 077;
  1903.       *bufp++ = (ck1 = tochar(chksum));   /* Put it in the packet */
  1904.    }
  1905.    else if (check == 2)                   /* Two character checksum */
  1906.    {
  1907.       *bufp++ = (ck1 = tochar((chksum >> 6) & 077));
  1908.       *bufp++ = (ck2 = tochar(chksum & 077));
  1909.    }
  1910.    else if (check == 3)                   /* Three character CRC */
  1911.    {
  1912.       *bufp++ = (ck1 = tochar((crc >> 12) & 017));
  1913.       *bufp++ = (ck2 = tochar((crc >> 6) & 077));
  1914.       *bufp++ = (ck3 = tochar(crc & 077));
  1915.    }
  1916.    if (debug)
  1917.    {
  1918.       if (debug >= 1)
  1919. #ifdef SCREEN
  1920.          posit(59,7);
  1921. #else
  1922.          puts("Checksum: ");
  1923. #endif
  1924.       prtdbgf("Checksum: ");
  1925.       switch(check)
  1926.       {
  1927.          case 1:
  1928.                prtdbg("%02x\n",unchar(ck1));
  1929.                break;
  1930.          case 2:
  1931.                prtdbg("%02x%02x\n",unchar(ck1),unchar(ck2));
  1932.                break;
  1933.          case 3:
  1934.                prtdbg("%02x%02x%02x\n",unchar(ck1),unchar(ck2),unchar(ck3));
  1935.       }
  1936.    }
  1937.    *bufp++ = eol;                         /* Extra-packet line terminator */
  1938.    datachr_sent += len;                   /* Adjust character counters */
  1939.    write(ttyfd, buffer,bufp-buffer);      /* Send the packet */
  1940.    if (sflg)
  1941.       disp_size_transferred();            /* Show how far we've got */
  1942. }
  1943.  
  1944. /*
  1945.  *  r p a c k
  1946.  *
  1947.  *  Read a Packet
  1948.  */
  1949.  
  1950. rpack(len,num,data,check)
  1951. char  *num, check,                        /* length, number, checksum type */
  1952.       *len, *data;                        /* Packet data */
  1953. {
  1954.    int   i, done,                         /* Data char number, loop exit */
  1955.          numtry,                          /* retry counter */
  1956.          cchksum,                         /* Our (computed) checksum */
  1957.          ck1, ck2, ck3,                   /* Temporary save */
  1958.          rchksum,                         /* Checksum received from host */
  1959.          crc;                             /* CRC value */
  1960.    char  t,                               /* Current input character */
  1961.          type;                            /* Packet type */
  1962.  
  1963.    do                                     /* Wait for packet header */
  1964.    {
  1965.       if (read(ttyfd,&t,1) == TIMEOUT)
  1966.          return ('T');                    /* Return timeout */
  1967.       t &= 0177;                          /* Handle parity */
  1968.    }
  1969.    while (t != mypackstart);
  1970.  
  1971.    done = FALSE;                          /* Got packet start, init loop */
  1972.    while (!done)                          /* Loop to get a packet */
  1973.    {
  1974.       init_crc();                         /* Start new CRC calculation */
  1975.       if (read(ttyfd,&t,1) == TIMEOUT)    /* Get character */
  1976.          return ('T');
  1977.       t &= 0177;                          /* Handle parity */
  1978.       if (t == mypackstart)               /* Resynch if start of packet */
  1979.          continue;
  1980.       cchksum = t;                        /* Start the checksum */
  1981.       calc_crc(t);                        /* Calculate CRC */
  1982.  
  1983.       *len = unchar(t)-check-2;           /* Character count */
  1984.  
  1985.       if (read(ttyfd,&t,1) == TIMEOUT)    /* Get character */
  1986.          return ('T');
  1987.       t &= 0177;                          /* Handle parity */
  1988.       if (t == mypackstart)               /* Resynch if start of packet */
  1989.          continue;
  1990.       cchksum += t;                       /* Update checksum */
  1991.       calc_crc(t);                        /* Calculate CRC */
  1992.       *num = unchar(t);                   /* Packet number */
  1993.  
  1994.       if (read(ttyfd,&t,1) == TIMEOUT)    /* Get character */
  1995.          return ('T');
  1996.       t &= 0177;                          /* Handle parity */
  1997.       if (t == mypackstart)               /* Resynch if start of packet */
  1998.          continue;
  1999.       cchksum += t;                       /* Update checksum */
  2000.       crc = calc_crc(t);                  /* Calculate CRC */
  2001.       type = t;                           /* Packet type */
  2002.       if (type == 'N')
  2003.          nak_rec++;                       /* Count received nak */
  2004.  
  2005.       for (i = 0; i < (*len); i++)        /* The data itself, if any */
  2006.       {                                   /* Loop for character count */
  2007.          if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
  2008.             return ('T');
  2009.          if (!image)                      /* Handle parity */
  2010.             t &= 0177;
  2011.          if (t == mypackstart)            /* Resynch if start of packet */
  2012.             continue;
  2013.          cchksum += t;                    /* Update checksum */
  2014.          crc = calc_crc(t);               /* Calculate CRC */
  2015.          data[i] = t;                     /* Put it in the data buffer */
  2016.       }
  2017.       data[*len] = '\0';                  /* Mark the end of the data */
  2018.  
  2019.       if (read(ttyfd,&t,1) == TIMEOUT)    /* Get character */
  2020.          return ('T');
  2021.       if (check == 1)
  2022.          rchksum = (ck1 = unchar(t));     /* Convert to numeric */
  2023.       else if (check == 2)
  2024.       {
  2025.          rchksum = (ck1 = unchar(t)) << 6;
  2026.          if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
  2027.             return ('T');
  2028.          rchksum += (ck2 = unchar(t));
  2029.       }
  2030.       else if (check == 3)
  2031.       {
  2032.          rchksum = (ck1 = unchar(t)) << 12;
  2033.          if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
  2034.             return ('T');
  2035.          rchksum += (ck2 = unchar(t)) << 6;
  2036.          if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */
  2037.             return ('T');
  2038.          rchksum += (ck3 = unchar(t));
  2039.       }
  2040.       if (read(ttyfd,&t,1) == TIMEOUT)    /* get EOL character and toss it */
  2041.          return ('T');
  2042.       t &= 0177;                          /* Handle parity */
  2043.       if (t == mypackstart)               /* Resynch if start of packet */
  2044.          continue;
  2045.       done = TRUE;                        /* Got checksum, done */
  2046.    }
  2047.  
  2048.    datachr_rec += *len;                   /* Count received data characters */
  2049.    pack_rec++;                            /* Count packet */
  2050.    if (check == 3)
  2051.       cchksum = crc;                      /* Set calculated value */
  2052.    else if (check == 2)
  2053.       cchksum &= 07777;                   /* Strip result to 12 bits */
  2054.    if (check == 1)
  2055.       cchksum = (((cchksum & 0300) >> 6) + cchksum) & 077; /* Final checksum */
  2056.  
  2057.    prtdbgf("Packet received: %d, Type: %c, Length: %d\n",*num,type,*len);
  2058.    if (!remote)
  2059.    {
  2060. #ifdef SCREEN
  2061.       posit(20,6);
  2062.       printf("%d ",*num);
  2063. #else
  2064.       printf("Packet received: %d\n",*num);
  2065. #endif
  2066.    }
  2067.    if (debug)                             /* Display incoming packet */
  2068.    {
  2069.       if ((debug >= 1) && !remote)
  2070.       {
  2071. #ifdef SCREEN
  2072.          posit(33,6);
  2073.          printf("%c",type);
  2074.          posit(45,6);
  2075.          printf("%d ",*len);
  2076.          posit(59,6);
  2077. #else
  2078.          printf("Type: %c Length: %d\n",type,*len);
  2079. #endif
  2080.       }
  2081.       prtdbgf("Checksum: ");
  2082. #ifndef SCREEN
  2083.       puts("Checksum: ");
  2084. #endif
  2085.       switch(check)
  2086.       {
  2087.          case 1:
  2088.                prtdbg("%02x\n",ck1);
  2089.                break;
  2090.          case 2:
  2091.                prtdbg("%02x%02x\n",ck1,ck2);
  2092.                break;
  2093.          case 3:
  2094.                prtdbg("%02x%02x%02x\n",ck1,ck2,ck3);
  2095.       }
  2096. #ifdef SCREEN
  2097.       disp(20,9,CLREOL);
  2098.       disp(0,10,CLREOL);
  2099. #endif
  2100.       if (*len != 0)
  2101.       {
  2102.          data[*len] = '\0';               /* Null terminate data to print it */
  2103.          if ((debug >= 1) && !remote)
  2104.          {
  2105. #ifdef SCREEN
  2106.             posit(20,9);
  2107.             putchar('"');
  2108.             puts(data);
  2109.             putchar('"');
  2110. #else
  2111.             printf("Data received: \"%s\"\n",data);
  2112. #endif
  2113.          }
  2114.          prtdbgf("Data received: \"%s\"\n",data);
  2115.       }
  2116.    }
  2117.  
  2118.    if (rflg)
  2119.       disp_size_transferred();            /* Show how far we've got */
  2120.    if (cchksum != rchksum)
  2121.       return(FALSE);                      /* Checksum error */
  2122.    else
  2123.       return(type);                       /* All OK, return packet type */
  2124. }
  2125. <<< flrecs.c >>>
  2126. #include "FLK.H"
  2127.  
  2128. char rec_filnam[50], stopflag;
  2129.  
  2130. recfile()
  2131. {
  2132.    if (numprm > 2)
  2133.       prterr("Only one filename allowed");
  2134.    else
  2135.    {
  2136.       if (numprm == 2)
  2137.          strcpy(rec_filnam,params[1]); /* Get filename to use */
  2138.       else
  2139.          rec_filnam[0] = '\0';         /* Use default name */
  2140.       rflg++;                          /* Receive command */
  2141.       n = 0;                           /* Init packet number */
  2142.       set_frame();
  2143.       start_remote();                  /* Setup port if remote */
  2144.       purgeline(ttyfd);                /* Eat old input */
  2145.       if (!recsw('R'))                 /* Receive the file(s) */
  2146.          disp(0,16,"Receive failed.");
  2147.       disp(0,20,CURSON);
  2148.       beep();
  2149.       finish_remote();
  2150.    }
  2151. }
  2152.  
  2153. getfile()
  2154. {
  2155.    char status, i;
  2156.  
  2157.    if (numprm <= 1)                    /* check for parameter */
  2158.       prterr("Filespec(s) required");
  2159.    else
  2160.    {
  2161.       rec_filnam[0] = '\0';            /* Use default name */
  2162.       rflg = 2;                        /* 'GET' command */
  2163.       n = 0;                           /* Init packet number */
  2164.       set_frame();
  2165.       start_remote();                  /* Setup port if remote */
  2166.       i = TRUE;
  2167.       while (get_file_spec(i))         /* Get filespec */
  2168.       {
  2169.          i = FALSE;
  2170.          if (!(status = get()))        /* Get the file */
  2171.             break;
  2172.       }
  2173.       if (!status)
  2174.          disp(0,16,"Get failed.");     /* Report failure */
  2175.       disp(0,20,CURSON);
  2176.       beep();
  2177.       finish_remote();
  2178.    }
  2179. }
  2180.  
  2181. /*
  2182.  * get file from remote server
  2183.  */
  2184.  
  2185. get()
  2186. {
  2187.    char len, num;
  2188.    n = 0;
  2189.    numtry = 0;
  2190.  
  2191.    set_default_comm();                 /* Set default communication */
  2192.    aborted = FALSE;
  2193.    while(TRUE)
  2194.    {
  2195.       len = strlen(filnam);
  2196.       strcpy(packet,filnam);           /* Setup filename */
  2197.  
  2198.       if (debug)
  2199.       {
  2200.          prtdbgf("Receive state: ");
  2201. #ifndef SCREEN
  2202.          puts("Receice state: ");
  2203. #endif
  2204.          disp_state(20,13,'R');
  2205.       }
  2206.       purgeline(ttyfd);                /* Eat old input */
  2207.       spack('R',n,len,packet,1);       /* Receiver init */
  2208.       switch(rpack(&len,&num,recpkt,1))
  2209.       {
  2210.          case 'S':
  2211.                   rpar(recpkt,len);    /* Get the other side's init data */
  2212.                   spar(packet,&len);   /* Fill up packet with my init info */
  2213.                   spack('Y',n,len,packet,1); /* ACK with my parameters */
  2214.                   oldtry = numtry;     /* Save old try count */
  2215.                   numtry = 0;          /* Start a new counter */
  2216.                   n = (n + 1) % 64;    /* Bump packet number, mod 64 */
  2217.                   return(recsw('F'));  /* Enter File-Receive state */
  2218.  
  2219.          case 'E':
  2220.                   prerrpkt(recpkt);    /* error return */
  2221.                   return(FALSE);
  2222.  
  2223.          case 'T':
  2224.                   if (aborted)         /* user abort */
  2225.                      return(FALSE);
  2226.  
  2227.          default:
  2228.                   if (numtry++ >= maxtry)
  2229.                      return (FALSE);   /* max try's exceeded */
  2230.       }
  2231.    }
  2232. }
  2233.  
  2234. /*
  2235.  *  r e c s w
  2236.  *
  2237.  *  This is the state table switcher for receiving files.
  2238.  */
  2239.  
  2240. recsw(istate)
  2241. char istate;
  2242. {
  2243.    char  rinit(), rfile(), rdata();       /* Use these procedures */
  2244.  
  2245.    init_xfer();                           /* reset character counters */
  2246.    if (istate != 'F')                     /* if not already done */
  2247.       set_default_comm();                 /* Set default communication */
  2248.    state = istate;                        /* set start state 'R' or 'F' */
  2249.    numtry = 0;                            /* Say no tries yet */
  2250.    stopflag = FALSE;                      /* Not stopped yet */
  2251.    aborted = FALSE;                       /* Not aborted yet */
  2252.  
  2253.    while(TRUE)
  2254.    {
  2255.       if (debug)
  2256.       {
  2257.          prtdbgf("Receive state: ");
  2258. #ifndef SCREEN
  2259.          puts("Receive state: ");
  2260. #endif
  2261.          disp_state(20,13,state);
  2262.       }
  2263.       switch(state)                       /* Do until done */
  2264.       {
  2265.          case 'R':                        /* Receive-Init */
  2266.                state = rinit();
  2267.                break;
  2268.  
  2269.          case 'F':                        /* Receive-File */
  2270.                state = rfile();
  2271.                break;
  2272.  
  2273.          case 'D':                        /* Receive-Data */
  2274.                state = rdata();
  2275.                break;
  2276.  
  2277.          case 'C':                        /* Complete state */
  2278.                fin_xfer();
  2279.                return(TRUE);
  2280.  
  2281.          default:                         /* Unknown or abort */
  2282.                fin_xfer();
  2283.                return(FALSE);
  2284.       }
  2285.    }
  2286. }
  2287.  
  2288.  
  2289. /*
  2290.  *  r i n i t
  2291.  *
  2292.  *  Receive Initialization
  2293.  */
  2294.  
  2295. char rinit()
  2296. {
  2297.    char  len, num;                        /* Packet length, number */
  2298.  
  2299.    if (numtry++ >= maxtry)                /* If too many tries, "abort" */
  2300.       return('A');
  2301.  
  2302.    switch(rpack(&len,&num,packet,1))      /* Get a packet */
  2303.    {
  2304.       case 'S':                           /* Send-Init */
  2305.             rpar(packet,len);             /* Get the other side's init data */
  2306.             spar(packet,&len);            /* Fill packet with my init info */
  2307.             spack('Y',n,len,packet,1);    /* ACK with my parameters */
  2308.             oldtry = numtry;              /* Save old try count */
  2309.             numtry = 0;                   /* Start a new counter */
  2310.             n = (n + 1) % 64;             /* Bump packet number, mod 64 */
  2311.             return('F');                  /* Enter File-Receive state */
  2312.  
  2313.       case 'E':                           /* Error packet received */
  2314.             prerrpkt(recpkt);             /* Print it out and */
  2315.             return('A');                  /* abort */
  2316.  
  2317.       case 'T':                           /* Timeout */
  2318.             if (aborted)
  2319.                return('A');               /* aborted by user */
  2320.       case FALSE:                         /* Didn't get packet */
  2321.             spack('N',n,0,0,1);           /* Return a NAK */
  2322.             return(state);                /* Keep trying */
  2323.  
  2324.       default:                            /* Some other packet type, "abort" */
  2325.             return('A');
  2326.    }
  2327. }
  2328.  
  2329.  
  2330. /*
  2331.  *  r f i l e
  2332.  *
  2333.  *  Receive File Header
  2334.  */
  2335.  
  2336. char rfile()
  2337. {
  2338.    char  num, len,                        /* Packet number, length */
  2339.          *w;
  2340.  
  2341.    if (numtry++ >= maxtry)                /* "abort" if too many tries */
  2342.       return('A');
  2343.  
  2344.    switch(rpack(&len,&num,packet,block_check_type)) /* Get a packet */
  2345.    {
  2346.       case 'S':                           /* Send-Init, maybe our ACK lost */
  2347.             if (oldtry++ >= maxtry)       /* If too many tries "abort" */
  2348.                return('A');
  2349.             if (num == ((n == 0) ? 63 : n-1)) /* Previous packet, mod 64? */
  2350.             {                             /* Yes, ACK it again with  */
  2351.                spar(packet,&len);         /* our Send-Init parameters */
  2352.                spack('Y',num,len,packet,1);
  2353.                numtry = 0;                /* Reset try counter */
  2354.                return(state);             /* Stay in this state */
  2355.             }
  2356.             else                          /* Not previous packet, "abort" */
  2357.                return('A');
  2358.  
  2359.       case 'Z':                           /* End-Of-File */
  2360.             if (oldtry++ >= maxtry)
  2361.                return('A');
  2362.             if (num == ((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */
  2363.             {                             /* Yes, ACK it again. */
  2364.                spack('Y',num,0,0,block_check_type);
  2365.                numtry = 0;
  2366.                return(state);             /* Stay in this state */
  2367.             }
  2368.             else                          /* Not previous packet, "abort" */
  2369.                return('A');
  2370.  
  2371.       case 'F':                           /* File Header (just what we want) */
  2372.             if (num != n)                 /* The packet number must be right */
  2373.                return('A'); 
  2374.             if (!rec_filnam[0])           /* Copy filename if not given */
  2375.                strcpy(rec_filnam, packet);
  2376.             cvt_case(rec_filnam);         /* Convert case */
  2377.             transmit_chr_count = 0;       /* Counter for total data size */
  2378.             if(image)
  2379.                w = "bw";                  /* open binary file */
  2380.             else
  2381.                w = "w";                   /* open text file   */
  2382.  
  2383.             while ((fp = fopen(rec_filnam,"r")) != ERROR)
  2384.             {                             /* File already there */
  2385.                fclose(fp);
  2386.                if (warning)               /* File warning on ? */
  2387.                {
  2388.                   if (!remote)
  2389.                   {
  2390.                      posit(0,18);
  2391.                printf("%sWarning: File %s already exists, creating new name",
  2392.                          CLREOL,rec_filnam);
  2393.                      beep();
  2394. #ifndef SCREEN
  2395.                      puts("\n");
  2396. #endif
  2397.                   }
  2398.                   new_name(rec_filnam);    /* Create new filename */
  2399.                }
  2400.                else
  2401.                   break;                  /* Leave it as it is */
  2402.             }
  2403.             if ((fp = fopen(rec_filnam,w)) == ERROR)/* Try to open new file */
  2404.             {
  2405.                error(4,"%s",rec_filnam);  /* Give up if error */
  2406.                return('A');
  2407.             }
  2408.             else                          /* OK, give message */
  2409.             {
  2410.                disp(0,2,"Receiving: ");
  2411.                disp(20,2,rec_filnam);
  2412.                puts(CLREOL);
  2413.                prtdbgf("New file name: %s\n",rec_filnam);
  2414.             }
  2415.  
  2416.             purgeline(ttyfd);             /* Eat old input */
  2417.             spack('Y',n,0,0,block_check_type); /* Acknowledge file header */
  2418.             oldtry = numtry;              /* Reset try counters */
  2419.             numtry = 0;                   /* ... */
  2420.             stopflag = FALSE;             /* In case we're aborted */
  2421.             aborted = FALSE;
  2422.             n = (n + 1) % 64;             /* Bump packet number, mod 64 */
  2423.             return('D');                  /* Switch to Data state */
  2424.  
  2425.       case 'B':                           /* Break transmission (EOT) */
  2426.             if (num != n)                 /* Need right packet number here */
  2427.                return ('A');
  2428.             spack('Y',n,0,0,block_check_type); /* Say OK */
  2429.             return('C');                  /* Go to complete state */
  2430.  
  2431.       case 'E':                           /* Error packet received */
  2432.             prerrpkt(packet);             /* Print it out and */
  2433.             return('A');                  /* abort */
  2434.  
  2435.       case 'T':                           /* Timeout */
  2436.             if (aborted)
  2437.             {
  2438.                error(0);                  /* send error packet */
  2439.                return('A');               /* aborted by user */
  2440.             }
  2441.       case FALSE:                         /* Didn't get packet */
  2442.             spack('N',n,0,0,block_check_type); /* Return a NAK */
  2443.             return(state);                /* Keep trying */
  2444.  
  2445.       default:                            /* Some other packet, "abort" */
  2446.             return ('A');
  2447.    }
  2448. }
  2449.  
  2450.  
  2451. /*
  2452.  *  r d a t a
  2453.  *
  2454.  *  Receive Data
  2455.  */
  2456.  
  2457. char rdata()
  2458. {
  2459.    char  num, len, tlen;                  /* Packet number, length */
  2460.  
  2461.    if (numtry++ >= maxtry)                /* "abort" if too many tries */
  2462.       return('A');
  2463.    switch(rpack(&len,&num,packet,block_check_type)) /* Get packet */
  2464.    {
  2465.       case 'D':                           /* Got Data packet */
  2466.             if (num != n)                 /* Right packet? */
  2467.             {                             /* No */
  2468.                if (oldtry++ >= maxtry)
  2469.                   return('A');            /* If too many tries, abort */
  2470.                if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */
  2471.                {                          /* Previous packet again? */
  2472.                   spack('Y',num,0,0,block_check_type); /* Yes, re-ACK it */
  2473.                   numtry = 0;             /* Reset try counter */
  2474.                   return(state);          /* Don't write out data! */
  2475.                }
  2476.                else                       /* sorry, wrong number */
  2477.                   return('A');
  2478.             }
  2479.             if (stopflag)                 /* Other side still sending ? */
  2480.             {
  2481.                error(0);                  /* Transfer aborted */
  2482.                return('A');
  2483.             }
  2484.             /* Got data with right packet number */
  2485.             if (bufemp(packet,len) == ERROR) /* Write the data to the file */
  2486.             {
  2487.                error(3,"%d",errno);       /* FLEX error */
  2488.                return('A');               /* enter abort state */
  2489.             }
  2490.             tlen = 1;                     /* Assume aborted */
  2491.             stopflag = TRUE;
  2492.             if (aborted == ABORTX)        /* Abort current file ? */
  2493.                packet[0] = 'X';
  2494.             else if (aborted == ABORTZ)   /* Abort whole batch ? */
  2495.             {
  2496.                packet[0] = 'Z';
  2497.                filecount = 0;             /* No more files for 'GET' */
  2498.             }
  2499.             else
  2500.             {
  2501.                tlen = 0;                  /* Nothing to abort, length = 0 */
  2502.                stopflag = FALSE;
  2503.             }
  2504.             spack('Y',n,tlen,packet,block_check_type); /* Acknowledge packet */
  2505.             oldtry = numtry;              /* Reset the try counters */
  2506.             numtry = 0;                   /* ... */
  2507.             n = (n + 1) % 64;             /* Bump packet number, mod 64 */
  2508.             return('D');                  /* Remain in data state */
  2509.  
  2510.       case 'F':                           /* Got a File Header */
  2511.       case 'X':
  2512.             if (oldtry++ >= maxtry)
  2513.                return('A');               /* If too many tries, "abort" */
  2514.             if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */
  2515.             {                             /* It was the previous one */
  2516.                spack('Y',num,0,0,block_check_type); /* ACK it again */
  2517.                numtry = 0;                /* Reset try counter */
  2518.                return(state);             /* Stay in Data state */
  2519.             }
  2520.             else                          /* Not previous packet, "abort" */
  2521.                return('A');
  2522.  
  2523.       case 'Z':                           /* End-Of-File */
  2524.             if (num != n)                 /* Must have right packet number */
  2525.                return('A');
  2526.             spack('Y',n,0,0,block_check_type); /* OK, ACK it. */
  2527.             fclose(fp);                   /* Close the file */
  2528.             if (len == 1)                 /* Interrupt */
  2529.             {
  2530. #ifdef SCREEN
  2531.                disp(0,18,CLREOL);
  2532.                disp(0,18,"Transfer aborted.");
  2533. #else
  2534.                puts("Transfer aborted.\n");
  2535. #endif
  2536.                beep();
  2537.                if ((packet[0] == 'D') && !save_file)
  2538.                   unlink(rec_filnam);     /* Discard input file */
  2539.             }
  2540.             rec_filnam[0] = '\0';         /* Use default for next transfer */
  2541.             n = (n + 1) % 64;             /* Bump packet number */
  2542.             return('F');                  /* Go back to Receive File state */
  2543.  
  2544.       case 'E':                           /* Error packet received */
  2545.             prerrpkt(packet);             /* Print it out and */
  2546.             return('A');                  /* abort */
  2547.  
  2548.       case 'T':                           /* Timeout */
  2549.             if (aborted)
  2550.             {
  2551.                error(0);                  /* send error packet */
  2552.                return('A');               /* aborted by user */
  2553.             }
  2554.       case FALSE:                         /* Didn't get packet */
  2555.             spack('N',n,0,0,block_check_type); /* Return a NAK */
  2556.             return(state);                /* Keep trying */
  2557.  
  2558.       default:                            /* Some other packet, "abort" */
  2559.             return('A');
  2560.    }
  2561. }
  2562. <<< flsend.c >>>
  2563. #include "FLK.H"
  2564.          
  2565. sendfile()
  2566. {
  2567.    if (numprm <= 1)                    /* check parameter */
  2568.       prterr("Filespec(s) required");
  2569.    else if (!get_file_spec(TRUE))      /* Get filespec for send */
  2570.       prterr("No files selected");
  2571.    else
  2572.    {
  2573.       sflg++;
  2574.       set_frame();
  2575.       start_remote();                  /* Setup port if remote */
  2576.       if (!sendsw())                   /* Send the file(s) */
  2577.          disp(0,16,"Send failed.");    /* Report failure */
  2578.       disp(0,20,CURSON);
  2579.       beep();
  2580.       finish_remote();
  2581.    }
  2582. }
  2583.  
  2584. /*
  2585.  *  s e n d s w
  2586.  *
  2587.  *  Sendsw is the state table switcher for sending files.  It loops until
  2588.  *  either it finishes, or an error is encountered.  The routines called
  2589.  *  by sendsw are responsible for changing the state.
  2590.  *
  2591.  */
  2592.  
  2593. sendsw()
  2594. {
  2595.    char sinit(), sfile(), sdata(), seof(), sbreak();
  2596.  
  2597.    init_xfer();                           /* Reset counters */
  2598.    set_default_comm();                    /* Set communication parameters */
  2599.    state = 'S';                           /* Send initiate is start state */
  2600.    n = 0;                                 /* Initialize message number */
  2601.    numtry = 0;                            /* Say no tries yet */
  2602.    if (remote)
  2603.       wait(send_delay * 1000);            /* Wait before sending if remote */
  2604.    purgeline(ttyfd);                      /* Eat old input */
  2605.    while(TRUE)                            /* Do this as long as necessary */
  2606.    {
  2607.       if (debug)
  2608.       {
  2609.          prtdbgf("Send state: ");
  2610. #ifndef SCREEN
  2611.          puts("Send state: ");
  2612. #endif 
  2613.          disp_state(20,14,state);
  2614.       }
  2615.       switch(state)
  2616.       {
  2617.          case 'S':                        /* Send-init */
  2618.                state = sinit();
  2619.                break;
  2620.  
  2621.          case 'F':                        /* Send-file */
  2622.                state = sfile();
  2623.                break;
  2624.  
  2625.          case 'D':                        /* Send-data */
  2626.                state = sdata();
  2627.                break;
  2628.  
  2629.          case 'Z':                        /* Send-End-of-File */
  2630.                state = seof();
  2631.                break;
  2632.  
  2633.          case 'B':                        /* Send-Break */
  2634.                state = sbreak();
  2635.                break;
  2636.  
  2637.          case 'C':                        /* Complete */
  2638.                fin_xfer();
  2639.                return (TRUE);
  2640.  
  2641.          default:                         /* Unknown or abort, fail */
  2642.                fin_xfer();
  2643.                return (FALSE);
  2644.       }
  2645.    }
  2646. }
  2647.  
  2648.  
  2649. /*
  2650.  *  s i n i t
  2651.  *
  2652.  *  Send Initiate: send this host's parameters and get other side's back.
  2653.  */
  2654.  
  2655. char sinit()
  2656. {
  2657.    char  num, len;                        /* Packet number, length */
  2658.  
  2659.    if (numtry++ >= maxtry)                /* If too many tries, give up */
  2660.       return('A');
  2661.    spar(packet,&len);                     /* Fill up init info packet */
  2662.  
  2663.    spack('S',n,len,packet,1);             /* Send an S packet */
  2664.    switch(rpack(&len,&num,recpkt,1))      /* What was the reply? */
  2665.    {
  2666.       case 'N':                           /* NAK, try it again */
  2667.             return(state);
  2668.  
  2669.       case 'Y':                           /* ACK */
  2670.             if (n != num)                 /* If wrong ACK, stay in S state */
  2671.                return(state);             /* and try again */
  2672.             rpar(recpkt,len);             /* Get other side's init info */
  2673.             numtry = 0;                   /* Reset try counter */
  2674.             n = ( n + 1) % 64;            /* Bump packet count */
  2675.             return('F');                  /* OK, switch state to F */
  2676.  
  2677.       case 'E':                           /* Error packet received */
  2678.             prerrpkt(recpkt);             /* Print it out and */
  2679.             return('A');                  /* Abort */
  2680.  
  2681.       case 'T':                           /* Timeout */
  2682.             if (aborted)
  2683.                return('A');               /* aborted by user */
  2684.       case FALSE:                         /* Receive failure, try again */
  2685.             return(state);
  2686.  
  2687.       default:                            /* Anything else, just "abort" */
  2688.             return('A');
  2689.    }
  2690. }
  2691.  
  2692.  
  2693. /*
  2694.  *  s f i l e
  2695.  *
  2696.  *  Send File Header.
  2697.  */
  2698.  
  2699. char sfile()
  2700. {
  2701.    char  num, len,                        /* Packet number, length */
  2702.          fnm[50];
  2703.    extern int drive;
  2704.  
  2705.    if (numtry++ >= maxtry)                /* If too many tries, give up */
  2706.       return('A');
  2707.  
  2708.    aborted = FALSE;
  2709.    if (fp == ERROR)                       /* If not already open, */
  2710.    {
  2711.       fnm[0] = drive + '0';               /* Insert drive in spec */
  2712.       fnm[1] = '.';
  2713.       strcpy(&fnm[2],filnam);
  2714.       if (image)
  2715.          fp = fopen(fnm,"br");            /* open the file to be sent */
  2716.       else
  2717.          fp = fopen(fnm,"r");             /* open the file to be sent */
  2718.       if (fp == ERROR)                    /* If bad file pointer, give up */
  2719.       {
  2720.          error(5,"%s",fnm);               /* Can't open file */
  2721.          if (!get_file_spec(FALSE))
  2722.             return('C');                  /* No more files to do */
  2723.          else
  2724.             return('S');                  /* Try next file */
  2725.       }
  2726.    }
  2727.    disp(0,2,"Sending: ");
  2728.    disp(20,2,fnm);
  2729.    puts(CLREOL);
  2730.    len = strlen(filnam);
  2731.    spack('F',n,len,filnam,block_check_type); /* Send an F packet */
  2732.    switch(rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */
  2733.    {
  2734.       case 'N':                           /* NAK, just stay in this state, */
  2735.             num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
  2736.             if (n != num)                 /* which is just like an ACK for */
  2737.                return(state);             /* this packet so fall thru to... */
  2738.  
  2739.       case 'Y':                           /* ACK */
  2740.             if (n != num)                 /* If wrong ACK, stay in F state */
  2741.                return(state); 
  2742.             numtry = 0;                   /* Reset try counter */
  2743.             n = (n + 1) % 64;             /* Bump packet count */
  2744.             size = bufill(packet,TRUE);   /* Get first data from file */
  2745.             return('D');                  /* Switch state to D */
  2746.  
  2747.       case 'E':                           /* Error packet received */
  2748.             prerrpkt(recpkt);             /* Print it out and */
  2749.             return('A');                  /* abort */
  2750.  
  2751.       case 'T':                           /* Timeout */
  2752.             if (aborted)
  2753.             {
  2754.                error(0);                  /* send error packet */
  2755.                return('A');               /* aborted by user */
  2756.             }
  2757.       case FALSE:                         /* Receive failure, stay in F */
  2758.             return(state);
  2759.  
  2760.       default:                            /* Something else, just "abort" */
  2761.             return('A');
  2762.    }
  2763. }
  2764.  
  2765.  
  2766. /*
  2767.  *  s d a t a
  2768.  *
  2769.  *  Send File Data
  2770.  */
  2771.  
  2772. char sdata()
  2773. {
  2774.    char  num, len,                        /* Packet number, length */
  2775.          tmpc;
  2776.  
  2777.    if (numtry++ >= maxtry)                /* If too many tries, give up */
  2778.       return('A');
  2779.    spack('D',n,(char)size,packet,block_check_type); /* Send a D packet */
  2780.    switch(rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */
  2781.    {
  2782.       case 'N':                           /* NAK, just stay in this state, */
  2783.             num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
  2784.             if (n != num)                 /* which is just like an ACK for */
  2785.                return(state);             /* this packet so fall thru to... */
  2786.  
  2787.       case 'Y':                           /* ACK */
  2788.             if (n != num)                 /* If wrong ACK, fail */
  2789.                return(state);
  2790.             numtry = 0;                   /* Reset try counter */
  2791.             n = (n + 1) % 64;             /* Bump packet count */
  2792.             if ((size = bufill(packet,FALSE)) == EOF) /* Get data from file */
  2793.                return('Z');               /* If EOF set state to that */
  2794.             tmpc = recpkt[0];
  2795.             if (len == 1)                 /* Data on ack */
  2796.             {
  2797.                if (tmpc == 'Z')           /* Stop entire batch */
  2798.                   filecount = 0;          /* No more files to send */
  2799.                if ((tmpc == 'X') || (tmpc == 'Z'))
  2800.                   aborted = tmpc - 64;    /* Make binary */
  2801.             }
  2802.             if ((aborted == ABORTX) || (aborted == ABORTZ))
  2803.             {
  2804. #ifdef SCREEN
  2805.                disp(0,18,"Transfer interrupted.");
  2806. #else
  2807.                puts("Transfer interrupted.\n");
  2808. #endif
  2809.                beep();
  2810.                return('Z');               /* Send abort */
  2811.             }
  2812.             return('D');                  /* Got data, stay in state D */
  2813.  
  2814.       case 'E':                           /* Error packet received */
  2815.             prerrpkt(recpkt);             /* Print it out and */
  2816.             return('A');                  /* abort */
  2817.  
  2818.       case 'T':                           /* Timeout */
  2819.             if (aborted)
  2820.             {
  2821.                error(0);                  /* send error packet */
  2822.                return('A');               /* aborted by user */
  2823.             }
  2824.       case FALSE:                         /* Receive failure, stay in D */
  2825.             return(state);
  2826.  
  2827.       default:                            /* Anything else, "abort" */
  2828.             return('A');
  2829.    }
  2830. }
  2831.  
  2832.  
  2833. /*
  2834.  *  s e o f
  2835.  *
  2836.  *  Send End-Of-File.
  2837.  */
  2838.  
  2839. char seof()
  2840. {
  2841.    char  num, len, tlen;                  /* Packet number, length */
  2842.    
  2843.    if (numtry++ >= maxtry)                /* If too many tries, "abort" */
  2844.       return('A');
  2845.  
  2846.    tlen = 0;                              /* Assume no abort */
  2847.    if ((aborted == ABORTX) || (aborted == ABORTZ))
  2848.    {
  2849.       packet[0] = 'D';                    /* Discard file on abort */
  2850.       tlen = 1;
  2851.    }
  2852.    spack('Z',n,tlen,packet,block_check_type); /* Send a 'Z' packet */
  2853.    switch(rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */
  2854.    {
  2855.       case 'N':                           /* NAK, just stay in this state, */
  2856.             num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
  2857.             if (n != num)                 /* which is just like an ACK for */
  2858.                return(state);             /* this packet so fall thru to... */
  2859.  
  2860.       case 'Y':                           /* ACK */
  2861.             if (n != num)                 /* If wrong ACK, hold out */
  2862.                return(state);
  2863.             numtry = 0;                   /* Reset try counter */
  2864.             n = (n + 1) % 64;             /* and bump packet count */
  2865.             fclose(fp);                   /* Close the input file */
  2866.             fp = ERROR;                   /* flag no file open */
  2867.  
  2868.             if (!get_file_spec(FALSE))
  2869.                return ('B');              /* Stop if no more files */
  2870.             if (aborted == ABORTZ)        /* Abort the rest ? */
  2871.             {
  2872.                while (get_file_spec(FALSE)); /* FLush directory buffer */
  2873.                return ('B');
  2874.             }
  2875.             return('F');                  /* More files, switch state to F */
  2876.  
  2877.       case 'E':                           /* Error packet received */
  2878.             prerrpkt(recpkt);             /* Print it out and */
  2879.             return('A');                  /* abort */
  2880.  
  2881.       case 'T':                           /* Timeout */
  2882.             if (aborted)
  2883.             {
  2884.                error(0);                  /* send error packet */
  2885.                return('A');               /* aborted by user */
  2886.             }
  2887.       case FALSE:                         /* Receive failure, stay in Z */
  2888.             return(state);
  2889.  
  2890.       default:                            /* Something else, "abort" */
  2891.             return('A');
  2892.    }
  2893. }
  2894.  
  2895.  
  2896. /*
  2897.  *  s b r e a k
  2898.  *
  2899.  *  Send Break (EOT)
  2900.  */
  2901.  
  2902. char sbreak()
  2903. {
  2904.    char  num, len;                        /* Packet number, length */
  2905.  
  2906.    if (numtry++ >= maxtry)                /* If too many tries "abort" */
  2907.       return('A');
  2908.  
  2909.    spack('B',n,0,packet,block_check_type);/* Send a B packet */
  2910.    switch (rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */
  2911.    {
  2912.       case 'N':                           /* NAK, just stay in this state, */
  2913.             num = (--num < 0 ? 63 : num); /* unless NAK for previous packet, */
  2914.             if (n != num)                 /* which is just like an ACK for */
  2915.                return(state);             /* this packet so fall thru to... */
  2916.  
  2917.       case 'Y':                           /* ACK */
  2918.             if (n != num)                 /* If wrong ACK, fail */
  2919.                return(state);
  2920.             numtry = 0;                   /* Reset try counter */
  2921.             n = (n + 1) % 64;             /* and bump packet count */
  2922.             return('C');                  /* Switch state to Complete */
  2923.  
  2924.       case 'E':                           /* Error packet received */
  2925.             prerrpkt(recpkt);             /* Print it out and */
  2926.             return('A');                  /* abort */
  2927.  
  2928.       case 'T':                           /* Timeout */
  2929.             if (aborted)
  2930.             {
  2931.                error(0);                  /* send error packet */
  2932.                return('A');               /* aborted by user */
  2933.             }
  2934.       case FALSE:                         /* Receive failure, stay in B */
  2935.             return(state); 
  2936.  
  2937.       default:                            /* Other, "abort" */
  2938.             return ('A');
  2939.    }
  2940. }
  2941. <<< flserv.c >>>
  2942. #include "FLK.H"
  2943.  
  2944. /*
  2945.  *      s e r v e r
  2946.  */
  2947.  
  2948. server()
  2949. {
  2950.    char num, len, i;
  2951.    extern char rec_filnam[];
  2952.    char filename[50];
  2953.  
  2954.    n = 0;                              /* initialize message number */
  2955.    numtry = 0;                         /* say no tries yet */
  2956.    set_frame();
  2957.    posit(0,20);
  2958.    puts("Server running... Type your kermit 'BYE' or 'FINISH'\n");
  2959.    puts("commands, or ctrl-X to quit the server.\n");
  2960.    set_default_comm();                 /* Set default communication */
  2961.    start_remote();                     /* Setup port if remote */
  2962.    while(TRUE)
  2963.    {
  2964.       switch(rpack(&len,&num,packet,1))/* do this for as long as necessary */
  2965.       {
  2966.          case 'S':
  2967.                   set_frame();
  2968.                   n = num;
  2969.                   rpar(packet,len);    /* setup receive parameters */
  2970.                   spar(packet,&len);   /* setup transmit parameters */
  2971.                   spack('Y',n,len,packet,1);
  2972.                   oldtry = numtry;
  2973.                   numtry = 0;
  2974.                   rec_filnam[0] = '\0';   /* Use default name */
  2975.                   n = (n + 1) % 64;
  2976.                   rflg++;              /* Flag receive file */
  2977.                   recsw('F');          /* switch to 'F' state */
  2978.                   break;
  2979.  
  2980.          case 'I':
  2981.                   set_frame();
  2982.                   n = num;
  2983.                   rpar(packet,len);    /* setup receive parameters */
  2984.                   spar(packet,&len);   /* setup transmit parameters */
  2985.                   spack('Y',n,len,packet,1);
  2986.                   break;
  2987.  
  2988.          case 'R':
  2989.                   i = 0;
  2990.                   do
  2991.                      filename[i] = packet[i];  /* copy filename */
  2992.                   while((packet[i++] != '\0') && (i < len));
  2993.                   filename[i] = '\0';     /* Mark end of string */
  2994.                   numprm = 2;
  2995.                   params[1] = &filename;  /* Setup pointer to filename */
  2996.                   get_file_spec(TRUE);    /* Parse filespec */
  2997.                   sflg++;                 /* Flag end file */
  2998.                   sendsw();               /* Send file */
  2999.                   n = 0;
  3000.                   break;
  3001.  
  3002.          case 'G':                        /* 'general' command */
  3003.                   set_frame();
  3004.                   switch(packet[0])
  3005.                   {
  3006.                      case 'L':            /* logout */
  3007.                               spack('Y',num,0,0,1);  /* acknowledge */
  3008.                               disp(0,23,CURSON);
  3009.                               finish_remote();
  3010.                               kerm_exit();
  3011.  
  3012.                      case 'F':            /* finish */
  3013.                               spack('Y',num,0,0,1);  /* acknowledge */
  3014.                               disp(0,23,CURSON);
  3015.                               finish_remote();
  3016.                               return;
  3017.  
  3018.                      default:
  3019.                               error(1);   /* Not implemented */
  3020.                   }
  3021.                   break;
  3022.                   
  3023.          case 'T':                        /* timeout */
  3024.                   if (aborted)
  3025.                   {
  3026.                      disp(0,23,CURSON);
  3027.                      finish_remote();
  3028.                      return;              /* aborted by user */
  3029.                   }
  3030.                   spack('N',n,0,0,1);     /* send NAK */
  3031.                   break;
  3032.  
  3033.          case 'N':
  3034.          case 'E':
  3035.                   break;                  /* Eat NAK and error packet */
  3036.  
  3037.          case FALSE:
  3038.                   error(2);               /* Packet error */
  3039.                   break;
  3040.  
  3041.          default:
  3042.                   if (aborted)
  3043.                   {
  3044.                      disp(0,23,CURSON);
  3045.                      finish_remote();
  3046.                      return;
  3047.                   }
  3048.                   error(1);               /* Not implemented */
  3049.       }
  3050.       rflg = sflg = 0;
  3051.       set_default_comm();                 /* Set default communication */
  3052.    }
  3053. }
  3054.  
  3055. /*
  3056.  * stop remote server
  3057.  */
  3058.  
  3059. finish()
  3060. {
  3061.    if (remote)
  3062.       prterr("Not allowed if REMOTE");
  3063.    else
  3064.    {
  3065.       if (!do_generic('F'))
  3066.       {
  3067.          disp(0,16,"Finish failed\n");
  3068.          beep();
  3069.       }
  3070.       disp(0,23,CURSON);
  3071.       finish_remote();
  3072.    }
  3073. }
  3074.  
  3075. /*
  3076.  * log out remote server and local kermit
  3077.  */
  3078.  
  3079. bye()
  3080. {
  3081.    if (remote)
  3082.       prterr("Not allowed if REMOTE");
  3083.    else
  3084.    {
  3085.       if (!do_generic('L'))
  3086.       {
  3087.          disp(0,16,"Bye failed\n");
  3088.          disp(0,23,CURSON);
  3089.          beep();
  3090.       }
  3091.       else
  3092.       {
  3093.          disp(0,23,CURSON);
  3094.          kerm_exit();                     /* stop program if successful */
  3095.       }
  3096.       finish_remote();
  3097.    }
  3098. }
  3099.  
  3100. /*
  3101.  * send server function
  3102.  */
  3103.  
  3104. do_generic(function)
  3105. char function;
  3106. {
  3107.    char len, num,
  3108.         status;
  3109.  
  3110.    n = 0;                                 /* initialize message number */
  3111.    numtry = 0;                            /* say no tries yet */
  3112.  
  3113.    set_frame();
  3114.    set_default_comm();                    /* setup default communication */
  3115.    start_remote();                        /* Setup port if remote */
  3116.    packet[0] = function;                  /* insert GENERIC command */
  3117.  
  3118.    while(TRUE)
  3119.    {
  3120.       num = 0;
  3121.       spack('G',num,1,packet,1);          /* send GENERIC packet */
  3122.       switch(rpack(&len,&num,recpkt,1))
  3123.       {
  3124.          case 'Y':
  3125.                   return(TRUE);           /* valid response */
  3126.  
  3127.          case 'E':
  3128.                   prerrpkt(recpkt);
  3129.                   return(FALSE);          /* received an error */
  3130.  
  3131.          case 'T':
  3132.                   if (aborted)
  3133.                      return(FALSE);       /* aborted by user */
  3134.  
  3135.          default:
  3136.                   if (numtry++ > maxtry)
  3137.                      return(FALSE);       /* too many errors */
  3138.       }
  3139.    }
  3140. }
  3141. <<< flset.c >>>
  3142. #include "FLK.H"
  3143.  
  3144. TABLE  set_table[] =
  3145. {
  3146.    "debug", 1,
  3147.    "escape", 2,
  3148.    "line", 3,
  3149.    "baud", 4,
  3150.    "configuration", 5,
  3151.    "timeout", 6,
  3152.    "prompt", 7,
  3153.    "filetype", 8,
  3154.    "log", 9,
  3155.    "duplex", 10,
  3156.    "handshake", 11,
  3157.    "block_check_type", 12,
  3158.    "repeat_quote", 13,
  3159.    "retry", 14,
  3160.    "packet_length", 15,
  3161.    "padding", 16,
  3162.    "padchar", 17,
  3163.    "start_of_packet", 18,
  3164.    "end_of_line", 19,
  3165.    "quote", 20,
  3166.    "eight_bit_quote", 21,
  3167.    "incomplete", 22,
  3168.    "delay", 23,
  3169.    "warning", 24,
  3170.    "", 0
  3171. };
  3172.  
  3173. set()
  3174. {
  3175.    int   fpoint;
  3176.  
  3177.    fpoint = parse(params[1], set_table);  /* Parse 'set' command */
  3178.    if (fpoint == NULL)                    /* Ambiguous */
  3179.       prterr("Ambiguous 'set' command");
  3180.    else if (fpoint == ERROR)              /* Unknown */
  3181.       prterr("Unknown 'set' command");
  3182.    else if (!synerr(3))                   /* Dispatch to command if no error */
  3183.       switch(fpoint)
  3184.       {
  3185.          case 1:
  3186.                   set_debug();
  3187.                   break;
  3188.          case 2:
  3189.                   set_escape();
  3190.                   break;
  3191.          case 3:
  3192.                   set_line();
  3193.                   break;
  3194.          case 4:
  3195.                   set_baud();
  3196.                   break;
  3197.          case 5:
  3198.                   set_config();
  3199.                   break;
  3200.          case 6:
  3201.                   set_timeout();
  3202.                   break;
  3203.          case 7:
  3204.                   set_prompt();
  3205.                   break;
  3206.          case 8:
  3207.                   set_filetype();
  3208.                   break;
  3209.          case 9:
  3210.                   set_log();
  3211.                   break;
  3212.          case 10:
  3213.                   set_dup();
  3214.                   break;
  3215.          case 11:
  3216.                   set_hsh();
  3217.                   break;
  3218.          case 12:
  3219.                   set_block_check_type();
  3220.                   break;
  3221.          case 13:
  3222.                   set_repeat_quote();
  3223.                   break;
  3224.          case 14:
  3225.                   set_retry();
  3226.                   break;
  3227.          case 15:
  3228.                   set_packet_length();
  3229.                   break;
  3230.          case 16:
  3231.                   set_padding();
  3232.                   break;
  3233.          case 17:
  3234.                   set_padchar();
  3235.                   break;
  3236.          case 18:
  3237.                   set_start_of_packet();
  3238.                   break;
  3239.          case 19:
  3240.                   set_end_of_line();
  3241.                   break;
  3242.          case 20:
  3243.                   set_quote();
  3244.                   break;
  3245.          case 21:
  3246.                   set_eight_bit_quote();
  3247.                   break;
  3248.          case 22:
  3249.                   set_incomplete();
  3250.                   break;
  3251.          case 23:
  3252.                   set_delay();
  3253.                   break;
  3254.          case 24:
  3255.                   set_warning();
  3256.       }
  3257. }
  3258.  
  3259. set_debug()
  3260. {
  3261.    int temp;
  3262.  
  3263.    if ((temp = set_onoff(2)) != ERROR)
  3264.    {
  3265.       debug = temp;
  3266.       if (dbgfil != ERROR)                /* Close file */
  3267.          fclose(dbgfil);
  3268.       dbgfil = ERROR;
  3269.    }
  3270.    else if (tolower(*params[2]) == 'l')   /* Open debug log file */
  3271.    {
  3272.       if (numprm < 4)
  3273.          prterr("Filespec required");
  3274.       else
  3275.          if (dbgfil != ERROR)
  3276.             prterr("Debug log file already open");
  3277.          else
  3278.          {
  3279.             strcpy(dbgfname,params[3]);
  3280.             cvt_case(params[3]);
  3281.             if ((dbgfil = fopen(params[3],"w")) == ERROR)
  3282.                prterr("Error opening debug log file %s, error number is %d",
  3283.                      params[3], errno);
  3284.             else
  3285.                debug = 2;
  3286.          }
  3287.    }
  3288.    else
  3289.       synerr(0);
  3290. }
  3291.  
  3292. set_escape()
  3293. {
  3294.    escchr = *params[2];                   /* Get escape character */
  3295. }
  3296.  
  3297. set_line()
  3298. {
  3299.    if (tolower(*params[2]) == 'r')
  3300.    {
  3301.       cleanup();                          /* Reset port */
  3302.       ttyfd = REMOTE;                     /* Remote connection */
  3303.       remote = TRUE;
  3304.    }
  3305.    else
  3306.    {
  3307.       sscanf(params[2],"%x",&ttyfd);      /* Get hex address */
  3308.       if (initport(ttyfd,0) == FALSE)     /* Try to init the port */
  3309.          prterr("No such line available");
  3310.       else
  3311.          remote = FALSE;
  3312.    }
  3313. }
  3314.  
  3315. set_baud()
  3316. {
  3317.    int   temp,
  3318.          speed_value,
  3319.          found,
  3320.          *p;
  3321.    extern int v_speed_6850[];
  3322. #ifdef VIDIS
  3323.    extern int v_speed_6551[];
  3324. #endif
  3325.  
  3326. #ifdef VIDIS
  3327.    if (use_6850)
  3328.       p = v_speed_6850;
  3329.    else
  3330.       p = v_speed_6551;
  3331. #else
  3332.    p = v_speed_6850;
  3333. #endif
  3334.  
  3335.    temp = atoi(params[2]);                /* Get speed value */
  3336.    found = FALSE;
  3337.    while (*p)                             /* Do until end of table */
  3338.    {
  3339.       if (temp == *p++)
  3340.       {                                   /* Match! */
  3341.          speed_value = *p;
  3342.          found = TRUE;
  3343.          break;
  3344.       }
  3345.       p++;                                /* Skip speed value */
  3346.    }
  3347.    if (found)
  3348.    {
  3349.       speed = temp;                       /* Set new speed value */
  3350.       initport(ttyfd,0);                  /* Init the port */
  3351.    }
  3352.    else
  3353.       prterr("Invalid speed");
  3354. }
  3355.  
  3356. set_config()
  3357. {
  3358.    int temp;
  3359.  
  3360.    temp = atoi(params[2]);                /* Get configuration */
  3361.    if ((temp < 0) || (temp > 7))          /* Check range */
  3362.       prterr("Improper value");
  3363.    else
  3364.    {
  3365.       config = temp;                      /* Set new value */
  3366.       initport(ttyfd,0);                  /* Init the port */
  3367.    }
  3368. }
  3369.  
  3370. set_timeout()
  3371. {
  3372.    int temp;
  3373.  
  3374.    temp = atoi(params[2]);                /* Get timeout value */
  3375.    if ((temp <= 0) || (temp > 100))       /* Check range */
  3376.       prterr("Improper value");
  3377.    else
  3378.       mytime = temp;                      /* Set new value */
  3379. }
  3380.  
  3381. set_prompt()
  3382. {
  3383.    if (strlen(params[2]) > 20)
  3384.       params[2][20] = '\0';               /* Truncate string */
  3385.    strcpy(prompt, params[2]);             /* Setup new prompt */
  3386. }
  3387.  
  3388. set_filetype()
  3389. {
  3390.    char temp;
  3391.  
  3392.    temp = tolower(*params[2]);
  3393.    if (temp == 'a')                       /* ASCII */
  3394.       image = FALSE;
  3395.    else if (temp == 'b')                  /* BINARY */
  3396.       image = TRUE;
  3397.    else
  3398.       synerr(0);
  3399. }
  3400.  
  3401. set_log()
  3402. {
  3403.    if ((params[2][0] == '-') && logfileopen)
  3404.    {                                      /* Close file */
  3405.       if (fclose(lfp) == ERROR)
  3406.          prterr("Error closing log file %s", logfile);
  3407.       logfile[0] = '\0';                  /* Zap filename */
  3408.       logfileopen = logging = FALSE;
  3409.    }
  3410.    else
  3411.    {
  3412.       if (logfileopen)
  3413.          prterr("Log file already open");
  3414.       else
  3415.       {
  3416.       if (strlen(params[2]) > 20)
  3417.          params[2][20] = '\0';            /* Truncate string */
  3418.       strcpy(logfile,params[2]);
  3419.       cvt_case(logfile);                  /* Take care of case mapping */
  3420.       if ((lfp = fopen(logfile, "w")) == ERROR)
  3421.       {
  3422.          prterr("Error opening log file %s", logfile);
  3423.          logfile[0] = '\0';               /* Zap filename */
  3424.          logfileopen = logging = FALSE;
  3425.       }
  3426.       else
  3427.          logfileopen = TRUE;
  3428.       }
  3429.    }
  3430. }
  3431.  
  3432. set_dup()
  3433. {
  3434.    char ch;
  3435.  
  3436.    ch = tolower(*params[2]);
  3437.  
  3438.    if (ch == 'f')
  3439.       fulldup = TRUE;
  3440.    else if (ch == 'h')
  3441.       fulldup = FALSE;
  3442.    else
  3443.       synerr(0);
  3444. }
  3445.  
  3446. set_hsh()
  3447. {
  3448.    char start_tmp, stop_tmp;
  3449.  
  3450.    if (!synerr(4))                    /* Be sure there are enough parameters */
  3451.    {
  3452.       start_tmp = atoi(params[2]);        /* Set data start character */
  3453.       stop_tmp = atoi(params[3]);         /* Set data stop character */
  3454.       if ((start_tmp < 0) || (start_tmp > 127)
  3455.          || (stop_tmp < 0) || (stop_tmp > 127))
  3456.          prterr("Illegal value");
  3457.       else
  3458.          dstart = start_tmp;
  3459.          dstop = stop_tmp;
  3460.    }
  3461. }
  3462.  
  3463. set_quote()
  3464. {
  3465.    char c;
  3466.  
  3467.    if (check_quote(c = *params[2]))
  3468.    {
  3469.       if ((c != myeightquote) && (c != myrptquote))
  3470.          myquote = c;
  3471.       else
  3472.          prterr("Character already in use");
  3473.    }
  3474. }
  3475.  
  3476. set_eight_bit_quote()
  3477. {
  3478.    char c;
  3479.  
  3480.    if (toupper(c = *params[2]) == 'N')
  3481.       myeightquote = 0;                   /* No eight bit quoting done */
  3482.    else if (check_quote(c))
  3483.    {
  3484.       if ((c != myquote) && (c != myrptquote))
  3485.          myeightquote = c;
  3486.       else
  3487.          prterr("Character already in use");
  3488.    }
  3489. }
  3490.  
  3491. set_repeat_quote()
  3492. {
  3493.    char c;
  3494.  
  3495.    if (toupper(c = *params[2]) == 'N')
  3496.       myrptquote = 0;                     /* No repeat quoting done */
  3497.    else if (check_quote(c))
  3498.    {
  3499.       if ((c != myquote) && (c != myeightquote))
  3500.          myrptquote = c;
  3501.       else
  3502.          prterr("Character already in use");
  3503.    }
  3504. }
  3505.  
  3506. set_packet_length()
  3507. {
  3508.    char size;
  3509.  
  3510.    size = atoi(params[2]);
  3511.    if ((size < 10) || (size > 94))
  3512.       prterr("Invalid length");
  3513.    else
  3514.       maxpacksiz = size;
  3515. }
  3516.  
  3517. set_padding()
  3518. {
  3519.    int ptmp;
  3520.  
  3521.    ptmp = atoi(params[2]);
  3522.    if (ptmp > 94)
  3523.       prterr("Value out of range");
  3524.    else
  3525.       mypad = ptmp;
  3526. }
  3527.  
  3528. set_padchar()
  3529. {
  3530.    int ptmp;
  3531.  
  3532.    sscanf(params[2], "%x", &ptmp);
  3533.    mypchar = ptmp;
  3534. }
  3535.  
  3536. set_retry()
  3537. {
  3538.    maxtry = atoi(params[2]);
  3539. }
  3540.  
  3541. set_end_of_line()
  3542. {
  3543.    int etmp;
  3544.  
  3545.    sscanf(params[2], "%x", &etmp);
  3546.    if (etmp == mypackstart)
  3547.       prterr("End of line must be different of start of packet");
  3548.    else
  3549.       myeol = etmp;
  3550. }
  3551.  
  3552. set_start_of_packet()
  3553. {
  3554.    int ptmp;
  3555.  
  3556.    sscanf(params[2], "%x", &ptmp);
  3557.    if (ptmp == myeol)
  3558.       prterr("Start of packet must be different of end of line");
  3559.    else
  3560.       mypackstart = ptmp;
  3561. }
  3562.  
  3563. set_block_check_type()
  3564. {
  3565.    char c;
  3566.  
  3567.    c = atoi(params[2]);
  3568.    if ((c >= 1) && (c <= 3))
  3569.       myblock_check_type = c;
  3570.    else
  3571.       prterr("Invalid check type");
  3572. }
  3573.  
  3574. set_incomplete()
  3575. {
  3576.    char c;
  3577.  
  3578.    c = toupper(*params[2]);
  3579.    if (c == 'K')
  3580.       save_file = TRUE;                   /* Keep file */
  3581.    else if (c == 'D')
  3582.       save_file = FALSE;                  /* Discard file */
  3583.    else
  3584.       synerr(0);
  3585. }
  3586.  
  3587. set_delay()
  3588. {
  3589.    send_delay = atoi(params[2]);
  3590. }
  3591.  
  3592. set_warning()
  3593. {
  3594.    int temp;
  3595.  
  3596.    temp = set_onoff(2);
  3597.    if (temp != ERROR)
  3598.       warning = temp;
  3599.    else
  3600.       synerr(0);
  3601. }
  3602.  
  3603. check_quote(qchar)
  3604. char qchar;
  3605. {
  3606.    if (((qchar >= '!') && (qchar <= '>')) ||
  3607.       ((qchar >= '{') && (qchar <= '~')) ||
  3608.       (qchar == '`'))
  3609.       return (TRUE);                      /* Valid character */
  3610.    else
  3611.    {
  3612.       prterr("Invalid character");
  3613.       return (FALSE);                     /* Invalid character */
  3614.    }
  3615. }
  3616.  
  3617. set_onoff(i)
  3618. int i;
  3619. {
  3620.    make_lower(params[i]);
  3621.    if (strcmp(params[i], "on") == 0)
  3622.       return TRUE;
  3623.    else
  3624.       if ((strcmp(params[i], "of") == 0) ||
  3625.           (strcmp(params[i], "off") == 0))
  3626.          return FALSE;
  3627.    else return ERROR;
  3628. }
  3629. <<< flshow.c >>>
  3630. #include "FLK.H"
  3631.  
  3632. TABLE  show_table[] =
  3633. {
  3634.    "all", 1,
  3635.    "debug", 2,
  3636.    "escape", 3,
  3637.    "line", 4,
  3638.    "baud", 5,
  3639.    "configuration", 6,
  3640.    "timeout", 7,
  3641.    "filetype", 8,
  3642.    "log", 9,
  3643.    "duplex", 10,
  3644.    "handshake", 11,
  3645.    "block_check_type", 12,
  3646.    "repeat_quote", 13,
  3647.    "retry", 14,
  3648.    "packet_length", 15,
  3649.    "padding", 16,
  3650.    "padchar", 17,
  3651.    "start_of_packet", 18,
  3652.    "end_of_line", 19,
  3653.    "quote", 20,
  3654.    "eight_bit_quote", 21,
  3655.    "incomplete", 22,
  3656.    "delay", 23,
  3657.    "warning", 24,
  3658.    "", 0
  3659. };
  3660.  
  3661. show()
  3662. {
  3663.    int   fpoint;
  3664.  
  3665.    fpoint = parse(params[1], show_table); /* Parse 'show' command */
  3666.    if (fpoint == NULL)                    /* Ambiguous */
  3667.       prterr("Ambiguous 'show' command");
  3668.    else if (fpoint == ERROR)              /* Unknown */
  3669.       prterr("Unknown 'show' command");
  3670.    else                                   /* Dispatch to command if no error */
  3671.       switch(fpoint)
  3672.       {
  3673.          case 1:
  3674.                   show_all();
  3675.                   break;
  3676.          case 2:
  3677.                   show_debug();
  3678.                   break;
  3679.          case 3:
  3680.                   show_escape();
  3681.                   break;
  3682.          case 4:
  3683.                   show_line();
  3684.                   break;
  3685.          case 5:
  3686.                   show_baud();
  3687.                   break;
  3688.          case 6:
  3689.                   show_config();
  3690.                   break;
  3691.          case 7:
  3692.                   show_timeout();
  3693.                   break;
  3694.          case 8:
  3695.                   show_filetype();
  3696.                   break;
  3697.          case 9:
  3698.                   show_log();
  3699.                   break;
  3700.          case 10:
  3701.                   show_dup();
  3702.                   break;
  3703.          case 11:
  3704.                   show_hsh();
  3705.                   break;
  3706.          case 12:
  3707.                   show_block_check_type();
  3708.                   break;
  3709.          case 13:
  3710.                   show_repeat_quote();
  3711.                   break;
  3712.          case 14:
  3713.                   show_retry();
  3714.                   break;
  3715.          case 15:
  3716.                   show_packet_length();
  3717.                   break;
  3718.          case 16:
  3719.                   show_padding();
  3720.                   break;
  3721.          case 17:
  3722.                   show_padchar();
  3723.                   break;
  3724.          case 18:
  3725.                   show_start_of_packet();
  3726.                   break;
  3727.          case 19:
  3728.                   show_end_of_line();
  3729.                   break;
  3730.          case 20:
  3731.                   show_quote();
  3732.                   break;
  3733.          case 21:
  3734.                   show_eight_bit_quote();
  3735.                   break;
  3736.          case 22:
  3737.                   show_incomplete();
  3738.                   break;
  3739.          case 23:
  3740.                   show_delay();
  3741.                   break;
  3742.          case 24:
  3743.                   show_warning();
  3744.       }
  3745. }
  3746.  
  3747. /*
  3748.  * Show various parameters
  3749.  */
  3750.  
  3751. show_all()
  3752. {
  3753.    show_line();
  3754.    show_baud();
  3755.    show_config();
  3756.    show_escape();
  3757.    show_filetype();
  3758.    show_warning();
  3759.    show_log();
  3760.    show_dup();
  3761.    show_debug();
  3762.    show_incomplete();
  3763.    show_hsh();
  3764.    show_retry();
  3765.    show_timeout();
  3766.    show_delay();
  3767.    show_start_of_packet();
  3768.    show_end_of_line();
  3769.    show_quote();
  3770.    show_eight_bit_quote();
  3771.    show_repeat_quote();
  3772.    show_packet_length();
  3773.    show_padding();
  3774.    show_padchar();
  3775.    show_block_check_type();
  3776. }
  3777.  
  3778. show_debug()
  3779. {
  3780.    puts("Debug:\t\t\t\t");
  3781.    if (debug != 2)
  3782.       show_onoff(debug);
  3783.    else
  3784.       printf("File: %s\n",dbgfname);
  3785. }
  3786.  
  3787. show_dup()
  3788. {
  3789.    puts("Duplex:\t\t\t\t");
  3790.    if (fulldup)
  3791.       puts("Full\n");
  3792.    else
  3793.       puts("Half\n");
  3794. }
  3795.  
  3796. show_escape()
  3797. {
  3798.    printf("Escape character:\t\t%c\n", escchr);
  3799. }
  3800.  
  3801. show_line()
  3802. {
  3803.    puts("Line:\t\t\t\t");
  3804.    if (remote)
  3805.       puts("Remote\n");
  3806.    else
  3807.       printf("%x\n", ttyfd);
  3808. }
  3809.  
  3810. show_baud()
  3811. {
  3812.    printf("Baudrate:\t\t\t%d baud\n", speed);
  3813. }
  3814.  
  3815. show_config()
  3816. {
  3817.    static int *conftab[] =
  3818.    {
  3819.       "7 bits, even parity, 2 stop bits",
  3820.       "7 bits, odd parity, 2 stop bits",
  3821.       "7 bits, even parity, 1 stop bit",
  3822.       "7 bits, odd parity, 1 stop bit",
  3823.       "8 bits, no parity, 2 stop bits",
  3824.       "8 bits, no parity, 1 stop bit",
  3825.       "8 bits, even parity, 1 stop bit",
  3826.       "8 bits, odd parity, 1 stop bit"
  3827.    };
  3828.  
  3829.    printf("Configuration:\t\t\t%s\n", conftab[config]);
  3830. }
  3831.  
  3832. show_timeout()
  3833. {
  3834.    printf("Timeout:\t\t\t%d seconds\n", mytime);
  3835. }
  3836.  
  3837. show_filetype()
  3838. {
  3839.    puts("Filetype:\t\t\t", image);
  3840.    if (image)
  3841.       puts("Binary\n");
  3842.    else
  3843.       puts("Ascii\n");
  3844. }
  3845.  
  3846. show_log()
  3847. {
  3848.    puts("Log file:\t\t\t");
  3849.    if (logfile[0])
  3850.       printf("%s\n", logfile);
  3851.    else
  3852.       puts("None\n");
  3853. }
  3854.  
  3855. show_hsh()
  3856. {
  3857.    printf("Handshake start:\t\t%d (dec)\n", dstart);
  3858.    printf("Handshake stop: \t\t%d (dec)\n", dstop);
  3859. }
  3860.  
  3861. show_quote()
  3862. {
  3863.    printf("Quote character:\t\t%c\n", myquote);
  3864. }
  3865.  
  3866. show_repeat_quote()
  3867. {
  3868.    puts("Repeat quote character:\t\t");
  3869.    if (myrptquote == 0)
  3870.       puts("None\n");
  3871.    else   
  3872.       printf("%c\n",myrptquote);
  3873. }
  3874.  
  3875. show_eight_bit_quote()
  3876. {
  3877.    puts("Eight-bit quote character:\t");
  3878.    if (myeightquote == 0)
  3879.       puts("None\n");
  3880.    else
  3881.       printf("%c\n",myeightquote);
  3882. }
  3883.  
  3884. show_start_of_packet()
  3885. {
  3886.    printf("Start of packet:\t\t%02.2x (hex)\n", mypackstart);
  3887. }
  3888.  
  3889. show_retry()
  3890. {
  3891.    printf("Maximum retry's:\t\t%d (dec)\n", maxtry);
  3892. }
  3893.  
  3894. show_packet_length()
  3895. {
  3896.    printf("Packet length:\t\t\t%d (dec)\n", maxpacksiz);
  3897. }
  3898.  
  3899. show_end_of_line()
  3900. {
  3901.    printf("End of line character:\t\t%02.2x (hex)\n", myeol);
  3902. }
  3903.  
  3904. show_padding()
  3905. {
  3906.    printf("Padding count:\t\t\t%d (dec)\n", mypad);
  3907. }
  3908.  
  3909. show_padchar()
  3910. {
  3911.    printf("Padding character:\t\t%02.2x (hex)\n", mypchar);
  3912. }
  3913.  
  3914. show_block_check_type()
  3915. {
  3916.    puts("Blockcheck type:\t\t");
  3917.    switch (myblock_check_type)
  3918.    {
  3919.       case 1:
  3920.                puts("One character checksum\n");
  3921.                break;
  3922.       case 2:
  3923.                puts("Two character checksum\n");
  3924.                break;
  3925.       case 3:
  3926.                puts("Three character CRC-CCITT\n");
  3927.                break;
  3928.    }
  3929. }
  3930.    
  3931. show_incomplete()
  3932. {
  3933.    puts("Incomplete file disposition:\t");
  3934.    if (save_file)
  3935.       puts("Keep\n");
  3936.    else
  3937.       puts("Discard\n");
  3938. }
  3939.  
  3940. show_delay()
  3941. {
  3942.    printf("Delay before sending:\t\t%d seconds\n",send_delay);
  3943. }
  3944.  
  3945. show_warning()
  3946. {
  3947.    puts("File conflict warning:\t\t");
  3948.    show_onoff(warning);
  3949. }
  3950.  
  3951. show_onoff(flag)
  3952. int flag;
  3953. {
  3954.    if (flag)
  3955.       puts("On\n");
  3956.    else
  3957.       puts("Off\n");
  3958. }
  3959. <<< flutil.c >>>
  3960. #include "FLK.H"
  3961.  
  3962. /*
  3963.  * split command line into seperate strings
  3964.  */
  3965.  
  3966. split(cmd_str, cmds)
  3967. char  *cmd_str[],
  3968.       *cmds[];
  3969. {
  3970.    char  *malloc();
  3971.    char  *p,
  3972.          *q,
  3973.          result[128];
  3974.  
  3975.    numprm = 0;                         /* no parameters yet */
  3976.    p = cmd_str;                        /* setup pointer to input string */
  3977.    while (*p)                          /* do till end of string */
  3978.    {
  3979.       if (numprm == MAXPRM)            /* no more space */
  3980.       {
  3981.          prterr("Too many command parameters");
  3982.          return(FALSE);
  3983.       }
  3984.       while (isspace(*p))              /* strip leading white space */
  3985.          p++;
  3986.       sscanf(p, "%s", result);         /* get part of input string */
  3987.       if ((q = malloc(strlen(result) + 1)) == NULL) /* allocate string space */
  3988.       {
  3989.          prterr("Fatal error allocating memory");
  3990.          kerm_exit();
  3991.       }
  3992.       strcpy(q, result);               /* copy part to allocated memory */
  3993.       cmds[numprm++] = q;              /* save pointer to string */
  3994.       while ((!isspace(*p)) && *p)     /* skip to end of this string */
  3995.          p++;
  3996.    }
  3997.    return (TRUE);
  3998. }
  3999.  
  4000. /*
  4001.  * parse command components
  4002.  */
  4003.  
  4004. parse(command_string, table)
  4005. char *command_string;
  4006. TABLE table[];
  4007. {
  4008.    char  i = 0,
  4009.          j;
  4010.    int   mstat,
  4011.          cmd_num = 0,
  4012.          tv = 0,
  4013.          unique = FALSE;
  4014.  
  4015.    make_lower(command_string);         /* convert to lower case */
  4016.    while (*table[i].string)            /* do until end of command table */
  4017.    {
  4018.       mstat = match(table[i].string, command_string); /* do compare */
  4019.       if (mstat == -1)
  4020.          return (table[i].funcadr);    /* exact match found */
  4021.       if (mstat != 0)                  /* some characters did match */
  4022.       {
  4023.          if (mstat > tv)               /* longer than so far ? */
  4024.          {
  4025.             tv = mstat;                /* save longest length */
  4026.             cmd_num = i;               /* remember which command */
  4027.             unique = TRUE;             /* it's unique so far */
  4028.          }
  4029.          j = i;
  4030.          while (*table[++j].string)    /* start new search from next entry */
  4031.          {
  4032.             mstat = match(table[j].string, command_string); /* other match ? */
  4033.             if (mstat == -1)
  4034.                return (table[j].funcadr); /* exact match */
  4035.             if (mstat != 0)            /* some characters did match */
  4036.             {
  4037.                if (mstat > tv)         /* longer than so far ? */
  4038.                {
  4039.                   tv = mstat;          /* save greatest length */
  4040.                   cmd_num = i;         /* remember which command */
  4041.                   unique = TRUE;       /* it's unique so far */
  4042.                }
  4043.                if (mstat == tv)        /* another one of the same length ? */
  4044.                   unique = FALSE;      /* yes, it's not unique anymore */
  4045.             }
  4046.          }
  4047.          if (!unique)                  /* if it was'nt unique it's ambiguous */
  4048.             return (NULL);
  4049.          else
  4050.             return (table[cmd_num].funcadr); /* else it's a valid command */
  4051.       }
  4052.       i++;                             /* try next entry */
  4053.    }
  4054.    if (cmd_num == 0)
  4055.       return (ERROR);                  /* no such command */
  4056.    else return (table[cmd_num].funcadr); /* return command number */
  4057. }
  4058.  
  4059. match(s, t)
  4060. char *s, *t;
  4061. {
  4062.    int   len = 0,
  4063.          inputlen;
  4064.  
  4065.    inputlen = strlen(t);               /* length of input command */
  4066.    while (*s)                          /* do until end of string */
  4067.    {
  4068.       if (*s++ != *t++)                /* if no match */
  4069.       {
  4070.          if (inputlen == 0)            /* total command checked */
  4071.             return (len);              /* return matched length */
  4072.          else
  4073.             return (0);                /* no match for this command */
  4074.       }
  4075.       len++;                           /* one more character done */
  4076.       --inputlen;                      /* count down input string length */
  4077.    }
  4078.    return (-1);                        /* full match found */
  4079. }
  4080.  
  4081. /*
  4082.  *  m a k e _ u p p e r
  4083.  *
  4084.  *  Convert string to upper case
  4085.  */
  4086.  
  4087. make_upper(p)
  4088. char  *p;
  4089. {
  4090.    while (*p)
  4091.       *p++ = toupper(*p);
  4092. }
  4093.  
  4094. /*
  4095.  *  m a k e _ l o w e r
  4096.  *
  4097.  *  Convert string to lower case
  4098.  */
  4099.  
  4100. make_lower(p)
  4101. char *p;
  4102. {
  4103.    while (*p)
  4104.       *p++ = tolower(*p);
  4105. }
  4106.  
  4107.  
  4108. prterr(fmt, a1, a2, a3, a4, a5)
  4109. char *fmt;
  4110. {
  4111.    printf(fmt,a1,a2,a3,a4,a5);
  4112.    printf("\n");
  4113.    beep();
  4114. }
  4115.  
  4116. /*
  4117.  *  e r r o r
  4118.  *
  4119.  *  Print error message.
  4120.  *
  4121.  *  send an error packet with the message.
  4122.  */
  4123.  
  4124. error(number,fmt, a1, a2, a3, a4, a5)
  4125. int number;
  4126. char  *fmt;
  4127. {
  4128.    char  msg1[80], msg2[80];
  4129.    char  len;
  4130.    static char *errmsg[] =
  4131.    {
  4132.       "Aborted by user",
  4133.       "Unimplemented server command",
  4134.       "Packet error",
  4135.       "FLEX error writing data, error number is ",
  4136.       "Cannot create file ",
  4137.       "Cannot open file "
  4138.    };
  4139.  
  4140.    strcpy(msg1,prompt);                      /* Start with prompt */
  4141.    strcat(msg1,": ");
  4142.    strcat(msg1,errmsg[number]);              /* Append error string */
  4143.    if (number > 2)
  4144.    {
  4145.       sprintf(msg2,fmt,a1,a2,a3,a4,a5);      /* Make it a string */
  4146.       strcat(msg1,msg2);                     /* Form one string */
  4147.    }
  4148.    len = strlen(msg1);
  4149.    spack('E',n,len,msg1,block_check_type);   /* Send the error packet */
  4150. #ifdef SCREEN
  4151.    disp(0,18,CLREOL);
  4152.    disp(0,18,"Error:");
  4153.    disp(20,18,msg1);
  4154. #else
  4155.    printf("Error: %s\n",msg1);
  4156. #endif
  4157.    beep();
  4158. }
  4159.  
  4160. /*
  4161.  *  p r e r r p k t
  4162.  *
  4163.  *  Print contents of error packet received from remote host.
  4164.  */
  4165. prerrpkt(msg)
  4166. char  *msg;
  4167. {
  4168.    disp(0,18,"Kermit aborting with following error from remote host:");
  4169.    disp(0,19,msg);
  4170.    beep();
  4171. }
  4172.  
  4173. /*
  4174.  * send ASCII file to remote without protocol.
  4175.  * handshake is used.
  4176.  */
  4177.  
  4178. transmit()
  4179. {
  4180.    FILE *xmitfp;
  4181.    char xmitfilename[20];
  4182.    int  c;
  4183.  
  4184.    if (numprm <= 1)                       /* check for parameters */
  4185.       prterr("Filespec required");
  4186.    else
  4187.    {
  4188.       strcpy(xmitfilename, params[1]);
  4189.       cvt_case(xmitfilename);             /* take care of filename mapping */
  4190.       if ((xmitfp = fopen(xmitfilename, "r")) == ERROR)
  4191.          prterr("Error opening %s", xmitfilename);
  4192.       else
  4193.       {
  4194.          while ((c = getc(xmitfp)) != EOF)/* get character from file */
  4195.          {
  4196.             if (debug)
  4197.             {
  4198.                outchar(c, consfd);        /* send to console as well */
  4199.                if (c == LF)
  4200.                   outchar(CR, consfd);
  4201.             }
  4202.             if (instat(ttyfd))               /* Check if character received */
  4203.                if (inchar(ttyfd) == dstop)   /* Stop character ? */
  4204.                   do                         /* Yes */
  4205.                      while (!instat(ttyfd))  /* Wait for next character */
  4206.                         if (aborted)         /* Check user abort */
  4207.                         {
  4208.                            puts("\n");
  4209.                            return;           /* User abort */
  4210.                         }
  4211.                   while (inchar(ttyfd) != dstart); /* Wait for start char */
  4212.             if (aborted)                     /* Check user abort */
  4213.             {
  4214.                puts("\n");
  4215.                return;                       /* User abort */
  4216.             }
  4217.             if (c == LF)                     /* Convert LF to CR */
  4218.                c = CR;
  4219.             outchar(c, ttyfd);               /* Send to output port */
  4220.          }
  4221.          fclose(xmitfp);
  4222.       }
  4223.    }
  4224. }
  4225.  
  4226. /*
  4227.  * Read KERMIT commands from file
  4228.  */
  4229.  
  4230. take(startup,echo)
  4231. char startup, echo;
  4232. {
  4233.    FILE *tfp;
  4234.    char  data[257],                       /* Command input */
  4235.          fname[50];
  4236.  
  4237.    if (startup)
  4238.       strcpy(fname, INITFILE);            /* Use default name at startup */
  4239.    else
  4240.    {
  4241.       if (numprm <= 1)                    /* Filename must be given */
  4242.       {
  4243.          prterr("Filespec required");
  4244.          return;
  4245.       }
  4246.       else
  4247.          strcpy(fname, params[1]);
  4248.    }
  4249.    cvt_case(fname);                       /* Take care of filename mapping */
  4250.    if ((tfp = fopen(fname,"r")) != ERROR) /* Look for command file */
  4251.       {                                   /* Found file, read commands */
  4252.          while (fgets(data,256,tfp))
  4253.          {
  4254.             if (echo)
  4255.             {
  4256.                puts(prompt);              /* Echo prompt */
  4257.                puts(data);                /* Echo command */
  4258.             }
  4259.             if (data[0] != '\n')          /* Not a blank line */
  4260.                kerm_command(data);        /* Do command */
  4261.          }
  4262.          fclose(tfp);
  4263.       }
  4264.    else
  4265.       if (!startup)
  4266.          prterr("Error opening %s as input",fname);
  4267. }
  4268.  
  4269. /*
  4270.  * call FLEX to perform external command
  4271.  */
  4272.  
  4273. do_flex()
  4274. {
  4275.    char  *cp1, *cp2;
  4276.    int   i;
  4277.  
  4278.    if (numprm <= 1)                    /* no command given */
  4279.    {
  4280.       printf("Enter FLEX command: ");
  4281.       call(inbuff);                    /* use FLEX */
  4282.    }
  4283.    else
  4284.    {
  4285.       cp1 = *flinepointer = flinebuffer;
  4286.       for(i = 1; i < numprm; i++)
  4287.       {                                /* copy command parameters to
  4288.                                           FLEX command buffer */
  4289.          cp2 = params[i];
  4290.          while (*cp2)                  /* copy string */
  4291.             *cp1++ = *cp2++;
  4292.          *cp1++ = ' ';                 /* parameter seperator */
  4293.       }
  4294.       *--cp1 = '\r';                   /* required by flex  */
  4295.    }
  4296.    call(docmd);                        /* call FLEX */
  4297.    puts("\n");
  4298. }
  4299.  
  4300. /*
  4301.  * show statistics about connection
  4302.  */
  4303.  
  4304. statistics()
  4305. {
  4306.    static char s1[] = "Characters sent:\t\t%ld\n";
  4307.    static char s2[] = "Data characters sent:\t\t%ld\n";
  4308.    static char s3[] = "NAK's sent:\t\t\t%d\n";
  4309.    static char s4[] = "Packets sent:\t\t\t%d\n";
  4310.    static char s5[] = "Characters received:\t\t%ld\n";
  4311.    static char s6[] = "Data characters received:\t%ld\n";
  4312.    static char s7[] = "NAK's received:\t\t\t%d\n";
  4313.    static char s8[] = "Packets received:\t\t%d\n";
  4314.    
  4315.    printf("Totals for the last transfer:\n\n");
  4316.    printf(s1, chr_sent);
  4317.    printf(s2, datachr_sent);
  4318.    printf(s3, nak_sent);
  4319.    printf(s4, pack_sent);
  4320.    printf(s5, chr_rec);
  4321.    printf(s6, datachr_rec);
  4322.    printf(s7, nak_rec);
  4323.    printf(s8, pack_rec);
  4324. #ifdef CLOCK
  4325.    printf("Effective data rate:\t\t%d baud\n", data_rate);
  4326. #endif
  4327.    printf("\nTotals since KERMIT was started:\n\n");
  4328.    printf(s1, t_chr_sent);
  4329.    printf(s2, t_datachr_sent);
  4330.    printf(s3, t_nak_sent);
  4331.    printf(s4, t_pack_sent);
  4332.    printf(s5, t_chr_rec);
  4333.    printf(s6, t_datachr_rec);
  4334.    printf(s7, t_nak_rec);
  4335.    printf(s8, t_pack_rec);
  4336. #ifdef CLOCK
  4337.    printf("Mean effective data rate:\t%d baud\n", t_data_rate);
  4338. #endif
  4339. }
  4340.  
  4341. #define  POLYIT  0x8408       /* Polynomial for CRC-CCITT */
  4342. #define  POLY16  0xa001       /* Polynomial for CRC-16 (not used here) */
  4343.  
  4344. int   crc_value, crc[256];    /* Global accessible variables */
  4345.  
  4346. init_crc_table()
  4347. {
  4348.    int count, nr;
  4349.    unsigned int accum, crcch;
  4350.  
  4351.    for (count = 0; count < 256; count++)     /* Build CRC lookup table */
  4352.    {
  4353.       accum = 0;
  4354.       crcch = count;
  4355.       for (nr = 0; nr < 8; nr++)
  4356.       {
  4357.          if (((accum & 0xff) ^ crcch) & 1)
  4358.             accum = (accum / 2) ^ POLYIT;
  4359.          else
  4360.             accum = (accum / 2);
  4361.          crcch = (crcch / 2);
  4362.       }
  4363.       crc[count] = accum;                 /* Save calculated value in table */
  4364.    }
  4365. }
  4366.  
  4367. init_crc()
  4368. {
  4369.    crc_value = 0;                            /* Initial value is zero */
  4370. }
  4371.  
  4372. calc_crc(value)
  4373. char value;
  4374. {
  4375.    crc_value = crc[value ^ (crc_value & 0xff)] ^ ((crc_value >> 8) & 0xff);
  4376.    return crc_value;                      /* Return accumulated value so far */
  4377. }
  4378.  
  4379. /*
  4380.  * Convert string case if mapping is off
  4381.  */
  4382.  
  4383. cvt_case(p)
  4384. char *p;
  4385. {
  4386.    if (mapup == 0x60)                  /* refer to flag in FLEX memory */
  4387.       make_upper(p);
  4388. }
  4389.  
  4390. beep()
  4391. {
  4392.    if (!remote)
  4393.       _putchr(BELL);
  4394. }
  4395.  
  4396. disp(x,y,string)
  4397. int x,y;
  4398. char *string;
  4399. {
  4400.    if (!remote)
  4401.    {
  4402.       posit(x,y);
  4403. #ifndef SCREEN
  4404.       puts("\n");
  4405. #endif
  4406.       puts(string);
  4407.    }
  4408. }
  4409.  
  4410. posit(x,y)
  4411. int x,y;
  4412. {
  4413. #ifdef SCREEN
  4414.    if (!remote)
  4415.    {
  4416.       _putchr(ESC);
  4417.       _putchr(POSCUR);
  4418.       _putchr(y + CHROFS);
  4419.       _putchr(x + CHROFS);
  4420.    }
  4421. #endif
  4422. }
  4423.  
  4424. set_frame()
  4425. {
  4426. #ifdef SCREEN
  4427.    if (!remote)
  4428.    {
  4429.       puts(CLRSCR);                 /* Clear screen */
  4430.       puts(CURSOFF);                /* Disable cursor */
  4431.       puts(INVBEG);                 /* Start inverse screen */
  4432.       puts("                            KERMIT version ");
  4433.       puts(VERSION);
  4434.       puts("                         ");
  4435.       puts(INVEND);                 /* End inverse screen */
  4436.       if (sflg || rflg)
  4437.       {
  4438.          disp(0,4,"Transferred:");
  4439.          if (image && sflg)
  4440.             disp(27,4,"Percentage:");
  4441.       }
  4442.       disp(0,6,"Packet received:");
  4443.       disp(0,7,"Packet transmitted:");
  4444.       if (debug >= 1)
  4445.       {
  4446.          disp(0,9,"Data received:");
  4447.          disp(0,11,"Data transmitted:");
  4448.          disp(0,13,"Receive state:");
  4449.          disp(0,14,"Send state:");
  4450.          disp(27,6,"Type:");
  4451.          disp(27,7,"Type:");
  4452.          disp(37,6,"Length:");
  4453.          disp(37,7,"Length:");
  4454.          disp(49,6,"Checksum:");
  4455.          disp(49,7,"Checksum:");
  4456.       }
  4457.    }
  4458. #endif
  4459. }
  4460.  
  4461. disp_state(x,y,state)
  4462. int x,y;
  4463. char state;
  4464. {
  4465.    static char sa[] = "Abort       ";
  4466.    static char sb[] = "Break       ";
  4467.    static char sc[] = "Complete    ";
  4468.    static char sd[] = "Data        ";
  4469.    static char sf[] = "Filename    ";
  4470.    static char sr[] = "Receive init";
  4471.    static char ss[] = "Send init   ";
  4472.    static char st[] = "Timeout     ";
  4473.    static char sz[] = "End of file ";
  4474.    static char un[] = "Unknown     ";
  4475.    static char dsc[] =  "%s\n";
  4476.  
  4477.    posit(x,y);
  4478.    switch(state)
  4479.    {
  4480.       case 'A':
  4481.                   prtdbg(dsc,sa);
  4482.                   break;
  4483.       case 'B':
  4484.                   prtdbg(dsc,sb);
  4485.                   break;
  4486.       case 'C':
  4487.                   prtdbg(dsc,sc);
  4488.                   break;
  4489.       case 'D':
  4490.                   prtdbg(dsc,sd);
  4491.                   break;
  4492.       case 'F':
  4493.                   prtdbg(dsc,sf);
  4494.                   break;
  4495.       case 'R':
  4496.                   prtdbg(dsc,sr);
  4497.                   break;
  4498.       case 'S':
  4499.                   prtdbg(dsc,ss);
  4500.                   break;
  4501.       case 'T':
  4502.                   prtdbg(dsc,st);
  4503.                   break;
  4504.       case 'Z':
  4505.                   prtdbg(dsc,sz);
  4506.                   break;
  4507.       default:
  4508.                   prtdbg(dsc,un);
  4509.    }
  4510. }
  4511.  
  4512. prtdbg(fmt, a1, a2, a3, a4, a5, a6)
  4513. char *fmt;
  4514. {
  4515.    if ((debug >= 1) && !remote)
  4516.       printf(fmt,a1,a2,a3,a4,a5,a6);
  4517.    if (debug == 2)
  4518.       fprintf(dbgfil,fmt,a1,a2,a3,a4,a5,a6);
  4519. }
  4520.  
  4521. prtdbgf(fmt, a1, a2, a3, a4, a5, a6)
  4522. char *fmt;
  4523. {
  4524.    if (debug == 2)
  4525.       fprintf(dbgfil,fmt,a1,a2,a3,a4,a5,a6);
  4526. }
  4527.  
  4528. new_name(s)
  4529. char *s;
  4530. {
  4531.  
  4532.    s += strlen(s) - 1;                    /* Point to last character */
  4533.    if (isdigit(*s))
  4534.    {                                      /* Already a digit */
  4535.       if (*s == '9')                      /* Test for wrap */
  4536.          *s = '0';
  4537.       else
  4538.          (*s)++;                          /* Form new number */
  4539.    }
  4540.    else                                   /* It was no digit, make one */
  4541.       if (*--s == '.')                    /* Only one char in extension */
  4542.       {
  4543.          s++;
  4544.          *++s = '0';                      /* Append zero */
  4545.          *++s = '\0';                     /* Mark end of string */
  4546.       }
  4547.       else
  4548.         *++s = '0';                       /* More than one chr in extension */
  4549. }
  4550.  
  4551. synerr(threshold)
  4552. int threshold;
  4553. {
  4554.    if ((threshold != 0) && (numprm >= threshold))
  4555.       return FALSE;
  4556.    prterr("Syntax error");
  4557.    return TRUE;
  4558. }
  4559.  
  4560. <<<flk.h >>>
  4561.  
  4562. /*
  4563.  * KERMIT09 - flex version header file
  4564.  */
  4565.  
  4566. #include "stdio.h"
  4567.  
  4568. #define VERSION      "V 3.1"
  4569. #define IDENT        "KERMIT FLEX 6809 version "
  4570. #define DEFPROMPT    "Kermit-09>"
  4571. #define INITFILE     "KERMIT.INI"
  4572. #define HELPFILE     "KERMIT.HLP"
  4573.  
  4574. /*
  4575.  * The VIDIS system normally only has a 6551 type acia available,
  4576.  * and optionally an 6850 acia.
  4577.  * At startup the program looks for an 6850 at address ADDRESS_6850.
  4578.  * If it's there, that one will be used initially. If not,
  4579.  * the 6551 acia at address ADDRESS_6551 will be used.
  4580.  * When issueing an SET LINE command, the program automatically
  4581.  * determines the acia type (6850 or 6551).
  4582.  * The speed setting depends on the acia. In case of a 6551, all
  4583.  * the values of the 6551 can be used. In case of a 6850, 1200 baud
  4584.  * will be selected by a clock divider of 16, and 300 baud by
  4585.  * a divider of 64.
  4586.  */
  4587.  
  4588. #ifdef VIDIS
  4589. #define CLOCK                       /* Real time clock available (MC 146818) */
  4590. #endif
  4591.  
  4592. /*
  4593.  * The clock will be used for determination of the effective data rate
  4594.  */
  4595.  
  4596. #ifdef VIDIS
  4597. #define CLOCKSPEED   1.33333333           /* Clock speed in MHz */
  4598. #else
  4599. #define CLOCKSPEED   1                    /* Clock speed in MHz */
  4600. #endif
  4601. #define DELAYVALUE   (4300 * CLOCKSPEED)  /* Count for 1 second delay */
  4602.  
  4603. /* Symbol Definitions */
  4604.  
  4605. #define SOH          1                    /* Start of header */
  4606. #define BELL         7                    /* ASCII Bell */
  4607. #define BS           8                    /* ASCII Backspace */
  4608. #define TAB          9                    /* ASCII Tab */
  4609. #define LF           10                   /* ASCII Linefeed */
  4610. #define CR           13                   /* ASCII Carriage Return */
  4611. #define ESC          27                   /* ASCII Escape */
  4612. #define SP           32                   /* ASCII space */
  4613. #define DEL          127                  /* Delete (rubout) */
  4614. #define XON          17                   /* Start output */
  4615. #define XOFF         19                   /* Stop output */
  4616. #define ESCCHR       '^'                  /* Default escape char for CONNECT */
  4617. #define TOGDBG       'D' - 64             /* Toggle debug on/off */
  4618. #define ABORTX       'X' - 64             /* Ctrl-X to abort transfer */
  4619. #define ABORTZ       'Z' - 64             /* Ctrl-Z to abort transfer */
  4620.  
  4621. #define TABSIZE      8                    /* Tabstop every eight places */
  4622.  
  4623. #define I_MYPACKSTART      SOH            /* Start of packet character */
  4624. #define I_MAXPACKSIZ       94             /* Maximum packet size */
  4625. #define I_MYPACKSIZE       80             /* Default value if no 'S' packet */
  4626. #define I_MAXTRY           10             /* Times to retry a packet */
  4627. #define I_MYQUOTE          '#'            /* Quote character I will use */
  4628. #define I_MYPAD            0              /* Number of padding char's I need */
  4629. #define I_MYPCHAR          0              /* Padding character I need (NULL) */
  4630. #define I_MYEOL            '\r'           /* End-Of-Line character I need */
  4631. #define I_MYTIME           5              /* My timeout in seconds */
  4632. #define I_MYRPTQUOTE       '~'            /* Repeat quote character */
  4633. #define I_MYEIGHTQUOTE     '&'            /* Eight_bit quote character */
  4634. #define I_BLOCKCHECKTYPE   1              /* Initial checksum type */
  4635. #define I_SEND_DELAY       5              /* Delay time before sending */
  4636.  
  4637. #define MAXPRM       20           /* Max. number of command line parameters */
  4638. #define LOGBUFSIZE   5000                 /* Size of log buffer */
  4639. #define WAITVAL      800 * CLOCKSPEED     /* Wait counter in connect */
  4640.  
  4641. #define TIMEOUT      1                    /* Internal codes */
  4642. #define REMOTE      -1
  4643.  
  4644. #ifdef VIDIS
  4645. #define CONSOLE      0                    /* Dummy for console */
  4646. #define ADDRESS_6850 0xec24               /* Default modem acia address */
  4647. #define ADDRESS_6551 0xec00               /* VIDIS modem acia address */
  4648. #define INIT_6850    0x15                 /* Port init 8 bits 1 stop clk/16 */
  4649. #define RESET_6850   0x03
  4650. #define RESET_6551   0x00
  4651. #define INITCMND_6551 0x0b       /* Init for command register of 6551 acia */
  4652. #define INITCTRL_6551 0x10       /* Init for control register */
  4653. #define IRQVEC_6850  0xe810
  4654. #define IRQVEC_6551  0xe816
  4655. #define NMIVEC       0xe80c
  4656. #else
  4657. #define CONSOLE      0xe004               /* Console acia address */
  4658. #define TTYPORT      0xe000               /* Modem acia address */
  4659. #define INIT_6850    0x15                 /* Port init 8 bits 1 stop clk/16 */
  4660. #define RESET_6850   0x03
  4661. #define IRQVEC_6850  0xdfc8
  4662. #define NMIVEC       0xdfca
  4663. #endif
  4664.  
  4665. #ifdef   SCREEN
  4666. #define  POSCUR      'A'                  /* Cursor positioning character */
  4667. #define  CHROFS      1                    /* Character offset */
  4668. #define  CLRSCR      "\033D\f"            /* Clear screen string */
  4669. #define  INVBEG      "\033U\033K"         /* Start underline */
  4670. #define  INVEND      "\033U\033K"         /* End underline */
  4671. #define  CLREOL      "\025"               /* Clear till end of line */
  4672. #define  CURSOFF     "\033B"              /* Cursor off */
  4673. #define  CURSON      "\033C"              /* Cursor on */
  4674. #else
  4675. #define  CURSON      ""                   /* Dummy's if no screen */
  4676. #define  CURSOFF     ""
  4677. #define  CLREOL      ""
  4678. #endif
  4679.  
  4680. /* Macro Definitions */
  4681.  
  4682. /*
  4683.  * tochar: converts a control character to a printable one by adding a space.
  4684.  *
  4685.  * unchar: undoes tochar.
  4686.  *
  4687.  * ctl:    converts between control characters and printable characters by
  4688.  *         toggling the control bit (ie. ^A becomes A and A becomes ^A).
  4689.  */
  4690. #define tochar(ch)   ((ch) + ' ')
  4691. #define unchar(ch)   ((ch) - ' ')
  4692. #define ctl(ch)      ((ch) ^ 64 )
  4693.  
  4694. #define callind(p1)  (*(char (*)())*((int *)(&p1)))()
  4695. #define call(p1)     (*(char (*)())p1)()
  4696. #define dmem(adr)    ((int *)(adr))
  4697. #define mem(adr)     ((char *)(adr))
  4698.  
  4699. /*
  4700.  * FLEX constants
  4701.  */
  4702. #define mapup        (*mem(0xcc49))   /* place to find filename mapping flag */
  4703. #define inchne(p1)   ((*(int (*)())*((int *)(0xd3e5)))(p1) >> 8) /* input char
  4704.                                           without echo */
  4705. #define workdrive    (*mem(0xcc0c))       /* Work drive number */
  4706. #define system_fcb_drive (*mem(0xc843))   /* Drive KERMIT came from */
  4707. #define flinebuffer  ((char *)0xc080)     /* Line input buffer */
  4708. #define flinepointer ((unsigned *)0xcc14) /* Line buffer pointer */
  4709. #define inbuff       0xcd1b               /* Get input buffer routine */
  4710. #define docmd        0xcd4b               /* Call flex routine */
  4711.  
  4712. /* Global Variables */
  4713.  
  4714. /* Structure used by command parser */
  4715.  
  4716. typedef struct table_point
  4717. {
  4718.    char *string;                          /* Command name */
  4719.    int funcadr;                           /* Function address */
  4720. } TABLE;
  4721.  
  4722. #ifdef CLOCK
  4723. #define RTCADR 0xee20                     /* Address of MC 146818 */
  4724. long int read_clock(),
  4725.          start_time,
  4726.          end_time;
  4727. #endif
  4728.  
  4729. int   send_delay,             /* Start sending delay time */
  4730.       ttyfd,                  /* I/O port address */
  4731.       consfd,                 /* Console port address */
  4732.       wtcnt,                  /* stop time counter */
  4733.       speed,                  /* line speed */
  4734.       tabsleft,               /* Tab counter */
  4735.       file_size,              /* Size of current file in blocks */
  4736.       size,                   /* Size of present data */
  4737.       nak_sent,               /* nak's sent */
  4738.       pack_sent,              /* packets sent */
  4739.       nak_rec,                /* nak's received */
  4740.       pack_rec,               /* packets received */
  4741.       data_rate,              /* effective data rate */
  4742.       t_nak_sent,             /* total naks sent */
  4743.       t_pack_sent,            /* total packets sent */
  4744.       t_nak_rec,              /* total nak's received */
  4745.       t_pack_rec,             /* total packets received */
  4746.       t_data_rate;            /* total effective data rate */
  4747.  
  4748. long int chr_sent,            /* characters sent */
  4749.          datachr_sent,        /* data characters sent */
  4750.          chr_rec,             /* characters received */
  4751.          datachr_rec,         /* data characters received */
  4752.          t_chr_sent,          /* total characters sent */
  4753.          t_datachr_sent,      /* total data characters sent */
  4754.          t_chr_rec,           /* total characters received */
  4755.          t_datachr_rec,       /* total data characters received */
  4756.          timecount,           /* Timeout counter */
  4757.          transmit_chr_count;  /* Character count for data size calculation */
  4758.  
  4759. char  state,                  /* Present state of the automaton */
  4760.       padchar,                /* Padding character to send */
  4761.       eol,                    /* End-Of-Line character to send */
  4762.       escchr,                 /* Connect command escape character */
  4763.       quote,                  /* Quote character in incoming data */
  4764.       block_check_type,       /* Checksum type */
  4765.       eight_quote,            /* eight_bit quote character */
  4766.       repeat_quote,           /* repeat quote character */
  4767.       timint,                 /* Timeout for foreign host on sends */
  4768.       spsiz,                  /* Maximum send packet size */
  4769.       pad,                    /* How much padding to send */
  4770.       n,                      /* Packet number */
  4771.       numtry,                 /* Times this packet retried */
  4772.       oldtry,                 /* Times previous packet retried */
  4773.       image,                  /* TRUE means 8-bit mode */
  4774.       warning,                /* File conflict warning flag */
  4775.       debug,                  /* indicates debugging output done (0=none) */
  4776.       fulldup,                /* TRUE means full duples in connect */
  4777.       logfileopen,            /* TRUE means log file open */
  4778.       logging,                /* TRUE means loggin active */
  4779.       dstop,                  /* stop character for remote */
  4780.       dstart,                 /* start character for remote */
  4781.       stopped,                /* TRUE if dstop sent */
  4782.       filecount,              /* Number of files left to send */
  4783.       filenum,                /* current filenumber */
  4784.       config,                 /* initialize value */
  4785.       numprm,                 /* number of command parameters */
  4786.       aborted,                /* TRUE means we're aborted */
  4787.       save_file,              /* keep/discard file on abort */
  4788.       sflg,                   /* send active flag */
  4789.       rflg,                   /* receive active flag */
  4790.       cflg,                   /* connect active flag */
  4791.       *filnam,                /* Current file name */
  4792.       use_6850,               /* 6850 acia in use */
  4793.       remote,                 /* Remote line in use */
  4794.       *params[MAXPRM],        /* parameter list */
  4795.       prompt[21],             /* prompt string */
  4796.       logfile[21],            /* filename for logfile */
  4797.       recpkt[I_MAXPACKSIZ+5], /* Receive packet buffer */
  4798.       packet[I_MAXPACKSIZ+5], /* Packet buffer */
  4799.       logbuf[LOGBUFSIZE],     /* buffer for log */
  4800.       *plog,                  /* pointer for logbuffer */
  4801.       dbgfname[50],           /* Filename for debug file */
  4802.       load_drive,             /* Drive KERMIT came from */
  4803.       mypackstart,            /* Start of packet character */
  4804.       maxpacksiz,             /* Maximum packet size */
  4805.       maxtry,                 /* Times to retry a packet */
  4806.       myquote,                /* Quote character I will use */
  4807.       mypad,                  /* Number of padding characters I will need */
  4808.       mypchar,                /* Padding character I need (NULL) */
  4809.       myeol,                  /* End-Of-Line character I need */
  4810.       mytime,                 /* Seconds after which I should be timed out */
  4811.       myrptquote,             /* Repeat quote character */
  4812.       myeightquote,           /* Eight_bit quote character */
  4813.       myblock_check_type;     /* My checksum type */
  4814.  
  4815. FILE  *fp,                    /* File pointer for current disk file */
  4816.       *lfp,                   /* File pointer for log file */
  4817.       *dbgfil;                /* File pointer for debug file output */
  4818.  
  4819. #ifdef INTERRUPT
  4820. #define INBUFSIZE    500
  4821. #define FULL_LIMIT   (INBUFSIZE - 250)
  4822. #define EMPTY_LIMIT  10
  4823.  
  4824. int   irqhdr(),
  4825.       irqprp(),
  4826.       nmihdr(),
  4827.       save_vector,
  4828.       save_nmi;
  4829.  
  4830. char  input_buffer[INBUFSIZE],
  4831.       *inptr,
  4832.       *outptr;
  4833.  
  4834. #endif
  4835.