home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / RXCOMM.ZIP / RXCOMM.C < prev    next >
C/C++ Source or Header  |  1990-12-23  |  34KB  |  965 lines

  1. /* 09-27-90                                                   Mark Smith */
  2. /*************************************************************************/
  3. /*                           RxComm.c                                    */  
  4. /* Purpose: Handle COMM port through REXX/SAA.  This package is loaded   */
  5. /*          as a REXX extension, and therefore the following lines MUST  */
  6. /*          be executed in REXX before they may be used:                 */
  7. /*                                                                       */
  8. /*        call RxFuncAdd 'RxCommOpen'     , 'RXCOMM', 'RXCOMMOPEN'       */
  9. /*        call RxFuncAdd 'RxCommClose'    , 'RXCOMM', 'RXCOMMCLOSE'      */
  10. /*        call RxFuncAdd 'RxCommPut'      , 'RXCOMM', 'RXCOMMPUT'           */
  11. /*        call RxFuncAdd 'RxCommGet'      , 'RXCOMM', 'RXCOMMGET'           */
  12. /*        call RxFuncAdd 'RxCommGetParams', 'RXCOMM', 'RXCOMMGETPARAMS'  */   
  13. /*        call RxFuncAdd 'RxCommSetParams', 'RXCOMM', 'RXCOMMSETPARAMS'  */
  14. /*        call RxFuncAdd 'RxCommSendBreak', 'RXCOMM', 'RXCOMMSENDBREAK'  */
  15. /*        call RxFuncAdd 'RxCommCheck'    , 'RXCOMM', 'RXCOMMCHECK'      */
  16. /*        call RxFuncAdd 'RxCommSetDTR'   , 'RXCOMM', 'RXCOMMSETDTR'     */
  17. /*        call RxFuncAdd 'RxCommFlush'    , 'RXCOMM', 'RXCOMMFLUSH'      */
  18. /*        call RxFuncAdd 'RxGetChar'      , 'RXCOMM', 'RXGETCHAR'           */
  19. /*        call RxFuncAdd 'RxSay'          , 'RXCOMM', 'RXSAY'               */
  20. /*                                                                       */
  21. /* NOTE:  This code has been released into the Public Domain by the      */
  22. /*        author.  This code has NOT been extensivly tested, being a     */
  23. /*        3 hour development project that was abandoned due to the speed */
  24. /*        of the REXX interpreter under OS/2.  If you find any bugs,     */
  25. /*        or would like to contact the author, he can be reached at:     */
  26. /*                                                                       */
  27. /*   Copyright (c) 1990 by:     Mark C. Smith                            */
  28. /*                              2638 Marrietta                           */
  29. /*                              Farmersvilles, Tx 75234                  */
  30. /*                                                                       */
  31. /*                              214/484-4470                             */
  32. /*                                                                       */
  33. /*************************************************************************/
  34.  
  35. #define INCL_BASE
  36. #include <os2.h>
  37. #include <dos.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <memory.h>
  42. #include <rexxsaa.h>
  43.  
  44. /* Define our error return codes */
  45.  
  46. #define OK                     0
  47. #define INCORRECT_NUM_PARAMS  -1      
  48. #define UNABLE_TO_FIND_COM    -2
  49. #define IOCTL_ERROR           -3
  50.  
  51. /* Structure to define each port opened by REXX */
  52.  
  53. struct OPEN_PORTS {
  54.   CHAR *Name;                          /* Name of this COM port */
  55.   USHORT handle;                       /* handle to this COM port */
  56.   struct OPEN_PORTS *Next;             /* Pointer to next COMM port */
  57.   struct OPEN_PORTS *Prev;             /* Pointer to prev COMM port */
  58. };
  59.  
  60. static struct OPEN_PORTS *Top = NULL;  /* This is the 1st COMM port opened */
  61.  
  62. /* Function prototypes for internal functions */
  63.  
  64. static struct OPEN_PORTS *FindCOM(RXSTRING);
  65.   
  66. /*************************************************************************/
  67. /* RxCommFlush: flush the input queue of all characters                  */
  68. /*************************************************************************/
  69.  
  70. SHORT APIENTRY  RxCommFlush(
  71.       PSZ    szName,              /* name function called as         */
  72.       USHORT argc,                /* argument count                  */
  73.       PRXSTRING argv,             /* argument list                   */
  74.       PSZ szQueue,                /* current active queue            */
  75.       PRXSTRING retval)           /* return value                    */
  76.  
  77. {
  78.    SHORT rc;
  79.    USHORT zero = 0;
  80.    struct OPEN_PORTS *curr;
  81.  
  82.  
  83.  
  84.    rc = OK;                      /* System return code */
  85.  
  86.    retval->strlength = 0;
  87.    retval->strptr = NULL;
  88.    rc = INCORRECT_NUM_PARAMS;
  89.  
  90.    switch(argc) {
  91.  
  92.        case 0: break;
  93.  
  94.        case 1:
  95.  
  96.             rc = UNABLE_TO_FIND_COM;
  97.  
  98.             if ((curr = FindCOM(argv[0])) != NULL) {
  99.                
  100.                rc = DosDevIOCtl(0L,
  101.                                 &zero,
  102.                                 DEV_FLUSHINPUT,
  103.                                 IOCTL_GENERAL,
  104.                                 curr->handle);
  105.  
  106.                if (rc)
  107.                  rc = IOCTL_ERROR;
  108.  
  109.             }
  110.             break;
  111.  
  112.        default: break;
  113.    }
  114.  
  115.    return(rc);
  116. }
  117.  
  118.  
  119.  
  120. /*************************************************************************/
  121. /* RxCommSetDTR: Set the DTR value - returns old DTR value               */
  122. /*************************************************************************/
  123.  
  124. SHORT APIENTRY  RxCommSetDTR(
  125.       PSZ    szName,              /* name function called as         */
  126.       USHORT argc,                /* argument count                  */
  127.       PRXSTRING argv,             /* argument list                   */
  128.       PSZ szQueue,                /* current active queue            */
  129.       PRXSTRING retval)           /* return value                    */
  130.  
  131. {
  132.    PSZ tmp;
  133.    SHORT rc;
  134.    SHORT cc;
  135.    USHORT cset;
  136.    PSZ data;
  137.    MODEMSTATUS ms;
  138.    struct OPEN_PORTS *curr;
  139.  
  140.    rc = OK;                      /* System return code */
  141.    cc = 0;                       /* IOCTL return code */
  142.  
  143.    retval->strlength = 0;
  144.  
  145.    switch(argc) {
  146.  
  147.        case 0: 
  148.             rc = INCORRECT_NUM_PARAMS;
  149.             break;
  150.  
  151.        case 1:
  152.        case 2:
  153.             
  154.             rc = UNABLE_TO_FIND_COM;
  155.  
  156.             if ((curr = FindCOM(argv[0])) != NULL) {
  157.  
  158.                 rc = OK;
  159.                 cc = DosDevIOCtl(&cset,
  160.                                  0L,
  161.                                  ASYNC_GETMODEMOUTPUT,
  162.                                  IOCTL_ASYNC,
  163.                                  curr->handle);
  164.                 
  165.                 _fmemcpy(retval->strptr,(((cset&DTR_ON)==0) ? "OFF\0" : "ON \0"),4);
  166.                 retval->strlength = _fstrlen(retval->strptr);
  167.  
  168.                 if (argc > 1 && argv[1].strlength > 0) {
  169.  
  170.                    ms.fbModemOn = 0x00;
  171.                    ms.fbModemOff = 0xFF;
  172.                    if (!_fmemcmp(argv[1].strptr, "ON", 2))
  173.                      ms.fbModemOn = DTR_ON;
  174.                    else if (!_fmemcmp(argv[1].strptr, "OFF", 2))
  175.                      ms.fbModemOff = DTR_OFF;
  176.  
  177.                    cc = DosDevIOCtl(&cset, 
  178.                                     &ms, 
  179.                                     ASYNC_SETMODEMCTRL, 
  180.                                     IOCTL_ASYNC,
  181.                                     curr->handle);
  182.                 }
  183.  
  184.             }
  185.  
  186.             break;
  187.  
  188.        default:
  189.             rc = INCORRECT_NUM_PARAMS;
  190.             break;
  191.  
  192.    }
  193.  
  194.    if (cc)
  195.      rc = IOCTL_ERROR;
  196.  
  197.  
  198.    return(rc);
  199. }
  200.  
  201. /***************************************************************************/
  202. /* RxCommSendBreak: send the break signal out the COMM port for (n) msecs. */
  203. /***************************************************************************/
  204.  
  205. SHORT APIENTRY  RxCommSendBreak(
  206.       PSZ    szName,              /* name function called as         */
  207.       USHORT argc,                /* argument count                  */
  208.       PRXSTRING argv,             /* argument list                   */
  209.       PSZ szQueue,                /* current active queue            */
  210.       PRXSTRING retval)           /* return value                    */
  211.  
  212. {
  213.    SHORT rc;
  214.    USHORT err;
  215.    ULONG msec;
  216.    CHAR tmp[20];
  217.    struct OPEN_PORTS *curr;
  218.  
  219.  
  220.    msec = 0L;
  221.    rc = INCORRECT_NUM_PARAMS;
  222.  
  223.    retval->strlength = 0;
  224.    retval->strptr = NULL;
  225.  
  226.    switch(argc) {
  227.     
  228.       case 0:
  229.           break;
  230.  
  231.       case 1:
  232.           msec = 50L;
  233.  
  234.       case 2:
  235.  
  236.          rc = UNABLE_TO_FIND_COM;
  237.  
  238.          if ((curr = FindCOM(argv[0])) != NULL) {
  239.  
  240.             rc = OK;
  241.  
  242.             if (!msec) {
  243.               _fmemset(tmp,'\0',sizeof(tmp));
  244.               _fmemcpy(tmp, argv[1].strptr, (USHORT)argv[1].strlength);
  245.               msec = atol(tmp);
  246.             }
  247.  
  248.             rc = DosDevIOCtl(&err, 
  249.                              0L, 
  250.                              ASYNC_SETBREAKON,
  251.                              IOCTL_ASYNC,
  252.                              curr->handle);
  253.             DosSleep(msec);
  254.  
  255.             rc += DosDevIOCtl(&err,
  256.                              0L,
  257.                              ASYNC_SETBREAKOFF,
  258.                              IOCTL_ASYNC,
  259.                              curr->handle);
  260.             if(rc) 
  261.               rc = IOCTL_ERROR;
  262.          }
  263.  
  264.          break;
  265.  
  266.       default:
  267.          break;
  268.    }
  269.  
  270.    return(rc);
  271. }
  272.  
  273.  
  274. /*************************************************************************/
  275. /* RxCommSetParams: set the baud rate for the specified COMM port        */
  276. /*************************************************************************/
  277.  
  278. SHORT APIENTRY  RxCommSetParams(
  279.       PSZ    szName,              /* name function called as         */
  280.       USHORT argc,                /* argument count                  */
  281.       PRXSTRING argv,             /* argument list                   */
  282.       PSZ szQueue,                /* current active queue            */
  283.       PRXSTRING retval)           /* return value                    */
  284. {
  285.    SHORT rc;
  286.    SHORT brc;
  287.    SHORT lrc;
  288.    USHORT baud;
  289.    USHORT words;
  290.    USHORT bits;
  291.    CHAR tmp[20];
  292.    struct OPEN_PORTS *curr;
  293.    LINECONTROL lc;
  294.  
  295.    retval->strlength = 0;
  296.    retval->strptr = NULL;
  297.    rc = INCORRECT_NUM_PARAMS;
  298.  
  299.    switch(argc) {
  300.  
  301.       case 0:  break;
  302.  
  303.       default:
  304.  
  305.            rc = UNABLE_TO_FIND_COM;
  306.            if ((curr = FindCOM(argv[0])) != NULL) {
  307.  
  308.                DosDevIOCtl(&lc,
  309.                            0L,
  310.                            ASYNC_GETLINECTRL,
  311.                            IOCTL_ASYNC,
  312.                            curr->handle);
  313.  
  314.                rc = OK;
  315.  
  316.                if (argc >= 2) {
  317.  
  318.                           _fmemset(tmp,'\0', sizeof(tmp));
  319.                           _fmemcpy(tmp, argv[1].strptr, (USHORT)argv[1].strlength);
  320.                           baud = atoi(tmp);
  321.                
  322.                           if (baud == 110 ||
  323.                               baud == 150 ||
  324.                               baud == 300 ||
  325.                               baud == 600 ||
  326.                               baud == 1200 ||
  327.                               baud == 2400 ||
  328.                               baud == 4800 ||
  329.                               baud == 9600 ||
  330.                               baud == 19200)
  331.  
  332.                           brc = DosDevIOCtl(0L,
  333.                                             &baud, 
  334.                                             ASYNC_SETBAUDRATE,
  335.                                             IOCTL_ASYNC,
  336.                                             curr->handle);
  337.                  }
  338.                  if (argc >= 3) {
  339.  
  340.                           lrc = DosDevIOCtl(&lc,
  341.                                             0L,
  342.                                             ASYNC_GETLINECTRL,
  343.                                             IOCTL_ASYNC,
  344.                                             curr->handle);
  345.  
  346.                           _fmemset(tmp,'\0', sizeof(tmp));
  347.                           _fmemcpy(tmp, argv[2].strptr, (USHORT)argv[2].strlength);
  348.                           words = atoi(tmp);
  349.                           if (words > 4 && words < 9) 
  350.                             lc.bDataBits = words;
  351.  
  352.                  }
  353.                  if (argc >= 4) {
  354.                           if (!_fmemcmp(argv[3].strptr, "NONE",1))
  355.                              lc.bParity = 0x0;
  356.                           else if (!_fmemcmp(argv[3].strptr, "EVEN",1))
  357.                              lc.bParity = 0x02;
  358.                           else if (!_fmemcmp(argv[3].strptr, "ODD",1))
  359.                              lc.bParity = 0x01;
  360.                           else if (!_fmemcmp(argv[3].strptr, "MARK",1))
  361.                              lc.bParity = 0x03;
  362.                           else if (!_fmemcmp(argv[3].strptr, "SPACE",1))
  363.                              lc.bParity = 0x04;
  364.                  }
  365.                  if (argc >= 5) {
  366.  
  367.                           _fmemset(tmp,'\0', sizeof(tmp));
  368.                           _fmemcpy(tmp, argv[4].strptr, (USHORT)argv[4].strlength);
  369.                           bits = atoi(tmp);
  370.                           switch(bits) {
  371.                              case 1:  lc.bStopBits = 0x00;
  372.                              case 2:  lc.bStopBits = 0x02;
  373.                           }
  374.                  }
  375.        
  376.                  if (argc >= 3) 
  377.                           lrc = DosDevIOCtl(0L,
  378.                                             &lc,
  379.                                             ASYNC_SETLINECTRL,
  380.                                             IOCTL_ASYNC,
  381.                                             curr->handle);
  382.            }  
  383.    }
  384.  
  385.    return(rc);
  386. }
  387.  
  388. /**************************************************************************/
  389. /* RxCommGetParams:  get the line statistics                              */
  390. /*                                                                        */
  391. /* Return codes         0 - Ok                                            */
  392. /*                     -1 - invalid number of parameters                  */
  393. /*                     -2 - Unable to find comm port                      */
  394. /*                     -3 - IOCTL error                                   */
  395. /**************************************************************************/
  396.  
  397. SHORT APIENTRY  RxCommGetParams(
  398.       PSZ    szName,              /* name function called as         */
  399.       USHORT argc,                /* argument count                  */
  400.       PRXSTRING argv,             /* argument list                   */
  401.       PSZ szQueue,                /* current active queue            */
  402.       PRXSTRING retval)           /* return value                    */
  403. {
  404.    SHORT rc;
  405.    SHORT brc;
  406.    SHORT trc;
  407.    SHORT mirc;
  408.    SHORT morc;
  409.    USHORT baud;
  410.    USHORT inputp;
  411.    USHORT outputp;
  412.    USHORT stopbits;
  413.    CHAR parity[20];
  414.    PSZ data;
  415.    LINECONTROL lc;
  416.    struct OPEN_PORTS *curr;
  417.  
  418.    retval->strlength = 0;
  419.  
  420.    rc = INCORRECT_NUM_PARAMS;
  421.  
  422.    switch(argc) {
  423.  
  424.       case 0:  break;
  425.  
  426.       case 1:
  427.                rc = UNABLE_TO_FIND_COM;
  428.  
  429.                if ((curr = FindCOM(argv[0])) != NULL) {
  430.  
  431.                    rc = OK;
  432.  
  433.                    brc =  DosDevIOCtl(&baud,
  434.                                      0L,
  435.                                      ASYNC_GETBAUDRATE,
  436.                                      IOCTL_ASYNC,
  437.                                      curr->handle);
  438.  
  439.                    brc += DosDevIOCtl(&lc,
  440.                                      0L,
  441.                                      ASYNC_GETLINECTRL,
  442.                                      IOCTL_ASYNC,
  443.                                      curr->handle);
  444.  
  445.                    brc += DosDevIOCtl(&inputp,
  446.                                       0L,
  447.                                       ASYNC_GETMODEMINPUT,
  448.                                       IOCTL_ASYNC,
  449.                                       curr->handle);
  450.  
  451.                    brc += DosDevIOCtl(&outputp,
  452.                                       0L,
  453.                                       ASYNC_GETMODEMOUTPUT,
  454.                                       IOCTL_ASYNC,
  455.                                       curr->handle);
  456.  
  457.                    if (!brc) {
  458.  
  459.                        rc = 0;
  460.                        brc = inputp & CTS_ON;
  461.                        trc = inputp & DSR_ON;
  462.                        mirc = inputp & RI_ON;
  463.                        morc = inputp & DCD_ON;
  464.                        inputp = outputp & DTR_ON;
  465.                        outputp = outputp & RTS_ON;
  466.  
  467.                        switch(lc.bParity) {
  468.                           case 0x00:  strcpy(parity, "NONE"); break;
  469.                           case 0x01:  strcpy(parity, "ODD"); break;
  470.                           case 0x02:  strcpy(parity, "EVEN"); break;
  471.                           case 0x03:  strcpy(parity, "MARK"); break;
  472.                           case 0x04:  strcpy(parity, "SPACE"); break;
  473.                           default:    strcpy(parity, "UNKNOWN"); break;
  474.                        }
  475.                        strcat(parity, "\0");
  476.  
  477.                        switch(lc.bStopBits) {
  478.                           case 0x00:  stopbits = 1;
  479.                           case 0x01:  stopbits = 1;
  480.                           case 0x02:  stopbits = 2;
  481.                           default:    stopbits = 0;
  482.                        }
  483.  
  484.                        data = (PSZ) retval->strptr;
  485.                        retval->strlength = sprintf(data,
  486. "BAUD=%d PARITY=%s DATABITS=%d STOPBITS=%d CTS=%s DSR=%s RI=%s CD=%s DTR=%s RTS=%s",
  487.                            baud, parity, lc.bDataBits, stopbits,
  488.                            ((brc > 0) ? "ON" : "OFF"),
  489.                            ((trc > 0) ? "ON" : "OFF"),
  490.                            ((mirc > 0) ? "ON" : "OFF"),
  491.                            ((morc > 0) ? "ON" : "OFF"),
  492.                            ((inputp > 0) ? "ON" : "OFF"),
  493.                            ((outputp > 0) ? "ON" : "OFF"));
  494.                    }
  495.                    else
  496.                      rc = IOCTL_ERROR;
  497.  
  498.                }
  499.  
  500.       default:     break;
  501.    }
  502.  
  503.    return(rc);
  504. }
  505.  
  506. /**************************************************************************/
  507. /* RxCommOpen: execute an open on a COMM port                             */
  508. /*                                                                        */
  509. /* return codes:     0 - Ok                                               */
  510. /*                  -1 - Incorrect number of arguments                    */
  511. /*                  -2 - COMM port not found / already open               */
  512. /**************************************************************************/
  513.  
  514. SHORT APIENTRY  RxCommOpen(
  515.       PSZ    szName,              /* name function called as         */
  516.       USHORT argc,                /* argument count                  */
  517.       PRXSTRING argv,             /* argument list                   */
  518.       PSZ szQueue,                /* current active queue            */
  519.       PRXSTRING retval)           /* return value                    */
  520.  
  521. {
  522.    SHORT rc;
  523.    USHORT handle;
  524.    USHORT act;
  525.    char *comp;
  526.    struct OPEN_PORTS *tmp;
  527.    struct OPEN_PORTS *curr;
  528.  
  529.    retval->strlength = 0;
  530.    retval->strptr = NULL;
  531.    rc = INCORRECT_NUM_PARAMS;
  532.  
  533.    switch (argc) {
  534.  
  535.        case 0:  break;
  536.  
  537.        case 1:
  538.  
  539.                 rc = UNABLE_TO_FIND_COM;
  540.  
  541.                 if (FindCOM(argv[0]) == NULL) {
  542.  
  543.                     comp = malloc((USHORT)argv[0].strlength+1);
  544.                     _fmemset(comp, '\0', (USHORT)argv[0].strlength+1);
  545.                     _fmemcpy(comp, argv[0].strptr, (USHORT)argv[0].strlength);
  546.  
  547.                     rc = DosOpen(comp,
  548.                                  &handle,
  549.                                  &act, 
  550.                                  0L,
  551.                                  0,
  552.                                  0x01,
  553.                                  0x0012,
  554.                                  0L);
  555.  
  556.                     free(comp);
  557.  
  558.                     if (rc == 0) {
  559.  
  560.                         tmp = malloc(sizeof(struct OPEN_PORTS));
  561.  
  562.                         if (tmp == NULL) 
  563.                           rc = IOCTL_ERROR;
  564.                         else {
  565.                           rc = OK;
  566.                           tmp->Next = NULL;
  567.                           tmp->Prev = NULL;
  568.                           tmp->Name = malloc((USHORT)argv[0].strlength);
  569.                           _fmemcpy(tmp->Name, argv[0].strptr, (USHORT)argv[0].strlength);
  570.                           tmp->handle = handle;
  571.  
  572.                           curr = Top;
  573.                           if (curr == NULL) 
  574.                             Top = tmp;
  575.                           else {
  576.                             while (curr->Next != NULL) 
  577.                               curr = curr->Next;
  578.                             curr->Next = tmp;
  579.                             tmp->Prev = curr;
  580.                           }
  581.                         }
  582.                     }
  583.                     else 
  584.                       rc = IOCTL_ERROR;
  585.                 }
  586.        default: break;
  587.    }
  588.  
  589.  
  590.    return(rc);
  591. }
  592.  
  593. /**************************************************************************/
  594. /* RxCommClose:  execute a close on a COMM port                           */
  595. /*                                                                        */
  596. /* Return codes:         0 - Ok                                           */
  597. /*                      -1 - incorrect # of args                          */
  598. /*                      -2 - port not found                               */
  599. /**************************************************************************/
  600.  
  601. SHORT APIENTRY  RxCommClose(
  602.       PSZ    szName,              /* name function called as         */
  603.       USHORT argc,                /* argument count                  */
  604.       PRXSTRING argv,             /* argument list                   */
  605.       PSZ szQueue,                /* current active queue            */
  606.       PRXSTRING retval)           /* return value                    */
  607.  
  608. {
  609.    SHORT rc;
  610.    struct OPEN_PORTS *tmp;
  611.    struct OPEN_PORTS *curr;
  612.  
  613.    rc = INCORRECT_NUM_PARAMS;
  614.    retval->strlength = 0;
  615.    retval->strptr = NULL;
  616.  
  617.    switch(argc) {
  618.  
  619.      case 0: break;
  620.  
  621.      case 1:
  622.  
  623.              rc = UNABLE_TO_FIND_COM;
  624.  
  625.              if (( curr = FindCOM(argv[0])) != NULL) {
  626.                 DosClose(curr->handle);
  627.                 if (curr == Top)
  628.                   Top = curr->Next;
  629.                 if (curr->Prev != NULL)
  630.                   curr->Prev->Next = curr->Next;
  631.                 free(curr->Name);
  632.                 free(curr);
  633.                 rc = OK;
  634.              }
  635.  
  636.      default: break;
  637.    }
  638.  
  639.    return(rc);
  640. }   
  641.  
  642. /*************************************************************************/
  643. /* RxCommCheck: return the number of characters available from COMM port */
  644. /*                                                                       */
  645. /* Return codes        xx - number of characters available               */
  646. /*                     -1 - wrong # of args                              */
  647. /*                     -2 - unable to find COM port                      */
  648. /*************************************************************************/
  649.  
  650. SHORT APIENTRY  RxCommCheck(
  651.       PSZ    szName,              /* name function called as         */
  652.       USHORT argc,                /* argument count                  */
  653.       PRXSTRING argv,             /* argument list                   */
  654.       PSZ szQueue,                /* current active queue            */
  655.       PRXSTRING retval)           /* return value                    */
  656.  
  657. {
  658.    char Param[20];
  659.    struct OPEN_PORTS *curr;
  660.    RXQUEUE ccount;
  661.    SHORT rc;
  662.  
  663.    retval->strlength = 0;
  664.    rc = INCORRECT_NUM_PARAMS;
  665.  
  666.    switch(argc) {
  667.  
  668.       case 0:  break;
  669.  
  670.       case 1:
  671.                rc = UNABLE_TO_FIND_COM;
  672.  
  673.                if (( curr = FindCOM(argv[0])) != NULL) {
  674.  
  675.                  rc = DosDevIOCtl(&ccount,
  676.                                    0L,
  677.                                    ASYNC_GETINQUECOUNT, 
  678.                                    IOCTL_ASYNC,
  679.                                    curr->handle);
  680.  
  681.                  if (rc == 0) {
  682.                    itoa(ccount.cch, retval->strptr, 10);
  683.                    retval->strlength = _fstrlen(retval->strptr);
  684.                  }
  685.                  else 
  686.                    rc = IOCTL_ERROR;
  687.                }
  688.       default: break;
  689.  
  690.    }
  691.  
  692.    return(rc);
  693. }
  694.    
  695. /**************************************************************************/
  696. /* RxCommGet: execute a getc on a COMM port                               */
  697. /*                                                                        */
  698. /* Return codes         xx - number of characters returned                */
  699. /*                       0 - no characters available                      */
  700. /*                      -1 - wrong # of args                              */
  701. /*                      -2 - unable to find COM port                      */
  702. /*                      -3 - IOCTL error                                  */
  703. /**************************************************************************/
  704.  
  705. SHORT APIENTRY RxCommGet(
  706.       PSZ    szName,              /* name function called as         */
  707.       USHORT argc,                /* argument count                  */
  708.       PRXSTRING argv,             /* argument list                   */
  709.       PSZ szQueue,                /* current active queue            */
  710.       PRXSTRING retval)           /* return value                    */
  711.  
  712. {
  713.    USHORT bytes;
  714.    USHORT rc;
  715.    PSZ ptr1;
  716.    char *ptr;
  717.    char *buff;
  718.    RXQUEUE ccount;
  719.    struct OPEN_PORTS *curr;
  720.  
  721.    rc = INCORRECT_NUM_PARAMS;
  722.    retval->strlength = 0;
  723.  
  724.    switch(argc) {
  725.  
  726.      case 0:  break;
  727.  
  728.      case 1:
  729.  
  730.               rc = UNABLE_TO_FIND_COM;
  731.  
  732.               if (( curr = FindCOM(argv[0])) != NULL) {
  733.  
  734.                  rc = IOCTL_ERROR;
  735.                  bytes = DosDevIOCtl(&ccount,
  736.                                      0L,
  737.                                      ASYNC_GETINQUECOUNT, 
  738.                                      IOCTL_ASYNC,
  739.                                      curr->handle);
  740.  
  741.                  if ((bytes == 0) && (ccount.cch > 0)) {
  742.  
  743.                    rc = OK;
  744.  
  745.                    DosRead(curr->handle,
  746.                            retval->strptr,
  747.                            ccount.cch,
  748.                            &bytes);
  749.                    retval->strlength = bytes;
  750.                  } 
  751.                  else
  752.                    rc = OK;
  753.               } 
  754.               break;
  755.  
  756.      default: break;
  757.  
  758.    }
  759.  
  760.    return(rc);
  761. }
  762.  
  763. /**************************************************************************/
  764. /* RxCommPut: execute a putc on a COMM port                               */
  765. /*                                                                        */
  766. /*  Return codes              0 - Ok                                      */
  767. /*                           -1 - wrong # of args                         */
  768. /*                           -2 - Unable to find COM port                 */
  769. /**************************************************************************/
  770.  
  771. SHORT APIENTRY RxCommPut(
  772.       PSZ    szName,              /* name function called as         */
  773.       USHORT argc,                /* argument count                  */
  774.       PRXSTRING argv,             /* argument list                   */
  775.       PSZ szQueue,                /* current active queue            */
  776.       PRXSTRING retval)           /* return value                    */
  777.  
  778. {
  779.    USHORT bytes;
  780.    SHORT rc;
  781.    PSZ data;
  782.    struct OPEN_PORTS *curr;
  783.  
  784.    rc = INCORRECT_NUM_PARAMS;
  785.    retval->strlength = 0;
  786.    retval->strptr = NULL;
  787.  
  788.    switch(argc) {
  789.  
  790.       case 0: break;
  791.       case 1: break;
  792.  
  793.       case 2:
  794.  
  795.               rc = INCORRECT_NUM_PARAMS;
  796.  
  797.               if (argv[1].strlength > 0) {
  798.                 rc = UNABLE_TO_FIND_COM;
  799.                 if (( curr = FindCOM(argv[0])) != NULL) {
  800.                   data = malloc((USHORT)argv[1].strlength + 1);
  801.                   if (data != NULL) {
  802.                     rc = OK;
  803.                     _fmemset(data, '\0', (USHORT)argv[1].strlength+1);
  804.                     _fmemcpy(data, argv[1].strptr, (USHORT)argv[1].strlength);
  805.  
  806.                     DosWrite(curr->handle, 
  807.                              data,
  808.                              strlen(data),
  809.                              &bytes);
  810.                     free(data);
  811.                   }
  812.                 }
  813.               }
  814.               break;
  815.  
  816.       default: break;
  817.    }
  818.  
  819.    return(rc);
  820. }   
  821.  
  822. /**************************************************************************/
  823. /* FindCOM - find the com port in the list                                */
  824. /*           Internal routine                                             */
  825. /**************************************************************************/
  826.  
  827. static struct OPEN_PORTS *FindCOM(RXSTRING var)
  828. {
  829.    struct OPEN_PORTS *curr;
  830.  
  831.    if (var.strlength == 0L)
  832.      return(NULL);
  833.  
  834.    curr = Top;
  835.    while(curr != NULL) {
  836.      if (_fmemcmp(curr->Name, var.strptr, (USHORT)var.strlength) == 0)
  837.        return(curr);
  838.      curr = curr->Next;
  839.    }
  840.  
  841.    return(NULL);
  842. }
  843.  
  844. /**************************************************************************/
  845. /* RxGetChar:  get a character from the keyboard - wait for it            */
  846. /*                                                                        */
  847. /*  Return codes              0 - Ok                                      */
  848. /**************************************************************************/
  849.  
  850. SHORT APIENTRY RxGetChar(
  851.       PSZ    szName,              /* name function called as         */
  852.       USHORT argc,                /* argument count                  */
  853.       PRXSTRING argv,             /* argument list                   */
  854.       PSZ szQueue,                /* current active queue            */
  855.       PRXSTRING retval)           /* return value                    */
  856.  
  857. {
  858.    USHORT bytes;
  859.    PSZ    data;
  860.    INT    ch;
  861.  
  862.     ch = getch();
  863.  
  864.    switch(argc) {
  865.  
  866.       case 0: if (ch != 0x00) putchar(ch); break;
  867.       
  868.       default: break; 
  869.    }
  870.  
  871.    if (ch == 0x00 | ch == 0xE0)
  872.     {
  873.       ch = getch();
  874.       switch(ch)
  875.       {
  876.          case 0x3b:  strcpy(retval->strptr, "F1");
  877.                      retval->strlength = 2;
  878.                      break;
  879.          case 0x3c:  strcpy(retval->strptr, "F2");
  880.                      retval->strlength = 2;
  881.                      break;
  882.          case 0x3d:  strcpy(retval->strptr, "F3");
  883.                      retval->strlength = 2;
  884.                      break;
  885.          case 0x3e:  strcpy(retval->strptr, "F4");
  886.                      retval->strlength = 2;
  887.                      break;
  888.          case 0x3f:  strcpy(retval->strptr, "F5");
  889.                      retval->strlength = 2;
  890.                      break;
  891.          case 0x40:  strcpy(retval->strptr, "F6");
  892.                      retval->strlength = 2;
  893.                      break;
  894.          case 0x41:  strcpy(retval->strptr, "F7");
  895.                      retval->strlength = 2;
  896.                      break;
  897.          case 0x42:  strcpy(retval->strptr, "F8");
  898.                      retval->strlength = 2;
  899.                      break;
  900.          case 0x43:  strcpy(retval->strptr, "F9");
  901.                      retval->strlength = 2;
  902.                      break;
  903.          case 0x44:  strcpy(retval->strptr, "F10");
  904.                      retval->strlength = 3;
  905.                      break;
  906.             case 0x47:  strcpy(retval->strptr, "HOME");
  907.                      retval->strlength = 4;
  908.                      break;
  909.          case 0x48:  strcpy(retval->strptr, "UP");
  910.                      retval->strlength = 2;
  911.                      break;
  912.          case 0x49:  strcpy(retval->strptr, "PGUP");
  913.                      retval->strlength = 4;
  914.                      break;
  915.          case 0x4b:  strcpy(retval->strptr, "LEFT");
  916.                      retval->strlength = 4;
  917.                      break;
  918.          case 0x4d:  strcpy(retval->strptr, "RIGHT");
  919.                      retval->strlength = 5;
  920.                      break;
  921.          case 0x52:  strcpy(retval->strptr, "INSERT");
  922.                      retval->strlength = 6;
  923.                      break;
  924.          case 0x53:  strcpy(retval->strptr, "DEL");
  925.                      retval->strlength = 3;
  926.                      break;
  927.          default:    strcpy(retval->strptr, "UNKNOWN");
  928.                      retval->strlength = 7;
  929.                      break;
  930.        }
  931.     }
  932.    else
  933.      retval->strlength = sprintf(retval->strptr, "%c", ch);
  934.  
  935.    return(0);
  936. }   
  937.  
  938. /**************************************************************************/
  939. /* RxSay:  output a string at the current cursor location w/o cr-lf.      */
  940. /*                                                                        */
  941. /*  Return codes              0 - Ok                                      */
  942. /**************************************************************************/
  943.  
  944. SHORT APIENTRY RxSay(
  945.       PSZ    szName,              /* name function called as         */
  946.       USHORT argc,                /* argument count                  */
  947.       PRXSTRING argv,             /* argument list                   */
  948.       PSZ szQueue,                /* current active queue            */
  949.       PRXSTRING retval)           /* return value                    */
  950.  
  951. {
  952.   char  *p;
  953.   unsigned long count;
  954.  
  955.   if (argc > 0)
  956.     {
  957.     count = argv[0].strlength;
  958.     p = argv[0].strptr;
  959.     while (count--)
  960.       putchar(*p++);
  961.    }
  962.   return(0);
  963. }  
  964.  
  965.