home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / STerm_src.lzh / sterm.c < prev    next >
C/C++ Source or Header  |  1984-12-20  |  18KB  |  671 lines

  1. /*
  2.  * STERM Ver 1.5 - A terminal emulator & minimal file xfer program.
  3.  *
  4.  *      Original source code - Smod9.c by Carl Kreider
  5.  *
  6.  *      Modified by Mark Griffith for the OS9 Forum's Simple
  7.  *      Terminal program for new users
  8.  *
  9.  *      Originally released as STERM Ver. 1.0
  10.  *          Version 1.1 was a maintenance release
  11.  *          Version 1.2 Added B+ protocol file transfers
  12.  *
  13.  *      Summary of additional changes by various hackers since version 1.2
  14.  *
  15.  * 08-13-88 CRK changed signal handling and a bunch of other stuff  (ver 1.3)
  16.  * 08-27-88 MDG added XMODEM file transfers (ver 1.3)
  17.  * 08-28-88 MDG added termcap capability    (ver 1.3)
  18.  * 06-17-89 SrT Modified for use with OSK, fixed filename bug,
  19.  *              standard termcap code incorporated, fixed
  20.  *              filename with xmodem routine, and some other things.
  21.  *              (ver 1.4)
  22.  * 08-22-89 PWL added append/overwrite to capture buffer saves  (ver 1.4)
  23.  * 08-22-89 MDG fixed logic error in bplus.c when changing default
  24.  *              B protocol packet sizes. (ver 1.4)
  25.  * 10-17-89 MDG fixed dropping of ENQ and DLE characters to external terminals
  26.  *              and false B protocol starts. (ver 1.4)
  27.  * -------- MDG Version 1.4 never released - started on 1.5
  28.  * 07-23-90 crk Change to getopt for arg parsing. (ver 1.5)
  29.  *           Maximum timeout error user settable.
  30.  *           DEbug code in bplus.
  31.   *           Failsafe timer on signals.
  32.  *           Clean exit on fatal signal (helps debug).
  33.  *           Move termcap stuff to io.c
  34.  * 01-27-91 MDG Fixed stupid mistake of mine (not telling where *8^)
  35.  * 02-02-91 MDG Added usage() for OSK Help utility and some cosmetic stuff
  36.  * 02-08-91 MDG Fixed a bug in Sterm for 3 years....not all characters rcvd
  37.  *              from the modem were displayed on the screen because of NULLS
  38.  *              in the stream.  Using tputs() caused all chars UP TO THE NULL
  39.  *              to be written to the screen.  Changed to a direct write()
  40.  *              and viola!
  41.  * 02-08-91 MDG Made some small changes to allow the code to compile in both
  42.  *              the 6809/OS-9 and _OSK environments
  43.  *
  44.  * 12-18-94 EG  Hacked (rather ungracefully) by Ed Gresick to compile under
  45.  *                Ultra-C.  Changing the CPU entry in the makefile will permit
  46.  *                compiling and execution under either the OS9/68K or OS9000/386
  47.  *                environments.
  48.  *                Xmodem was tested with DELPHI downloading files as large as
  49.  *                900K.  B+ protocol was tested with CIS with files in the
  50.  *                mid 20k range.
  51.  *                Important - this version will not compile in the 6809/OS-9
  52.  *                environment.
  53.  *                Changed version number to 2.0 (20).
  54. */
  55.  
  56. #include <stdio.h>
  57. #include <ctype.h>
  58. #include <modes.h>
  59. #include <errno.h>
  60.  
  61. #ifdef _OSK
  62. extern char *optarg;
  63. #endif
  64.  
  65. #include "common.h"
  66. #include "sterm.h"
  67. #include <strings.h>
  68.  
  69. #ifdef _OSK
  70. void   opendsk(), xmodem();
  71. #else
  72. extern opterr, optind;
  73. extern char *optarg;
  74. #endif
  75.  
  76. extern int      max_err;
  77.  
  78. main(argc, argv)
  79. int   argc;
  80. char  **argv;
  81.     {
  82.     int            option;
  83.     register int   c;
  84.     int            lastchar;
  85.     int            cistate = CIDLE;
  86.     int            trap();
  87.     char        *p;
  88.  
  89. /* #ifdef _OSK    */
  90.     to_floppy = FALSE;
  91. /* #else
  92.     to_floppy = TRUE;          /* Initially floppy xfer is TRUE to */
  93.                             /* prevent new users from having */
  94.                             /* transfer problems to disk */
  95. /* #endif    */
  96.  
  97.     while ((option = getopt(argc, argv, "defl:?")) != EOF)
  98.        switch (tolower(option))
  99.           {
  100.           case 'd' :
  101.              bug_on++;         /* may use debug levels later */
  102.              break;
  103.  
  104.           case 'e' :
  105.              max_err = atoi(optarg);
  106.              break;
  107.  
  108.           case 'f' :
  109.              to_floppy = FALSE;
  110.              break;
  111.  
  112.           case 'l' :
  113.              mport = optarg;
  114.              break;
  115.  
  116.           case '?' :
  117.              usage();
  118.              exit(0);
  119.              
  120.           default  :
  121.              help();
  122.           }
  123.  
  124.     intercept(trap);                       /* set up interrupt handler */
  125.     
  126.     termsetup();                /* configure stdin for terminal action */
  127.     
  128.     modsetup(mport);                     /* open and set up modem path */
  129.  
  130.     tputs0(CL);
  131.     help();
  132.     show_baud(cur_baud);
  133.     t_puts("\n\012\012***** STERM is online *****\n\012\012");
  134.     
  135.  
  136. /*
  137.  * Loop forever reading the modem port and perfoming functions as needed
  138.  */
  139.  
  140.     for ( ; ; )
  141.        {
  142.        if (m_rdy())
  143.           {
  144.           switch (cistate)
  145.              {
  146.              case CIDLE :                                /* idle state */
  147.                 sbp = sbuf;
  148.                 while (m_rdy() && ((sbp - sbuf) < 10))
  149.                    switch (c = (m_getc() & 0x7f))
  150.                       {
  151.                       case ENQ :             /* Starting B+ transfer */
  152.                          lastchar = c;       /* save last rcvd char */
  153.                          bp_ENQ();
  154.                          break;
  155.  
  156.                       case DLE :
  157.                          if (lastchar == ENQ)
  158.                             {  /* MUST follow an ENQ */
  159.                             up_priority();   
  160.                             c = bp_DLE(to_floppy);
  161.                             cistate = CIDLE;   /* Return to normal */
  162.                             down_priority();
  163.                             }
  164.                          else
  165.                             {
  166.                             *sbp++ = lastchar; /* nothing is missed */
  167.                             *sbp++ = c;        /* save char */
  168.                             }
  169.                          break;
  170.  
  171.                       default  :
  172.                          *sbp++ = c;          /* save the character */
  173.                          lastchar = c;              /* set lastchar */
  174.                          if (capflg)           /* if a file is open */
  175.                             dskout(c);       /* save received data */
  176.                       }
  177.  
  178.                 write(1, sbuf, (sbp - sbuf)); /* changed from tputs() */
  179.                 break;                     /* to make sure EVERY */
  180.                                         /* char (including nulls */
  181.                                         /* gets written */
  182.              }   /* End of Switch */
  183.           }  /* End of if m_rdy */
  184.  
  185.        if (t_rdy())
  186.           {                              /* if there is something there */
  187.           c = t_getc();                  /* go get it */
  188.  
  189.           if (echoflg && isprint(c))     /* if half-duplex echo to screen */
  190.              t_putc(c);
  191.  
  192.           if (escflg)                    /* if ESC was pressed previously */
  193.              internal(c);                /* check for command */
  194.           else
  195.              if (c == ESC)               /* if it is an ESC key press */
  196.                 escflg = TRUE;           /* set the flag */
  197.              else
  198.                 m_putc(c);
  199.           } /* End of if t_rdy */
  200.        } /* End of Loop Forever */
  201.     } /* End of Main */
  202. /*page*/
  203. /*
  204.  * handler for internal operations
  205.  */
  206.  
  207. static
  208. internal(c)
  209. register int   c;
  210.     {
  211.     escflg = FALSE;
  212.     switch (tolower(c))
  213.        {
  214.        case CAPTURE :
  215.           if (capflg)
  216.              closdsk();
  217.           else
  218.              opendsk();
  219.           break;
  220.  
  221.        case ECHO :
  222.           toggleduplex();
  223.           break;
  224.  
  225.        case SHELL :
  226.           shell();
  227.           break;
  228.  
  229.        case XMODEM :
  230.           xmodem();
  231.           break;
  232.  
  233.        case TRANSMIT :
  234.           xmit();
  235.           break;
  236.  
  237.        case DIR :
  238.           cwd();
  239.           break;
  240.  
  241.        case QUIT :
  242.           if (getans("\n\012QUIT - are you sure? ") == TRUE)
  243.              {
  244.              tputs0(CL);
  245.              cleanup();
  246.              exit(0);
  247.              }
  248.           break;
  249.  
  250.        case HELP :
  251.           help();
  252.           break;
  253.  
  254.        case ESC :
  255.           m_putc(ESC);
  256.           break;
  257.  
  258.        case STATS :
  259.           stats();
  260.           break;
  261.  
  262.        default  :
  263.           m_putc(ESC);                   /* Send ESC char if no commands */
  264.           m_putc(c);                     /* and then send the next char */
  265.        }
  266.     }
  267. /*page*/
  268. static
  269. char  *hlpmsg[] = {
  270.        "\n\012",
  271.        "                              The OS-9 Forum's\012\n",
  272.        "                          Simple Terminal Ver 2.0\n\012\012",
  273.        "         Esc A   - ABORT Transfer     Esc S   - Execute OS9 Shell\n\012",
  274.        "         Esc C   - Capture ON/OFF     Esc T   - Transmit a file\n\012",
  275.        "         Esc D   - Change Directory   Esc Q   - Quit to OS9\n\012",
  276.        "         Esc E   - Echo ON/OFF        Esc X   - XMODEM transfers\n\012",
  277.        "         Esc H   - Show this help     Esc Z   - Show transfer stats\n\012",
  278.        "                           Esc Esc - Send an ESC\n\012\012",
  279.        ""
  280.        };
  281.  
  282. static
  283. help()
  284.     {
  285.     register char  **hscan;
  286.  
  287.     for (hscan = hlpmsg; **hscan; hscan++)
  288.        t_puts(*hscan);
  289.     }
  290.  
  291. usage()
  292. {
  293.     fprintf(stderr, "\nSterm Ver. 2.0\n\n");
  294.     fprintf(stderr, "Usage:  sterm [-df? -l'p' -e'x']\n");
  295.     fprintf(stderr, "    -d       Debug mode on (displays during downloads)\n");
  296.     fprintf(stderr, "    -f    NOT downloading to floppy disks (CoCo only)\n");
  297.     fprintf(stderr, "    -?    Print this usage message\n");
  298.     fprintf(stderr, "    -l p  Link to modem port 'p' (Default /t2)\n");
  299.     fprintf(stderr, "    -e x  Set B+ MAXERRS to 'x' (default 10)\n\n");
  300. }
  301.  
  302. close_file()                /* close any capture file opened before exiting */
  303.      {
  304.      /* if (cp_pn != NULL)      /* if a file is opend */
  305.      if (cp_pn != 0x00)    /* bloop */
  306.          {
  307.          wrt_dbuf();         /* write out the remaining buffer */
  308.          close(cp_pn);       /* and close it */
  309.          }
  310.      }
  311.  
  312. static
  313. closdsk()                   /* close a disk capture file */
  314.     {
  315.     t_puts("\nCapture OFF - ");
  316.  
  317.     /* if (cp_pn == NULL)   */
  318.     if (cp_pn == 0x00)   /* bloop */
  319.        {
  320.        t_puts(" FILE NOT OPENED\n\012");
  321.        capflg = FALSE;
  322.        }
  323.     else
  324.        {
  325.        wrt_dbuf();
  326.        capflg = FALSE;
  327.        if (getans(" Close File? ") == TRUE)
  328.           {
  329.           close(cp_pn);
  330.           cp_pn = 0;
  331.           t_puts("\n\012File CLOSED\n/012");
  332.           }
  333.        else
  334.           t_puts("\n\012File REMAINS OPEN\n\012");
  335.        }
  336.     }
  337.  
  338. /* open capture file - modified for appending [PWL] */
  339.  
  340. #ifdef _OSK
  341. void 
  342. #else
  343. static
  344. #endif
  345. opendsk()
  346. {
  347.     if (cp_pn)
  348.        {
  349.        t_puts("\n\012Capture ON - File already opened\n\012");
  350.        capflg = TRUE;
  351.        return (0);
  352.        }
  353.     else
  354.        if (!getfile())
  355.           {
  356.           t_puts(" No filename given\n\012");
  357.           return (0);
  358.           }
  359.     if (access(filename, 0) == 0)
  360.        {
  361.        t_puts("\n\012FILE EXISTS - [O]verwrite, [A]ppend, or [RETURN]: ");
  362.           {
  363.            int ansok = FALSE;
  364.            char cz;
  365.  
  366.            while(ansok == FALSE)
  367.               {
  368.               sig_off();
  369.               cz = t_getc();
  370.               sig_on();
  371.  
  372.               switch (tolower(cz))
  373.                 {
  374.                 case 0x0d:
  375.                      t_puts("\n\012ABORTED\n\012");
  376.                      return (0);
  377.  
  378.                 case 'o':
  379.                      t_puts("\012\nOverwriting ...\n\012");
  380.                      cp_pn = creat(filename, S_IWRITE);
  381.                      ansok = TRUE;
  382.                      break;
  383.  
  384.                 case 'a':
  385.                      t_puts("\012\nAppending ...\n");
  386.                      if((cp_pn = open(filename, S_IWRITE)) >= 0)
  387.                      lseek(cp_pn, 0L, 2);
  388.                      ansok = TRUE;
  389.                      break;
  390.                 }
  391.              }
  392.           }
  393.        }
  394.   else
  395.       cp_pn = creat(filename, S_IWRITE);
  396.  
  397.     if (cp_pn == -1)
  398.        {
  399.        char errstr[200];
  400.        sprintf(errstr,"Can't open '%s' - error %d %c!\n\012",
  401.                    filename, errno, 7);
  402.        t_puts(errstr);
  403.        cp_pn = 0;
  404.        capflg = FALSE;
  405.        }
  406.     else
  407.        {
  408.        dbp = dbuf;
  409.        t_puts("\n\012Capture ON - File Opened\n\012");
  410.        capflg = TRUE;
  411.        }
  412. }
  413.  
  414. static
  415. xmit()
  416.     {
  417.     int   ch, c, i;
  418.  
  419.     t_puts("\012\nTransmit");
  420.     if (!getfile())
  421.        t_puts("ABORTED - No Filename given\n\012");
  422.     else
  423.        if ((xmf = fopen(filename, "r")) == NULL)
  424.           {
  425.           t_puts("CAN'T OPEN ");
  426.           t_puts(filename);
  427.           t_putc(BELL);
  428.           t_puts("\n\012");
  429.           }
  430.        else
  431.           {
  432.           tputs0(CL); 
  433.           while (fgets(sbuf, MAXLIN, xmf) != NULL)
  434.              {                                     /* Get line to xmit */
  435.              m_puts(sbuf);                          /* and send it out */
  436.              tsleep(10);             /* wait one-sixth of a second */
  437.  
  438.              while (m_rdy())
  439.                 t_putc(_toascii(m_getc()));
  440.                 
  441.              if (t_rdy())
  442.                 {                          /* check for terminal input */
  443.                 ch = t_getc();
  444.                 if (ch == BREAK)             /* ABORT if it's a CNTL-C */
  445.                    break;
  446.                 }
  447.              }
  448.           fclose(xmf);
  449.  
  450.           for (i = 0; i < 5; i++)
  451.              {
  452.              while (m_rdy())
  453.                 {                                /* catch any dribbles */
  454.                 c = m_getc();
  455.                 t_putc(c);
  456.                 }
  457.              tsleep(5);
  458.              }
  459.           if (ch == BREAK)
  460.              t_puts("\012\nABORTED");
  461.  
  462.           t_puts("\n\012Transmit File Closed\n\012");
  463.           }
  464.     }
  465.  
  466. getans(s)        /* Get a single character response from the keyboard */
  467. char  *s;
  468.     {
  469.     char  c;
  470.  
  471.     t_puts(s);
  472.  
  473.     while (!t_rdy())
  474.        tsleep(1);
  475.  
  476.     t_putc(c = tolower(t_getc()));
  477.  
  478.     return (c == 'y');
  479.     }
  480.  
  481. static
  482. getfile()                    /* Get a filename -- CR by itself aborts */
  483.     {
  484.     t_puts("\n\012Filename ? ");
  485.     t_gets(filename);
  486.     return (filename[0] != '\0');
  487.     }
  488.  
  489. /*  use cr to abort  */
  490.  
  491. static
  492. cwd()
  493.     {
  494.     t_puts("\n\012New Directory ? ");
  495.     t_gets(filename);
  496.  
  497.     if (filename[0] == '\0')
  498.        t_puts("ABORTED\n\012");
  499.     else
  500.        if (chdir(filename) == -1)
  501.           t_puts("Can't CHD\n\012");
  502.        else
  503.           t_puts("OK!\n\012");
  504.     }
  505.  
  506. /*
  507. ** Write what is received to disk using buffering and XOFF/XON
  508. ** flow control to the host.
  509. */
  510.  
  511. static
  512. dskout(c)
  513. char  c;
  514.     {
  515.     if ((isspace(c) && (c != 0x0a)) || c == BACKSP || isprint(c))
  516.        {
  517.        *dbp++ = c;                               /* store the char */
  518.        if ((dbp - dbuf) > (CAP_SIZ - 100))       /* If the buffer is full */
  519.           {
  520.           m_putc(XOFF);                          /* Shutup the host */
  521.           wrt_dbuf();                            /* And write out the buffer */
  522.           m_putc(XON);                           /* Return to receiving */
  523.           }
  524.        }
  525.     }
  526.  
  527. static
  528. wrt_dbuf()
  529.     {
  530.     if ((write(cp_pn, dbuf, dbp - dbuf)) < 0)
  531.        {
  532.        t_putc(BELL);                             /* If an error occurs */
  533.        t_puts("\012\nERROR during write!!\n\012");
  534.        }
  535.     dbp = dbuf;
  536.     }
  537.  
  538. static
  539. shell()
  540.     {
  541.     t_puts("OS9: ");
  542.     t_gets(sbuf);
  543.     cook_io();
  544.     system(sbuf);
  545.     raw_io();
  546.     t_puts("\n\012**** STERM back online ****\n\012");
  547.     }
  548.  
  549.  
  550. /* Do an XMODEM file transfer */
  551.  
  552. #ifdef _OSK
  553. void
  554. #else
  555. static
  556. #endif
  557. xmodem()
  558.     {
  559.     int c;
  560.  
  561.     t_puts("\n\012XMODEM: <S>end or <R>eceive? ");
  562.     while (!t_rdy())
  563.        tsleep(1);
  564.  
  565.     t_putc(c = tolower(t_getc()));
  566.  
  567.     if ((c == 's') || (c == 'r'))
  568.        {
  569.        if (!getfile())
  570.           t_puts("\n\012ABORTED");
  571.        else
  572.           {
  573.           show_box(5, 55, 8, 20);
  574.           if (c == 's')
  575.              {
  576.              show_at(13, 9, "Uploading");
  577.              c = XMODEM_Send(filename);
  578.              }
  579.           else
  580.              {
  581.              show_at(10, 9, "Downloading");
  582.              c = XMODEM_Read(filename);
  583.              }
  584.           }
  585.        }
  586.     else
  587.        {
  588.        t_puts("\012\nABORTED");
  589.        return (0);
  590.        }
  591.  
  592.     t_puts("\n\012");
  593.     }
  594.  
  595. /* Toggle echo mode (duplex) */
  596.  
  597. static
  598. toggleduplex()
  599.     {
  600.     if (echoflg)
  601.        {
  602.        t_puts("\012\nFull duplex\012\n");
  603.        echoflg = FALSE;
  604.        }
  605.     else
  606.        {
  607.        t_puts("\012\nHalf duplex\012\n");
  608.        echoflg = TRUE;
  609.        }
  610.     }
  611.  
  612.  
  613. /*
  614. ** Function to increase STERM's priority while running and insure no
  615. ** errors are generated do to background processes. (used only with OS9/6809)
  616. */
  617.  
  618. static
  619. up_priority()
  620.     {
  621. #ifndef _OSK
  622.     setpr(getpid(), 132);        /* bump process priority up */
  623. #endif
  624.     }
  625.  
  626. static
  627. down_priority()
  628.     {
  629. #ifndef _OSK
  630.     setpr(getpid(), 128);        /* bring process priority back down */
  631. #endif
  632.     }
  633.  
  634.  
  635. /*
  636. ** Routine to print the statistics on the last file transfer.
  637. */
  638.  
  639. static
  640. stats()
  641.     {
  642.     int   realbaud;
  643.     long  totime;
  644.  
  645.     totime = endtime - startime;
  646.  
  647. /* Prevent division by Zero  ++SrT */
  648.  
  649.     if (!totime)
  650.          totime = 1L;
  651.          
  652.     realbaud = get_baud(cur_baud);
  653.     t_puts("\n\012Last file transfer statistics\n\012");
  654.     sprintf(tmp, "    Transfer Time: %-6ld seconds\n\012", totime);
  655.     t_puts(tmp);
  656.     sprintf(tmp, " Bytes transfered: %-6ld\n\012", totalbytes);
  657.     t_puts(tmp);
  658.     sprintf(tmp, "        Baud rate: %-4d\n\012", realbaud);
  659.     t_puts(tmp);
  660.     sprintf(tmp, "     Total Errors: %d\n\012", errors);
  661.     t_puts(tmp);
  662.     sprintf(tmp, "         Timeouts: %d\n\012", timeouts);
  663.     t_puts(tmp);
  664.     sprintf(tmp, "       Actual bps: %-4.0f\n\012",
  665.            (double)((totalbytes / totime))*8);
  666.     t_puts(tmp);
  667.     sprintf(tmp, "Efficiency Rating: %2.1f%%\n\012",
  668.        (((double) totalbytes * 800) / totime) / realbaud);
  669.     t_puts(tmp);
  670.     }
  671.