home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / STERM.ZIP / STERMP.C < prev    next >
Text File  |  1991-01-14  |  15KB  |  675 lines

  1.  
  2. /* Process an STERM command file */
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #define  INCL_SUB
  7. #define  INCL_DOS
  8. #include <os2kernl.h>
  9.  
  10. #define STERMP
  11. #include "sterm.h"
  12.  
  13.  
  14. /* working copy of port definition */
  15. static PortDef *wp;
  16.  
  17. /* ptr to command string */
  18. static char *verb;
  19.  
  20. /* check for phone number */
  21. static int phoncheck( void )
  22.   {
  23.   /* value must be numeric, '-', ',' */
  24.   char *fp;
  25.  
  26.   fp = strtok( NULL, " ;\n" );
  27.  
  28.   /* just uppercase and copy string */
  29.   if ( strlen ( fp ) > PHONEL-2 )
  30.      {
  31.      emsg( "Phone String too Long." );
  32.      return(9);
  33.      }
  34.  
  35.   /* set phone string with CR  */
  36.   strcpy( wp->phone, fp );
  37.   strupr( wp->phone );
  38.   strcat( wp->phone, "/r" );
  39.   return (0);
  40.   } /* end phoncheck */
  41.  
  42.  
  43. /* ECHO: set halfplex TRUE or FALSE */
  44. static int pecho( void )
  45.   {
  46.   char *fp;
  47.   fp = strtok( NULL, " ;\n" );
  48.   fp = strupr( fp );
  49.   if ( strcmp( fp, "ON" ) == 0 )
  50.      wp->halfplex = TRUE;
  51.   else
  52.   if ( strcmp( fp, "OFF" ) == 0 )
  53.      wp->halfplex = FALSE;
  54.   else
  55.      {
  56.      emsg( "ON or OFF required" );
  57.      return ( 2 );
  58.      }
  59.   return ( 0 );
  60.   } /* end pecho */
  61.  
  62. /* check for port number */
  63. static int portcheck( void )
  64.   {
  65.   /* value must be 1-3 */
  66.   long dv;
  67.   char *fp, *ep;
  68.   int  dval;
  69.  
  70.   fp = strtok( NULL, " ;\n" );
  71.   dv  = strtoul( fp, &ep, 0 );
  72.   if ( *ep != '\0' )
  73.       {
  74.       emsg( "Non-numeric Port" );
  75.       return( 4 );
  76.       }
  77.   dval = (int) dv;
  78.   if ( ( dval < 1 ) || ( dval > 3 ) )
  79.       {
  80.       emsg( "Invalid Port" );
  81.       return( 6 );
  82.       }
  83.   /* set port string with ascii num */
  84.   wp->cport[3] = (char) (dval + '0');
  85.   return (0);
  86.   } /* end portcheck */
  87.  
  88. /* verify stopbits and store */
  89. static int stopcheck( void )
  90.   {
  91.   char * stbl[] =
  92.     { "1", "1.5", "2", "\0" };
  93.   int s;
  94.   char *fp;
  95.  
  96.   fp = strtok( NULL, " ;\n" );
  97.   fp = strupr( fp );
  98.  
  99.   for ( s = 0; *stbl[s]; s++ )
  100.      if ( strcmp( stbl[s], fp ) == 0 )
  101.         {
  102.         wp->ltype.StopBits = (char) s;
  103.         return(0);
  104.         }
  105.  
  106.   emsg( "Unknown Stop Value" );
  107.   return(8);
  108.   }
  109.  
  110. /* verify parity and store */
  111. static int parcheck( void )
  112.   {
  113.   char * ptbl[] =
  114.     { "NONE", "ODD", "EVEN", "MARK", "SPACE", "\0" };
  115.   int p;
  116.   char *fp;
  117.  
  118.   fp = strtok( NULL, " ;\n" );
  119.   fp = strupr( fp );
  120.   for ( p = 0; *ptbl[p]; p++ )
  121.      if ( strcmp( ptbl[p], fp ) == 0 )
  122.         {
  123.         wp->ltype.Parity = (char) p;
  124.         return(0);
  125.         }
  126.   emsg( "Unknown Parity" );
  127.   return(7);
  128.   }  /* end parcheck */
  129.  
  130. /*  verify databits and store */
  131. static int datcheck( void )
  132.   {
  133.   /* value must be 5-8 */
  134.   long dv;
  135.   char *fp, *ep;
  136.   int  dval;
  137.  
  138.   fp = strtok( NULL, " ;\n" );
  139.   dv  = strtoul( fp, &ep, 0 );
  140.   if ( *ep != '\0' )
  141.       {
  142.       emsg( "Non-numeric Databits" );
  143.       return( 4 );
  144.       }
  145.   dval = (int) dv;
  146.   if ( ( dval < 5 ) || ( dval > 8 ) )
  147.       {
  148.       emsg( "Non-standard Databits" );
  149.       return( 6 );
  150.       }
  151.   wp->ltype.DataBits = (char) dval;
  152.   return (0);
  153.   } /* end datcheck */
  154.  
  155. /*  verify BaudRate and store */
  156. static int baudcheck( void )
  157.   {
  158.   unsigned int speed_vals[] =
  159.      {   50,   75,  110,  135,  150,  300,  600,  1200,
  160.      1800, 2000, 2400, 3600, 4800, 7200, 9600, 19200,
  161.      28800, 0 };  /* zero for anchor */
  162.   char *fp, *ep;
  163.   long  par;
  164.   int   p;
  165.  
  166.   /* next token should be a speed_val */
  167.   fp = strtok( NULL, " ;\n" );
  168.   par = strtoul( fp, &ep, 0 );
  169.   if ( *ep != '\0' )
  170.       {
  171.       emsg( "Non-numeric Baud" );
  172.       return( 3 );
  173.       }
  174.   for ( p=0; speed_vals[p] ; p++ )
  175.       if ( par == speed_vals[p] )
  176.          break;
  177.   if  ( ! speed_vals[p] )
  178.       {
  179.       emsg( "Non-standard Baud" );
  180.       return( 2 );
  181.       }
  182.  
  183.   wp->lspeed.BaudRate = (unsigned) par;
  184.   return ( 0 );
  185.   } /* end baudcheck */
  186.  
  187. /* static table for identifier - char mapping */
  188. typedef struct
  189.   {
  190.     char *ident;
  191.     char *idchar;
  192.   } identry;
  193.  
  194. #define NULS ""
  195. #define CR "\x0d\0"
  196. #define LF "\x0a\0"
  197. #define SOH "\x01\0"
  198. #define STX "\x02\0"
  199. #define ETX "\x03\0"
  200. #define XON "\x11\0"
  201.  
  202. #define NIDS 6
  203. static identry idtbl[NIDS] =
  204.   { { "CR", CR }, { "ETX", ETX }, { "STX", STX },
  205.     { "LF", LF }, { "XON", XON }, { "ANY", NULS } };
  206.  
  207. /* find quoted string or resolve identifier */
  208. static char *nxtstr( char *vp )
  209.   {
  210.   char *fp;
  211.   int  id;
  212.  
  213.   fp = vp;
  214.   /* get the next string */
  215.   while ( ( *fp != '\n' ) && ( *fp == ' ' ) )
  216.     fp++;
  217.   if ( *fp == '\n' )
  218.      {
  219.       emsg( "No SEND data." );
  220.       return( NULL );
  221.      }
  222.   /* if start of quoted string, get that token */
  223.   if ( ( *fp == '\"' ) || ( *fp == '\'' ) )
  224.      {
  225.      fp = strtok( fp, "\"\'" );
  226.      if ( !fp )
  227.         return ( NULL );
  228.      }
  229.   else
  230.      { /* fp -> identifier representing ctl char */
  231.      fp = strtok( fp, "\n;" );
  232.      if ( !fp )
  233.         return ( NULL );
  234.      fp = strupr( fp );
  235.      for ( id = 0; id < NIDS; id++ )
  236.          if ( strcmp( fp, idtbl[id].ident ) == 0 )
  237.             break;
  238.      if  ( id >= NIDS )
  239.          {
  240.          emsg( "Unknown key Identifier" );
  241.          return( NULL );
  242.          }
  243.      fp = idtbl[id].idchar;
  244.      }
  245.   return ( fp );
  246.   } /* end nxtstr */
  247.  
  248. /* SEND: pass a string to port */
  249. static int psend( void )
  250.   {
  251.   char *fp;
  252.   MsgH portmsg;
  253.   USHORT plen;
  254.   int    clen;
  255.  
  256.   if ( wp->beforex )
  257.      {  /* initialize port once */
  258.      wp->beforex = FALSE;
  259.      if ( setport( wp ) )
  260.         errexit( "Unable to Initialize" );
  261.      CurP = wp;
  262.      }
  263.  
  264.   fp = nxtstr( verb+5 );
  265.   if ( !fp )
  266.      return ( 2 );
  267.  
  268.   if ( ( clen = strlen( fp ) ) > WSLEN-2 )
  269.      return( 3 );
  270.  
  271.  
  272.   /* pump the string to comoW */
  273.   portmsg.mlen = clen;
  274.   if ( clen == 1 )
  275.      {
  276.      portmsg.mtype = immed;
  277.      portmsg.imdat = *fp;
  278.      }
  279.   else
  280.      portmsg.mtype = dhead; /* data header */
  281.  
  282.   DosWrite( comoW, (PVOID) &portmsg, sizeof(MsgH), (PUSHORT) &plen );
  283.   if ( clen > 1 )
  284.      DosWrite( comoW, (PVOID) fp, clen, (PUSHORT) &plen );
  285.   return ( 0 );
  286.   }  /* end psend */
  287.  
  288.  
  289.  
  290. #define NCOLOR 16
  291. typedef struct {
  292.        char *colname;  /* uppercase color name */
  293.        char color;    /* color */
  294.        } vio_color;
  295.  
  296. static vio_color colentry[NCOLOR] =
  297.        {
  298.         {"BLACK",       '\x00'},
  299.         {"BLUE",        '\x01'},
  300.         {"GREEN",       '\x02'},
  301.         {"CYAN",        '\x03'},
  302.         {"RED",         '\x04'},
  303.         {"MAGENTA",     '\x05'},
  304.         {"BROWN",       '\x06'},
  305.         {"WHITE",       '\x07'},
  306.         {"GRAY",        '\x08'},
  307.         {"LITEBLUE",    '\x09'},
  308.         {"LITEGREEN",   '\x0A'},
  309.         {"LITECYAN",    '\x0B'},
  310.         {"LITERED",     '\x0C'},
  311.         {"LITEMAGENTA", '\x0D'},
  312.         {"YELLOW",      '\x0E'},
  313.         {"BRITE",       '\x0F'},
  314.        };
  315.  
  316. /* COLOR: fg ON bg  screen colors */
  317. static int pcolor( void )
  318.   {
  319.   char *fp;
  320.   char tcol[33];
  321.   USHORT    ix;
  322.   UCHAR     bc, fc;
  323.  
  324.   /* 1st token is foreground */
  325.   fp = strtok( NULL, " ;\n" );
  326.   strcpy( tcol, fp );
  327.   strupr( tcol );
  328.  
  329.   for ( ix = 0; ix < NCOLOR; ix++ )
  330.     if  ( strcmp( tcol, colentry[ix].colname ) == 0 )
  331.         break;
  332.   if ( ix >= NCOLOR )
  333.      {
  334.      emsg( "Unknown Color?!?");
  335.      return( NULL );
  336.      }
  337.   fc = colentry[ix].color;
  338.  
  339.   /* 2nd token is background */
  340.   fp = strtok( NULL, " ;\n" );
  341.   strcpy( tcol, fp );
  342.   strupr( tcol );
  343.  
  344.   if ( strcmp( tcol, "ON" ) == 0 )
  345.      {
  346.      fp = strtok( NULL, " ;\n" );
  347.      strcpy( tcol, fp );
  348.      strupr( tcol );
  349.      }
  350.  
  351.   for ( ix = 0; ix < NCOLOR; ix++ )
  352.     if  ( strcmp( tcol, colentry[ix].colname ) == 0 )
  353.         break;
  354.   if ( ix >= NCOLOR )
  355.      {
  356.      emsg( "Unknown Color?!?");
  357.      return( NULL );
  358.      }
  359.   bc = colentry[ix].color;
  360.  
  361.  
  362.   /* now build an attribute byte  */
  363.   fldcolor = ( ( bc << 4 ) | fc );
  364.  
  365.   clrscrn();
  366.  
  367.   return ( 0 );
  368.   }  /* end pcolor */
  369.  
  370.  
  371. /* DELAY: sleep a specified amount */
  372. static int pdelay( void )
  373.   {
  374.   char *fp, *ep;
  375.   long  par;
  376.  
  377.   /* next token should be interval */
  378.   fp = strtok( NULL, " ;\n" );
  379.   par = strtoul( fp, &ep, 0 );
  380.   if ( *ep != '\0' )
  381.       {
  382.       emsg( "Non-numeric Delay" );
  383.       return( 3 );
  384.       }
  385.   /* value in millisecs */
  386.   if ( par < 20 )
  387.      {
  388.      emsg( "Delay too small." ); return ( 4 );
  389.      }
  390.  
  391.   DosSleep( par );  /* do it here */
  392.   return ( 0 );
  393.   }
  394.  
  395. /* AWAIT: wait for a string to arrive */
  396. static  int pwait( void )
  397.   {
  398.   char *fp;
  399.   USHORT rc;  /* return code from WaitSem */
  400.  
  401.   fp = nxtstr( verb+6 );  /* skip AWAIT */
  402.   if  ( !fp )
  403.       return ( 2 );
  404.   strcpy( waitstr, fp );
  405.   waitsem = 0L;
  406.   waitlen = strlen( waitstr );  /* now armed */
  407.   if (!waitlen)
  408.      waitlen = 1;  /* case of ANY */
  409.  
  410.   /* wait 30 sec.?  small window from 'waitlen' being set */
  411.   waitrc = AWAIT_OK;  /* assume fine */
  412.   rc = DosSemSetWait( (HSEM) &waitsem, timelim );
  413.   if ( rc == 0 )
  414.      return( waitrc );
  415.   else
  416.      return( AWAIT_EOJ );
  417.  
  418.   }  /* end pwait */
  419.  
  420.  
  421. /* COMLOG: set/reset port log */
  422. static int logcheck( void )
  423.   {
  424.   char *fp;
  425.   char  tterm[12];
  426.  
  427.   fp = strtok( NULL, " \n;" );
  428.   strcpy( tterm, fp );
  429.   strupr( tterm );
  430.   if ( strcmp( tterm, "ON" ) == 0 )
  431.      ComLog = TRUE;
  432.   else
  433.   if ( strcmp ( tterm, "OFF" ) == 0 )
  434.      ComLog = FALSE;
  435.   else
  436.      emsg( "Invalid ComLog Option" );
  437.   return( 0 );
  438.   } /* end termcheck */
  439.  
  440. /* TIMELIM: set 'await' timeout */
  441. static int ptimelim( void )
  442.   {
  443.   char *fp, *ep;
  444.   LONG  tval;
  445.  
  446.   fp = strtok( NULL, " \n;" );
  447.   tval = strtol( fp, &ep, 10 );
  448.   if ( ( tval < 1000 ) || ( tval > 500000 ) )
  449.      {
  450.      emsg( "Invalid Timelim Value" );
  451.      return( AWAIT_WARN );
  452.      }
  453.   timelim = tval;
  454.   return( 0 );
  455.   } /* end termcheck */
  456.  
  457. /* TERMINAL: set emulation type */
  458. static int termcheck( void )
  459.   {
  460.   char *fp;
  461.   char  tterm[12];
  462.  
  463.   fp = strtok( NULL, " \n;" );
  464.   strcpy( tterm, fp );
  465.   strupr( tterm );
  466.   if ( strcmp( tterm, "TTY" ) == 0 )
  467.      {
  468.      keymode = tty; return ( 0 );
  469.      }
  470.   else
  471.   if ( strcmp ( tterm, "SIMVT" ) == 0 )
  472.      {
  473.      keymode = SIMVT; return ( 0 );
  474.      }
  475.  
  476.   emsg( "Invalid Terminal Emulator" );
  477.   return( 8 );
  478.   } /* end termcheck */
  479.  
  480. /* build 3270 key translate tbl */
  481. static int p3270key( void )
  482.   {
  483.   PUCHAR ntbl, fp;
  484.  
  485.   fp = (PUCHAR) strtok( NULL, " \n;" );
  486.   ntbl = prockey( fp );
  487.   if ( !ntbl )
  488.      errexit( "Key Table Build Error" );
  489.   Sim3270 = (PUCHAR *) ntbl;
  490.   } /* end p3270key */
  491.  
  492. /*  have the host send a file on the VTSIM interface
  493.     'VTSEND fn ft fm' */
  494. static int vtsend( void )
  495.   {
  496.   /* we must be in SIMVT keymode now */
  497.   if ( keymode != SIMVT )
  498.      {
  499.      emsg( "Must be in SIMVT mode" );
  500.      return( 8 );
  501.      }
  502.   /* obtain a blokchar and link it */
  503.   /* obtain a transfil area, plant it in global 'blkp' */
  504.   if ( !blkp )
  505.      {
  506.      blkp = (transfil *) malloc( sizeof(transfil) );
  507.      blkp->buf = (blokchar *) malloc( sizeof(blokchar) );
  508.      blkp->nextb = NULL;
  509.      blkp->bufp = (char *) blkp->buf;
  510.      }
  511.   /* set xstate to VTSEND */
  512.   xstate = VTSEND;
  513.  
  514.   /* send command to host */
  515.  
  516.   /* wait for ACK */
  517.  
  518.   /* if we timed out, or host err, change state to TERM,
  519.         give error msg and exit */
  520.   return( 0 );
  521.   } /* end vtsend */
  522.  
  523. /*  parsing vector table */
  524. typedef struct {
  525.        char *verbn;  /* uppercase cmd name */
  526.        int (*verbf)( void ); /* process function */
  527.        } verb_entry;
  528.  
  529. #define NVERBS 15  /* total cmds */
  530. static verb_entry verb_tbl[NVERBS] =
  531.      { { "PARITY", parcheck },
  532.        { "DATABITS", datcheck },
  533.        { "STOPBITS", stopcheck },
  534.        { "PORT", portcheck },
  535.        { "TERMINAL", termcheck },
  536.        { "TIMELIM", ptimelim },
  537.        { "COMLOG",   logcheck },
  538.        { "PHONE", phoncheck },
  539.        { "DELAY", pdelay },
  540.        { "COLOR", pcolor },
  541.        { "ECHO", pecho },
  542.        { "SEND", psend },
  543.        { "3270KEYS", p3270key },
  544.        { "AWAIT", pwait },
  545.        { "SPEED", baudcheck } };
  546.  
  547. /* search for verb and execute statement
  548.    input is command verb string
  549. */
  550. PREF int verbex( PCHAR instmt )
  551.   {
  552.   char estr[WSLEN];
  553.   int   i, rc;
  554.  
  555.   /* isolate the 1st token == verb */
  556.   verb = strtok( instmt, " ;\n" );
  557.   verb = strupr( verb );
  558.   if ( *verb == '*' )
  559.      return( AWAIT_OK );
  560.  
  561.   for ( i = 0; i < NVERBS; i++ )
  562.       if ( strcmp( verb, verb_tbl[i].verbn ) == 0 )
  563.          { /* call verb function */
  564.          #pragma warn(wpnd => off)
  565.          rc =  (*verb_tbl[i].verbf)( );
  566.          #pragma warn(wpnd => err)
  567.          if ( rc != AWAIT_OK )
  568.             {
  569.             sprintf( estr, "\nVerb %s returned %d", verb, rc );
  570.             emsg( estr );
  571.  
  572.             if ( strcmp( verb, "AWAIT" ) == 0 )
  573.                {
  574.                sprintf( estr, "  was waiting for %s.", waitstr );
  575.                sprintf( estr, "  compbuf: %.132s", compbuf );
  576.                emsg( estr );
  577.                }
  578.             }
  579.          return( rc );
  580.          }
  581.  
  582.      sprintf( estr, "Unknown command verb: %s", verb );
  583.      emsg( estr );
  584.      return( AWAIT_ENDP - 1 );
  585.  
  586.   } /* end verbex */
  587.  
  588.  
  589. /* process definition file
  590.    cmds of the form verb obj0 obj1 ...
  591.    port:  either 1,2,or 3
  592.    stopbits: either 1,1.5, or 2
  593.    databits: 5-8
  594.    parity: even, odd, none, mark, space
  595.    Input:   definition filespec
  596.    Returns: ptr to PortDef
  597. */
  598.  
  599.  
  600. PREF PortDef *defile( PCHAR pfn )
  601.   {
  602.   FILE *dfhand;  /* def file handle */
  603.  
  604.   #define MAXSTMT 140
  605.   char iline[MAXSTMT];
  606.   char filn[MAXSTMT];
  607.   char *fn;
  608.   int  hiret, rc;
  609.  
  610.   hiret = 0;
  611.   /* copy file path to filn, uppercase it
  612.      then if no extension given, add .PRM */
  613.   strcpy( filn, pfn );
  614.   fn = filn;
  615.   strupr( fn );
  616.   if ( strchr( fn, '.' ) == NULL )
  617.      strcat( fn, ".PRM" );
  618.  
  619.   dfhand = fopen( fn, "r" );
  620.   if ( dfhand == NULL )
  621.      errexit( "Definition file not found." );
  622.  
  623. /* TBD
  624.    Read into memory and
  625.    display list of connections in definition
  626.    file, then open the .PRM file which
  627.    represents that connection
  628. */
  629.  
  630.  
  631.   wp = (PortDef *) malloc( sizeof( PortDef ) );
  632.   wp->cport = (PSZ) "COM1"; /* set default port */
  633.   wp->beforex = TRUE; /* no xmit yet */
  634.   wp->halfplex = FALSE;  /* no echo */
  635.  
  636.   /* set default line characteristics */
  637.   wp->lspeed.BaudRate = 2400;
  638.   wp->ltype.DataBits = 7;
  639.   wp->ltype.Parity = 2;  /* even */
  640.   wp->ltype.StopBits = 0;  /* 1 */
  641.  
  642.  
  643.   /* read parm file lines until eof or error */
  644.   verb = fgets( iline, MAXSTMT-1, dfhand );
  645.  
  646.   while ( verb )
  647.      {
  648.      rc = verbex( verb );
  649.      if ( rc > hiret )
  650.         hiret = rc;
  651.  
  652.      if ( hiret >= AWAIT_ENDP )
  653.         break;
  654.      verb = fgets( iline, MAXSTMT-1, dfhand );
  655.      } /* endwhile */
  656.  
  657.   fclose( dfhand );
  658.   if ( hiret > AWAIT_ENDP )
  659.      {
  660.      free( (void *) wp );
  661.      errexit( "Initialization Failed...." );
  662.      return( NULL );
  663.      }
  664.  
  665.   /* we had successful process of parms, but
  666.      if no 'SEND' occurred, the port is useless */
  667.   if ( wp->beforex )
  668.      {  /* initialize port once */
  669.      wp->beforex = FALSE;
  670.      if ( setport( wp ) )
  671.         errexit( "Unable to Initialize" );
  672.      }
  673.   return ( wp );
  674.   }  /* end defile */
  675.