home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rxasync2.zip / RXASYNC.C < prev    next >
Text File  |  1994-12-30  |  219KB  |  4,180 lines

  1. /*****************************************************************************/
  2. /*                                                                           */
  3. /*  MODULE         RXASYNC.C                                                 */
  4. /*                                                                           */
  5. /*  VERSION        Version 2.0 - 26th Dec 1994                               */
  6. /*                                                                           */
  7. /*  COPYRIGHT      Copyright (c) 1993, 1994 by Crucial Applications          */
  8. /*                              All rights reserved.                         */
  9. /*                                                                           */
  10. /*  AUTHOR         Ian Timms                                                 */
  11. /*                                                                           */
  12. /*  DESCRIPTION    Rexx Asynchronous Communications Functions                */
  13. /*                                                                           */
  14. /*    The enclosed REXX DLL comprises a set of functions which are used to   */
  15. /*    to extend the REXX language by providing FULL exposure of the ASYNC    */
  16. /*    communications API. In addition a number of higher level functions     */
  17. /*    are also provided to simplify the task of enabling REXX to be used     */
  18. /*    as a scripting language for serial communications control.             */
  19. /*                                                                           */
  20. /*    They are by no means perfect but do function sufficiently well for the */
  21. /*    author who uses them to provide a means of automating the collection   */
  22. /*    of mail from the BBS.  If you have any comments or suggestions for     */
  23. /*    improvement then I'd be glad to hear from you.                         */
  24. /*                                                                           */
  25. /*    The author can be contacted (in order of preference) at:               */
  26. /*                                                                           */
  27. /*         Bunyips Cave BBS    3:633/379                                     */
  28. /*                                                                           */
  29. /*         Internet            itimms@ariel.ucs.unimelb.edu.au               */
  30. /*                                                                           */
  31. /*         Compuserve          100236,1404                                   */
  32. /*                                                                           */
  33. /*         Snail mail          Ian Timms,                                    */
  34. /*                             13 Cowper Street                              */
  35. /*                             Footscray, Victoria,                          */
  36. /*                             Australia, 3011                               */
  37. /*                                                                           */
  38. /*  FUNCTIONS                                                                */
  39. /*                                                                           */
  40. /*       House keeping                                                       */
  41. /*                                                                           */
  42. /*    RxAsyncDropFuncs     - + Drop the functions from REXX                  */
  43. /*    RxAsyncLoadFuncs     -   Load the functions into REXX                  */
  44. /*                                                                           */
  45. /*       Process control                                                     */
  46. /*                                                                           */
  47. /*    RxAsyncPriority      -   Set Rexx process priority                     */
  48. /*                                                                           */
  49. /*       ASYNC IOCTL interface                                               */
  50. /*                                                                           */
  51. /*    RxAsyncGetDcbInfo    -   Get the device control block info             */
  52. /*    RxAsyncSetDcbInfo    -   Set the device control block info             */
  53. /*    RxAsyncGetEnhParm    -   Get the enhanced parameters                   */
  54. /*    RxAsyncSetEnhParm    -   Set the enhanced parameters                   */
  55. /*    RxAsyncGetLnCtrl     -   Get the comms port settings                   */
  56. /*    RxAsyncSetLnCtrl     -   Set the comms port settings                   */
  57. /*                                                                           */
  58. /*    RxAsyncSetBreakOff   -   Turn break off                                */
  59. /*    RxAsyncSetBreakOn    -   Turn break on                                 */
  60. /*    RxAsyncTxImmediate   -   Transmit byte immediately                     */
  61. /*    RxAsyncTxStop        -   Stop transmission (ala XOFF)                  */
  62. /*    RxAsyncTxStart       -   Start transmission (ala XON)                  */
  63. /*    RxAsyncGetComStatus  -   Get COM status                                */
  64. /*    RxAsyncGetTxStatus   -   Get Transmit status                           */
  65. /*    RxAsyncGetMdmOutput  -   Get modem output signals                      */
  66. /*    RxAsyncGetMdmInput   -   Get modem input signals                       */
  67. /*    RxAsyncSetMdmOutput  -   Set modem output signals                      */
  68. /*    RxAsyncGetRxCount    -   Get size and number of chars in RX queue      */
  69. /*    RxAsyncGetTxCount    -   Get size and number of chars in TX queue      */
  70. /*    RxAsyncGetComError   -   Get the COM Error Word                        */
  71. /*    RxAsyncGetComEvent   -   Get the COM Event Word                        */
  72. /*                                                                           */
  73. /*       Extensions                                                          */
  74. /*                                                                           */
  75. /*    RxAsyncOpen          -   Open the specified comms port                 */
  76. /*    RxAsyncClose         -   Close the specified comms port                */
  77. /*    RxAsyncWait          -   Wait for receipt of input                     */
  78. /*    RxAsyncWatch         -   Wait for receipt of specified strings         */
  79. /*    RxAsyncRead          -   Read data and wait if necessary               */
  80. /*    RxAsyncWrite         -   Write data to the comms port                  */
  81. /*    RxAsyncCarrier       -   Test/Wait for Data Carrier Detect (DCD)       */
  82. /*    RxAsyncBreak         -   Send break for defined period                 */
  83. /*    RxAsyncDcbInfo       -   Print the device control block info           */
  84. /*    RxAsyncActive        -   Test for active modem signal                  */
  85. /*    RxAsyncRaise         -   Raise specified modem signal                  */
  86. /*    RxAsyncLower         -   Lower specified modem signal                  */
  87. /*                                                                           */
  88. /*       File handling                                                       */
  89. /*                                                                           */
  90. /*    RxAsyncFileExists    - + Test for file(s) existence                    */
  91. /*    RxAsyncFileDelete    - + Delete specified file                         */
  92. /*    RxAsyncFileCopy      - + Copy specified file                           */
  93. /*    RxAsyncFileMove      - + Move specified file                           */
  94. /*    RxAsyncFileRename    - + Rename specified file                         */
  95. /*    RxAsyncFileNameIs    - + Determine file name                           */
  96. /*    RxAsyncFilePathIs    - + Determine file path                           */
  97. /*    RxAsyncDirectory     - + Query/Change directory/drive                  */
  98. /*                                                                           */
  99. /*       Miscellaneous                                                       */
  100. /*                                                                           */
  101. /*    RxAsyncSleep         - + Wait for some defined period                  */
  102. /*    RxAsyncPrint         - + Print string on stdout                        */
  103. /*    RxAsyncMsgBox        - + Display PM message box (PM use only)          */
  104. /*                                                                           */
  105. /*  FILES                                                                    */
  106. /*                                                                           */
  107. /*    READ.ME      -  Documentation (such as it is)                          */
  108. /*    RXASYNC.C    -  Rexx async comms functions DLL source                  */
  109. /*    RXASYNC.H    -  Header file                                            */
  110. /*    RXVPFUNC.C   -  Rexx variable pool functions                           */
  111. /*    RXVPFUNC.H   -  Header file                                            */
  112. /*    COMSFUNC.C   -  Communications functions                               */
  113. /*    COMSFUNC.H   -  Header file                                            */
  114. /*    FILEFUNC.C   -  File system functions                                  */
  115. /*    FILEFUNC.H   -  Header file                                            */
  116. /*    MISCFUNC.C   -  Miscellaneous functions                                */
  117. /*    MISCFUNC.H   -  Header file                                            */
  118. /*    RXASYNC.DEF  -  Definitions file for linker                            */
  119. /*    RXASYNC.DEP  -  Dependancy file make                                   */
  120. /*    RXASYNC.MAK  -  Make file                                              */
  121. /*    RXASYNC.DLL  -  The final product                                      */
  122. /*    RXASYNC.CMD  -  Rexx script showing basic usage of DLL                 */
  123. /*    RXMSG.CMD    -  Rexx script showing usage with message boxes           */
  124. /*                                                                           */
  125. /*  LICENSE                                                                  */
  126. /*                                                                           */
  127. /*    This Program is released to the public, you may use this Program in    */
  128. /*    any way you see fit, pursuant to the following restrictions:           */
  129. /*                                                                           */
  130. /*    o  You may not sell the Program or use this code _in_ a commercial     */
  131. /*       application nor may you distribute this Program as a part of any    */
  132. /*       such application without the express permission of the author;      */
  133. /*                                                                           */
  134. /*    o  The Program may be freely used for non commercial and educational   */
  135. /*       purposes, privately and by registered charities, non-profit         */
  136. /*       organisations and educational institutions;                         */
  137. /*                                                                           */
  138. /*    o  Distribution on Shareware and Developer CD-ROMs is also permitted;  */
  139. /*                                                                           */
  140. /*    o  You may not charge a fee for distribution of the Program;           */
  141. /*                                                                           */
  142. /*    o  The Program shall be supplied in its original, unmodified form, as  */
  143. /*       distributed by the author, which includes all source code;          */
  144. /*                                                                           */
  145. /*    o  Share/Freeware authors wishing to incorporate this program in the   */
  146. /*       distribution package of their own product may do so freely provided */
  147. /*       the FULL RxAsync archive is included intact;                        */
  148. /*                                                                           */
  149. /*    o  Special dispensation to distribute the RXASYNC.DLL on its own may   */
  150. /*       be given upon request.                                              */
  151. /*                                                                           */
  152. /*  DISCLAIMER                                                               */
  153. /*                                                                           */
  154. /*    Use of this Program and/or documentation for any purpose whatsoever    */
  155. /*    constitutes your unqualified acceptance of the following statements.   */
  156. /*                                                                           */
  157. /*    The author, Ian Timms, makes no warranty or representation that the    */
  158. /*    Program or Documentation will be error free.  The author disclaims     */
  159. /*    any warranties, either express or implied, including but not limited   */
  160. /*    to any implied warranty of merchantability or fitness for any          */
  161. /*    particular purpose.                                                    */
  162. /*                                                                           */
  163. /*    The author has no obligation to provide service, defect correction, or */
  164. /*    any maintenance for the Program.  The author has no obligation to      */
  165. /*    supply any Program updates or enhancements to you even if such are or  */
  166. /*    later become available.                                                */
  167. /*                                                                           */
  168. /*    In no event will the author be liable for any damages whatsoever       */
  169. /*    (including without limitation damages for loss of business profits,    */
  170. /*    business interruption, loss of business information or other           */
  171. /*    incidental or consequential damages) arising out of the use of,        */
  172. /*    interruption in the use of, or inability to use the Program, even if   */
  173. /*    the author has been advised of any possibility or likelihood of such   */
  174. /*    damages.                                                               */
  175. /*                                                                           */
  176. /*    The user agrees to take full responsibility for the selection of and   */
  177. /*    any use whatsoever made of the Program and Documentation such as it    */
  178. /*    exists.                                                                */
  179. /*                                                                           */
  180. /*  NOTES                                                                    */
  181. /*                                                                           */
  182. /*    Online timeout etc. is checked in hundredths of a second as this is    */
  183. /*    the maximum granularity available with standard OS/2 calls.  Use of a  */
  184. /*    high resolution timer might enhance this aspect significantly but I    */
  185. /*    have not yet found a need for this. The MyDiffTime routine which is    */
  186. /*    used for handling timeout calculation can only calulate a maximum      */
  187. /*    period difference to within 1 week which should be sufficient.         */
  188. /*                                                                           */
  189. /*    The routines themselves do NOT check for the loss of carrier.  Such    */
  190. /*    checking as exists in the communications drivers is relied upon for    */
  191. /*    this. I use the NO CARRIER response from the modem and this does the   */
  192. /*    trick reasonably well. There is now an RxAsyncCarrier function which   */
  193. /*    will tell you the carrier status, ideal for loop control.              */
  194. /*                                                                           */
  195. /*    Nulls are NOT stripped from any input read from the device. I had      */
  196. /*    initially intended doing this but have so far not implemented this     */
  197. /*    facility, even though the majority of the code is already there. I     */
  198. /*    should also note that it would only strip nulls from the scripted      */
  199. /*    side of things, that is to say I would NOT tell the device driver to   */
  200. /*    do it, that would be an unwise move for reasons which should become    */
  201. /*    obvious when you think about the effect it would have on an external   */
  202. /*    protocol. The facility to strip nulls has now been implemented in the  */
  203. /*    RxAsyncRead routine, you can optionally specify a replacement value.   */
  204. /*                                                                           */
  205. /*    Please use the RxAsyncPrint function to display all "stdout" style     */
  206. /*    output, in this way you will correctly see the error results returned  */
  207. /*    by the routines should a failure occur. It also avoids the problem of  */
  208. /*    REXX adding <cr><lf> to everything.                                    */
  209. /*                                                                           */
  210. /*    In order to make sure that output containing ANSI escape sequences is  */
  211. /*    correctly handled you will need to load the ANSI.sys driver in your    */
  212. /*    CONFIG.sys file.                                                       */
  213. /*                                                                           */
  214. /*    The file handling functions which I have added are NOT replacements    */
  215. /*    for the standard OS/2 command line functions. They do NOT handle       */
  216. /*    wildcard nameing (except for FileExists) and unpredictable results     */
  217. /*    may occur if you attempt to do so.  What the functions WILL do is      */
  218. /*    enable you to easily move/copy/delete/rename and find a file without   */
  219. /*    having to shell out to the CMD.EXE command processor.  The FileMove    */
  220. /*    function has also been written so that it is possible to move a file   */
  221. /*    across drives, something the standard MOVE command will not allow.     */
  222. /*                                                                           */
  223. /*    I have now implemented propper device control block handling which     */
  224. /*    permits setting of more reasonable timeouts using the standard OS/2    */
  225. /*    COM.SYS driver. The default values of 1 minute can now be overridden   */
  226. /*    after the communications port is opened by using the RxAsyncSetDcbInfo */
  227. /*    function.                                                              */
  228. /*                                                                           */
  229. /*    If you use the COM.SYS driver supplied with OS/2 2.x GA and elect NOT  */
  230. /*    to set read and write timeouts using the RxAsyncSetDcbInfo function    */
  231. /*    then you'll find the functionality of these routines a little lacking. */
  232. /*                                                                           */
  233. /*    To control handshaking, extended buffering etc. etc. I recommend that  */
  234. /*    you use the MODE command to set up your port appropriately before      */
  235. /*    using these routines. You can also do this using the RxAsyncSetDcbInfo */
  236. /*    and RxAsyncSetLnCtrl functions but generally it is much simpler to use */
  237. /*    the MODE command. Locking your pc<->modem port speed is highly         */
  238. /*    recommended.                                                           */
  239. /*                                                                           */
  240. /*    The following MODE setting is recommended to be placed in your         */
  241. /*    STARTUP.CMD file for best results:                                     */
  242. /*                                                                           */
  243. /*       MODE COM4:19200,N,8,1,TO=OFF,XON=OFF,        full duplex            */
  244. /*                             OCTS=ON,RTS=HS,        hardware CTS/RTS       */
  245. /*                             DTR=ON,                DTR control mode       */
  246. /*                             IDSR=OFF,ODSR=OFF,     disable DSR checking   */
  247. /*                             BUFFER=ON              bufferred              */
  248. /*                                                                           */
  249. /*    Note that I have DSR checking disabled, my modem does not appear to    */
  250. /*    handle the DSR signal correctly, if you are not getting any response   */
  251. /*    from yours then the same may well be true. Also having this enabled    */
  252. /*    may cause unpredictable responses when using the SIO drivers.          */
  253. /*    (Ray may have fixed this now, however I do not use SIO these days      */
  254. /*    except for testing so your mileage may vary.)                          */
  255. /*                                                                           */
  256. /*    You should also use the following Hayes or equivalent modem settings:  */
  257. /*                                                                           */
  258. /*        E0, Q0, V1, X4 or X6, &C1, &D2                                     */
  259. /*                                                                           */
  260. /*    If you do NOT have a 16550 UART then you will need to make sure that   */
  261. /*    the DCB information supplied to the RxAsyncSetDcbInfo routine is       */
  262. /*    appropriate. Usually this means using '00000010' for Flags3 and        */
  263. /*    setting BUFFER=OFF in the MODE command above.                          */
  264. /*                                                                           */
  265. /*    If you need a more in depth discussion of handling DCB parameters      */
  266. /*    etc. then the best initial source is the SIOREF document provided      */
  267. /*    with the SIO drivers. Second best although more comprehensive is       */
  268. /*    the OS/2 Physical Device Driver reference, it's heavier reading.<g>    */
  269. /*                                                                           */
  270. /*  HISTORY                                                                  */
  271. /*                                                                           */
  272. /*    14-Aug-1993  Original release.                                         */
  273. /*    24-Aug-1993  Added carrier test function. Thanks to M.N.Stephenson.    */
  274. /*    04-Sep-1993  Added file handling functions.                            */
  275. /*    02-Nov-1993  Added RxAsyncGetDcbInfo function.                         */
  276. /*    06-Nov-1993  Added RxAsyncBreak function.                              */
  277. /*    18-Dec-1993  Changed RxAsyncGetDcbInfo to RxAsyncDcbInfo               */
  278. /*    18-Dec-1993  Improved documentation                                    */
  279. /*    11-Mar-1994  Permit passing empty string to RxAsyncWrite.              */
  280. /*    11-Mar-1994  Changed both read and write timeouts to 1 second.         */
  281. /*    11-Mar-1994  Added RxAsyncGetDcbInfo function.                         */
  282. /*    11-Mar-1994  Added RxAsyncGetEnhParm function.                         */
  283. /*    03-May-1994  Added generic Str2Num function.                           */
  284. /*    03-May-1994  Added RxAsyncSetDcbInfo function.                         */
  285. /*    03-May-1994  Added RxAsyncSetEnhParm function.                         */
  286. /*    03-May-1994  Removed forcing of full duplex and read/write timeouts.   */
  287. /*    03-May-1994  Changed name to RXASYNC.                                  */
  288. /*    03-May-1994  Cleaned up parameter validations.                         */
  289. /*    20-May-1994  Added extra modem control and signal query functions.     */
  290. /*    22-May-1994  Prepared for distribution as version 1.5.                 */
  291. /*                                                                           */
  292. /*    22-Oct-1994  Added RxAsyncMsgBox function for PM usage.                */
  293. /*    13-Nov-1994  Added ability to optionally specify a null replace char   */
  294. /*                 in the RxAsyncRead function. And corrected to return ALL  */
  295. /*                 data read by default, regardless of nulls. Also fixed a   */
  296. /*                 minor performance bug when waiting for data.              */
  297. /*    13-Nov-1994  Expanded RxAsyncFileNameIs and RxAsyncFilePathIs funcs    */
  298. /*                 to permit an empty string as a parameter. Corrected bug   */
  299. /*                 in FilePathIs where it was modifying the arguement.       */
  300. /*    17-Nov-1994  Added ability to optionally specify a timeout for the     */
  301. /*                 RxAsyncCarrier function to enable wait_for_carrier usage. */
  302. /*    26-Nov-1994  Enhanced RxAsyncLoadFuncs so that it caters for any       */
  303. /*                 load failures and unloads functions if unable to          */
  304. /*                 complete successfully.                                    */
  305. /*    26-Nov-1994  Added/enhanced rexx variable pool miscellaneous           */
  306. /*                 functions to cater for fetch only and stem handling.      */
  307. /*    27-Nov-1994  Added stub for RxAsyncWatch function.                     */
  308. /*    28-Nov-1994  Split RXASYNC module into pieces, resulting in modules    */
  309. /*                 COMSFUNC, FILEFUNC, RXVPFUNC, MISCFUNC and RXASYNC.       */
  310. /*    02-Dec-1994  Added RxAsyncActive, RxAsyncRaise and RxAsyncLower.       */
  311. /*    07-Dec-1994  Corrected bug in RxAsyncSetEnhParm function.              */
  312. /*    08-Dec-1994  Added optional parameter to RxAsyncRead to allow user to  */
  313. /*                 specify an additional line termination character to those */
  314. /*                 currently used. (defaults are LF, FF and EOF).            */
  315. /*    24-Dec-1994  Completed work on RxAsyncWatch function.                  */
  316. /*    26-Dec-1994  Added RxAsyncRC return code variable. RxAsyncRc = 0 if    */
  317. /*                 all okay, non zero if error, where the value is the error */
  318. /*                 return code of the DosCall made, normally an IOCTL.       */
  319. /*                 For obvious reasons the File Handling and Miscellaneous   */
  320. /*                 functions do not set this variable, nor does DropFuncs.   */
  321. /*    26-Dec-1994  Prepared for distribution as version 2.0.                 */
  322. /*                                                                           */
  323. /*  KNOWN PROBLEMS                                                           */
  324. /*                                                                           */
  325. /*    There is a bug in OS/2 2.1 GA which causes output printed to stdout by */
  326. /*    a DLL function to appear on stderr when stdout output from a command   */
  327. /*    file is redirected.  It is not know whether this problem has been      */
  328. /*    resolved in later versions, if this poses a problem for you then       */
  329. /*    please raise it with IBM.                                              */
  330. /*                                                                           */
  331. /*  FUTURES                                                                  */
  332. /*                                                                           */
  333. /*    Add internal functions for ASCII file download/upload.                 */
  334. /*                                                                           */
  335. /*  FORTUNE TELLING                                                          */
  336. /*                                                                           */
  337. /*    Create a wraparound for the RexxStart command so that a script can     */
  338. /*     be run under PM using message boxes etc. and get its name registered  */
  339. /*     in the OS/2 task list. The beginnings of a propper scripting tool.    */
  340. /*    Add RxAsyncReadBuffer variable so that reading can be handled better.  */
  341. /*    Add internal functions for Zmodem download/upload.                     */
  342. /*    Add ability to use system messages in RxAsyncMsgBox function.          */
  343. /*    Add DBCS enablement where required.                                    */
  344. /*    Internalise the whole shebang into an EXE scripting tool. Eventually!  */
  345. /*                                                                           */
  346. /*****************************************************************************/
  347.  
  348. /*********************************************************************/
  349. /* Includes needed by this module                                    */
  350. /*********************************************************************/
  351.  
  352. #define  _MT
  353. #define  _DLL
  354. #define  INCL_DOS
  355. #define  INCL_ERRORS
  356. #define  INCL_REXXSAA
  357. #define  INCL_DOSDEVIOCTL
  358.  
  359. #include <os2.h>
  360. #include <stdio.h>
  361. #include <string.h>
  362. #include <stdlib.h>
  363. #include <rexxsaa.h>
  364.  
  365. #include "miscfunc.h"
  366. #include "rxvpfunc.h"
  367. #include "filefunc.h"
  368. #include "comsfunc.h"
  369. #include "rxasync.h"
  370.  
  371. /*********************************************************************/
  372. /* Declare exported functions as REXX functions.                     */
  373. /*********************************************************************/
  374.  
  375. RexxFunctionHandler RxAsyncDropFuncs;
  376. RexxFunctionHandler RxAsyncLoadFuncs;
  377.  
  378. RexxFunctionHandler RxAsyncPriority;
  379. RexxFunctionHandler RxAsyncSleep;
  380.  
  381. RexxFunctionHandler RxAsyncGetDcbInfo;
  382. RexxFunctionHandler RxAsyncSetDcbInfo;
  383. RexxFunctionHandler RxAsyncGetEnhParm;
  384. RexxFunctionHandler RxAsyncSetEnhParm;
  385. RexxFunctionHandler RxAsyncGetLnCtrl;
  386. RexxFunctionHandler RxAsyncSetLnCtrl;
  387. RexxFunctionHandler RxAsyncSetBreakOff;
  388. RexxFunctionHandler RxAsyncSetBreakOn;
  389. RexxFunctionHandler RxAsyncTxImmediate;
  390. RexxFunctionHandler RxAsyncTxStop;
  391. RexxFunctionHandler RxAsyncTxStart;
  392. RexxFunctionHandler RxAsyncGetComStatus;
  393. RexxFunctionHandler RxAsyncGetTxStatus;
  394. RexxFunctionHandler RxAsyncGetMdmOutput;
  395. RexxFunctionHandler RxAsyncSetMdmOutput;
  396. RexxFunctionHandler RxAsyncGetMdmInput;
  397. RexxFunctionHandler RxAsyncGetRxCount;
  398. RexxFunctionHandler RxAsyncGetTxCount;
  399. RexxFunctionHandler RxAsyncGetComError;
  400. RexxFunctionHandler RxAsyncGetComEvent;
  401.  
  402. RexxFunctionHandler RxAsyncOpen;
  403. RexxFunctionHandler RxAsyncClose;
  404. RexxFunctionHandler RxAsyncWait;
  405. RexxFunctionHandler RxAsyncRead;
  406. RexxFunctionHandler RxAsyncWrite;
  407. RexxFunctionHandler RxAsyncPrint;
  408. RexxFunctionHandler RxAsyncCarrier;
  409. RexxFunctionHandler RxAsyncBreak;
  410. RexxFunctionHandler RxAsyncDcbInfo;
  411.  
  412. RexxFunctionHandler RxAsyncFileExists;
  413. RexxFunctionHandler RxAsyncFileDelete;
  414. RexxFunctionHandler RxAsyncFileCopy;
  415. RexxFunctionHandler RxAsyncFileMove;
  416. RexxFunctionHandler RxAsyncFileRename;
  417. RexxFunctionHandler RxAsyncFileNameIs;
  418. RexxFunctionHandler RxAsyncFilePathIs;
  419. RexxFunctionHandler RxAsyncDirectory;
  420.  
  421. RexxFunctionHandler RxAsyncMsgBox;
  422. RexxFunctionHandler RxAsyncWatch;
  423.  
  424. RexxFunctionHandler RxAsyncFlushInput;
  425. RexxFunctionHandler RxAsyncFlushOutput;
  426.  
  427. RexxFunctionHandler RxAsyncActive;
  428. RexxFunctionHandler RxAsyncRaise;
  429. RexxFunctionHandler RxAsyncLower;
  430.  
  431. /*********************************************************************/
  432. /* RxFncTable                                                        */
  433. /*   Array of names of the RXASYNC functions.                        */
  434. /*   This list is used for registration and deregistration.          */
  435. /*********************************************************************/
  436.  
  437. #pragma pack(1)                        /* pack on 1 byte boundary    */
  438.  
  439. static PSZ  RxFncTable[] =
  440.    {
  441.       "RxAsyncDropFuncs"
  442.    ,  "RxAsyncLoadFuncs"
  443.    ,  "RxAsyncPriority"
  444.    ,  "RxAsyncSleep"
  445.    ,  "RxAsyncGetDcbInfo"
  446.    ,  "RxAsyncSetDcbInfo"
  447.    ,  "RxAsyncGetEnhParm"
  448.    ,  "RxAsyncSetEnhParm"
  449.    ,  "RxAsyncGetLnCtrl"
  450.    ,  "RxAsyncSetLnCtrl"
  451.    ,  "RxAsyncSetBreakOff"
  452.    ,  "RxAsyncSetBreakOn"
  453.    ,  "RxAsyncTxImmediate"
  454.    ,  "RxAsyncTxStop"
  455.    ,  "RxAsyncTxStart"
  456.    ,  "RxAsyncGetComStatus"
  457.    ,  "RxAsyncGetTxStatus"
  458.    ,  "RxAsyncGetMdmOutput"
  459.    ,  "RxAsyncSetMdmOutput"
  460.    ,  "RxAsyncGetMdmInput"
  461.    ,  "RxAsyncGetRxCount"
  462.    ,  "RxAsyncGetTxCount"
  463.    ,  "RxAsyncGetComError"
  464.    ,  "RxAsyncGetComEvent"
  465.    ,  "RxAsyncOpen"
  466.    ,  "RxAsyncClose"
  467.    ,  "RxAsyncWait"
  468.    ,  "RxAsyncRead"
  469.    ,  "RxAsyncWrite"
  470.    ,  "RxAsyncPrint"
  471.    ,  "RxAsyncCarrier"
  472.    ,  "RxAsyncBreak"
  473.    ,  "RxAsyncDcbInfo"
  474.    ,  "RxAsyncFileExists"
  475.    ,  "RxAsyncFileDelete"
  476.    ,  "RxAsyncFileCopy"
  477.    ,  "RxAsyncFileMove"
  478.    ,  "RxAsyncFileRename"
  479.    ,  "RxAsyncFileNameIs"
  480.    ,  "RxAsyncFilePathIs"
  481.    ,  "RxAsyncDirectory"
  482.    ,  "RxAsyncMsgBox"
  483.    ,  "RxAsyncWatch"
  484.    ,  "RxAsyncFlushInput"
  485.    ,  "RxAsyncFlushOutput"
  486.    ,  "RxAsyncActive"
  487.    ,  "RxAsyncRaise"
  488.    ,  "RxAsyncLower"
  489.    };
  490.  
  491. static CHAR RxAsyncRcVarName[10] = "RxAsyncRc";
  492.  
  493. /*********************************************************************/
  494. /* Function:  DropRxFuncs( entries )                                 */
  495. /* Purpose:   Deregister the specified number of function entries.   */
  496. /* Return:    none.                                                  */
  497. /*********************************************************************/
  498. VOID DropRxFuncs( LONG entries )
  499. {
  500.    LONG i;
  501.    i = entries;
  502.    while (i > 0) {
  503.       i = i - 1;
  504.       RexxDeregisterFunction( RxFncTable[i] );
  505.    }
  506.    return;
  507. }
  508.  
  509. /*********************************************************************/
  510. /* Function:  LoadRxFuncs                                            */
  511. /* Purpose:   Register the functions in the DLL to REXX.             */
  512. /* Return:    True if successful, False if not.                      */
  513. /*********************************************************************/
  514. BOOL LoadRxFuncs( VOID )
  515. {
  516.    APIRET rxrc;                        /* Rexx function return       */
  517.    LONG   entries;                     /* Num of entries             */
  518.    LONG   i;                           /* Counter                    */
  519.    entries = sizeof( RxFncTable ) / sizeof( PSZ );
  520.    i = 0;
  521.    while (i < entries) {
  522.       rxrc = RexxRegisterFunctionDll( RxFncTable[i],
  523.                                       RXASYNC_DLL_NAME,
  524.                                       RxFncTable[i] );
  525.       if ( rxrc == RXFUNC_NOMEM ) {    /* Registration failed        */
  526.          DropRxFuncs( i );
  527.          return( FALSE );
  528.       }
  529.       i = i + 1;
  530.    }
  531.    return( TRUE );
  532. }
  533.  
  534. /*********************************************************************/
  535. /* RXASYNC functions.                                                */
  536. /*********************************************************************/
  537.  
  538. /*********************************************************************/
  539. /*                                                                   */
  540. /* Function:  RxAsyncDropFuncs                                       */
  541. /*                                                                   */
  542. /* Purpose:   Unload the functions                                   */
  543. /*                                                                   */
  544. /* Syntax:    call RxAsyncDropFuncs                                  */
  545. /*                                                                   */
  546. /* Parms:     none                                                   */
  547. /*                                                                   */
  548. /* Return:                                                           */
  549. /*   Call successful - NO_ERROR (0)                                  */
  550. /*                                                                   */
  551. /* Example:                                                          */
  552. /*                                                                   */
  553. /*   call RxAsyncDropFuncs                                           */
  554. /*   Say 'RxAsyncDropFuncs is complete.'                             */
  555. /*                                                                   */
  556. /*********************************************************************/
  557.  
  558. APIRET RxAsyncDropFuncs(
  559.           CHAR     *name,
  560.           ULONG    numargs,
  561.           RXSTRING args[],
  562.           CHAR     *queuename,
  563.           RXSTRING *retstr
  564.        )
  565. {
  566.    if ( numargs != 0 )                 /* Must have no arguments     */
  567.       return( ROUTINE_INVALID );
  568.  
  569.    DropRxFuncs( (LONG) (sizeof( RxFncTable ) / sizeof( PSZ )) );
  570.  
  571.    BUILDRXDOSRET( retstr, NO_ERROR );  /* Initialise return value    */
  572.  
  573.    return( ROUTINE_VALID );
  574. }
  575.  
  576. /*********************************************************************/
  577. /*                                                                   */
  578. /* Function:  RxAsyncLoadFuncs                                       */
  579. /*                                                                   */
  580. /* Purpose:   Load the functions                                     */
  581. /*                                                                   */
  582. /* Syntax:    call RxAsyncLoadFuncs                                  */
  583. /*                                                                   */
  584. /* Params:    none                                                   */
  585. /*                                                                   */
  586. /* Return:                                                           */
  587. /*   Call successful - NO_ERROR (0)                                  */
  588. /*   Call failed     - ERROR_NOT_ENOUGH_MEMORY (8)                   */
  589. /*                                                                   */
  590. /* Example:                                                          */
  591. /*                                                                   */
  592. /*   call RxFuncAdd 'RxAsyncLoadFuncs','RXASYNC','RxAsyncLoadFuncs'  */
  593. /*   call RxAsyncLoadFuncs                                           */
  594. /*   Say 'RxAsyncLoadFuncs is complete.'                             */
  595. /*                                                                   */
  596. /*********************************************************************/
  597.  
  598. APIRET RxAsyncLoadFuncs(
  599.           CHAR     *name,
  600.           ULONG    numargs,
  601.           RXSTRING args[],
  602.           CHAR     *queuename,
  603.           RXSTRING *retstr
  604.        )
  605. {
  606.    APIRET    rc;                       /* Function return code       */
  607.  
  608.    if ( numargs != 0 )                 /* Must have no arguments     */
  609.       return( ROUTINE_INVALID );
  610.  
  611.    if ( LoadRxFuncs() ) {
  612.       rc = NO_ERROR;                   /* Load successful            */
  613.    } else {
  614.       rc = ERROR_NOT_ENOUGH_MEMORY;    /* Load failed                */
  615.    }
  616.  
  617.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  618.  
  619.    BUILDRXDOSRET( retstr, rc );
  620.  
  621.    return( ROUTINE_VALID );            /* All ok                     */
  622. }
  623.  
  624. /*********************************************************************/
  625. /*                                                                   */
  626. /* Function:  RxAsyncPriority                                        */
  627. /*                                                                   */
  628. /* Purpose:   Set Rexx process priority                              */
  629. /*                                                                   */
  630. /* Syntax:    rc = RxAsyncPriority( class, level )                   */
  631. /*                                                                   */
  632. /* Params:    class - Priority class 0..4                            */
  633. /*                       0 = NOCHANGE                                */
  634. /*                       1 = IDLETIME                                */
  635. /*                       2 = REGULAR                                 */
  636. /*                       3 = TIMECRITICAL                            */
  637. /*                       4 = FOREGROUNDSERVER                        */
  638. /*            level - Change current level -31..+31                  */
  639. /*                       (normally zero)                             */
  640. /*                                                                   */
  641. /* Return:                                                           */
  642. /*   Call successful - NO_ERROR (0)                                  */
  643. /*   Call failed     - rc from DosSetPriority                        */
  644. /*                                                                   */
  645. /* Example:                                                          */
  646. /*                                                                   */
  647. /*   Crit    = 3                                                     */
  648. /*   NormLvl = 0                                                     */
  649. /*   rc = RxAsyncPriority( Crit, NormLvl )                           */
  650. /*   if rc <> 0                                                      */
  651. /*   then say 'RxAsyncPriority failed with rc=>'rc'<'                */
  652. /*   else say 'RxAsyncPriority, Class=>'Crit'<, Level=>'NormLvl'<'   */
  653. /*                                                                   */
  654. /*********************************************************************/
  655.  
  656. APIRET RxAsyncPriority(
  657.           CHAR     *name,
  658.           ULONG    numargs,
  659.           RXSTRING args[],
  660.           CHAR     *queuename,
  661.           RXSTRING *retstr
  662.        )
  663. {
  664.    APIRET    rc;                       /* Function return code       */
  665.    ULONG     ulClass;                  /* Priority class             */
  666.    LONG      lLevel;                   /* Priority level             */
  667.  
  668.    if ( numargs != 2 )                 /* Must have two arguments    */
  669.       return( ROUTINE_INVALID );
  670.  
  671.    if (   !RXVALIDSTRING(args[0])      /* Must specify class         */
  672.        || !RXVALIDSTRING(args[1]) )    /* and priority level         */
  673.       return( ROUTINE_INVALID );
  674.  
  675.    if ( !Str2Num(args[0].strptr, &ulClass, STR2NUM_DEC2ULONG) )
  676.       return( ROUTINE_INVALID );       /* Convert class failed       */
  677.  
  678.    if ( !Str2Num(args[1].strptr, &lLevel, STR2NUM_DEC2LONG) )
  679.       return( ROUTINE_INVALID );       /* Convert level failed       */
  680.  
  681.    if (   (ulClass < PRTYC_NOCHANGE)
  682.        || (ulClass > PRTYC_FOREGROUNDSERVER) )
  683.       return( ROUTINE_INVALID );       /* Invalid class              */
  684.  
  685.    if (   (lLevel < PRTYD_MINIMUM)
  686.        || (lLevel > PRTYD_MAXIMUM) )
  687.       return( ROUTINE_INVALID );       /* Invalid priority           */
  688.  
  689.    rc = SetPriority( ulClass, lLevel );
  690.  
  691.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  692.  
  693.    BUILDRXDOSRET( retstr, rc );
  694.  
  695.    return( ROUTINE_VALID );
  696. }
  697.  
  698. /*********************************************************************/
  699. /*                                                                   */
  700. /* Function:  RxAsyncSleep                                           */
  701. /*                                                                   */
  702. /* Purpose:   Sleep the specified length of time                     */
  703. /*                                                                   */
  704. /* Syntax:    call RxAsyncSleep milliseconds                         */
  705. /*                                                                   */
  706. /* Params:    millisecs - length of time to sleep                    */
  707. /*                                                                   */
  708. /* Return:                                                           */
  709. /*   Call successful - NO_ERROR (0)                                  */
  710. /*                                                                   */
  711. /* Example:                                                          */
  712. /*                                                                   */
  713. /*   say 'Sleep for a bit 'time()                                    */
  714. /*   call RxAsyncSleep 2000                                          */
  715. /*   say 'Slept enough 'time()                                       */
  716. /*                                                                   */
  717. /*********************************************************************/
  718.  
  719. APIRET RxAsyncSleep(
  720.           CHAR     *name,
  721.           ULONG    numargs,
  722.           RXSTRING args[],
  723.           CHAR     *queuename,
  724.           RXSTRING *retstr
  725.        )
  726. {
  727.    LONG  millisecs;                    /* Time to sleep              */
  728.  
  729.    if ( numargs != 1 )                 /* Must have one argument     */
  730.       return( ROUTINE_INVALID );
  731.  
  732.    if (   !RXVALIDSTRING(args[0]) )    /* Must specify time limit    */
  733.       return( ROUTINE_INVALID );
  734.  
  735.    if ( !Str2Num(args[0].strptr, &millisecs, STR2NUM_DEC2LONG) )
  736.       return( ROUTINE_INVALID );       /* Convert millisecs failed   */
  737.  
  738.    if ( millisecs < 0 )                /* Can not wait negative time */
  739.       return( ROUTINE_INVALID );
  740.  
  741.    if ( millisecs > 0 )                /* Only if its worthwile      */
  742.       DosSleep( millisecs );
  743.  
  744.    BUILDRXDOSRET( retstr, NO_ERROR );  /* Initialise return value    */
  745.  
  746.    return( ROUTINE_VALID );            /* All ok                     */
  747. }
  748.  
  749. /*********************************************************************/
  750. /*                                                                   */
  751. /* Function:  RxAsyncGetDcbInfo                                      */
  752. /*                                                                   */
  753. /* Purpose:   Return current port settings                           */
  754. /*                                                                   */
  755. /*            Utilises IOCTL 73H ASYNC_GETDCBINFO.                   */
  756. /*                                                                   */
  757. /* Syntax:    call RxAsyncGetDcbInfo handlevar, write_timeout_var,   */
  758. /*                                              read_timeout_var,    */
  759. /*                                              handshake_var,       */
  760. /*                                              flow_replace_var,    */
  761. /*                                              timeout_var,         */
  762. /*                                              error_replace_var,   */
  763. /*                                              break_replace_var,   */
  764. /*                                              xon_var,             */
  765. /*                                              xoff_var             */
  766. /*                                                                   */
  767. /* Params:    handlevar  - rexx variable with com handle             */
  768. /*            writevar   - rexx variable to store write timeout      */
  769. /*            readvar    - rexx variable to store read timeout       */
  770. /*            handflgvar - rexx variable to store handshake flags 1  */
  771. /*            flowflgvar - rexx variable to store flow-repl flags 2  */
  772. /*            timeflgvar - rexx variable to store timeout flags 3    */
  773. /*            errreplvar - rexx variable to store error-repl char    */
  774. /*            brkreplvar - rexx variable to store break-repl char    */
  775. /*            xonvar     - rexx variable to store xon char           */
  776. /*            xoffvar    - rexx variable to store xoff char          */
  777. /*                                                                   */
  778. /* Return:                                                           */
  779. /*   Call successful - NO_ERROR (0)                                  */
  780. /*   Call failed     - ERROR_NOT_ENOUGH_MEMORY (8)                   */
  781. /*          "        - ERROR_INVALID_PARAMETER (87)                  */
  782. /*          "        - rc from DosDevIOCtl                           */
  783. /*                                                                   */
  784. /* Example:                                                          */
  785. /*                                                                   */
  786. /*   rc = RxAsyncGetDcbInfo( PortHandle, 'wlim','rlim','flags1',     */
  787. /*                           'flags2','flags3','errch','brkch',      */
  788. /*                           'xonch','xoffch' )                      */
  789. /*   if rc <> 0                                                      */
  790. /*      then say 'RxAsyncGetDcbInfo failed with rc=>'rc'<'           */
  791. /*      else say 'RxAsyncGetDcbInfo returned okay.'                  */
  792. /*                                                                   */
  793. /*********************************************************************/
  794.  
  795. APIRET RxAsyncGetDcbInfo(
  796.           CHAR     *name,
  797.           ULONG    numargs,
  798.           RXSTRING args[],
  799.           CHAR     *queuename,
  800.           RXSTRING *retstr
  801.        )
  802. {
  803.    APIRET   rc;                        /* Function return code       */
  804.    APIRET   rxrc;                      /* RexxVariablePool return    */
  805.    HFILE    hcomPort;                  /* Communications port handle */
  806.    DCBINFO2 dcbPortInfo;               /* Device control block       */
  807.    SHVBLOCK WlimVar;                   /* Rexx var for write timeout */
  808.    SHVBLOCK RlimVar;                   /* Rexx var for read timeout  */
  809.    SHVBLOCK Flg1Var;                   /* Rexx var for flags 1       */
  810.    SHVBLOCK Flg2Var;                   /* Rexx var for flags 2       */
  811.    SHVBLOCK Flg3Var;                   /* Rexx var for flags 3       */
  812.    SHVBLOCK ErrcVar;                   /* Rexx var for err repl char */
  813.    SHVBLOCK BrkcVar;                   /* Rexx var for brk repl char */
  814.    SHVBLOCK XoncVar;                   /* Rexx var for xon char      */
  815.    SHVBLOCK XoffVar;                   /* Rexx var for xoff char     */
  816.  
  817.    if ( numargs != 10 )                /* Must have ten arguments    */
  818.       return( ROUTINE_INVALID );
  819.  
  820.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  821.        || !RXVALIDSTRING(args[1])      /* and write timeout var name */
  822.        || !RXVALIDSTRING(args[2])      /* and read timeout var name  */
  823.        || !RXVALIDSTRING(args[3])      /* and flags 1 var name       */
  824.        || !RXVALIDSTRING(args[4])      /* and flags 2 var name       */
  825.        || !RXVALIDSTRING(args[5])      /* and flags 3 var name       */
  826.        || !RXVALIDSTRING(args[6])      /* and error replace var name */
  827.        || !RXVALIDSTRING(args[7])      /* and break replace var name */
  828.        || !RXVALIDSTRING(args[8])      /* and xon character var name */
  829.        || !RXVALIDSTRING(args[9]) )    /* and xoff character var name*/
  830.       return( ROUTINE_INVALID );
  831.  
  832.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  833.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  834.  
  835.    rc = GetDcbInfo( hcomPort, &dcbPortInfo );
  836.  
  837.    if ( rc == NO_ERROR ) {
  838.  
  839.       /* fetch rexx variables details (rexx mallocs, we free) */
  840.  
  841.       InitVar( &WlimVar, &RlimVar, args[1].strptr );
  842.       InitVar( &RlimVar, &Flg1Var, args[2].strptr );
  843.       InitVar( &Flg1Var, &Flg2Var, args[3].strptr );
  844.       InitVar( &Flg2Var, &Flg3Var, args[4].strptr );
  845.       InitVar( &Flg3Var, &ErrcVar, args[5].strptr );
  846.       InitVar( &ErrcVar, &BrkcVar, args[6].strptr );
  847.       InitVar( &BrkcVar, &XoncVar, args[7].strptr );
  848.       InitVar( &XoncVar, &XoffVar, args[8].strptr );
  849.       InitVar( &XoffVar, NULL,     args[9].strptr );
  850.  
  851.       rc = FetchVar( &WlimVar );       /* GET the rexx variables     */
  852.  
  853.       if ( rc == NO_ERROR ) {
  854.  
  855.          /* set rexx variable details with retrieved values */
  856.  
  857.          EditVar( &WlimVar, VAL2STR_USHORT2DEC, &(dcbPortInfo.usWriteTimeout) );
  858.          EditVar( &RlimVar, VAL2STR_USHORT2DEC, &(dcbPortInfo.usReadTimeout) );
  859.          EditVar( &Flg1Var, VAL2STR_BYTE2HEX,   &(dcbPortInfo.fbCtlHndShake) );
  860.          EditVar( &Flg2Var, VAL2STR_BYTE2HEX,   &(dcbPortInfo.fbFlowReplace) );
  861.          EditVar( &Flg3Var, VAL2STR_BYTE2HEX,   &(dcbPortInfo.fbTimeout) );
  862.          EditVar( &ErrcVar, VAL2STR_BYTE2HEX,   &(dcbPortInfo.bErrorReplacementChar) );
  863.          EditVar( &BrkcVar, VAL2STR_BYTE2HEX,   &(dcbPortInfo.bBreakReplacementChar) );
  864.          EditVar( &XoncVar, VAL2STR_BYTE2HEX,   &(dcbPortInfo.bXONChar) );
  865.          EditVar( &XoffVar, VAL2STR_BYTE2HEX,   &(dcbPortInfo.bXOFFChar) );
  866.  
  867.          rc = UpdateVar( &WlimVar );   /* SET the rexx variables     */
  868.       }
  869.  
  870.       FreeVar( &WlimVar );             /* Cleanup                    */
  871.    }
  872.  
  873.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  874.  
  875.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  876.  
  877.    return( ROUTINE_VALID );
  878. }
  879.  
  880. /*********************************************************************/
  881. /*                                                                   */
  882. /* Function:  RxAsyncSetDcbInfo                                      */
  883. /*                                                                   */
  884. /* Purpose:   Update current port settings                           */
  885. /*                                                                   */
  886. /*            Utilises IOCTLs 53H ASYNC_SETDCBINFO                   */
  887. /*                        and 73H ASYNC_GETDCBINFO.                  */
  888. /*                                                                   */
  889. /* Syntax:    call RxAsyncSetDcbInfo port,                           */
  890. /*                                   write_timeout,                  */
  891. /*                                   read_timeout,                   */
  892. /*                                   handshake,                      */
  893. /*                                   flow_replace,                   */
  894. /*                                   timeout,                        */
  895. /*                                   error_replace,                  */
  896. /*                                   break_replace,                  */
  897. /*                                   xon,                            */
  898. /*                                   xoff                            */
  899. /*                                                                   */
  900. /* Params:    port       - com port handle                           */
  901. /*            wlimit     - write timeout                             */
  902. /*            rlimit     - read timeout                              */
  903. /*            flags1     - handshake flags 1                         */
  904. /*            flags2     - flow-replace flags 2                      */
  905. /*            flags3     - timeout flags 3                           */
  906. /*            err_repl   - error-replace char                        */
  907. /*            brk_repl   - break-replace char                        */
  908. /*            xon        - xon char                                  */
  909. /*            xoff       - xoff char                                 */
  910. /*                                                                   */
  911. /* Return:                                                           */
  912. /*   Call successful - NO_ERROR (0)                                  */
  913. /*   Call failed     - rc from DosDevIOCtl                           */
  914. /*                                                                   */
  915. /* Notes:                                                            */
  916. /*   Parameters other than the PortHandle are optional in that if    */
  917. /*   specified as null items they will not cause the existing        */
  918. /*   settings to be alterred.                                        */
  919. /*                                                                   */
  920. /* Example:                                                          */
  921. /*                                                                   */
  922. /*   rc = RxAsyncSetDcbInfo( PortHandle,                             */
  923. /*                           100,                                    */
  924. /*                           50,                                     */
  925. /*                           '01001001',                             */
  926. /*                           '10100000',                             */
  927. /*                           '11010010',                             */
  928. /*                           '00',                                   */
  929. /*                           '00',                                   */
  930. /*                           '11',                                   */
  931. /*                           '13' )                                  */
  932. /*   if rc <> 0                                                      */
  933. /*      then say 'RxAsyncSetDcbInfo failed with rc=>'rc'<'           */
  934. /*      else say 'RxAsyncSetDcbInfo returned okay.'                  */
  935. /*                                                                   */
  936. /*********************************************************************/
  937.  
  938. APIRET RxAsyncSetDcbInfo(
  939.           CHAR     *name,
  940.           ULONG    numargs,
  941.           RXSTRING args[],
  942.           CHAR     *queuename,
  943.           RXSTRING *retstr
  944.        )
  945. {
  946.    APIRET   rc;                        /* Function return code       */
  947.    HFILE    hcomPort;                  /* Communications port handle */
  948.    DCBINFO2 dcbPortInfo;               /* Device control block       */
  949.  
  950.    if ( numargs != 10 )                /* Must have ten arguments    */
  951.       return( ROUTINE_INVALID );
  952.  
  953.    if ( !RXVALIDSTRING(args[0]) )      /* Must specify port          */
  954.       return( ROUTINE_INVALID );
  955.  
  956.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  957.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  958.  
  959.    rc = GetDcbInfo( hcomPort, &dcbPortInfo );
  960.  
  961.    if ( rc == NO_ERROR ) {
  962.  
  963.       if ( RXVALIDSTRING(args[1]) )    /* If specify write timeout   */
  964.          if ( !Str2Num(args[1].strptr, &(dcbPortInfo.usWriteTimeout), STR2NUM_DEC2USHORT) )
  965.             return( ROUTINE_INVALID );
  966.  
  967.       if ( RXVALIDSTRING(args[2]) )    /* If specify read timeout    */
  968.          if ( !Str2Num(args[2].strptr, &(dcbPortInfo.usReadTimeout), STR2NUM_DEC2USHORT) )
  969.             return( ROUTINE_INVALID );
  970.  
  971.       if ( RXVALIDSTRING(args[3]) )    /* If specify flags 1         */
  972.          if ( !Str2Num(args[3].strptr, &(dcbPortInfo.fbCtlHndShake), STR2NUM_BIN2BYTE) )
  973.             return( ROUTINE_INVALID );
  974.  
  975.       if ( RXVALIDSTRING(args[4]) )    /* If specify flags 2         */
  976.          if ( !Str2Num(args[4].strptr, &(dcbPortInfo.fbFlowReplace), STR2NUM_BIN2BYTE) )
  977.             return( ROUTINE_INVALID );
  978.  
  979.       if ( RXVALIDSTRING(args[5]) )    /* If specify flags 3         */
  980.          if ( !Str2Num(args[5].strptr, &(dcbPortInfo.fbTimeout), STR2NUM_BIN2BYTE) )
  981.             return( ROUTINE_INVALID );
  982.  
  983.       if ( RXVALIDSTRING(args[6]) )    /* If specify error replace   */
  984.          if ( !Str2Num(args[6].strptr, &(dcbPortInfo.bErrorReplacementChar), STR2NUM_HEX2BYTE) )
  985.             return( ROUTINE_INVALID );
  986.  
  987.       if ( RXVALIDSTRING(args[7]) )    /* If specify break replace   */
  988.          if ( !Str2Num(args[7].strptr, &(dcbPortInfo.bBreakReplacementChar), STR2NUM_HEX2BYTE) )
  989.             return( ROUTINE_INVALID );
  990.  
  991.       if ( RXVALIDSTRING(args[8]) )    /* If specify xon character   */
  992.          if ( !Str2Num(args[8].strptr, &(dcbPortInfo.bXONChar), STR2NUM_HEX2BYTE) )
  993.             return( ROUTINE_INVALID );
  994.  
  995.       if ( RXVALIDSTRING(args[9]) )    /* If specify xoff character  */
  996.          if ( !Str2Num(args[9].strptr, &(dcbPortInfo.bXOFFChar), STR2NUM_HEX2BYTE) )
  997.             return( ROUTINE_INVALID );
  998.  
  999.       rc = SetDcbInfo( hcomPort, &dcbPortInfo );
  1000.    }
  1001.  
  1002.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1003.  
  1004.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  1005.  
  1006.    return( ROUTINE_VALID );
  1007. }
  1008.  
  1009. /*********************************************************************/
  1010. /*                                                                   */
  1011. /* Function:  RxAsyncGetEnhParm                                      */
  1012. /*                                                                   */
  1013. /* Purpose:   Return current settings                                */
  1014. /*                                                                   */
  1015. /*            Utilises IOCTL 74H ASYNC_GETENHPARM.                   */
  1016. /*                                                                   */
  1017. /* Syntax:    call RxAsyncGetEnhParm handlevar, enhparmvar           */
  1018. /*                                                                   */
  1019. /* Params:    handlevar  - rexx variable with com handle             */
  1020. /*            enhparmvar - rexx variable to store parameter value    */
  1021. /*                                                                   */
  1022. /* Return:                                                           */
  1023. /*   Call successful - NO_ERROR (0)                                  */
  1024. /*   Call failed     - rc from DosDevIOCtl                           */
  1025. /*                                                                   */
  1026. /* Example:                                                          */
  1027. /*                                                                   */
  1028. /*   EnhParm = '00'                                                  */
  1029. /*   rc = RxAsyncGetEnhParm( PortHandle, 'EnhParm' )                 */
  1030. /*   if rc <> 0                                                      */
  1031. /*      then say 'RxAsyncGetEnhParm failed with rc=>'rc'<'           */
  1032. /*      else do                                                      */
  1033. /*             say 'RxAsyncGetEnhParm returned okay.'                */
  1034. /*             if substr( X2B(EnhParm), 1, 1 ) = '1'                 */
  1035. /*                then say 'Enhanced mode DMA transmit is ON.'       */
  1036. /*             if substr( X2B(EnhParm), 2, 1 ) = '1'                 */
  1037. /*                then say 'Enhanced mode DMA receive is ON.'        */
  1038. /*             if substr( X2B(EnhParm), 3, 2 ) = '10'                */
  1039. /*                then say 'DMA transmit on with dedicated channel.' */
  1040. /*             if substr( X2B(EnhParm), 3, 2 ) = '01'                */
  1041. /*                then say 'DMA transmit is enabled.'                */
  1042. /*             if substr( X2B(EnhParm), 3, 2 ) = '00'                */
  1043. /*                then say 'DMA transmit is disabled.'               */
  1044. /*             if substr( X2B(EnhParm), 5, 2 ) = '10'                */
  1045. /*                then say 'DMA receive on with dedicated channel.'  */
  1046. /*             if substr( X2B(EnhParm), 5, 2 ) = '01'                */
  1047. /*                then say 'DMA receive is enabled.'                 */
  1048. /*             if substr( X2B(EnhParm), 5, 2 ) = '00'                */
  1049. /*                then say 'DMA receive is disabled.'                */
  1050. /*             if substr( X2B(EnhParm), 7, 1 ) = '1'                 */
  1051. /*                then say 'Enhanced mode is enabled.'               */
  1052. /*             if substr( X2B(EnhParm), 8, 1 ) = '1'                 */
  1053. /*                then say 'Enhanced mode is supported.'             */
  1054. /*           end                                                     */
  1055. /*                                                                   */
  1056. /*********************************************************************/
  1057.  
  1058. APIRET RxAsyncGetEnhParm(
  1059.           CHAR     *name,
  1060.           ULONG    numargs,
  1061.           RXSTRING args[],
  1062.           CHAR     *queuename,
  1063.           RXSTRING *retstr
  1064.        )
  1065. {
  1066.    APIRET   rc;                        /* Function return code       */
  1067.    HFILE    hcomPort;                  /* Communications port handle */
  1068.    BYTE     bEnhancedFlags;            /* Enhanced Mode Parameters   */
  1069.  
  1070.    if ( numargs != 2 )                 /* Must have two arguments    */
  1071.       return( ROUTINE_INVALID );
  1072.  
  1073.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  1074.        || !RXVALIDSTRING(args[1]) )    /* and enh parameters var name*/
  1075.       return( ROUTINE_INVALID );
  1076.  
  1077.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1078.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1079.  
  1080.    rc = GetEnhParm( hcomPort, &bEnhancedFlags );
  1081.  
  1082.    if ( rc == NO_ERROR ) {
  1083.       rc = SetRexxValue( args[1].strptr, VAL2STR_BYTE2HEX, &bEnhancedFlags );
  1084.    }
  1085.  
  1086.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1087.  
  1088.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  1089.  
  1090.    return( ROUTINE_VALID );
  1091. }
  1092.  
  1093. /*********************************************************************/
  1094. /*                                                                   */
  1095. /* Function:  RxAsyncSetEnhParm                                      */
  1096. /*                                                                   */
  1097. /* Purpose:   Update current settings                                */
  1098. /*                                                                   */
  1099. /*            Utilises IOCTLs 54H ASYNC_SETENHPARM                   */
  1100. /*                        and 74H ASYNC_GETENHPARM.                  */
  1101. /*                                                                   */
  1102. /* Syntax:    call RxAsyncSetEnhParm handlevar, enhparmvar           */
  1103. /*                                                                   */
  1104. /* Params:    handlevar  - rexx variable with com handle             */
  1105. /*            enhparmvar - rexx variable with parameter settings     */
  1106. /*                                                                   */
  1107. /* Return:                                                           */
  1108. /*   Call successful - NO_ERROR (0)                                  */
  1109. /*   Call failed     - rc from DosDevIOCtl                           */
  1110. /*                                                                   */
  1111. /* Example:                                                          */
  1112. /*                                                                   */
  1113. /*   EnhParm = '00000010'                                            */
  1114. /*   rc = RxAsyncSetEnhParm( PortHandle, EnhParm )                   */
  1115. /*   if rc <> 0                                                      */
  1116. /*      then say 'RxAsyncSetEnhParm failed with rc=>'rc'<'           */
  1117. /*      else say 'RxAsyncSetEnhParm returned okay.'                  */
  1118. /*                                                                   */
  1119. /*********************************************************************/
  1120.  
  1121. APIRET RxAsyncSetEnhParm(
  1122.           CHAR     *name,
  1123.           ULONG    numargs,
  1124.           RXSTRING args[],
  1125.           CHAR     *queuename,
  1126.           RXSTRING *retstr
  1127.        )
  1128. {
  1129.    APIRET   rc;                        /* Function return code       */
  1130.    HFILE    hcomPort;                  /* Communications port handle */
  1131.    BYTE     bEnhancedFlags;            /* Enhanced Mode Parameters   */
  1132.  
  1133.    if ( numargs != 2 )                 /* Must have two arguments    */
  1134.       return( ROUTINE_INVALID );
  1135.  
  1136.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  1137.        || !RXVALIDSTRING(args[1]) )    /* and enh parameters         */
  1138.       return( ROUTINE_INVALID );
  1139.  
  1140.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1141.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1142.  
  1143.    if ( !Str2Num(args[1].strptr, &bEnhancedFlags, STR2NUM_BIN2BYTE) )
  1144.       return( ROUTINE_INVALID );       /* Convert parameters failed  */
  1145.  
  1146.    rc = SetEnhParm( hcomPort, bEnhancedFlags );
  1147.  
  1148.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1149.  
  1150.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  1151.  
  1152.    return( ROUTINE_VALID );
  1153. }
  1154.  
  1155. /*********************************************************************/
  1156. /*                                                                   */
  1157. /* Function:  RxAsyncGetLnCtrl                                       */
  1158. /*                                                                   */
  1159. /* Purpose:   Get status of specified port                           */
  1160. /*                                                                   */
  1161. /*            Utilises IOCTLs 62H ASYNC_GETLINECTRL                  */
  1162. /*                        and 63H ASYNC_GETEXTDRATE.                 */
  1163. /*                                                                   */
  1164. /* Syntax:    call RxAsyncGetLnCtrl port                             */
  1165. /*                                  'baud' 'data' 'parity' 'stop'    */
  1166. /*                                                                   */
  1167. /* Params:    port   - handle of open port                           */
  1168. /*            baud   - rexx variable to store baudrate in            */
  1169. /*            data   - rexx variable to store databits in            */
  1170. /*            parity - rexx variable to store parity in              */
  1171. /*            stop   - rexx variable to store stopbits in            */
  1172. /*                                                                   */
  1173. /* Return:                                                           */
  1174. /*   Call successful - NO_ERROR (0)                                  */
  1175. /*   Call failed     - ERROR_NOT_ENOUGH_MEMORY (8)                   */
  1176. /*          "        - ERROR_INVALID_PARAMETER (87)                  */
  1177. /*          "        - rc from DosDevIOCtl                           */
  1178. /*                                                                   */
  1179. /* Example:                                                          */
  1180. /*                                                                   */
  1181. /*   OldBaud    = 0                                                  */
  1182. /*   OldData    = 0                                                  */
  1183. /*   OldParity  = ''                                                 */
  1184. /*   OldStop    = 0                                                  */
  1185. /*   rc = RxAsyncGetLnCtrl( PortHandle, 'OldBaud',                   */
  1186. /*                          'OldData', 'OldParity', 'OldStop' )      */
  1187. /*   if rc <> 0                                                      */
  1188. /*      then say 'RxAsyncGetLnCtrl failed with rc=>'rc'<'            */
  1189. /*      else say 'RxAsyncGetLnCtrl saved the original settings'      */
  1190. /*                                                                   */
  1191. /*   say 'Baudrate was >'OldBaud'<'                                  */
  1192. /*   say 'Databits was >'OldData'<'                                  */
  1193. /*   say 'Parity   was >'OldParity'<'                                */
  1194. /*   say 'Stopbits was >'OldStop'<'                                  */
  1195. /*                                                                   */
  1196. /*********************************************************************/
  1197.  
  1198. APIRET RxAsyncGetLnCtrl(
  1199.           CHAR     *name,
  1200.           ULONG    numargs,
  1201.           RXSTRING args[],
  1202.           CHAR     *queuename,
  1203.           RXSTRING *retstr
  1204.        )
  1205. {
  1206.    APIRET       rc;                    /* Function return code       */
  1207.    APIRET       rxrc;                  /* RexxVariablePool return    */
  1208.    HFILE        hcomPort;              /* Communications port handle */
  1209.    EXTDRATE     erateBaudRate;         /* Extended bitrate params    */
  1210.    LINECONTROL  lnctlLineControl;      /* Line control parameters    */
  1211.    SHVBLOCK     BaudVar;               /* Rexx variable for baudrate */
  1212.    SHVBLOCK     DataVar;               /* Rexx variable for databits */
  1213.    SHVBLOCK     PariVar;               /* Rexx variable for parity   */
  1214.    SHVBLOCK     StopVar;               /* Rexx variable for stopbits */
  1215.    PSZ          pszDataBits;
  1216.    PSZ          pszStopBits;
  1217.    PSZ          pszParity;
  1218.  
  1219.    if ( numargs != 5 )                 /* Must have five arguments   */
  1220.       return( ROUTINE_INVALID );
  1221.  
  1222.    if (   !RXVALIDSTRING(args[0])      /* Must specify port handle   */
  1223.        || !RXVALIDSTRING(args[1])      /* and baudrate var name      */
  1224.        || !RXVALIDSTRING(args[2])      /* and databits var name      */
  1225.        || !RXVALIDSTRING(args[3])      /* and parity var name        */
  1226.        || !RXVALIDSTRING(args[4]) )    /* and stopbits var name      */
  1227.       return( ROUTINE_INVALID );
  1228.  
  1229.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1230.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1231.  
  1232.    rc = GetLnCtrl( hcomPort, &erateBaudRate, &lnctlLineControl );
  1233.  
  1234.    if ( rc == NO_ERROR ) {
  1235.  
  1236.       switch( lnctlLineControl.bDataBits )
  1237.       {
  1238.          case DATA_BITS_5:
  1239.               pszDataBits = DATA_BITS_5_STR;
  1240.               break;
  1241.          case DATA_BITS_6:
  1242.               pszDataBits = DATA_BITS_6_STR;
  1243.               break;
  1244.          case DATA_BITS_7:
  1245.               pszDataBits = DATA_BITS_7_STR;
  1246.               break;
  1247.          case DATA_BITS_8:
  1248.               pszDataBits = DATA_BITS_8_STR;
  1249.               break;
  1250.          default:
  1251.               pszDataBits = DATA_BITS_UNKNOWN_STR;
  1252.               break;
  1253.       }
  1254.  
  1255.       switch( lnctlLineControl.bParity )
  1256.       {
  1257.          case PARITY_NONE:
  1258.               pszParity = PARITY_NONE_STR;
  1259.               break;
  1260.          case PARITY_ODD:
  1261.               pszParity = PARITY_ODD_STR;
  1262.               break;
  1263.          case PARITY_EVEN:
  1264.               pszParity = PARITY_EVEN_STR;
  1265.               break;
  1266.          case PARITY_MARK:
  1267.               pszParity = PARITY_MARK_STR;
  1268.               break;
  1269.          case PARITY_SPACE:
  1270.               pszParity = PARITY_SPACE_STR;
  1271.               break;
  1272.          default:
  1273.               pszParity = PARITY_UNKNOWN_STR;
  1274.               break;
  1275.       }
  1276.  
  1277.       switch( lnctlLineControl.bStopBits )
  1278.       {
  1279.          case STOP_BITS_1:
  1280.               pszStopBits = STOP_BITS_1_STR;
  1281.               break;
  1282.          case STOP_BITS_15:
  1283.               pszStopBits = STOP_BITS_15_STR;
  1284.               break;
  1285.          case STOP_BITS_2:
  1286.               pszStopBits = STOP_BITS_2_STR;
  1287.               break;
  1288.          default:
  1289.               pszStopBits = STOP_BITS_UNKNOWN_STR;
  1290.               break;
  1291.       }
  1292.  
  1293.       /* fetch rexx variables details (rexx mallocs, we free) */
  1294.  
  1295.       InitVar( &BaudVar, &DataVar, args[1].strptr );
  1296.       InitVar( &DataVar, &PariVar, args[2].strptr );
  1297.       InitVar( &PariVar, &StopVar, args[3].strptr );
  1298.       InitVar( &StopVar, NULL,     args[4].strptr );
  1299.  
  1300.       rc = FetchVar( &BaudVar );       /* GET the rexx variables     */
  1301.  
  1302.       if ( rc == NO_ERROR ) {
  1303.  
  1304.          /* set rexx variable details with retrieved values */
  1305.  
  1306.          EditVar( &BaudVar, VAL2STR_ULONG2DEC, &(erateBaudRate.ulCurrentBaudRate) );
  1307.          EditVar( &DataVar, VAL2STR_STR2STR,   pszDataBits );
  1308.          EditVar( &PariVar, VAL2STR_STR2STR,   pszParity );
  1309.          EditVar( &StopVar, VAL2STR_STR2STR,   pszStopBits );
  1310.  
  1311.          rc = UpdateVar( &BaudVar );   /* SET the rexx variables     */
  1312.       }
  1313.  
  1314.       FreeVar( &BaudVar );             /* Cleanup                    */
  1315.    }
  1316.  
  1317.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1318.  
  1319.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  1320.  
  1321.    return( ROUTINE_VALID );
  1322. }
  1323.  
  1324. /*********************************************************************/
  1325. /*                                                                   */
  1326. /* Function:  RxAsyncSetLnCtrl                                       */
  1327. /*                                                                   */
  1328. /* Purpose:   Set status of specified port                           */
  1329. /*                                                                   */
  1330. /*            Utilises IOCTLs 62H ASYNC_GETLINECTRL                  */
  1331. /*                        and 63H ASYNC_GETEXTDRATE                  */
  1332. /*                        and 42H ASYNC_SETLINECTRL                  */
  1333. /*                        and 43H ASYNC_SETEXTDRATE.                 */
  1334. /*                                                                   */
  1335. /* Syntax:    call RxAsyncSetLnCtrl port 19200 8 'N' 1               */
  1336. /*                                                                   */
  1337. /* Params:    port   - handle of open port                           */
  1338. /*            baud   - baudrate to set                               */
  1339. /*            data   - data bits to set                              */
  1340. /*            parity - parity to set                                 */
  1341. /*            stop   - stop bits to set                              */
  1342. /*                                                                   */
  1343. /* Return:                                                           */
  1344. /*   Call successful - NO_ERROR (0)                                  */
  1345. /*   Call failed     - ERROR_INVALID_PARAMETER (87)                  */
  1346. /*          "        - rc from DosDevIOCtl                           */
  1347. /*                                                                   */
  1348. /* Example:                                                          */
  1349. /*                                                                   */
  1350. /*   NewBaud    = 19200                                              */
  1351. /*   NewData    = 8                                                  */
  1352. /*   NewParity  = 'N'                                                */
  1353. /*   NewStop    = 1                                                  */
  1354. /*   rc = RxAsyncSetLnCtrl( PortHandle, NewBaud,                     */
  1355. /*                          NewData, NewParity, NewStop )            */
  1356. /*   if rc <> 0                                                      */
  1357. /*     then                                                          */
  1358. /*       say 'RxAsyncSetLnCtrl failed with rc=>'rc'<'                */
  1359. /*     else                                                          */
  1360. /*       say 'RxAsyncSetLnCtrl has set the new settings'             */
  1361. /*                                                                   */
  1362. /*   say 'Baudrate now >'NewBaud'<'                                  */
  1363. /*   say 'Databits now >'NewData'<'                                  */
  1364. /*   say 'Parity   now >'NewParity'<'                                */
  1365. /*   say 'Stopbits now >'NewStop'<'                                  */
  1366. /*                                                                   */
  1367. /*********************************************************************/
  1368.  
  1369. APIRET RxAsyncSetLnCtrl(
  1370.           CHAR     *name,
  1371.           ULONG    numargs,
  1372.           RXSTRING args[],
  1373.           CHAR     *queuename,
  1374.           RXSTRING *retstr
  1375.        )
  1376. {
  1377.    APIRET       rc;                    /* Function return code       */
  1378.    HFILE        hcomPort;              /* Communications port handle */
  1379.    EXTDRATE     erateBaudRate;         /* Extended bitrate params    */
  1380.    LINECONTROL  lnctlLineControl;      /* Line control parameters    */
  1381.  
  1382.    if ( numargs != 5 )                 /* Must have five arguments   */
  1383.       return( ROUTINE_INVALID );
  1384.  
  1385.    if ( !RXVALIDSTRING(args[0]) )      /* Must specify port handle   */
  1386.       return( ROUTINE_INVALID );
  1387.  
  1388.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1389.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1390.  
  1391.    rc = GetLnCtrl( hcomPort, &erateBaudRate, &lnctlLineControl );
  1392.  
  1393.    if ( rc == NO_ERROR ) {
  1394.  
  1395.       if ( RXVALIDSTRING(args[1]) ) /* If specify baud rate       */
  1396.       {
  1397.          if ( !Str2Num(args[1].strptr, &(erateBaudRate.ulCurrentBaudRate), STR2NUM_DEC2ULONG) )
  1398.             return( ROUTINE_INVALID );       /* Convert baudrate failed    */
  1399.  
  1400.          erateBaudRate.bCurrentFraction  = (BYTE)0;
  1401.       }
  1402.  
  1403.       if ( RXVALIDSTRING(args[2]) ) /* If specify data bits       */
  1404.       {
  1405.          if        ( strcmp(args[2].strptr,  DATA_BITS_5_STR) == 0 ) {
  1406.             lnctlLineControl.bDataBits  = DATA_BITS_5;
  1407.          } else if ( strcmp(args[2].strptr,  DATA_BITS_6_STR) == 0 ) {
  1408.             lnctlLineControl.bDataBits  = DATA_BITS_6;
  1409.          } else if ( strcmp(args[2].strptr,  DATA_BITS_7_STR) == 0 ) {
  1410.             lnctlLineControl.bDataBits  = DATA_BITS_7;
  1411.          } else if ( strcmp(args[2].strptr,  DATA_BITS_8_STR) == 0 ) {
  1412.             lnctlLineControl.bDataBits  = DATA_BITS_8;
  1413.          } else {
  1414.             rc = ERROR_INVALID_PARAMETER;
  1415.          }
  1416.       }
  1417.  
  1418.       if ( RXVALIDSTRING(args[3]) ) /* If specify parity          */
  1419.       {
  1420.          if        ( stricmp(args[3].strptr, PARITY_NONE_STR ) == 0 ) {
  1421.             lnctlLineControl.bParity    = PARITY_NONE;
  1422.          } else if ( stricmp(args[3].strptr, PARITY_ODD_STR  ) == 0 ) {
  1423.             lnctlLineControl.bParity    = PARITY_ODD;
  1424.          } else if ( stricmp(args[3].strptr, PARITY_EVEN_STR ) == 0 ) {
  1425.             lnctlLineControl.bParity    = PARITY_EVEN;
  1426.          } else if ( stricmp(args[3].strptr, PARITY_MARK_STR ) == 0 ) {
  1427.             lnctlLineControl.bParity    = PARITY_MARK;
  1428.          } else if ( stricmp(args[3].strptr, PARITY_SPACE_STR) == 0 ) {
  1429.             lnctlLineControl.bParity    = PARITY_SPACE;
  1430.          } else {
  1431.             rc = ERROR_INVALID_PARAMETER;
  1432.          }
  1433.       }
  1434.  
  1435.       if ( RXVALIDSTRING(args[4]) ) /* If specify stop bits       */
  1436.       {
  1437.          if        ( strcmp(args[4].strptr,  STOP_BITS_1_STR ) == 0 ) {
  1438.             lnctlLineControl.bStopBits  = STOP_BITS_1;
  1439.          } else if ( strcmp(args[4].strptr,  STOP_BITS_15_STR) == 0 ) {
  1440.             lnctlLineControl.bStopBits  = STOP_BITS_15;
  1441.          } else if ( strcmp(args[4].strptr,  STOP_BITS_2_STR ) == 0 ) {
  1442.             lnctlLineControl.bStopBits  = STOP_BITS_2;
  1443.          } else {
  1444.             rc = ERROR_INVALID_PARAMETER;
  1445.          }
  1446.       }
  1447.  
  1448.       if ( rc == NO_ERROR ) {
  1449.  
  1450.          rc = SetLnCtrl( hcomPort, &erateBaudRate, &lnctlLineControl );
  1451.  
  1452.       }
  1453.    }
  1454.  
  1455.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1456.  
  1457.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  1458.  
  1459.    return( ROUTINE_VALID );
  1460. }
  1461.  
  1462. /*********************************************************************/
  1463. /*                                                                   */
  1464. /* Function:  RxAsyncSetBreakOff                                     */
  1465. /*                                                                   */
  1466. /* Purpose:   Set break off                                          */
  1467. /*                                                                   */
  1468. /*            Utilises IOCTL 45H ASYNC_SETBREAKOFF.                  */
  1469. /*                                                                   */
  1470. /* Syntax:    call RxAsyncSetBreakOff handlevar                      */
  1471. /*                                                                   */
  1472. /* Params:    handlevar - rexx variable with com handle              */
  1473. /*                                                                   */
  1474. /* Return:                                                           */
  1475. /*   Call successful - NO_ERROR (0)                                  */
  1476. /*   Call failed     - rc from DosDevIOCtl                           */
  1477. /*                                                                   */
  1478. /* Example:                                                          */
  1479. /*                                                                   */
  1480. /*   rc = RxAsyncSetBreakOff( PortHandle )                           */
  1481. /*   if rc <> 0                                                      */
  1482. /*      then say 'RxAsyncSetBreakOff failed with rc=>'rc'<'          */
  1483. /*      else say 'RxAsyncSetBreakOff returned okay'                  */
  1484. /*                                                                   */
  1485. /*********************************************************************/
  1486.  
  1487. APIRET RxAsyncSetBreakOff(
  1488.           CHAR     *name,
  1489.           ULONG    numargs,
  1490.           RXSTRING args[],
  1491.           CHAR     *queuename,
  1492.           RXSTRING *retstr
  1493.        )
  1494. {
  1495.    APIRET    rc;                       /* Function return code       */
  1496.    HFILE    hcomPort;                  /* Communications port handle */
  1497.  
  1498.    if ( numargs != 1 )                 /* Must have one argument     */
  1499.       return( ROUTINE_INVALID );
  1500.  
  1501.    if ( !RXVALIDSTRING(args[0]) )      /* Must specify port handle   */
  1502.       return( ROUTINE_INVALID );
  1503.  
  1504.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1505.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1506.  
  1507.    rc = SetBreakOff( hcomPort );
  1508.  
  1509.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1510.  
  1511.    BUILDRXDOSRET( retstr, rc );
  1512.  
  1513.    return( ROUTINE_VALID );
  1514. }
  1515.  
  1516. /*********************************************************************/
  1517. /*                                                                   */
  1518. /* Function:  RxAsyncSetBreakOn                                      */
  1519. /*                                                                   */
  1520. /* Purpose:   Set break on                                           */
  1521. /*                                                                   */
  1522. /*            Utilises IOCTL 4BH ASYNC_SETBREAKON.                   */
  1523. /*                                                                   */
  1524. /* Syntax:    call RxAsyncSetBreakOn handlevar                       */
  1525. /*                                                                   */
  1526. /* Params:    handlevar - rexx variable with com handle              */
  1527. /*                                                                   */
  1528. /* Return:                                                           */
  1529. /*   Call successful - NO_ERROR (0)                                  */
  1530. /*   Call failed     - rc from DosDevIOCtl                           */
  1531. /*                                                                   */
  1532. /* Example:                                                          */
  1533. /*                                                                   */
  1534. /*   rc = RxAsyncSetBreakOn( PortHandle )                            */
  1535. /*   if rc <> 0                                                      */
  1536. /*      then say 'RxAsyncSetBreakOn failed with rc=>'rc'<'           */
  1537. /*      else say 'RxAsyncSetBreakOn returned okay'                   */
  1538. /*                                                                   */
  1539. /*********************************************************************/
  1540.  
  1541. APIRET RxAsyncSetBreakOn(
  1542.           CHAR     *name,
  1543.           ULONG    numargs,
  1544.           RXSTRING args[],
  1545.           CHAR     *queuename,
  1546.           RXSTRING *retstr
  1547.        )
  1548. {
  1549.    APIRET    rc;                       /* Function return code       */
  1550.    HFILE    hcomPort;                  /* Communications port handle */
  1551.  
  1552.    if ( numargs != 1 )                 /* Must have one argument     */
  1553.       return( ROUTINE_INVALID );
  1554.  
  1555.    if ( !RXVALIDSTRING(args[0]) )      /* Must specify port handle   */
  1556.       return( ROUTINE_INVALID );
  1557.  
  1558.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1559.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1560.  
  1561.    rc = SetBreakOn( hcomPort );
  1562.  
  1563.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1564.  
  1565.    BUILDRXDOSRET( retstr, rc );
  1566.  
  1567.    return( ROUTINE_VALID );
  1568. }
  1569.  
  1570. /*********************************************************************/
  1571. /*                                                                   */
  1572. /* Function:  RxAsyncTxImmediate                                     */
  1573. /*                                                                   */
  1574. /* Purpose:   Transmit specified byte immediately                    */
  1575. /*                                                                   */
  1576. /*            Utilises IOCTL 44H ASYNC_TRANSMITIMM.                  */
  1577. /*                                                                   */
  1578. /* Syntax:    call RxAsyncTxImmediate handlevar byte                 */
  1579. /*                                                                   */
  1580. /* Params:    handlevar - rexx variable with com handle              */
  1581. /*            byte      - byte to be transmitted                     */
  1582. /*                                                                   */
  1583. /* Return:                                                           */
  1584. /*   Call successful - NO_ERROR (0)                                  */
  1585. /*   Call failed     - rc from DosDevIOCtl                           */
  1586. /*                                                                   */
  1587. /* Example:                                                          */
  1588. /*                                                                   */
  1589. /*   escape_char = '1B'                                              */
  1590. /*   rc = RxAsyncTxImmediate( PortHandle, escape_char )              */
  1591. /*   if rc <> 0                                                      */
  1592. /*      then say 'RxAsyncTxImmediate failed with rc=>'rc'<'          */
  1593. /*      else say 'RxAsyncTxImmediate returned okay'                  */
  1594. /*                                                                   */
  1595. /*********************************************************************/
  1596.  
  1597. APIRET RxAsyncTxImmediate(
  1598.           CHAR     *name,
  1599.           ULONG    numargs,
  1600.           RXSTRING args[],
  1601.           CHAR     *queuename,
  1602.           RXSTRING *retstr
  1603.        )
  1604. {
  1605.    APIRET    rc;                       /* Function return code       */
  1606.    HFILE    hcomPort;                  /* Communications port handle */
  1607.    BYTE     bAnyByte;                  /* Byte to be sent            */
  1608.  
  1609.    if ( numargs != 2 )                 /* Must have two arguments    */
  1610.       return( ROUTINE_INVALID );
  1611.  
  1612.    if (   !RXVALIDSTRING(args[0])      /* Must specify port handle   */
  1613.        || !RXVALIDSTRING(args[1]) )    /* and byte to send           */
  1614.       return( ROUTINE_INVALID );
  1615.  
  1616.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1617.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1618.  
  1619.    if ( !Str2Num(args[1].strptr, &bAnyByte, STR2NUM_HEX2BYTE) )
  1620.       return( ROUTINE_INVALID );       /* Convert byte failed        */
  1621.  
  1622.    rc = TxImmediate( hcomPort, bAnyByte );
  1623.  
  1624.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1625.  
  1626.    BUILDRXDOSRET( retstr, rc );
  1627.  
  1628.    return( ROUTINE_VALID );
  1629. }
  1630.  
  1631. /*********************************************************************/
  1632. /*                                                                   */
  1633. /* Function:  RxAsyncTxStop                                          */
  1634. /*                                                                   */
  1635. /* Purpose:   Stop transmission (XOFF)                               */
  1636. /*                                                                   */
  1637. /*            Utilises IOCTL 47H ASYNC_STOPTRANSMIT.                 */
  1638. /*                                                                   */
  1639. /* Syntax:    call RxAsyncTxStop handlevar                           */
  1640. /*                                                                   */
  1641. /* Params:    handlevar  - rexx variable with com handle             */
  1642. /*                                                                   */
  1643. /* Return:                                                           */
  1644. /*   Call successful - NO_ERROR (0)                                  */
  1645. /*   Call failed     - rc from DosDevIOCtl                           */
  1646. /*                                                                   */
  1647. /* Example:                                                          */
  1648. /*                                                                   */
  1649. /*   rc = RxAsyncTxStop( PortHandle )                                */
  1650. /*   if rc <> 0                                                      */
  1651. /*      then say 'RxAsyncTxStop failed with rc=>'rc'<'               */
  1652. /*      else say 'RxAsyncTxStop returned okay.'                      */
  1653. /*                                                                   */
  1654. /*********************************************************************/
  1655.  
  1656. APIRET RxAsyncTxStop(
  1657.           CHAR     *name,
  1658.           ULONG    numargs,
  1659.           RXSTRING args[],
  1660.           CHAR     *queuename,
  1661.           RXSTRING *retstr
  1662.        )
  1663. {
  1664.    APIRET   rc;                        /* Function return code       */
  1665.    HFILE    hcomPort;                  /* Communications port handle */
  1666.  
  1667.    if ( numargs != 1 )                 /* Must have one argument     */
  1668.       return( ROUTINE_INVALID );
  1669.  
  1670.    if ( !RXVALIDSTRING(args[0]) )      /* Must specify port          */
  1671.       return( ROUTINE_INVALID );
  1672.  
  1673.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1674.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1675.  
  1676.    rc = TxStop( hcomPort );
  1677.  
  1678.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1679.  
  1680.    BUILDRXDOSRET( retstr, rc );
  1681.  
  1682.    return( ROUTINE_VALID );
  1683. }
  1684.  
  1685. /*********************************************************************/
  1686. /*                                                                   */
  1687. /* Function:  RxAsyncTxStart                                         */
  1688. /*                                                                   */
  1689. /* Purpose:   Start transmission (XON)                               */
  1690. /*                                                                   */
  1691. /*            Utilises IOCTL 48H ASYNC_STARTTRANSMIT.                */
  1692. /*                                                                   */
  1693. /* Syntax:    call RxAsyncTxStart handlevar                          */
  1694. /*                                                                   */
  1695. /* Params:    handlevar  - rexx variable with com handle             */
  1696. /*                                                                   */
  1697. /* Return:                                                           */
  1698. /*   Call successful - NO_ERROR (0)                                  */
  1699. /*   Call failed     - rc from DosDevIOCtl                           */
  1700. /*                                                                   */
  1701. /* Example:                                                          */
  1702. /*                                                                   */
  1703. /*   rc = RxAsyncTxStart( PortHandle )                               */
  1704. /*   if rc <> 0                                                      */
  1705. /*      then say 'RxAsyncTxStart failed with rc=>'rc'<'              */
  1706. /*      else say 'RxAsyncTxStart returned okay.'                     */
  1707. /*                                                                   */
  1708. /*********************************************************************/
  1709.  
  1710. APIRET RxAsyncTxStart(
  1711.           CHAR     *name,
  1712.           ULONG    numargs,
  1713.           RXSTRING args[],
  1714.           CHAR     *queuename,
  1715.           RXSTRING *retstr
  1716.        )
  1717. {
  1718.    APIRET    rc;                       /* Function return code       */
  1719.    HFILE    hcomPort;                  /* Communications port handle */
  1720.  
  1721.    if ( numargs != 1 )                 /* Must have one argument     */
  1722.       return( ROUTINE_INVALID );
  1723.  
  1724.    if ( !RXVALIDSTRING(args[0]) )      /* Must specify port          */
  1725.       return( ROUTINE_INVALID );
  1726.  
  1727.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1728.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1729.  
  1730.    rc = TxStart( hcomPort );
  1731.  
  1732.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1733.  
  1734.    BUILDRXDOSRET( retstr, rc );
  1735.  
  1736.    return( ROUTINE_VALID );
  1737. }
  1738.  
  1739. /*********************************************************************/
  1740. /*                                                                   */
  1741. /* Function:  RxAsyncGetComStatus                                    */
  1742. /*                                                                   */
  1743. /* Purpose:   Return current COM status                              */
  1744. /*                                                                   */
  1745. /*            Utilises IOCTL 64H ASYNC_GETCOMMSTATUS.                */
  1746. /*                                                                   */
  1747. /* Syntax:    call RxAsyncGetComStatus handlevar, statusvar          */
  1748. /*                                                                   */
  1749. /* Params:    handlevar  - rexx variable with com handle             */
  1750. /*            statusvar  - rexx variable to store status value       */
  1751. /*                                                                   */
  1752. /* Return:                                                           */
  1753. /*   Call successful - NO_ERROR (0)                                  */
  1754. /*   Call failed     - rc from DosDevIOCtl                           */
  1755. /*                                                                   */
  1756. /* Example:                                                          */
  1757. /*                                                                   */
  1758. /*   ComStatus = '00'                                                */
  1759. /*   rc = RxAsyncGetComStatus( PortHandle, 'ComStatus' )             */
  1760. /*   if rc <> 0                                                      */
  1761. /*      then say 'RxAsyncGetComStatus failed with rc=>'rc'<'         */
  1762. /*      else do                                                      */
  1763. /*             say 'RxAsyncGetComStatus returned okay.'              */
  1764. /*             if substr( X2B(ComStatus), 1, 1 ) = '1'               */
  1765. /*                then say 'Receive waiting for DSR.'                */
  1766. /*             if substr( X2B(ComStatus), 2, 1 ) = '1'               */
  1767. /*                then say 'Transmit waiting to send immediate.'     */
  1768. /*             if substr( X2B(ComStatus), 3, 1 ) = '1'               */
  1769. /*                then say 'Transmit waiting while break on.'        */
  1770. /*             if substr( X2B(ComStatus), 4, 1 ) = '1'               */
  1771. /*                then say 'Transmit waiting to send XON.'           */
  1772. /*             if substr( X2B(ComStatus), 5, 1 ) = '1'               */
  1773. /*                then say 'Transmit waiting for XON.'               */
  1774. /*             if substr( X2B(ComStatus), 6, 1 ) = '1'               */
  1775. /*                then say 'Transmit waiting for DCD.'               */
  1776. /*             if substr( X2B(ComStatus), 7, 1 ) = '1'               */
  1777. /*                then say 'Transmit waiting for DSR.'               */
  1778. /*             if substr( X2B(ComStatus), 8, 1 ) = '1'               */
  1779. /*                then say 'Transmit waiting for CTS.'               */
  1780. /*           end                                                     */
  1781. /*                                                                   */
  1782. /*********************************************************************/
  1783.  
  1784. APIRET RxAsyncGetComStatus(
  1785.           CHAR     *name,
  1786.           ULONG    numargs,
  1787.           RXSTRING args[],
  1788.           CHAR     *queuename,
  1789.           RXSTRING *retstr
  1790.        )
  1791. {
  1792.    APIRET   rc;                        /* Function return code       */
  1793.    HFILE    hcomPort;                  /* Communications port handle */
  1794.    BYTE     bComStatus;                /* COM status returned        */
  1795.  
  1796.    if ( numargs != 2 )                 /* Must have two arguments    */
  1797.       return( ROUTINE_INVALID );
  1798.  
  1799.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  1800.        || !RXVALIDSTRING(args[1]) )    /* and COM status var name    */
  1801.       return( ROUTINE_INVALID );
  1802.  
  1803.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1804.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1805.  
  1806.    rc = GetComStatus( hcomPort, &bComStatus );
  1807.  
  1808.    if ( rc == NO_ERROR ) {
  1809.       rc = SetRexxValue( args[1].strptr, VAL2STR_BYTE2HEX, &(bComStatus) );
  1810.    }
  1811.  
  1812.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1813.  
  1814.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  1815.  
  1816.    return( ROUTINE_VALID );
  1817. }
  1818.  
  1819. /*********************************************************************/
  1820. /*                                                                   */
  1821. /* Function:  RxAsyncGetTxStatus                                     */
  1822. /*                                                                   */
  1823. /* Purpose:   Return current Transmit status                         */
  1824. /*                                                                   */
  1825. /*            Utilises IOCTL 65H ASYNC_GETLINESTATUS.                */
  1826. /*                                                                   */
  1827. /* Syntax:    call RxAsyncGetTxStatus  handlevar, statusvar          */
  1828. /*                                                                   */
  1829. /* Params:    handlevar  - rexx variable with com handle             */
  1830. /*            statusvar  - rexx variable to store status value       */
  1831. /*                                                                   */
  1832. /* Return:                                                           */
  1833. /*   Call successful - NO_ERROR (0)                                  */
  1834. /*   Call failed     - rc from DosDevIOCtl                           */
  1835. /*                                                                   */
  1836. /* Example:                                                          */
  1837. /*                                                                   */
  1838. /*   TxStatus = '00'                                                 */
  1839. /*   rc = RxAsyncGetTxStatus( PortHandle, 'TxStatus' )               */
  1840. /*   if rc <> 0                                                      */
  1841. /*      then say 'RxAsyncGetTxStatus failed with rc=>'rc'<'          */
  1842. /*      else do                                                      */
  1843. /*             say 'RxAsyncGetTxStatus returned okay.'               */
  1844. /*             if substr( X2B(TxStatus), 3, 1 ) = '1'                */
  1845. /*                then say 'Waiting to send XOFF.'                   */
  1846. /*             if substr( X2B(TxStatus), 4, 1 ) = '1'                */
  1847. /*                then say 'Waiting to send XON.'                    */
  1848. /*             if substr( X2B(TxStatus), 5, 1 ) = '1'                */
  1849. /*                then say 'Char ready to send immediate.'           */
  1850. /*             if substr( X2B(TxStatus), 6, 1 ) = '1'                */
  1851. /*                then say 'Hardware is transmitting.'               */
  1852. /*             if substr( X2B(TxStatus), 7, 1 ) = '1'                */
  1853. /*                then say 'Data in transmit queue.'                 */
  1854. /*             if substr( X2B(TxStatus), 8, 1 ) = '1'                */
  1855. /*                then say 'Write request queued.'                   */
  1856. /*           end                                                     */
  1857. /*                                                                   */
  1858. /*********************************************************************/
  1859.  
  1860. APIRET RxAsyncGetTxStatus(
  1861.           CHAR     *name,
  1862.           ULONG    numargs,
  1863.           RXSTRING args[],
  1864.           CHAR     *queuename,
  1865.           RXSTRING *retstr
  1866.        )
  1867. {
  1868.    APIRET   rc;                        /* Function return code       */
  1869.    HFILE    hcomPort;                  /* Communications port handle */
  1870.    BYTE     bTxStatus;                 /* Tx status returned         */
  1871.  
  1872.    if ( numargs != 2 )                 /* Must have two arguments    */
  1873.       return( ROUTINE_INVALID );
  1874.  
  1875.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  1876.        || !RXVALIDSTRING(args[1]) )    /* and tx status var name     */
  1877.       return( ROUTINE_INVALID );
  1878.  
  1879.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1880.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1881.  
  1882.    rc = GetTxStatus( hcomPort, &bTxStatus );
  1883.  
  1884.    if ( rc == NO_ERROR ) {
  1885.       rc = SetRexxValue( args[1].strptr, VAL2STR_BYTE2HEX, &(bTxStatus) );
  1886.    }
  1887.  
  1888.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1889.  
  1890.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  1891.  
  1892.    return( ROUTINE_VALID );
  1893. }
  1894.  
  1895. /*********************************************************************/
  1896. /*                                                                   */
  1897. /* Function:  RxAsyncGetMdmOutput                                    */
  1898. /*                                                                   */
  1899. /* Purpose:   Return current Modem Output signals                    */
  1900. /*                                                                   */
  1901. /*            Utilises IOCTL 66H ASYNC_GETMODEMOUTPUT.               */
  1902. /*                                                                   */
  1903. /* Syntax:    call RxAsyncGetMdmOutput handlevar, signalvar          */
  1904. /*                                                                   */
  1905. /* Params:    handlevar  - rexx variable with com handle             */
  1906. /*            signalvar  - rexx variable to store signals value      */
  1907. /*                                                                   */
  1908. /* Return:                                                           */
  1909. /*   Call successful - NO_ERROR (0)                                  */
  1910. /*   Call failed     - rc from DosDevIOCtl                           */
  1911. /*                                                                   */
  1912. /* Example:                                                          */
  1913. /*                                                                   */
  1914. /*   MdmOutput = '00'                                                */
  1915. /*   rc = RxAsyncGetMdmOutput( PortHandle, 'MdmOutput' )             */
  1916. /*   if rc <> 0                                                      */
  1917. /*      then say 'RxAsyncGetMdmOutput failed with rc=>'rc'<'         */
  1918. /*      else do                                                      */
  1919. /*             say 'RxAsyncGetMdmOutput returned okay.'              */
  1920. /*             if substr( X2B(MdmOutput), 7, 1 ) = '1'               */
  1921. /*                then say 'RTS signal is ON.'                       */
  1922. /*             if substr( X2B(MdmOutput), 8, 1 ) = '1'               */
  1923. /*                then say 'DTR signal is ON.'                       */
  1924. /*           end                                                     */
  1925. /*                                                                   */
  1926. /*********************************************************************/
  1927.  
  1928. APIRET RxAsyncGetMdmOutput(
  1929.           CHAR     *name,
  1930.           ULONG    numargs,
  1931.           RXSTRING args[],
  1932.           CHAR     *queuename,
  1933.           RXSTRING *retstr
  1934.        )
  1935. {
  1936.    APIRET   rc;                        /* Function return code       */
  1937.    HFILE    hcomPort;                  /* Communications port handle */
  1938.    BYTE     bMdmOutput;                /* Modem Output returned      */
  1939.  
  1940.    if ( numargs != 2 )                 /* Must have two arguments    */
  1941.       return( ROUTINE_INVALID );
  1942.  
  1943.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  1944.        || !RXVALIDSTRING(args[1]) )    /* and modem output var name  */
  1945.       return( ROUTINE_INVALID );
  1946.  
  1947.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  1948.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  1949.  
  1950.    rc = GetModemOutput( hcomPort, &bMdmOutput );
  1951.  
  1952.    if ( rc == NO_ERROR ) {
  1953.       rc = SetRexxValue( args[1].strptr, VAL2STR_BYTE2HEX, &(bMdmOutput) );
  1954.    }
  1955.  
  1956.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  1957.  
  1958.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  1959.  
  1960.    return( ROUTINE_VALID );
  1961. }
  1962.  
  1963. /*********************************************************************/
  1964. /*                                                                   */
  1965. /* Function:  RxAsyncSetMdmOutput                                    */
  1966. /*                                                                   */
  1967. /* Purpose:   Alters current Modem Output signals                    */
  1968. /*                                                                   */
  1969. /*            Utilises IOCTL 46H ASYNC_SETMODEMCTRL.                 */
  1970. /*                                                                   */
  1971. /* Syntax:    call RxAsyncSetMdmOutput handlevar, onmask, offmask    */
  1972. /*                                                                   */
  1973. /* Params:    handlevar  - rexx variable with com handle             */
  1974. /*            onmask     - on mask setting                           */
  1975. /*            offmask    - off mask setting                          */
  1976. /*                                                                   */
  1977. /* Return:                                                           */
  1978. /*   Call successful - NO_ERROR (0)                                  */
  1979. /*   Call failed     - rc from DosDevIOCtl                           */
  1980. /*                                                                   */
  1981. /* Example:                                                          */
  1982. /*                                                                   */
  1983. /*   none_on  = '00'                                                 */
  1984. /*   dtr_on   = '01'                                                 */
  1985. /*   rts_on   = '02'                                                 */
  1986. /*   both_on  = '03'                                                 */
  1987. /*   none_off = 'FF'                                                 */
  1988. /*   dtr_off  = 'FE'                                                 */
  1989. /*   rts_off  = 'FD'                                                 */
  1990. /*   both_off = 'FC'                                                 */
  1991. /*   rc = RxAsyncSetMdmOutput( PortHandle, none_on, dtr_off )        */
  1992. /*   if rc <> 0                                                      */
  1993. /*      then say 'RxAsyncSetMdmOutput failed with rc=>'rc'<'         */
  1994. /*      else say 'RxAsyncSetMdmOutput returned okay.'                */
  1995. /*                                                                   */
  1996. /*********************************************************************/
  1997.  
  1998. APIRET RxAsyncSetMdmOutput(
  1999.           CHAR     *name,
  2000.           ULONG    numargs,
  2001.           RXSTRING args[],
  2002.           CHAR     *queuename,
  2003.           RXSTRING *retstr
  2004.        )
  2005. {
  2006.    APIRET    rc;                       /* Function return code       */
  2007.    HFILE     hcomPort;                 /* Communications port handle */
  2008.    BYTE      bModemOn;                 /* Modem control ON mask      */
  2009.    BYTE      bModemOff;                /* Modem control OFF mask     */
  2010.  
  2011.    if ( numargs != 3 )                 /* Must have three arguments  */
  2012.       return( ROUTINE_INVALID );
  2013.  
  2014.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  2015.        || !RXVALIDSTRING(args[1])      /* and signal on mask         */
  2016.        || !RXVALIDSTRING(args[2]) )    /* and signal off mask        */
  2017.       return( ROUTINE_INVALID );
  2018.  
  2019.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2020.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2021.  
  2022.    if ( !Str2Num(args[1].strptr, &bModemOn, STR2NUM_HEX2BYTE) )
  2023.       return( ROUTINE_INVALID );       /* Convert ON mask failed     */
  2024.  
  2025.    if ( !Str2Num(args[2].strptr, &bModemOff, STR2NUM_HEX2BYTE) )
  2026.       return( ROUTINE_INVALID );       /* Convert OFF mask failed    */
  2027.  
  2028.    rc = SetMdmOutput( hcomPort, bModemOn, bModemOff );
  2029.  
  2030.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2031.  
  2032.    BUILDRXDOSRET( retstr, rc );
  2033.  
  2034.    return( ROUTINE_VALID );
  2035. }
  2036.  
  2037. /*********************************************************************/
  2038. /*                                                                   */
  2039. /* Function:  RxAsyncGetMdmInput                                     */
  2040. /*                                                                   */
  2041. /* Purpose:   Return current Modem Input signals                     */
  2042. /*                                                                   */
  2043. /*            Utilises IOCTL 67H ASYNC_GETMODEMINPUT.                */
  2044. /*                                                                   */
  2045. /* Syntax:    call RxAsyncGetMdmInput handlevar, signalvar           */
  2046. /*                                                                   */
  2047. /* Params:    handlevar  - rexx variable with com handle             */
  2048. /*            signalvar  - rexx variable to store signals value      */
  2049. /*                                                                   */
  2050. /* Return:                                                           */
  2051. /*   Call successful - NO_ERROR (0)                                  */
  2052. /*   Call failed     - rc from DosDevIOCtl                           */
  2053. /*                                                                   */
  2054. /* Example:                                                          */
  2055. /*                                                                   */
  2056. /*   MdmInput = '00'                                                 */
  2057. /*   rc = RxAsyncGetMdmInput( PortHandle, 'MdmInput' )               */
  2058. /*   if rc <> 0                                                      */
  2059. /*      then say 'RxAsyncGetMdmInput failed with rc=>'rc'<'          */
  2060. /*      else do                                                      */
  2061. /*             say 'RxAsyncGetMdmInput returned okay.'               */
  2062. /*             if substr( X2B(MdmInput), 1, 1 ) = '1'                */
  2063. /*                then say 'DCD signal is ON.'                       */
  2064. /*             if substr( X2B(MdmInput), 2, 1 ) = '1'                */
  2065. /*                then say 'RI signal is ON.'                        */
  2066. /*             if substr( X2B(MdmInput), 3, 1 ) = '1'                */
  2067. /*                then say 'DSR signal is ON.'                       */
  2068. /*             if substr( X2B(MdmInput), 4, 1 ) = '1'                */
  2069. /*                then say 'CTS signal is ON.'                       */
  2070. /*           end                                                     */
  2071. /*                                                                   */
  2072. /*********************************************************************/
  2073.  
  2074. APIRET RxAsyncGetMdmInput(
  2075.           CHAR     *name,
  2076.           ULONG    numargs,
  2077.           RXSTRING args[],
  2078.           CHAR     *queuename,
  2079.           RXSTRING *retstr
  2080.        )
  2081. {
  2082.    APIRET   rc;                        /* Function return code       */
  2083.    HFILE    hcomPort;                  /* Communications port handle */
  2084.    BYTE     bMdmInput;                 /* Modem Input returned       */
  2085.  
  2086.    if ( numargs != 2 )                 /* Must have two arguments    */
  2087.       return( ROUTINE_INVALID );
  2088.  
  2089.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  2090.        || !RXVALIDSTRING(args[1]) )    /* and modem input var name   */
  2091.       return( ROUTINE_INVALID );
  2092.  
  2093.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2094.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2095.  
  2096.    rc = GetModemInput( hcomPort, &bMdmInput );
  2097.  
  2098.    if ( rc == NO_ERROR ) {
  2099.       rc = SetRexxValue( args[1].strptr, VAL2STR_BYTE2HEX, &(bMdmInput) );
  2100.    }
  2101.  
  2102.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2103.  
  2104.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  2105.  
  2106.    return( ROUTINE_VALID );
  2107. }
  2108.  
  2109. /*********************************************************************/
  2110. /*                                                                   */
  2111. /* Function:  RxAsyncGetRxCount                                      */
  2112. /*                                                                   */
  2113. /* Purpose:   Return current RX queue size and count                 */
  2114. /*                                                                   */
  2115. /*            Utilises IOCTL 68H ASYNC_GETINQUECOUNT.                */
  2116. /*                                                                   */
  2117. /* Syntax:    call RxAsyncGetRxCount  handlevar, countvar, sizevar   */
  2118. /*                                                                   */
  2119. /* Params:    handlevar  - rexx variable with com handle             */
  2120. /*            countvar   - rexx variable to store count value        */
  2121. /*            sizevar    - rexx variable to store size  value        */
  2122. /*                                                                   */
  2123. /* Return:                                                           */
  2124. /*   Call successful - NO_ERROR (0)                                  */
  2125. /*   Call failed     - rc from DosDevIOCtl                           */
  2126. /*                                                                   */
  2127. /* Example:                                                          */
  2128. /*                                                                   */
  2129. /*   RxCount = 0                                                     */
  2130. /*   RxSize  = 0                                                     */
  2131. /*   rc = RxAsyncGetRxCount( PortHandle, 'RxCount', 'RxSize' )       */
  2132. /*   if rc <> 0                                                      */
  2133. /*      then say 'RxAsyncGetRxCount failed with rc=>'rc'<'           */
  2134. /*      else do                                                      */
  2135. /*             say 'RxAsyncGetRxCount returned okay.'                */
  2136. /*             say 'There are 'RxCount' bytes in the RX queue.'      */
  2137. /*             say 'The RX queue is 'RxSize' bytes long.'            */
  2138. /*           end                                                     */
  2139. /*                                                                   */
  2140. /*********************************************************************/
  2141.  
  2142. APIRET RxAsyncGetRxCount(
  2143.           CHAR     *name,
  2144.           ULONG    numargs,
  2145.           RXSTRING args[],
  2146.           CHAR     *queuename,
  2147.           RXSTRING *retstr
  2148.        )
  2149. {
  2150.    APIRET   rc;                        /* Function return code       */
  2151.    HFILE    hcomPort;                  /* Communications port handle */
  2152.    USHORT   usRxCount;                 /* Number bytes in RX Queue   */
  2153.    USHORT   usRxSize;                  /* Size of RX Queue           */
  2154.  
  2155.    if ( numargs != 3 )                 /* Must have three arguments  */
  2156.       return( ROUTINE_INVALID );
  2157.  
  2158.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  2159.        || !RXVALIDSTRING(args[1])      /* and queue count var name   */
  2160.        || !RXVALIDSTRING(args[2]) )    /* and queue size var name    */
  2161.       return( ROUTINE_INVALID );
  2162.  
  2163.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2164.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2165.  
  2166.    rc = GetRxCount( hcomPort, &usRxCount, &usRxSize );
  2167.  
  2168.    if ( rc == NO_ERROR ) {
  2169.       rc = SetRexxValue( args[1].strptr, VAL2STR_USHORT2DEC, &usRxCount );
  2170.  
  2171.       if ( rc == NO_ERROR ) {
  2172.          rc = SetRexxValue( args[2].strptr, VAL2STR_USHORT2DEC, &usRxSize );
  2173.       }
  2174.    }
  2175.  
  2176.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2177.  
  2178.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  2179.  
  2180.    return( ROUTINE_VALID );
  2181. }
  2182.  
  2183. /*********************************************************************/
  2184. /*                                                                   */
  2185. /* Function:  RxAsyncGetTxCount                                      */
  2186. /*                                                                   */
  2187. /* Purpose:   Return current TX queue size and count                 */
  2188. /*                                                                   */
  2189. /*            Utilises IOCTL 69H ASYNC_GETOUTQUECOUNT.               */
  2190. /*                                                                   */
  2191. /* Syntax:    call RxAsyncGetTxCount  handlevar, countvar, sizevar   */
  2192. /*                                                                   */
  2193. /* Params:    handlevar  - rexx variable with com handle             */
  2194. /*            countvar   - rexx variable to store count value        */
  2195. /*            sizevar    - rexx variable to store size  value        */
  2196. /*                                                                   */
  2197. /* Return:                                                           */
  2198. /*   Call successful - NO_ERROR (0)                                  */
  2199. /*   Call failed     - rc from DosDevIOCtl                           */
  2200. /*                                                                   */
  2201. /* Example:                                                          */
  2202. /*                                                                   */
  2203. /*   TxCount = 0                                                     */
  2204. /*   TxSize  = 0                                                     */
  2205. /*   rc = RxAsyncGetTxCount( PortHandle, 'TxCount', 'TxSize' )       */
  2206. /*   if rc <> 0                                                      */
  2207. /*      then say 'RxAsyncGetTxCount failed with rc=>'rc'<'           */
  2208. /*      else do                                                      */
  2209. /*             say 'RxAsyncGetTxCount returned okay.'                */
  2210. /*             say 'There are 'TxCount' bytes in the TX queue.'      */
  2211. /*             say 'The TX queue is 'TxSize' bytes long.'            */
  2212. /*           end                                                     */
  2213. /*                                                                   */
  2214. /*********************************************************************/
  2215.  
  2216. APIRET RxAsyncGetTxCount(
  2217.           CHAR     *name,
  2218.           ULONG    numargs,
  2219.           RXSTRING args[],
  2220.           CHAR     *queuename,
  2221.           RXSTRING *retstr
  2222.        )
  2223. {
  2224.    APIRET   rc;                        /* Function return code       */
  2225.    HFILE    hcomPort;                  /* Communications port handle */
  2226.    USHORT   usTxCount;                 /* Number bytes in TX Queue   */
  2227.    USHORT   usTxSize;                  /* Size of TX Queue           */
  2228.  
  2229.    if ( numargs != 3 )                 /* Must have three arguments  */
  2230.       return( ROUTINE_INVALID );
  2231.  
  2232.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  2233.        || !RXVALIDSTRING(args[1])      /* and queue count var name   */
  2234.        || !RXVALIDSTRING(args[2]) )    /* and queue size var name    */
  2235.       return( ROUTINE_INVALID );
  2236.  
  2237.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2238.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2239.  
  2240.    rc = GetTxCount( hcomPort, &usTxCount, &usTxSize );
  2241.  
  2242.    if ( rc == NO_ERROR ) {
  2243.       rc = SetRexxValue( args[1].strptr, VAL2STR_USHORT2DEC, &usTxCount );
  2244.  
  2245.       if ( rc == NO_ERROR ) {
  2246.          rc = SetRexxValue( args[2].strptr, VAL2STR_USHORT2DEC, &usTxSize );
  2247.       }
  2248.    }
  2249.  
  2250.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2251.  
  2252.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  2253.  
  2254.    return( ROUTINE_VALID );
  2255. }
  2256.  
  2257. /*********************************************************************/
  2258. /*                                                                   */
  2259. /* Function:  RxAsyncGetComError                                     */
  2260. /*                                                                   */
  2261. /* Purpose:   Return current COM Error setting                       */
  2262. /*                                                                   */
  2263. /*            Utilises IOCTL 6DH ASYNC_GETCOMMERROR.                 */
  2264. /*                                                                   */
  2265. /* Syntax:    call RxAsyncGetComError handlevar, errorvar            */
  2266. /*                                                                   */
  2267. /* Params:    handlevar  - rexx variable with com handle             */
  2268. /*            errorvar   - rexx variable to store error value        */
  2269. /*                                                                   */
  2270. /* Return:                                                           */
  2271. /*   Call successful - NO_ERROR (0)                                  */
  2272. /*   Call failed     - rc from DosDevIOCtl                           */
  2273. /*                                                                   */
  2274. /* Example:                                                          */
  2275. /*                                                                   */
  2276. /*   ComError = '0000'                                               */
  2277. /*   rc = RxAsyncGetComError( PortHandle, 'ComError' )               */
  2278. /*   if rc <> 0                                                      */
  2279. /*      then say 'RxAsyncGetComError failed with rc=>'rc'<'          */
  2280. /*      else do                                                      */
  2281. /*             say 'RxAsyncGetComError returned okay.'               */
  2282. /*             if substr( X2B(ComError), 13, 1 ) = '1'               */
  2283. /*                then say 'Framing Error detected.'                 */
  2284. /*             if substr( X2B(ComError), 14, 1 ) = '1'               */
  2285. /*                then say 'Parity Error detected.'                  */
  2286. /*             if substr( X2B(ComError), 15, 1 ) = '1'               */
  2287. /*                then say 'Receive Hardware Overrun detected.'      */
  2288. /*             if substr( X2B(ComError), 16, 1 ) = '1'               */
  2289. /*                then say 'Receive Queue Overrun detected.'         */
  2290. /*           end                                                     */
  2291. /*                                                                   */
  2292. /*********************************************************************/
  2293.  
  2294. APIRET RxAsyncGetComError(
  2295.           CHAR     *name,
  2296.           ULONG    numargs,
  2297.           RXSTRING args[],
  2298.           CHAR     *queuename,
  2299.           RXSTRING *retstr
  2300.        )
  2301. {
  2302.    APIRET   rc;                        /* Function return code       */
  2303.    HFILE    hcomPort;                  /* Communications port handle */
  2304.    USHORT   usComError;                /* COM Error returned         */
  2305.  
  2306.    if ( numargs != 2 )                 /* Must have two arguments    */
  2307.       return( ROUTINE_INVALID );
  2308.  
  2309.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  2310.        || !RXVALIDSTRING(args[1]) )    /* and com error var name     */
  2311.       return( ROUTINE_INVALID );
  2312.  
  2313.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2314.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2315.  
  2316.    rc = GetComError( hcomPort, &usComError );
  2317.  
  2318.    if ( rc == NO_ERROR ) {
  2319.       rc = SetRexxValue( args[1].strptr, VAL2STR_USHORT2HEX, &(usComError) );
  2320.    }
  2321.  
  2322.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2323.  
  2324.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  2325.  
  2326.    return( ROUTINE_VALID );
  2327. }
  2328.  
  2329. /*********************************************************************/
  2330. /*                                                                   */
  2331. /* Function:  RxAsyncGetComEvent                                     */
  2332. /*                                                                   */
  2333. /* Purpose:   Return current COM Event setting                       */
  2334. /*                                                                   */
  2335. /*            Utilises IOCTL 72H ASYNC_GETCOMMEVENT.                 */
  2336. /*                                                                   */
  2337. /* Syntax:    call RxAsyncGetComEvent handlevar, eventvar            */
  2338. /*                                                                   */
  2339. /* Params:    handlevar  - rexx variable with com handle             */
  2340. /*            eventvar   - rexx variable to store event value        */
  2341. /*                                                                   */
  2342. /* Return:                                                           */
  2343. /*   Call successful - NO_ERROR (0)                                  */
  2344. /*   Call failed     - rc from DosDevIOCtl                           */
  2345. /*                                                                   */
  2346. /* Example:                                                          */
  2347. /*                                                                   */
  2348. /*   ComEvent = '0000'                                               */
  2349. /*   rc = RxAsyncGetComEvent( PortHandle, 'ComEvent' )               */
  2350. /*   if rc <> 0                                                      */
  2351. /*      then say 'RxAsyncGetComEvent failed with rc=>'rc'<'          */
  2352. /*      else do                                                      */
  2353. /*             say 'RxAsyncGetComEvent returned okay.'               */
  2354. /*             if substr( X2B(ComEvent),  8, 1 ) = '1'               */
  2355. /*                then say 'Ring Indicator detected.'                */
  2356. /*             if substr( X2B(ComEvent),  9, 1 ) = '1'               */
  2357. /*                then say 'Error occurred.'                         */
  2358. /*             if substr( X2B(ComEvent), 10, 1 ) = '1'               */
  2359. /*                then say 'Break detected.'                         */
  2360. /*             if substr( X2B(ComEvent), 11, 1 ) = '1'               */
  2361. /*                then say 'DCD changed state.'                      */
  2362. /*             if substr( X2B(ComEvent), 12, 1 ) = '1'               */
  2363. /*                then say 'DSR changed state.'                      */
  2364. /*             if substr( X2B(ComEvent), 13, 1 ) = '1'               */
  2365. /*                then say 'CTS changed state.'                      */
  2366. /*             if substr( X2B(ComEvent), 14, 1 ) = '1'               */
  2367. /*                then say 'Last character sent.'                    */
  2368. /*             if substr( X2B(ComEvent), 15, 1 ) = '1'               */
  2369. /*                then say 'Receive timeout interrupt.'              */
  2370. /*             if substr( X2B(ComEvent), 16, 1 ) = '1'               */
  2371. /*                then say 'Character received.'                     */
  2372. /*           end                                                     */
  2373. /*                                                                   */
  2374. /*********************************************************************/
  2375.  
  2376. APIRET RxAsyncGetComEvent(
  2377.           CHAR     *name,
  2378.           ULONG    numargs,
  2379.           RXSTRING args[],
  2380.           CHAR     *queuename,
  2381.           RXSTRING *retstr
  2382.        )
  2383. {
  2384.    APIRET   rc;                        /* Function return code       */
  2385.    HFILE    hcomPort;                  /* Communications port handle */
  2386.    USHORT   usComEvent;                /* COM Event returned         */
  2387.  
  2388.    if ( numargs != 2 )                 /* Must have two arguments    */
  2389.       return( ROUTINE_INVALID );
  2390.  
  2391.    if (   !RXVALIDSTRING(args[0])      /* Must specify port          */
  2392.        || !RXVALIDSTRING(args[1]) )    /* and com event var name     */
  2393.       return( ROUTINE_INVALID );
  2394.  
  2395.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2396.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2397.  
  2398.    rc = GetComEvent( hcomPort, &usComEvent );
  2399.  
  2400.    if ( rc == NO_ERROR ) {
  2401.       rc = SetRexxValue( args[1].strptr, VAL2STR_USHORT2HEX, &(usComEvent) );
  2402.    }
  2403.  
  2404.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2405.  
  2406.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  2407.  
  2408.    return( ROUTINE_VALID );
  2409. }
  2410.  
  2411. /*********************************************************************/
  2412. /*                                                                   */
  2413. /* Function:  RxAsyncOpen                                            */
  2414. /*                                                                   */
  2415. /* Purpose:   Open the specified port                                */
  2416. /*                                                                   */
  2417. /* Syntax:    call RxAsyncOpen name 'handlevar'                      */
  2418. /*                                                                   */
  2419. /* Params:    name      - name of com port or named pipe             */
  2420. /*            handlevar - rexx variable to store handle in           */
  2421. /*                                                                   */
  2422. /* Return:                                                           */
  2423. /*   Call successful - NO_ERROR (0)                                  */
  2424. /*   Call failed     - rc from DosOpen                               */
  2425. /*                                                                   */
  2426. /* Example:                                                          */
  2427. /*                                                                   */
  2428. /*   PortName   = 'COM4'                                             */
  2429. /*   PortHandle = ''                                                 */
  2430. /*   rc = RxAsyncOpen( PortName, 'PortHandle' )                      */
  2431. /*   if rc <> 0                                                      */
  2432. /*      then say 'RxAsyncOpen failed with rc=>'rc'<'                 */
  2433. /*      else say 'RxAsyncOpen opened device handle=>'PortHandle'<'   */
  2434. /*                                                                   */
  2435. /*********************************************************************/
  2436.  
  2437. APIRET RxAsyncOpen(
  2438.           CHAR     *name,
  2439.           ULONG    numargs,
  2440.           RXSTRING args[],
  2441.           CHAR     *queuename,
  2442.           RXSTRING *retstr
  2443.        )
  2444. {
  2445.    APIRET   rc;                        /* Function return code       */
  2446.    HFILE    hcomPort;                  /* Communications port handle */
  2447.  
  2448.    if ( numargs != 2 )                 /* Must have two arguments    */
  2449.       return( ROUTINE_INVALID );
  2450.  
  2451.    if (   !RXVALIDSTRING(args[0])      /* Must specify port name     */
  2452.        || !RXVALIDSTRING(args[1]) )    /* and handle var name        */
  2453.       return( ROUTINE_INVALID );
  2454.  
  2455.    rc = OpenPort( args[0].strptr, &hcomPort );
  2456.    if ( rc == NO_ERROR ) {             /* Port opened okay           */
  2457.  
  2458.       rc = SetRexxValue( args[1].strptr, VAL2STR_HFILE2DEC, &hcomPort );
  2459.       if ( rc != NO_ERROR ) {          /* Couldn't continue          */
  2460.  
  2461.          ClosePort( &hcomPort );
  2462.       }
  2463.    }
  2464.  
  2465.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2466.  
  2467.    BUILDRXDOSRET( retstr, rc );        /* Return DosOpen result      */
  2468.  
  2469.    return( ROUTINE_VALID );
  2470. }
  2471.  
  2472. /*********************************************************************/
  2473. /*                                                                   */
  2474. /* Function:  RxAsyncClose                                           */
  2475. /*                                                                   */
  2476. /* Purpose:   Close the specified port                               */
  2477. /*                                                                   */
  2478. /* Syntax:    call RxAsyncClose handlevar                            */
  2479. /*                                                                   */
  2480. /* Params:    handlevar - rexx variable with com handle              */
  2481. /*                                                                   */
  2482. /* Return:                                                           */
  2483. /*   Call successful - NO_ERROR (0)                                  */
  2484. /*   Call failed     - rc from DosClose                              */
  2485. /*                                                                   */
  2486. /* Example:                                                          */
  2487. /*                                                                   */
  2488. /*   rc = RxAsyncClose( PortHandle )                                 */
  2489. /*   if rc <> 0                                                      */
  2490. /*      then say 'RxAsyncClose failed with rc=>'rc'<'                */
  2491. /*      else say 'RxAsyncClose closed the device.'                   */
  2492. /*                                                                   */
  2493. /*********************************************************************/
  2494.  
  2495. APIRET RxAsyncClose(
  2496.           CHAR     *name,
  2497.           ULONG    numargs,
  2498.           RXSTRING args[],
  2499.           CHAR     *queuename,
  2500.           RXSTRING *retstr
  2501.        )
  2502. {
  2503.    APIRET   rc;                        /* Function return code       */
  2504.    HFILE    hcomPort;                  /* Communications port handle */
  2505.  
  2506.    if ( numargs != 1 )                 /* Must have one argument     */
  2507.       return( ROUTINE_INVALID );
  2508.  
  2509.    if ( !RXVALIDSTRING(args[0]) )      /* Must specify port          */
  2510.       return( ROUTINE_INVALID );
  2511.  
  2512.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2513.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2514.  
  2515.    rc = ClosePort( &hcomPort );
  2516.  
  2517.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2518.  
  2519.    BUILDRXDOSRET( retstr, rc );        /* Return DosClose result     */
  2520.  
  2521.    return( ROUTINE_VALID );
  2522. }
  2523.  
  2524. /*********************************************************************/
  2525. /*                                                                   */
  2526. /* Function:  RxAsyncWait                                            */
  2527. /*                                                                   */
  2528. /* Purpose:   Wait for input from the specified port                 */
  2529. /*                                                                   */
  2530. /*            Utilises IOCTL 72H ASYNC_GETCOMMEVENT.                 */
  2531. /*                                                                   */
  2532. /* Syntax:    call RxAsyncWait port timeout                          */
  2533. /*                                                                   */
  2534. /* Params:    port    - handle of open port                          */
  2535. /*            timeout - maximum period to wait in milliseconds       */
  2536. /*                                                                   */
  2537. /*                      If -1 is specified then the routine waits    */
  2538. /*                      forever.                                     */
  2539. /*                                                                   */
  2540. /*                      If 0 is specified then the routine will      */
  2541. /*                      return 0 if data was detected and -3 if no   */
  2542. /*                      data was detected.                           */
  2543. /*                                                                   */
  2544. /* Return:                                                           */
  2545. /*   Data detected    - NO_ERROR (0)                                 */
  2546. /*   Wait timed out   - RC_ASYNC_TIMED_OUT (-1)                      */
  2547. /*   No data detected - RC_ASYNC_NO_INPUT  (-3)                      */
  2548. /*   Error occurred   - rc from DosDevIOCtl                          */
  2549. /*                                                                   */
  2550. /* Example:                                                          */
  2551. /*                                                                   */
  2552. /*   say 'Wait for data 'time()                                      */
  2553. /*   rc = RxAsyncWait( PortHandle, 3000 )                            */
  2554. /*   say 'Waited enough 'time()                                      */
  2555. /*   if rc = 0                                                       */
  2556. /*      then say 'RxAsyncWait detected input.'                       */
  2557. /*      else if rc = -1                                              */
  2558. /*              then say 'RxAsyncWait timed out.'                    */
  2559. /*              else say 'RxAsyncWait failed with rc=>'rc'<'         */
  2560. /*                                                                   */
  2561. /* Note: RC_ASYNC_NO_INPUT is only returned if the timeout specified */
  2562. /*       is 0 (zero) and there is no data detected.                  */
  2563. /*                                                                   */
  2564. /*********************************************************************/
  2565.  
  2566. APIRET RxAsyncWait(
  2567.           CHAR     *name,
  2568.           ULONG    numargs,
  2569.           RXSTRING args[],
  2570.           CHAR     *queuename,
  2571.           RXSTRING *retstr
  2572.        )
  2573. {
  2574.    APIRET       rc;                    /* Function return code       */
  2575.    HFILE        hcomPort;              /* Communications port handle */
  2576.    LONG         lTimeLimit;            /* Time in hundredths         */
  2577.  
  2578.    if ( numargs != 2 )                 /* Must have two arguments    */
  2579.       return( ROUTINE_INVALID );
  2580.  
  2581.    if (   !RXVALIDSTRING(args[0])      /* Must specify port handle   */
  2582.        || !RXVALIDSTRING(args[1]) )    /* and timeout                */
  2583.       return( ROUTINE_INVALID );
  2584.  
  2585.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2586.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2587.  
  2588.    if ( !Str2Num(args[1].strptr, &lTimeLimit, STR2NUM_DEC2LONG) )
  2589.       return( ROUTINE_INVALID );       /* Convert timeout failed     */
  2590.  
  2591.    rc = WaitInput( hcomPort, lTimeLimit );
  2592.  
  2593.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2594.  
  2595.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  2596.  
  2597.    return( ROUTINE_VALID );            /* All ok                     */
  2598. }
  2599.  
  2600. /*********************************************************************/
  2601. /*                                                                   */
  2602. /* Function:  RxAsyncRead                                            */
  2603. /*                                                                   */
  2604. /* Purpose:   Read from the specified port                           */
  2605. /*                                                                   */
  2606. /*            Utilises IOCTL 72H ASYNC_GETCOMMEVENT.                 */
  2607. /*                                                                   */
  2608. /* Syntax:    rc = RxAsyncRead( port, length, timeout, 'varname' )   */
  2609. /*                                                                   */
  2610. /*      OR    rc = RxAsyncRead( port,                                */
  2611. /*                              length,                              */
  2612. /*                              timeout,                             */
  2613. /*                              'varname',                           */
  2614. /*                              nullrep )                            */
  2615. /*                                                                   */
  2616. /*      OR    rc = RxAsyncRead( port,                                */
  2617. /*                              length,                              */
  2618. /*                              timeout,                             */
  2619. /*                              'varname',                           */
  2620. /*                              nullrep,                             */
  2621. /*                              lineend )                            */
  2622. /*                                                                   */
  2623. /* Params:    port    - handle of open port                          */
  2624. /*                                                                   */
  2625. /*            length  - number of bytes to read, 0=a line, n=chars   */
  2626. /*                      Note: A line constitutes everything upto     */
  2627. /*                      and including a terminating linefeed char    */
  2628. /*                      if it can be read in the time specified.     */
  2629. /*                      A maximum line size of 255 bytes is read,    */
  2630. /*                      if this limit is reached then the portion    */
  2631. /*                      read upto this point will be returned.       */
  2632. /*                      If the read times out then whatever was      */
  2633. /*                      read upto that point is returned.            */
  2634. /*                                                                   */
  2635. /*            timeout - maximum period to wait in milliseconds       */
  2636. /*                      -1 = no timeout                              */
  2637. /*                                                                   */
  2638. /*            varname - name of rexx variable to return data in      */
  2639. /*                                                                   */
  2640. /*            nullrep - optional fifth parameter which when          */
  2641. /*                      specified permits null charatacers in the    */
  2642. /*                      input stream to be either discarded ('')     */
  2643. /*                      or replaced ('?'). An empty string tells     */
  2644. /*                      the function to discard nulls, otherwise     */
  2645. /*                      all nulls are replaced with the character    */
  2646. /*                      specified. If this parameter is not          */
  2647. /*                      specified then all nulls will be returned    */
  2648. /*                      in the string passed back to the caller.     */
  2649. /*                                                                   */
  2650. /*            lineend - optional sixth parameter which when          */
  2651. /*                      specified indicates an additional character  */
  2652. /*                      to be used in detecting end_of_line.         */
  2653. /*                      The defaults if not specified are line_feed, */
  2654. /*                      form_feed or end_of_file. When specified     */
  2655. /*                      the character acts in addition to the        */
  2656. /*                      defaults.                                    */
  2657. /*                                                                   */
  2658. /* Return:                                                           */
  2659. /*   Call successful  - NO_ERROR (0)                                 */
  2660. /*   Read timed out   - RC_ASYNC_TIMED_OUT (-1)                      */
  2661. /*   Call failed      - ERROR_NOT_ENOUGH_MEMORY (8)                  */
  2662. /*          "         - ERROR_INVALID_PARAMETER (87)                 */
  2663. /*          "         - rc from DosRead                              */
  2664. /*                                                                   */
  2665. /* Example:                                                          */
  2666. /*                                                                   */
  2667. /*   InpStr = ''                                                     */
  2668. /*   rc =  RxAsyncRead( PortHandle, 0, 3000, 'InpStr' )              */
  2669. /*   if rc = 0                                                       */
  2670. /*      then say 'RxAsyncRead returned >'InpStr'<'                   */
  2671. /*      else if rc = -1                                              */
  2672. /*              then say 'RxAsyncRead timed out, returned >'InpStr'<'*/
  2673. /*              else say 'RxAsyncRead failed with rc=>'rc'<'         */
  2674. /*                                                                   */
  2675. /*   -- to replace nulls with question marks use                     */
  2676. /*                                                                   */
  2677. /*   rc =  RxAsyncRead( PortHandle, 0, 3000, 'InpStr', '?' )         */
  2678. /*                                                                   */
  2679. /*   -- to use <CR> as line termination and discard nulls use        */
  2680. /*                                                                   */
  2681. /*   cret = d2c(13)                                                  */
  2682. /*   rc =  RxAsyncRead( PortHandle, 0, 3000, 'InpStr', '', cret )    */
  2683. /*                                                                   */
  2684. /*********************************************************************/
  2685.  
  2686. APIRET RxAsyncRead(
  2687.           CHAR     *name,
  2688.           ULONG    numargs,
  2689.           RXSTRING args[],
  2690.           CHAR     *queuename,
  2691.           RXSTRING *retstr
  2692.        )
  2693. {
  2694.    APIRET       rc;                    /* Function return code       */
  2695.    APIRET       rc2;                   /* RexxVariablePool return    */
  2696.    HFILE        hcomPort;              /* Communications port handle */
  2697.    BYTE         ReadBuff[RXAUTOBUFLEN];/* Input buffer               */
  2698.    ULONG        ulNumRequested;        /* Read length (0=line mode)  */
  2699.    SHVBLOCK     ReadVar;               /* Rexx variable for input    */
  2700.    LONG         lTimeLimit;            /* Timeout in milliseconds    */
  2701.    PSZ          pszNullReplace;        /* Null replace character     */
  2702.    PSZ          pszLineEnd;            /* Line end character         */
  2703.  
  2704.    if (   (numargs < 4)                /* May have either 4,5 or 6   */
  2705.        || (numargs > 6) )
  2706.       return( ROUTINE_INVALID );
  2707.  
  2708.    if (   !RXVALIDSTRING(args[0])      /* Must specify port handle   */
  2709.        || !RXVALIDSTRING(args[1])      /* and read length            */
  2710.        || !RXVALIDSTRING(args[2])      /* and timeout                */
  2711.        || !RXVALIDSTRING(args[3]) )    /* and string to return in    */
  2712.       return( ROUTINE_INVALID );
  2713.  
  2714.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2715.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2716.  
  2717.    if ( !Str2Num(args[1].strptr, &ulNumRequested, STR2NUM_DEC2ULONG) )
  2718.       return( ROUTINE_INVALID );       /* Convert length failed      */
  2719.  
  2720.    if ( ulNumRequested > RXAUTOBUFLEN-1 )
  2721.       return( ROUTINE_INVALID );       /* Invalid length specified   */
  2722.  
  2723.    if ( !Str2Num(args[2].strptr, &lTimeLimit, STR2NUM_DEC2LONG) )
  2724.       return( ROUTINE_INVALID );       /* Convert timeout failed     */
  2725.  
  2726.    pszNullReplace = NULL;
  2727.    if ( numargs >= 5 ) {               /* If five or more arguements */
  2728.       if ( RXVALIDSTRING(args[4]) )    /* If specified               */
  2729.          if ( args[4].strlength > 1 )  /* Must only be one or zero   */
  2730.             return( ROUTINE_INVALID );
  2731.  
  2732.       pszNullReplace = args[4].strptr;
  2733.    }
  2734.  
  2735.    pszLineEnd = NULL;
  2736.    if ( numargs >= 6 ) {               /* If six or more arguements  */
  2737.       if ( RXVALIDSTRING(args[5]) )    /* If specified               */
  2738.          if ( args[5].strlength > 1 )  /* Must only be one or zero   */
  2739.             return( ROUTINE_INVALID );
  2740.  
  2741.       pszLineEnd = args[5].strptr;
  2742.    }
  2743.  
  2744.    /* fetch rexx variable details  (rexx mallocs, we free) */
  2745.  
  2746.    InitVar( &ReadVar, NULL, args[3].strptr );
  2747.  
  2748.    rc = FetchVar( &ReadVar );
  2749.  
  2750.    if ( rc == NO_ERROR ) {
  2751.  
  2752.       ReadVar.shvvalue.strptr[0] = EOSTR_CH;
  2753.  
  2754.       if ( ulNumRequested > 0 ) {
  2755.          ReadVar.shvvalue.strlength = ulNumRequested;
  2756.       } else {
  2757.          ReadVar.shvvalue.strlength = RXAUTOBUFLEN;
  2758.       }
  2759.  
  2760.       rc = ReadPort( hcomPort,
  2761.                      ReadBuff,
  2762.                      ulNumRequested,
  2763.                      ReadVar.shvvalue.strptr,
  2764.                      &(ReadVar.shvvalue.strlength),
  2765.                      lTimeLimit,
  2766.                      pszNullReplace,
  2767.                      pszLineEnd );
  2768.  
  2769.       /* set rexx variable details with retrieved values */
  2770.  
  2771.       rc2 = UpdateVar( &ReadVar );     /* Set the rexx variable      */
  2772.  
  2773.       if ( rc == NO_ERROR ) {          /* Only if not already error  */
  2774.          rc = rc2;
  2775.       }
  2776.    }
  2777.  
  2778.    FreeVar( &ReadVar );                /* Cleanup                    */
  2779.  
  2780.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2781.  
  2782.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  2783.  
  2784.    return( ROUTINE_VALID );            /* All ok                     */
  2785. }
  2786.  
  2787. /*********************************************************************/
  2788. /*                                                                   */
  2789. /* Function:  RxAsyncWrite                                           */
  2790. /*                                                                   */
  2791. /* Purpose:   Write to the specified port                            */
  2792. /*                                                                   */
  2793. /* Syntax:    rc = RxAsyncWrite( port, delay, outvar, 'remvar' )     */
  2794. /*                                                                   */
  2795. /* Params:    port   - handle of open port                           */
  2796. /*            delay  - delay before writing (millisecs)              */
  2797. /*            outvar - string to be written                          */
  2798. /*            remvar - name of variable to return unwritten count in */
  2799. /*                                                                   */
  2800. /* Return:                                                           */
  2801. /*   Call successful - NO_ERROR (0)                                  */
  2802. /*   Call failed     - rc from DosWrite                              */
  2803. /*                                                                   */
  2804. /* Example:                                                          */
  2805. /*                                                                   */
  2806. /*   crlf = D2C(13)''D2C(10)                                         */
  2807. /*   Remaining = 0                                                   */
  2808. /*   rc = RxAsyncWrite( PortHandle, 0, 'ATZ'crlf, 'Remaining' )      */
  2809. /*   if rc <> 0                                                      */
  2810. /*      then say 'Modem not turned on, >'Remaining'< chars unwritten'*/
  2811. /*      else say 'RxAsyncWrite output ATZ<crlf>'                     */
  2812. /*                                                                   */
  2813. /*********************************************************************/
  2814.  
  2815. APIRET RxAsyncWrite(
  2816.           CHAR     *name,
  2817.           ULONG    numargs,
  2818.           RXSTRING args[],
  2819.           CHAR     *queuename,
  2820.           RXSTRING *retstr
  2821.        )
  2822. {
  2823.    APIRET       rc;                    /* Function return code       */
  2824.    APIRET       rc2;                   /* RexxVariablePool return    */
  2825.    HFILE        hcomPort;              /* Communications port handle */
  2826.    ULONG        ulRemains;             /* Number of chars not written*/
  2827.    LONG         millisecs;             /* Time to sleep              */
  2828.  
  2829.    if ( numargs != 4 )                 /* Must have four arguments   */
  2830.       return( ROUTINE_INVALID );
  2831.  
  2832.    if (   !RXVALIDSTRING(args[0])      /* Must specify port handle   */
  2833.        || !RXVALIDSTRING(args[1])      /* and write delay            */
  2834.        ||   RXNULLSTRING(args[2])      /* and var to write           */
  2835.        || !RXVALIDSTRING(args[3]) )    /* and var to return num left */
  2836.       return( ROUTINE_INVALID );
  2837.  
  2838.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2839.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2840.  
  2841.    if ( !Str2Num(args[1].strptr, &millisecs, STR2NUM_DEC2LONG) )
  2842.       return( ROUTINE_INVALID );       /* Convert millisecs failed   */
  2843.  
  2844.    if ( millisecs < 0 )                /* Can not wait negative time */
  2845.       return( ROUTINE_INVALID );
  2846.  
  2847.    if ( millisecs > 0 )                /* Only if its worthwile      */
  2848.       DosSleep( millisecs );
  2849.  
  2850.    rc = WritePort( hcomPort, args[2].strptr, args[2].strlength, &ulRemains );
  2851.  
  2852.    rc2 = SetRexxValue( args[3].strptr, VAL2STR_ULONG2DEC, &ulRemains );
  2853.    if ( rc2 != NO_ERROR ) {            /* Couldn't set rexx variable */
  2854.  
  2855.       if ( rc == NO_ERROR ) {          /* Not already in error       */
  2856.          rc = rc2;
  2857.       }
  2858.    }
  2859.  
  2860.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2861.  
  2862.    BUILDRXDOSRET( retstr, rc );        /* Return DosWrite result     */
  2863.  
  2864.    return( ROUTINE_VALID );
  2865. }
  2866.  
  2867. /*********************************************************************/
  2868. /*                                                                   */
  2869. /* Function:  RxAsyncPrint                                           */
  2870. /*                                                                   */
  2871. /* Purpose:   Write to stdout                                        */
  2872. /*                                                                   */
  2873. /* Syntax:    call RxAsyncPrint string                               */
  2874. /*                                                                   */
  2875. /* Params:    string  - text to be written                           */
  2876. /*                                                                   */
  2877. /* Return:                                                           */
  2878. /*   Call successful - NO_ERROR (0)                                  */
  2879. /*                                                                   */
  2880. /* Example:                                                          */
  2881. /*                                                                   */
  2882. /*   call RxAsyncPrint 'This is printed on stdout'                   */
  2883. /*                                                                   */
  2884. /*********************************************************************/
  2885.  
  2886. APIRET RxAsyncPrint(
  2887.           CHAR     *name,
  2888.           ULONG    numargs,
  2889.           RXSTRING args[],
  2890.           CHAR     *queuename,
  2891.           RXSTRING *retstr )
  2892. {
  2893.    if ( numargs != 1 )                 /* Must have one argument     */
  2894.       return( ROUTINE_INVALID );
  2895.  
  2896.    if (     RXNULLSTRING(args[0]) )    /* Must be a string (empty ok)*/
  2897.       return( ROUTINE_INVALID );
  2898.  
  2899.    fprintf( stdout, args[0].strptr );
  2900.  
  2901.    BUILDRXDOSRET( retstr, NO_ERROR );  /* Return result              */
  2902.  
  2903.    return( ROUTINE_VALID );
  2904. }
  2905.  
  2906. /*********************************************************************/
  2907. /*                                                                   */
  2908. /* Function:  RxAsyncCarrier                                         */
  2909. /*                                                                   */
  2910. /* Purpose:   Test for data carrier detect on specified port         */
  2911. /*                                                                   */
  2912. /*            Utilises IOCTL 67H ASYNC_GETMODEMINPUT.                */
  2913. /*                                                                   */
  2914. /* Syntax:    rc = RxAsyncCarrier( port )                            */
  2915. /*                                                                   */
  2916. /*      OR    rc = RxAsyncCarrier( port, timeout )                   */
  2917. /*                                                                   */
  2918. /* Params:    port    - handle of open port                          */
  2919. /*                                                                   */
  2920. /*            timeout - optional second parameter (milliseconds)     */
  2921. /*                      which when specified and > 0 causes this     */
  2922. /*                      routine to wait for an active DCD signal.    */
  2923. /*                                                                   */
  2924. /*                      If -1 is specified then the routine waits    */
  2925. /*                      forever.                                     */
  2926. /*                                                                   */
  2927. /*                      If 0 is specified or the parameter is        */
  2928. /*                      omitted then the current carrier status      */
  2929. /*                      is returned.                                 */
  2930. /*                                                                   */
  2931. /* Return:                                                           */
  2932. /*   Carrier active   - NO_ERROR (0)                                 */
  2933. /*   Wait timed out   - RC_ASYNC_TIMED_OUT (-1)                      */
  2934. /*   Carrier inactive - RC_ASYNC_NO_SIGNAL (-2)                      */
  2935. /*   Error occurred   - rc from DosDevIOCtl                          */
  2936. /*                                                                   */
  2937. /* Example:                                                          */
  2938. /*                                                                   */
  2939. /*   rc = RxAsyncCarrier( PortHandle )                               */
  2940. /*   if rc = 0                                                       */
  2941. /*      then say 'RxAsyncCarrier detected DCD'                       */
  2942. /*      else if rc = -2                                              */
  2943. /*              then say 'RxAsyncCarrier did not detect DCD'         */
  2944. /*              else say 'RxAsyncCarrier failed with rc=>'rc'<'      */
  2945. /*                                                                   */
  2946. /*********************************************************************/
  2947.  
  2948. APIRET RxAsyncCarrier(
  2949.           CHAR     *name,
  2950.           ULONG    numargs,
  2951.           RXSTRING args[],
  2952.           CHAR     *queuename,
  2953.           RXSTRING *retstr )
  2954. {
  2955.    APIRET    rc;                       /* Function return code       */
  2956.    HFILE     hcomPort;                 /* Communications port handle */
  2957.    LONG      lTimeLimit;               /* Timeout in milliseconds    */
  2958.  
  2959.    if (   (numargs < 1)                /* May have either one        */
  2960.        || (numargs > 2) )              /* or two arguments           */
  2961.       return( ROUTINE_INVALID );
  2962.  
  2963.    if (   !RXVALIDSTRING(args[0]) )    /* Must specify port handle   */
  2964.       return( ROUTINE_INVALID );
  2965.  
  2966.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  2967.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  2968.  
  2969.    lTimeLimit = 0;                     /* Default to return immediate*/
  2970.  
  2971.    if ( numargs == 2 ) {               /* If two arguments then      */
  2972.  
  2973.       if ( !RXVALIDSTRING(args[1]) )   /* Must specify timeout       */
  2974.          return( ROUTINE_INVALID );
  2975.  
  2976.       if ( !Str2Num(args[1].strptr, &lTimeLimit, STR2NUM_DEC2LONG) )
  2977.          return( ROUTINE_INVALID );    /* Convert timeout failed     */
  2978.    }
  2979.  
  2980.    rc = WaitCarrier( hcomPort, lTimeLimit );
  2981.  
  2982.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  2983.  
  2984.    BUILDRXDOSRET( retstr, rc );
  2985.  
  2986.    return( ROUTINE_VALID );
  2987. }
  2988.  
  2989. /*********************************************************************/
  2990. /*                                                                   */
  2991. /* Function:  RxAsyncBreak                                           */
  2992. /*                                                                   */
  2993. /* Purpose:   Send break for specified length of time                */
  2994. /*                                                                   */
  2995. /*            Utilises IOCTLs 45H ASYNC_SETBREAKOFF                  */
  2996. /*                        and 4BH ASYNC_SETBREAKON.                  */
  2997. /*                                                                   */
  2998. /* Syntax:    call RxAsyncBreak handlevar milliseconds               */
  2999. /*                                                                   */
  3000. /* Params:    handlevar - rexx variable with com handle              */
  3001. /*            millisecs - duration of break to send                  */
  3002. /*                                                                   */
  3003. /* Return:                                                           */
  3004. /*   Call successful - NO_ERROR (0)                                  */
  3005. /*   Call failed     - rc from DosDevIOCtl                           */
  3006. /*                                                                   */
  3007. /* Example:                                                          */
  3008. /*                                                                   */
  3009. /*   BreakTime = 500                                                 */
  3010. /*   rc = RxAsyncBreak( PortHandle, BreakTime )                      */
  3011. /*   if rc <> 0                                                      */
  3012. /*      then say 'RxAsyncBreak failed with rc=>'rc'<'                */
  3013. /*      else say 'RxAsyncBreak sent break for 'BreakTime' millisecs' */
  3014. /*                                                                   */
  3015. /*********************************************************************/
  3016.  
  3017. APIRET RxAsyncBreak(
  3018.           CHAR     *name,
  3019.           ULONG    numargs,
  3020.           RXSTRING args[],
  3021.           CHAR     *queuename,
  3022.           RXSTRING *retstr )
  3023. {
  3024.    APIRET    rc;                       /* Function return code       */
  3025.    HFILE     hcomPort;                 /* Communications port handle */
  3026.    ULONG     ulDuration;               /* Break duration             */
  3027.  
  3028.    if ( numargs != 2 )                 /* Must have two arguments    */
  3029.       return( ROUTINE_INVALID );
  3030.  
  3031.    if (   !RXVALIDSTRING(args[0])      /* Must specify port handle   */
  3032.        || !RXVALIDSTRING(args[1]) )    /* and break duration         */
  3033.       return( ROUTINE_INVALID );
  3034.  
  3035.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  3036.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  3037.  
  3038.    if ( !Str2Num(args[1].strptr, &ulDuration, STR2NUM_DEC2ULONG) )
  3039.       return( ROUTINE_INVALID );       /* Convert duration failed    */
  3040.  
  3041.    rc = SendBreak( hcomPort, ulDuration );
  3042.  
  3043.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  3044.  
  3045.    BUILDRXDOSRET( retstr, rc );
  3046.  
  3047.    return( ROUTINE_VALID );
  3048. }
  3049.  
  3050. /*********************************************************************/
  3051. /*                                                                   */
  3052. /* Function:  RxAsyncDcbInfo                                         */
  3053. /*                                                                   */
  3054. /* Purpose:   Print current port settings                            */
  3055. /*                                                                   */
  3056. /*            Utilises IOCTL 73H ASYNC_GETDCBINFO.                   */
  3057. /*                                                                   */
  3058. /* Syntax:    call RxAsyncDcbInfo handlevar                          */
  3059. /*                                                                   */
  3060. /* Params:    handlevar - rexx variable with com handle              */
  3061. /*                                                                   */
  3062. /* Return:                                                           */
  3063. /*   Call successful - NO_ERROR (0)                                  */
  3064. /*   Call failed     - rc from DosDevIOCtl                           */
  3065. /*                                                                   */
  3066. /* Example:                                                          */
  3067. /*                                                                   */
  3068. /*   rc = RxAsyncDcbInfo( PortHandle )                               */
  3069. /*   if rc <> 0                                                      */
  3070. /*      then say 'RxAsyncDcbInfo failed with rc=>'rc'<'              */
  3071. /*      else say 'RxAsyncDcbInfo returned okay.'                     */
  3072. /*                                                                   */
  3073. /*********************************************************************/
  3074.  
  3075. APIRET RxAsyncDcbInfo(
  3076.           CHAR     *name,
  3077.           ULONG    numargs,
  3078.           RXSTRING args[],
  3079.           CHAR     *queuename,
  3080.           RXSTRING *retstr )
  3081. {
  3082.    APIRET   rc;                        /* Function return code       */
  3083.    HFILE    hcomPort;                  /* Communications port handle */
  3084.  
  3085.    if ( numargs != 1 )                 /* Must have one argument     */
  3086.       return( ROUTINE_INVALID );
  3087.  
  3088.    if ( !RXVALIDSTRING(args[0]) )      /* Must specify port          */
  3089.       return( ROUTINE_INVALID );
  3090.  
  3091.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  3092.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  3093.  
  3094.    rc = PrtDcbInfo( hcomPort );
  3095.  
  3096.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  3097.  
  3098.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  3099.  
  3100.    return( ROUTINE_VALID );
  3101. }
  3102.  
  3103. /*********************************************************************/
  3104. /*                                                                   */
  3105. /* Function:  RxAsyncFileExists                                      */
  3106. /*                                                                   */
  3107. /* Purpose:   Test for existence of specified file                   */
  3108. /*                                                                   */
  3109. /* Syntax:    if RxAsyncFileExists( FileName )                       */
  3110. /*                                                                   */
  3111. /* Params:    FileName - Name of file to test for (WILDCARDS OK)     */
  3112. /*                                                                   */
  3113. /* Return:                                                           */
  3114. /*   File was found   - RC_REXX_TRUE (1)                             */
  3115. /*   File not found   - RC_REXX_FALSE (0)                            */
  3116. /*                                                                   */
  3117. /* Example:                                                          */
  3118. /*                                                                   */
  3119. /*   if RxAsyncFileExists( 'C:\*.BAT' )                              */
  3120. /*      then say 'RxAsyncFileExists found a batch file.'             */
  3121. /*                                                                   */
  3122. /*********************************************************************/
  3123.  
  3124. APIRET RxAsyncFileExists(
  3125.           CHAR     *name,
  3126.           ULONG    numargs,
  3127.           RXSTRING args[],
  3128.           CHAR     *queuename,
  3129.           RXSTRING *retstr )
  3130. {
  3131.    if ( numargs != 1 )                 /* Must have one argument     */
  3132.       return( ROUTINE_INVALID );
  3133.  
  3134.    if (   !RXVALIDSTRING(args[0]) )    /* Must specify file name     */
  3135.       return( ROUTINE_INVALID );
  3136.  
  3137.    if ( fFileExists( args[0].strptr ) ) {
  3138.       BUILDRXDOSRET( retstr, RC_REXX_TRUE );
  3139.    } else {
  3140.       BUILDRXDOSRET( retstr, RC_REXX_FALSE );
  3141.    }
  3142.  
  3143.    return( ROUTINE_VALID );
  3144. }
  3145.  
  3146. /*********************************************************************/
  3147. /*                                                                   */
  3148. /* Function:  RxAsyncFileDelete                                      */
  3149. /*                                                                   */
  3150. /* Purpose:   Delete specified file                                  */
  3151. /*                                                                   */
  3152. /* Syntax:    if RxAsyncFileDelete( FileName )                       */
  3153. /*                                                                   */
  3154. /* Params:    FileName - Name of file to delete (NO WILDCARDS)       */
  3155. /*                                                                   */
  3156. /* Return:                                                           */
  3157. /*   File was deleted - RC_REXX_TRUE (1)                             */
  3158. /*   File not deleted - RC_REXX_FALSE (0)                            */
  3159. /*                                                                   */
  3160. /* Example:                                                          */
  3161. /*                                                                   */
  3162. /*   if RxAsyncFileDelete( 'C:\FRED.TXT' )                           */
  3163. /*      then say 'RxAsyncFileDelete deleted file Fred.Txt'           */
  3164. /*                                                                   */
  3165. /*********************************************************************/
  3166.  
  3167. APIRET RxAsyncFileDelete(
  3168.           CHAR     *name,
  3169.           ULONG    numargs,
  3170.           RXSTRING args[],
  3171.           CHAR     *queuename,
  3172.           RXSTRING *retstr )
  3173. {
  3174.    if ( numargs != 1 )                 /* Must have one argument     */
  3175.       return( ROUTINE_INVALID );
  3176.  
  3177.    if (   !RXVALIDSTRING(args[0]) )    /* Must specify file name     */
  3178.       return( ROUTINE_INVALID );
  3179.  
  3180.    if ( fFileDelete( args[0].strptr ) ) {
  3181.       BUILDRXDOSRET( retstr, RC_REXX_TRUE );
  3182.    } else {
  3183.       BUILDRXDOSRET( retstr, RC_REXX_FALSE );
  3184.    }
  3185.  
  3186.    return( ROUTINE_VALID );
  3187. }
  3188.  
  3189. /*********************************************************************/
  3190. /*                                                                   */
  3191. /* Function:  RxAsyncFileCopy                                        */
  3192. /*                                                                   */
  3193. /* Purpose:   Copy a specified file                                  */
  3194. /*                                                                   */
  3195. /* Syntax:    if RxAsyncFileCopy( FromName, ToName )                 */
  3196. /*                                                                   */
  3197. /* Params:    FromName - Name of file to copy (NO WILDCARDS)         */
  3198. /*            ToName   - Name to copy to      (NO WILDCARDS)         */
  3199. /*                                                                   */
  3200. /* Return:                                                           */
  3201. /*   File was copied  - RC_REXX_TRUE (1)                             */
  3202. /*   File not copied  - RC_REXX_FALSE (0)                            */
  3203. /*                                                                   */
  3204. /* Example:                                                          */
  3205. /*                                                                   */
  3206. /*   if RxAsyncFileCopy( 'C:\FRED.TXT', 'D:\FRED.BAK' )              */
  3207. /*      then say 'RxAsyncFileCopy copied Fred.Txt to Fred.Bak'       */
  3208. /*                                                                   */
  3209. /*********************************************************************/
  3210.  
  3211. APIRET RxAsyncFileCopy(
  3212.           CHAR     *name,
  3213.           ULONG    numargs,
  3214.           RXSTRING args[],
  3215.           CHAR     *queuename,
  3216.           RXSTRING *retstr )
  3217. {
  3218.    if ( numargs != 2 )                 /* Must have two arguments    */
  3219.       return( ROUTINE_INVALID );
  3220.  
  3221.    if (   !RXVALIDSTRING(args[0])      /* Must specify file name src */
  3222.        || !RXVALIDSTRING(args[1]) )    /* Must specify file name trg */
  3223.       return( ROUTINE_INVALID );
  3224.  
  3225.    if ( fFileCopy( args[0].strptr, args[1].strptr ) ) {
  3226.       BUILDRXDOSRET( retstr, RC_REXX_TRUE );
  3227.    } else {
  3228.       BUILDRXDOSRET( retstr, RC_REXX_FALSE );
  3229.    }
  3230.  
  3231.    return( ROUTINE_VALID );
  3232. }
  3233.  
  3234. /*********************************************************************/
  3235. /*                                                                   */
  3236. /* Function:  RxAsyncFileMove                                        */
  3237. /*                                                                   */
  3238. /* Purpose:   Move a specified file                                  */
  3239. /*                                                                   */
  3240. /* Syntax:    if RxAsyncFileMove( FromName, ToName )                 */
  3241. /*                                                                   */
  3242. /* Params:    FromName - Name of file to move (NO WILDCARDS)         */
  3243. /*            ToName   - Name to move to      (NO WILDCARDS)         */
  3244. /*                                                                   */
  3245. /* Return:                                                           */
  3246. /*   File was moved   - RC_REXX_TRUE (1)                             */
  3247. /*   File not moved   - RC_REXX_FALSE (0)                            */
  3248. /*                                                                   */
  3249. /* Notes:                                                            */
  3250. /*   Permits the movement of files accross drives.                   */
  3251. /*                                                                   */
  3252. /* Example:                                                          */
  3253. /*                                                                   */
  3254. /*   if RxAsyncFileMove( 'C:\FRED.TXT', 'D:\FRED.TXT' )              */
  3255. /*      then say 'RxAsyncFileMove moved C:\Fred.Txt to D:\Fred.Txt'  */
  3256. /*                                                                   */
  3257. /*********************************************************************/
  3258.  
  3259. APIRET RxAsyncFileMove(
  3260.           CHAR     *name,
  3261.           ULONG    numargs,
  3262.           RXSTRING args[],
  3263.           CHAR     *queuename,
  3264.           RXSTRING *retstr )
  3265. {
  3266.    if ( numargs != 2 )                 /* Must have two arguments    */
  3267.       return( ROUTINE_INVALID );
  3268.  
  3269.    if (   !RXVALIDSTRING(args[0])      /* Must specify file name src */
  3270.        || !RXVALIDSTRING(args[1]) )    /* Must specify file name trg */
  3271.       return( ROUTINE_INVALID );
  3272.  
  3273.    if ( fFileMove( args[0].strptr, args[1].strptr ) ) {
  3274.       BUILDRXDOSRET( retstr, RC_REXX_TRUE );
  3275.    } else {
  3276.       BUILDRXDOSRET( retstr, RC_REXX_FALSE );
  3277.    }
  3278.  
  3279.    return( ROUTINE_VALID );
  3280. }
  3281.  
  3282. /*********************************************************************/
  3283. /*                                                                   */
  3284. /* Function:  RxAsyncFileRename                                      */
  3285. /*                                                                   */
  3286. /* Purpose:   Rename specified file                                  */
  3287. /*                                                                   */
  3288. /* Syntax:    if RxAsyncFileRename( FromName, ToName )               */
  3289. /*                                                                   */
  3290. /* Params:    FromName - Name of file to rename  (NO WILDCARDS)      */
  3291. /*            ToName   - Name to rename to       (NO WILDCARDS)      */
  3292. /*                                                                   */
  3293. /* Return:                                                           */
  3294. /*   File was renamed - RC_REXX_TRUE (1)                             */
  3295. /*   File not renamed - RC_REXX_FALSE (0)                            */
  3296. /*                                                                   */
  3297. /* Example:                                                          */
  3298. /*                                                                   */
  3299. /*   if RxAsyncFileRename( 'C:\FRED.TXT', 'C:\FRED.OLD' )            */
  3300. /*      then say 'RxAsyncFileRename renamed Fred.Txt to Fred.Old'    */
  3301. /*                                                                   */
  3302. /*********************************************************************/
  3303.  
  3304. APIRET RxAsyncFileRename(
  3305.           CHAR     *name,
  3306.           ULONG    numargs,
  3307.           RXSTRING args[],
  3308.           CHAR     *queuename,
  3309.           RXSTRING *retstr )
  3310. {
  3311.    if ( numargs != 2 )                 /* Must have two arguments    */
  3312.       return( ROUTINE_INVALID );
  3313.  
  3314.    if (   !RXVALIDSTRING(args[0])      /* Must specify file name old */
  3315.        || !RXVALIDSTRING(args[1]) )    /* Must specify file name new */
  3316.       return( ROUTINE_INVALID );
  3317.  
  3318.    if ( fFileRename( args[0].strptr, args[1].strptr ) ) {
  3319.       BUILDRXDOSRET( retstr, RC_REXX_TRUE );
  3320.    } else {
  3321.       BUILDRXDOSRET( retstr, RC_REXX_FALSE );
  3322.    }
  3323.  
  3324.    return( ROUTINE_VALID );            /* All ok                     */
  3325. }
  3326.  
  3327. /*********************************************************************/
  3328. /*                                                                   */
  3329. /* Function:  RxAsyncFileNameIs                                      */
  3330. /*                                                                   */
  3331. /* Purpose:   Determine file name                                    */
  3332. /*                                                                   */
  3333. /* Syntax:    Tname = RxAsyncFileNameIs( FileName )                  */
  3334. /*                                                                   */
  3335. /* Params:    FileName - File spec to extract name from              */
  3336. /*                                                                   */
  3337. /* Return:                                                           */
  3338. /*   File name extracted if any                                      */
  3339. /*                                                                   */
  3340. /* Example:                                                          */
  3341. /*                                                                   */
  3342. /*   Fname = RxAsyncFileNameIs( 'C:\FRED.TXT' )                      */
  3343. /*   say 'RxAsyncFileNameIs returned 'Fname                          */
  3344. /*                                                                   */
  3345. /*   RxAsyncFileNameIs returned FRED.TXT                             */
  3346. /*                                                                   */
  3347. /*********************************************************************/
  3348.  
  3349. APIRET RxAsyncFileNameIs(
  3350.           CHAR     *name,
  3351.           ULONG    numargs,
  3352.           RXSTRING args[],
  3353.           CHAR     *queuename,
  3354.           RXSTRING *retstr )
  3355. {
  3356.    if ( numargs != 1 )                 /* Must have one argument     */
  3357.       return( ROUTINE_INVALID );
  3358.  
  3359.    if ( RXNULLSTRING(args[0]) )        /* Must specify file name     */
  3360.       return( ROUTINE_INVALID );
  3361.  
  3362.    FileNameIs( args[0].strptr, retstr->strptr );
  3363.  
  3364.    retstr->strlength = strlen(retstr->strptr);
  3365.  
  3366.    return( ROUTINE_VALID );
  3367. }
  3368.  
  3369. /*********************************************************************/
  3370. /*                                                                   */
  3371. /* Function:  RxAsyncFilePathIs                                      */
  3372. /*                                                                   */
  3373. /* Purpose:   Determine path name                                    */
  3374. /*                                                                   */
  3375. /* Syntax:    Tpath = RxAsyncFilePathIs( FileName )                  */
  3376. /*                                                                   */
  3377. /* Params:    FileName - File spec to extract path from              */
  3378. /*                                                                   */
  3379. /* Return:                                                           */
  3380. /*   File path extracted if any                                      */
  3381. /*                                                                   */
  3382. /* Example:                                                          */
  3383. /*                                                                   */
  3384. /*   Fpath = RxAsyncFilePathIs( 'C:\FRED.TXT' )                      */
  3385. /*   say 'RxAsyncFilePathIs returned 'Fpath                          */
  3386. /*                                                                   */
  3387. /*   RxAsyncFilePathIs returned C:\                                  */
  3388. /*                                                                   */
  3389. /*********************************************************************/
  3390.  
  3391. APIRET RxAsyncFilePathIs(
  3392.           CHAR     *name,
  3393.           ULONG    numargs,
  3394.           RXSTRING args[],
  3395.           CHAR     *queuename,
  3396.           RXSTRING *retstr )
  3397. {
  3398.    if ( numargs != 1 )                 /* Must have one argument     */
  3399.       return( ROUTINE_INVALID );
  3400.  
  3401.    if ( RXNULLSTRING(args[0]) )        /* Must specify file name     */
  3402.       return( ROUTINE_INVALID );
  3403.  
  3404.    FilePathIs( args[0].strptr, retstr->strptr );
  3405.  
  3406.    retstr->strlength = strlen(retstr->strptr);
  3407.  
  3408.    return( ROUTINE_VALID );
  3409. }
  3410.  
  3411. /*********************************************************************/
  3412. /*                                                                   */
  3413. /* Function:  RxAsyncDirectory                                       */
  3414. /*                                                                   */
  3415. /* Purpose:   Query/Change directory                                 */
  3416. /*                                                                   */
  3417. /* Syntax:    Tdir = RxAsyncDirectory( NewDir )                      */
  3418. /*                                                                   */
  3419. /* Params:    NewDir - Name of directory to change to if specified   */
  3420. /*                                                                   */
  3421. /* Return:                                                           */
  3422. /*   Current/New directory name                                      */
  3423. /*                                                                   */
  3424. /* Notes:                                                            */
  3425. /*   Differs from the standard directory() function by always        */
  3426. /*   appending a trailing backslash to the returned path spec.       */
  3427. /*                                                                   */
  3428. /* Example:                                                          */
  3429. /*                                                                   */
  3430. /*   OldDir = RxAsyncDirectory()                                     */
  3431. /*   NewDir = 'C:\OS2\'                                              */
  3432. /*   CurDir = RxAsyncDirectory( NewDir )                             */
  3433. /*                                                                   */
  3434. /*********************************************************************/
  3435.  
  3436. APIRET RxAsyncDirectory(
  3437.           CHAR     *name,
  3438.           ULONG    numargs,
  3439.           RXSTRING args[],
  3440.           CHAR     *queuename,
  3441.           RXSTRING *retstr )
  3442. {
  3443.    if ( numargs > 1 )                  /* May have one argument/none */
  3444.       return( ROUTINE_INVALID );
  3445.  
  3446.    if ( numargs == 1 ) {               /* If argument specified      */
  3447.  
  3448.       if ( RXNULLSTRING(args[0]) )     /* Must be valid string       */
  3449.          return( ROUTINE_INVALID );
  3450.  
  3451.       FileChgDir( args[0].strptr );
  3452.    }
  3453.  
  3454.    FileGetDir( retstr->strptr );
  3455.  
  3456.    retstr->strlength = strlen(retstr->strptr);
  3457.  
  3458.    return( ROUTINE_VALID );
  3459. }
  3460.  
  3461. /*********************************************************************/
  3462. /*                                                                   */
  3463. /* Function:  RxAsyncMsgBox                                          */
  3464. /*                                                                   */
  3465. /* Purpose:   Display a PM message box                               */
  3466. /*                                                                   */
  3467. /* Syntax:    answ = RxAsyncMsgBox( MsgTitle,                        */
  3468. /*                                  MsgIcon,                         */
  3469. /*                                  MsgButtons,                      */
  3470. /*                                  MsgHelp,                         */
  3471. /*                                  MsgNumber,                       */
  3472. /*                                  MsgText )                        */
  3473. /*                                                                   */
  3474. /* Params:    MsgTitle    - Text to use as the title if specified    */
  3475. /*            MsgIcon     - Type of icon to display in box           */
  3476. /*                                                                   */
  3477. /*              N-one             NO_ICON                            */
  3478. /*              I-nformation      ICONASTERISK                       */
  3479. /*              W-arning          ICONEXCLAMATION                    */
  3480. /*              Q-uery            ICONQUESTION                       */
  3481. /*              S-top             ICONHAND                           */
  3482. /*                                                                   */
  3483. /*              Note: Only the first character is significant.       */
  3484. /*                                                                   */
  3485. /*            MsgButtons  - Type of message box to use               */
  3486. /*                                                                   */
  3487. /*              V-anilla          ENTER                              */
  3488. /*              I-nformation      OK                                 */
  3489. /*              W-arning          OK CANCEL                          */
  3490. /*              Q-uery            YES NO                             */
  3491. /*              S-top             CANCEL                             */
  3492. /*              R-etry            RETRY CANCEL                       */
  3493. /*              A-bort            ABORT RETRY IGNORE                 */
  3494. /*                                                                   */
  3495. /*              Note: Only the first character is significant.       */
  3496. /*                                                                   */
  3497. /*            MsgHelp     - Whether to add help button "Y"/"N"       */
  3498. /*                                                                   */
  3499. /*              Note: Only the first character is significant.       */
  3500. /*                                                                   */
  3501. /*            MsgNumber   - System message to retrieve if specified  */
  3502. /*            MsgText     - Text of message or parameters for Number */
  3503. /*                                                                   */
  3504. /*              Note: If using a system message (Number not 0) then  */
  3505. /*                    the parameters are supplied in the MsgText as  */
  3506. /*                    a linefeed (0x10) delimited list. Excess       */
  3507. /*                    parameters will be discarded and missing       */
  3508. /*                    parameters will have '<?>' substituted into    */
  3509. /*                    the constructed message text.                  */
  3510. /*                                                                   */
  3511. /* Return:                                                           */
  3512. /*   Value indicating response chosen.                               */
  3513. /*     0 - OK, YES, RETRY, ENTER                                     */
  3514. /*     1 - CANCEL, NO, ABORT, ERROR                                  */
  3515. /*     2 - IGNORE                                                    */
  3516. /*     3 - HELP                                                      */
  3517. /*                                                                   */
  3518. /* Notes:                                                            */
  3519. /*   At present the use of system messages is not implemented.       */
  3520. /*                                                                   */
  3521. /*   In order to use RxAsyncMsgBox your rexx script must be invoked  */
  3522. /*   under a CMD.EXE session which has been started as a PM session. */
  3523. /*                                                                   */
  3524. /*   To do this you use the following command:-                      */
  3525. /*                                                                   */
  3526. /*     START "Test script" /PM /PGM "Cmd.Exe" /C "Your.cmd"          */
  3527. /*                                                                   */
  3528. /*     (see the START command in the OS/2 Command Reference for a    */
  3529. /*      full explanation of the parameters.)                         */
  3530. /*                                                                   */
  3531. /*   WARNING: When running your script under PM in this way you will */
  3532. /*            NOT have a window session, hence NO stdin, stdout or   */
  3533. /*            stderr, unless you redirect them.                      */
  3534. /*                                                                   */
  3535. /* Example:                                                          */
  3536. /*                                                                   */
  3537. /*   Tans = RxAsyncMsgBox( "A message from RxAsync.",                */
  3538. /*                         "Question mark icon",                     */
  3539. /*                         "Query buttons",                          */
  3540. /*                         "No help button please",                  */
  3541. /*                         0,                                        */
  3542. /*                         "Hi there dudes! Want more?" )            */
  3543. /*   if Tans = 0                                                     */
  3544. /*      then call UserPressedYES                                     */
  3545. /*      else call UserPressedNO                                      */
  3546. /*                                                                   */
  3547. /*********************************************************************/
  3548.  
  3549. APIRET RxAsyncMsgBox(
  3550.           CHAR     *name,
  3551.           ULONG    numargs,
  3552.           RXSTRING args[],
  3553.           CHAR     *queuename,
  3554.           RXSTRING *retstr )
  3555. {
  3556.    APIRET    rc;                       /* Function return code       */
  3557.    CHAR      chIcon;                   /* Code for icon type         */
  3558.    CHAR      chButtons;                /* Code for button type       */
  3559.    CHAR      chHelp;                   /* Want help button           */
  3560.    USHORT    usNumber;                 /* Message number if any      */
  3561.  
  3562.    if ( numargs != 6 )                 /* Must have five arguments   */
  3563.       return( ROUTINE_INVALID );
  3564.  
  3565.    if ( RXVALIDSTRING(args[1]) ) {
  3566.       chIcon = (args[1].strptr)[0];    /* Only want first character  */
  3567.    } else {
  3568.       chIcon = 'N';                    /* Default to No icon         */
  3569.    }
  3570.  
  3571.    if ( RXVALIDSTRING(args[2]) ) {
  3572.       chButtons = (args[2].strptr)[0]; /* Only want first character  */
  3573.    } else {
  3574.       chButtons = 'V';                 /* Default to Vanilla button  */
  3575.    }
  3576.  
  3577.    if ( RXVALIDSTRING(args[3]) ) {
  3578.       chHelp = (args[3].strptr)[0];    /* Only want first character  */
  3579.    } else {
  3580.       chHelp = 'N';                    /* Default to No help button  */
  3581.    }
  3582.  
  3583.    if ( strchr(MSG_ICON_STYLES, chIcon) == NULL )
  3584.       return( ROUTINE_INVALID );       /* Invalid icon style         */
  3585.  
  3586.    if ( strchr(MSG_BUTTON_STYLES, chButtons) == NULL )
  3587.       return( ROUTINE_INVALID );       /* Invalid button style       */
  3588.  
  3589.    if ( strchr(YESNO_OPTIONS, chHelp) == NULL )
  3590.       return( ROUTINE_INVALID );       /* Invalid help style         */
  3591.  
  3592.    if ( RXVALIDSTRING(args[4]) ) {
  3593.       if ( !Str2Num(args[4].strptr, &(usNumber), STR2NUM_DEC2USHORT) )
  3594.          return( ROUTINE_INVALID );    /* Invalid message number     */
  3595.    } else {
  3596.       usNumber = 0;
  3597.    }
  3598.  
  3599.    rc = MsgBox( args[0].strptr,
  3600.                 chIcon,
  3601.                 chButtons,
  3602.                 chHelp,
  3603.                 usNumber,
  3604.                 args[5].strptr );
  3605.  
  3606.    BUILDRXDOSRET( retstr, rc );
  3607.  
  3608.    return( ROUTINE_VALID );            /* All ok                     */
  3609. }
  3610.  
  3611. /*********************************************************************/
  3612. /*                                                                   */
  3613. /* Function:  RxAsyncWatch                                           */
  3614. /*                                                                   */
  3615. /* Purpose:   Wait for one or more strings to be read.               */
  3616. /*                                                                   */
  3617. /*            Utilises IOCTL 72H ASYNC_GETCOMMEVENT.                 */
  3618. /*                                                                   */
  3619. /* Syntax:    rc = RxAsyncWatch( port,                               */
  3620. /*                               'match',                            */
  3621. /*                               nocase,                             */
  3622. /*                               timeout,                            */
  3623. /*                               'varname',                          */
  3624. /*                               'findndx',                          */
  3625. /*                               nullrep,                            */
  3626. /*                               lineend )                           */
  3627. /*                                                                   */
  3628. /* Params:    port    - Handle of open port.                         */
  3629. /*                                                                   */
  3630. /*            match   - Name of stem variable which specifies the    */
  3631. /*                      strings to search for.                       */
  3632. /*                                                                   */
  3633. /*            nocase  - Whether to ignore case "Y"/"N".              */
  3634. /*                                                                   */
  3635. /*                      Note: Only first character is significant.   */
  3636. /*                                                                   */
  3637. /*            timeout - Maximum period to wait in milliseconds.      */
  3638. /*                                                                   */
  3639. /*                       0 = no waiting                              */
  3640. /*                      -1 = no timeout                              */
  3641. /*                                                                   */
  3642. /*            varname - Name of rexx variable to return data in.     */
  3643. /*                                                                   */
  3644. /*            findndx - Name of rexx variable to return ndx found.   */
  3645. /*                                                                   */
  3646. /*            nullrep - Optional parameter which when specified      */
  3647. /*                      permits null charatacers in the input stream */
  3648. /*                      to be either discarded ('') or replaced      */
  3649. /*                      ('?').  An empty string tells the function   */
  3650. /*                      to discard nulls, otherwise all nulls are    */
  3651. /*                      replaced with the character specified.  If   */
  3652. /*                      this parameter is not specified then all     */
  3653. /*                      nulls will be returned in the string passed  */
  3654. /*                      back to the caller.                          */
  3655. /*                                                                   */
  3656. /*            lineend - Optional parameter which when specified      */
  3657. /*                      indicates an additional character to be used */
  3658. /*                      in detecting end_of_line.  The defaults if   */
  3659. /*                      not specified are line_feed, form_feed or    */
  3660. /*                      end_of_file.  When specified the character   */
  3661. /*                      acts in addition to the defaults.            */
  3662. /*                                                                   */
  3663. /* Notes:     RxAsyncWatch is a line mode only routine, as each line */
  3664. /*            is read it is checked to see if one of the specified   */
  3665. /*            strings is present.  If found then the line containing */
  3666. /*            the string is returned in the variable specified, and  */
  3667. /*            the number of the string found is returned in the find */
  3668. /*            index.  If not found then the line is printed on       */
  3669. /*            stdout and the next line is read.                      */
  3670. /*                                                                   */
  3671. /* Return:                                                           */
  3672. /*   Call successful  - NO_ERROR (0)                                 */
  3673. /*   Read timed out   - RC_ASYNC_TIMED_OUT (-1)                      */
  3674. /*   Call failed      - ERROR_NOT_ENOUGH_MEMORY (8)                  */
  3675. /*          "         - ERROR_INVALID_PARAMETER (87)                 */
  3676. /*          "         - rc from DosRead                              */
  3677. /*                                                                   */
  3678. /* Example:                                                          */
  3679. /*                                                                   */
  3680. /*   lnfd = d2c(10)                                                  */
  3681. /*   MatchStr.0 = 2                                                  */
  3682. /*   MatchStr.1 = 'Hello'                                            */
  3683. /*   MatchStr.2 = 'Goodbye'                                          */
  3684. /*   InpStr = ''                                                     */
  3685. /*   NumFound = 0                                                    */
  3686. /*   rc =  RxAsyncWatch( PortHandle, 'MatchStr', 'Y', 3000,          */
  3687. /*                       'InpStr', 'NumFound', '', lnfd )            */
  3688. /*   if rc = 0                                                       */
  3689. /*      then do                                                      */
  3690. /*             say 'RxAsyncWatch returned >'InpStr'<'                */
  3691. /*             say 'Index of string found was >'NumFound'<'          */
  3692. /*             switch                                                */
  3693. /*                when NumFound = 1 then say 'Hi dude'               */
  3694. /*                when NumFound = 2 then say 'Later dude'            */
  3695. /*                otherwise say 'Nothing found'                      */
  3696. /*             end                                                   */
  3697. /*           end                                                     */
  3698. /*      else if rc = -1                                              */
  3699. /*              then say 'RxAsyncWatch timed out'                    */
  3700. /*              else say 'RxAsyncWatch failed rc=>'rc'<'             */
  3701. /*                                                                   */
  3702. /*********************************************************************/
  3703.  
  3704. APIRET RxAsyncWatch(
  3705.           CHAR     *name,
  3706.           ULONG    numargs,
  3707.           RXSTRING args[],
  3708.           CHAR     *queuename,
  3709.           RXSTRING *retstr )
  3710. {
  3711.    APIRET       rc;                    /* Function return code       */
  3712.    APIRET       rc2;                   /* RexxVariablePool return    */
  3713.    HFILE        hcomPort;              /* Communications port handle */
  3714.    BYTE         ReadBuff[RXAUTOBUFLEN];/* Input buffer               */
  3715.    LONG         lTimeLimit;            /* Timeout in milliseconds    */
  3716.    SHVBLOCK     ReadVar;               /* Rexx variable for input    */
  3717.    PSZ          pszNullReplace;        /* Null replace character     */
  3718.    PSZ          pszLineEnd;            /* Line end character         */
  3719.    ULONG        ulMaxStrings;          /* Number of strings to check */
  3720.    ULONG        ulCurString;           /* Number of current string   */
  3721.    CHAR         StemBuff[RXAUTOBUFLEN];/* Stem content buffer        */
  3722.    BOOL         bStringFound;          /* Found required string      */
  3723.    BOOL         bIgnoreCase;           /* Whether to ignore case     */
  3724.  
  3725.    if (   (numargs < 6)                /* May have either 6,7 or 8   */
  3726.        || (numargs > 8) )
  3727.       return( ROUTINE_INVALID );
  3728.  
  3729.    if (   !RXVALIDSTRING(args[0])      /* Must specify port handle   */
  3730.        || !RXVALIDSTRING(args[1])      /* and match stem var name    */
  3731.        || !RXVALIDSTRING(args[2])      /* and case option            */
  3732.        || !RXVALIDSTRING(args[3])      /* and timeout                */
  3733.        || !RXVALIDSTRING(args[4])      /* and string to return data  */
  3734.        || !RXVALIDSTRING(args[5]) )    /* and string to return index */
  3735.       return( ROUTINE_INVALID );
  3736.  
  3737.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  3738.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  3739.  
  3740.    if ( (args[1].strptr)[args[1].strlength-1] == FILE_DELIM_CH )
  3741.       return( ROUTINE_INVALID );       /* Invalid stem variable name */
  3742.  
  3743.    if ( strchr(YESNO_OPTIONS, (CHAR) (args[2].strptr)[0]) == NULL )
  3744.       return( ROUTINE_INVALID );       /* Invalid ignore case option */
  3745.  
  3746.    if ( !Str2Num(args[3].strptr, &lTimeLimit, STR2NUM_DEC2LONG) )
  3747.       return( ROUTINE_INVALID );       /* Convert timeout failed     */
  3748.  
  3749.    pszNullReplace = NULL;
  3750.    if ( numargs >= 7 ) {               /* If seven or more arguements*/
  3751.       if ( RXVALIDSTRING(args[6]) )    /* If specified               */
  3752.          if ( args[6].strlength > 1 )  /* Must only be one or zero   */
  3753.             return( ROUTINE_INVALID );
  3754.  
  3755.       pszNullReplace = args[6].strptr;
  3756.    }
  3757.  
  3758.    pszLineEnd = NULL;
  3759.    if ( numargs >= 8 ) {               /* If eight or more arguements*/
  3760.       if ( RXVALIDSTRING(args[7]) )    /* If specified               */
  3761.          if ( args[7].strlength > 1 )  /* Must only be one or zero   */
  3762.             return( ROUTINE_INVALID );
  3763.  
  3764.       pszLineEnd = args[7].strptr;
  3765.    }
  3766.  
  3767.    /* set ignore case flag */
  3768.  
  3769.    bIgnoreCase = ( strchr(YES_OPTIONS, (CHAR) (args[2].strptr)[0]) != NULL );
  3770.  
  3771.    /* initialise returned index */
  3772.  
  3773.    ulCurString = 0;
  3774.    rc = SetRexxValue( args[5].strptr, VAL2STR_ULONG2DEC, &ulCurString );
  3775.    if ( rc != NO_ERROR ) {
  3776.       NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  3777.       BUILDRXDOSRET( retstr, rc );
  3778.       return( ROUTINE_VALID );
  3779.    }
  3780.  
  3781.    /* fetch stem.0 count of elements */
  3782.  
  3783.    ulMaxStrings = 0;
  3784.    rc = GetStemValue( args[1].strptr, 0, STR2NUM_DEC2ULONG, &ulMaxStrings );
  3785.    if ( rc != NO_ERROR ) {
  3786.       NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  3787.       BUILDRXDOSRET( retstr, rc );
  3788.       return( ROUTINE_VALID );         /* Fetch element count failed */
  3789.    }
  3790.  
  3791.    if ( ulMaxStrings == 0 ) {
  3792.       NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  3793.       BUILDRXDOSRET( retstr, ERROR_INVALID_PARAMETER );
  3794.       return( ROUTINE_VALID );         /* Must be non zero           */
  3795.    }
  3796.  
  3797.    /* fetch rexx variable details  (rexx mallocs, we free) */
  3798.  
  3799.    InitVar( &ReadVar, NULL, args[4].strptr );
  3800.  
  3801.    rc = FetchVar( &ReadVar );
  3802.  
  3803.    if ( rc == NO_ERROR ) {
  3804.  
  3805.       rc2 = NO_ERROR;
  3806.  
  3807.       bStringFound = FALSE;
  3808.  
  3809.       do {
  3810.  
  3811.          /* read a line */
  3812.  
  3813.          ReadVar.shvvalue.strptr[0] = EOSTR_CH; /* Initialise return var   */
  3814.  
  3815.          ReadVar.shvvalue.strlength = RXAUTOBUFLEN;
  3816.  
  3817.          rc = ReadPort( hcomPort,
  3818.                         ReadBuff,
  3819.                         0,
  3820.                         ReadVar.shvvalue.strptr,
  3821.                         &(ReadVar.shvvalue.strlength),
  3822.                         lTimeLimit,
  3823.                         pszNullReplace,
  3824.                         pszLineEnd );
  3825.  
  3826.          /* check if line contains a required string */
  3827.  
  3828.          strcpy(ReadBuff, ReadVar.shvvalue.strptr); /* save copy for testing */
  3829.          if ( bIgnoreCase ) {
  3830.             strupr(ReadBuff);
  3831.          }
  3832.  
  3833.          ulCurString = 0;
  3834.          do {
  3835.             ulCurString = ulCurString + 1;
  3836.             rc2 = GetStemValue( args[1].strptr, ulCurString, STR2NUM_STR2STR, StemBuff );
  3837.             if ( rc2 == NO_ERROR ) {
  3838.                /* check to see if required string is present */
  3839.                if ( bIgnoreCase ) {
  3840.                   strupr(StemBuff);
  3841.                }
  3842.                bStringFound = (strstr(ReadBuff, StemBuff) != NULL);
  3843.             }
  3844.          } while( (!bStringFound) && (ulCurString < ulMaxStrings) && (rc2 == NO_ERROR) );
  3845.  
  3846.          if ( !bStringFound ) {
  3847.             fprintf( stdout, ReadVar.shvvalue.strptr );
  3848.          }
  3849.  
  3850.       } while( (!bStringFound) && (rc == NO_ERROR) && (rc2 == NO_ERROR) );
  3851.  
  3852.       if ( bStringFound ) {
  3853.          rc = SetRexxValue( args[5].strptr, VAL2STR_ULONG2DEC, &ulCurString );
  3854.       } else if ( rc == NO_ERROR ) {
  3855.          rc = rc2;
  3856.       }
  3857.  
  3858.       /* set rexx variable details with retrieved values */
  3859.  
  3860.       rc2 = UpdateVar( &ReadVar );     /* Set the rexx variable      */
  3861.  
  3862.       if ( rc == NO_ERROR ) {          /* Only if not already error  */
  3863.          rc = rc2;
  3864.       }
  3865.    }
  3866.  
  3867.    FreeVar( &ReadVar );                /* Cleanup                    */
  3868.  
  3869.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  3870.  
  3871.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  3872.  
  3873.    return( ROUTINE_VALID );            /* All ok                     */
  3874. }
  3875.  
  3876. /*********************************************************************/
  3877. /*                                                                   */
  3878. /* Function:  RxAsyncFlushInput                                      */
  3879. /*                                                                   */
  3880. /* Purpose:   Flush device driver input queue                        */
  3881. /*                                                                   */
  3882. /*            Utilises IOCTL 01H DEV_FLUSHINPUT.                     */
  3883. /*                                                                   */
  3884. /* Syntax:    call RxAsyncFlushInput port                            */
  3885. /*                                                                   */
  3886. /* Params:    port   - handle of open port                           */
  3887. /*                                                                   */
  3888. /* Return:                                                           */
  3889. /*   Call successful - NO_ERROR (0)                                  */
  3890. /*   Call failed     - rc from DosDevIOCtl                           */
  3891. /*                                                                   */
  3892. /* Example:                                                          */
  3893. /*                                                                   */
  3894. /*   rc = RxAsyncFlushInput( PortHandle )                            */
  3895. /*   if rc <> 0                                                      */
  3896. /*      then say 'RxAsyncFlushInput failed with rc=>'rc'<'           */
  3897. /*      else say 'RxAsyncFlushInput returned okay.'                  */
  3898. /*                                                                   */
  3899. /*********************************************************************/
  3900.  
  3901. APIRET RxAsyncFlushInput(
  3902.           CHAR     *name,
  3903.           ULONG    numargs,
  3904.           RXSTRING args[],
  3905.           CHAR     *queuename,
  3906.           RXSTRING *retstr
  3907.        )
  3908. {
  3909.    APIRET   rc;                        /* Function return code       */
  3910.    HFILE    hcomPort;                  /* Communications port handle */
  3911.  
  3912.    if ( numargs != 1 )                 /* Must have one argument     */
  3913.       return( ROUTINE_INVALID );
  3914.  
  3915.    if (   !RXVALIDSTRING(args[0]) )    /* Must specify port          */
  3916.       return( ROUTINE_INVALID );
  3917.  
  3918.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  3919.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  3920.  
  3921.    rc = FlushInput( hcomPort );
  3922.  
  3923.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  3924.  
  3925.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  3926.  
  3927.    return( ROUTINE_VALID );
  3928. }
  3929.  
  3930. /*********************************************************************/
  3931. /*                                                                   */
  3932. /* Function:  RxAsyncFlushOutput                                     */
  3933. /*                                                                   */
  3934. /* Purpose:   Flush device driver output queue                       */
  3935. /*                                                                   */
  3936. /*            Utilises IOCTL 02H DEV_FLUSHOUTPUT.                    */
  3937. /*                                                                   */
  3938. /* Syntax:    call RxAsyncFlushOutput port                           */
  3939. /*                                                                   */
  3940. /* Params:    port   - handle of open port                           */
  3941. /*                                                                   */
  3942. /* Return:                                                           */
  3943. /*   Call successful - NO_ERROR (0)                                  */
  3944. /*   Call failed     - rc from DosDevIOCtl                           */
  3945. /*                                                                   */
  3946. /* Example:                                                          */
  3947. /*                                                                   */
  3948. /*   rc = RxAsyncFlushOutput( PortHandle )                           */
  3949. /*   if rc <> 0                                                      */
  3950. /*      then say 'RxAsyncFlushOutput failed with rc=>'rc'<'          */
  3951. /*      else say 'RxAsyncFlushOutput returned okay.'                 */
  3952. /*                                                                   */
  3953. /*********************************************************************/
  3954.  
  3955. APIRET RxAsyncFlushOutput(
  3956.           CHAR     *name,
  3957.           ULONG    numargs,
  3958.           RXSTRING args[],
  3959.           CHAR     *queuename,
  3960.           RXSTRING *retstr
  3961.        )
  3962. {
  3963.    APIRET   rc;                        /* Function return code       */
  3964.    HFILE    hcomPort;                  /* Communications port handle */
  3965.  
  3966.    if ( numargs != 1 )                 /* Must have one argument     */
  3967.       return( ROUTINE_INVALID );
  3968.  
  3969.    if (   !RXVALIDSTRING(args[0]) )    /* Must specify port          */
  3970.       return( ROUTINE_INVALID );
  3971.  
  3972.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  3973.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  3974.  
  3975.    rc = FlushOutput( hcomPort );
  3976.  
  3977.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  3978.  
  3979.    BUILDRXDOSRET( retstr, rc );        /* Return DosDevIOCtl result  */
  3980.  
  3981.    return( ROUTINE_VALID );
  3982. }
  3983.  
  3984. /*********************************************************************/
  3985. /*                                                                   */
  3986. /* Function:  RxAsyncActive                                          */
  3987. /*                                                                   */
  3988. /* Purpose:   Test if specified signal is active                     */
  3989. /*                                                                   */
  3990. /* Syntax:    if RxAsyncActive( port, signal )                       */
  3991. /*                                                                   */
  3992. /* Params:    port   - handle of open port                           */
  3993. /*            signal - modem signal to test                          */
  3994. /*                     DTR, RTS, CTS, DSR, RI, DCD                   */
  3995. /*                                                                   */
  3996. /* Return:                                                           */
  3997. /*   Signal active    - RC_REXX_TRUE (1)                             */
  3998. /*   Signal inactive  - RC_REXX_FALSE (0)                            */
  3999. /*                                                                   */
  4000. /* Example:                                                          */
  4001. /*                                                                   */
  4002. /*   if RxAsyncActive( PortHandle, "CTS" )                           */
  4003. /*      then say 'RxAsyncActive detected CTS signal.'                */
  4004. /*                                                                   */
  4005. /*********************************************************************/
  4006.  
  4007. APIRET RxAsyncActive(
  4008.           CHAR     *name,
  4009.           ULONG    numargs,
  4010.           RXSTRING args[],
  4011.           CHAR     *queuename,
  4012.           RXSTRING *retstr )
  4013. {
  4014.    APIRET   rc;                        /* Function return code       */
  4015.    HFILE    hcomPort;                  /* Communications port handle */
  4016.    BYTE     bMdmSignal;                /* Modem signal to check      */
  4017.  
  4018.    if ( numargs != 2 )                 /* Must have two arguments    */
  4019.       return( ROUTINE_INVALID );
  4020.  
  4021.    if (   !RXVALIDSTRING(args[0])      /* Must specify port handle   */
  4022.        || !RXVALIDSTRING(args[1]) )    /* and signal type            */
  4023.       return( ROUTINE_INVALID );
  4024.  
  4025.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  4026.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  4027.  
  4028.    if        ( stricmp(args[1].strptr, "CTS") == 0 ) {
  4029.       bMdmSignal = CTS_ON;
  4030.    } else if ( stricmp(args[1].strptr, "DSR") == 0 ) {
  4031.       bMdmSignal = DSR_ON;
  4032.    } else if ( stricmp(args[1].strptr, "RI" ) == 0 ) {
  4033.       bMdmSignal = RI_ON;
  4034.    } else if ( stricmp(args[1].strptr, "DCD") == 0 ) {
  4035.       bMdmSignal = DCD_ON;
  4036.    } else if ( stricmp(args[1].strptr, "DTR") == 0 ) {
  4037.       bMdmSignal = DTR_ON;
  4038.    } else if ( stricmp(args[1].strptr, "RTS") == 0 ) {
  4039.       bMdmSignal = RTS_ON;
  4040.    } else {
  4041.       return( ROUTINE_INVALID );       /* Invalid signal string      */
  4042.    }
  4043.  
  4044.    rc = ActiveSignal( hcomPort, bMdmSignal );
  4045.  
  4046.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  4047.  
  4048.    if ( rc == NO_ERROR ) {
  4049.       BUILDRXDOSRET( retstr, RC_REXX_TRUE );
  4050.    } else {
  4051.       BUILDRXDOSRET( retstr, RC_REXX_FALSE );
  4052.    }
  4053.  
  4054.    return( ROUTINE_VALID );
  4055. }
  4056.  
  4057. /*********************************************************************/
  4058. /*                                                                   */
  4059. /* Function:  RxAsyncRaise                                           */
  4060. /*                                                                   */
  4061. /* Purpose:   Activate specified signal                              */
  4062. /*                                                                   */
  4063. /* Syntax:    if RxAsyncRaise( port, signal )                        */
  4064. /*                                                                   */
  4065. /* Params:    port   - handle of open port                           */
  4066. /*            signal - modem signal to enable (either DTR or RTS)    */
  4067. /*                                                                   */
  4068. /* Return:                                                           */
  4069. /*   Call successful - NO_ERROR (0)                                  */
  4070. /*   Call failed     - rc from DosDevIOCtl                           */
  4071. /*                                                                   */
  4072. /* Example:                                                          */
  4073. /*                                                                   */
  4074. /*   if RxAsyncRaise( PortHandle, "DTR" ) = 0                        */
  4075. /*      then say 'RxAsyncRaise enabled DTR.'                         */
  4076. /*                                                                   */
  4077. /*********************************************************************/
  4078.  
  4079. APIRET RxAsyncRaise(
  4080.           CHAR     *name,
  4081.           ULONG    numargs,
  4082.           RXSTRING args[],
  4083.           CHAR     *queuename,
  4084.           RXSTRING *retstr )
  4085. {
  4086.    APIRET   rc;                        /* Function return code       */
  4087.    HFILE    hcomPort;                  /* Communications port handle */
  4088.    BYTE     bModemOn;                  /* Modem signal to activate   */
  4089.  
  4090.    if ( numargs != 2 )                 /* Must have two arguments    */
  4091.       return( ROUTINE_INVALID );
  4092.  
  4093.    if (   !RXVALIDSTRING(args[0])      /* Must specify port handle   */
  4094.        || !RXVALIDSTRING(args[1]) )    /* and signal type            */
  4095.       return( ROUTINE_INVALID );
  4096.  
  4097.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  4098.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  4099.  
  4100.    if        ( stricmp(args[1].strptr, "DTR") == 0 ) {
  4101.       bModemOn = DTR_ON;
  4102.    } else if ( stricmp(args[1].strptr, "RTS") == 0 ) {
  4103.       bModemOn = RTS_ON;
  4104.    } else {
  4105.       return( ROUTINE_INVALID );       /* Invalid signal string      */
  4106.    }
  4107.  
  4108.    rc = SetMdmOutput( hcomPort, bModemOn, NONE_OFF );
  4109.  
  4110.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  4111.  
  4112.    BUILDRXDOSRET( retstr, rc );
  4113.  
  4114.    return( ROUTINE_VALID );
  4115. }
  4116.  
  4117. /*********************************************************************/
  4118. /*                                                                   */
  4119. /* Function:  RxAsyncLower                                           */
  4120. /*                                                                   */
  4121. /* Purpose:   De-activate specified signal                           */
  4122. /*                                                                   */
  4123. /* Syntax:    if RxAsyncLower( port, signal )                        */
  4124. /*                                                                   */
  4125. /* Params:    port   - handle of open port                           */
  4126. /*            signal - modem signal to drop (either DTR or RTS)      */
  4127. /*                                                                   */
  4128. /* Return:                                                           */
  4129. /*   Call successful - NO_ERROR (0)                                  */
  4130. /*   Call failed     - rc from DosDevIOCtl                           */
  4131. /*                                                                   */
  4132. /* Example:                                                          */
  4133. /*                                                                   */
  4134. /*   if RxAsyncLower( PortHandle, "DTR" ) = 0                        */
  4135. /*      then say 'RxAsyncLower dropped DTR.'                         */
  4136. /*                                                                   */
  4137. /*********************************************************************/
  4138.  
  4139. APIRET RxAsyncLower(
  4140.           CHAR     *name,
  4141.           ULONG    numargs,
  4142.           RXSTRING args[],
  4143.           CHAR     *queuename,
  4144.           RXSTRING *retstr )
  4145. {
  4146.    APIRET   rc;                        /* Function return code       */
  4147.    HFILE    hcomPort;                  /* Communications port handle */
  4148.    BYTE     bModemOff;                 /* Modem signal to activate   */
  4149.  
  4150.    if ( numargs != 2 )                 /* Must have two arguments    */
  4151.       return( ROUTINE_INVALID );
  4152.  
  4153.    if (   !RXVALIDSTRING(args[0])      /* Must specify port handle   */
  4154.        || !RXVALIDSTRING(args[1]) )    /* and signal type            */
  4155.       return( ROUTINE_INVALID );
  4156.  
  4157.    if ( !Str2Num(args[0].strptr, &hcomPort, STR2NUM_DEC2ULONG) )
  4158.       return( ROUTINE_INVALID );       /* Convert handle failed      */
  4159.  
  4160.    if        ( stricmp(args[1].strptr, "DTR") == 0 ) {
  4161.       bModemOff = DTR_OFF;
  4162.    } else if ( stricmp(args[1].strptr, "RTS") == 0 ) {
  4163.       bModemOff = RTS_OFF;
  4164.    } else {
  4165.       return( ROUTINE_INVALID );       /* Invalid signal string      */
  4166.    }
  4167.  
  4168.    rc = SetMdmOutput( hcomPort, NONE_ON, bModemOff );
  4169.  
  4170.    NewRexxValue( RxAsyncRcVarName, VAL2STR_ULONG2DEC, &rc );
  4171.  
  4172.    BUILDRXDOSRET( retstr, rc );
  4173.  
  4174.    return( ROUTINE_VALID );
  4175. }
  4176.  
  4177. /*********************************************************************/
  4178. /* END MODULE                                                        */
  4179. /*********************************************************************/
  4180.