═══ 1. Name Changed! ═══ Starting with this version of the RXU function package, all the pieces of the package will have the name RXU (no longer any references to YDBAUTIL). I'm doing this for two reasons: 1) The package is known and distributed in many places as RXU 2) The name YDBAUTIL isn't as easy to build on as RXU I don't think this will have any effect on anyone using the package, other than that you must now have RXU.DLL in your LIBPATH to use the functions, and the function registration function is now called "RxuInit()" (rather than the old "RxYdbaUtilInit()"). My apologies for any inconvenience this name change may cause (forseen and unforseen). ═══ 2. About RXU ═══ RXU is a package of diverse OS/2 Rexx External Functions. Almost all the functions in this package are in use in many of my own programs and are fairly well de-bugged. Please let me know of any problems you encounter in using the functions, or of any suggestions for enhancements to existing functions, or ideas for new ones. I've written the functions in RXU both to more fully enable Rexx as a programming language for the OS/2 environment, and as a personal technical challenge. Since I'm not making any money off them, I do from time to time put support/enhancement on the back burner due to other distractions. I'm waiting to see what the Rexx landscape will look like in the Win95 world before I explore porting RXU (at least, the portable parts) from OS/2 to Win95. With the functions in the RXU function package, you can make use of some of OS/2's most powerful facilities, such as multi-threading, processes, sessions, semaphores, memory access, OS/2 queues, etc. Some of these features are not only useful in pure Rexx applications, but they allow you to write Rexx programs which can talk to compiled programs on their level (i.e. reference memory by address, use semaphores, etc.). Another benefit is the ability to quickly prototype real OS/2 programs using real OS/2 APIs so that you can cheaply 'prove' techniques before committing them to 'C' code. The capabilities provided to Rexx programs by this package, in conjunction with those provided by other Rexx function packages (database access, APPC, etc.) and the base language itself allow you to prototype or build Rexx applications with much of the functional sophistication (and complexity, unfortunately) of "real" OS/2 applications. In addition to the many OS/2 API "passthrough" functions, there are many Rexx-specific enhancements and additions. Author: Dave Boll (CompuServe = 74170,2016) Internet: 74170.2016@compuserve.com Release Date: 1 November, 1995 Version: 1.9 ═══ 3. Release Notes ═══ Release information follows: Release 1.9 features: (The PassByName functions were motivated by seeing many posts in various places inquiring whether variables could be shared twixt separate command files, and by David Durgee, who specifically inquired about this capability and provided feedback during development of these functions (thanks David). In fairness to him, he suggested a far more rich and useful function scheme than I could figure out how to implement (sorry for not doing justice to the concept). But I do think the way variable sharing is implemented here will be at least somewhat useful. ) RxPassByName - Allows rexx program to call another rexx program (external .CMD file), passing rexx variables (including stems) by name (reference or value). RxReturnByName - Allows a called rexx program to return rexx variables (including stems) by name (reference or value) back to a calling rexx program. RxPBNBufSize - Set/Query fetch buffer size (used by RxPassByName) RxPhysicalDisk - Query information about partitionable disks RxTmrQueryFreq - Query frequency of IRQ0 high-resolution timer RxTmrQueryTime - Query snapshot of IRQ0 high-resolution timer value Release 1.8 features: RxSetRelMaxFH - Set max file handles for process (relative to current value) RxSetMaxFH - Set maximum file handles for process RxDevConfig - Obtain device configuration information RxDevIOCtl - Do DosDevIOCtl calls (to talk to character devices directly) RxWaitChild - Wait for child process(es) to end RxDosRead - Alias for "RxRead()" RxDosWrite - Alias for "RxWrite()" RxSetExceptionExit - Specify the address of exception exit function Release 1.7 features: RxRsoe2q - Redirect StdOut/StdErr to a rexx queue (by queue name) RxGlobalVar - Put,Get,Delete system-wide global variables Release 1.6 features: RxRegisterFunctionExe - Use "RexxRegisterFunctionExe()" RxRegisterExitDll - Use "RexxRegisterExitDll()" RxRegisterExitExe - Use "RexxRegisterExitExe()" RxQueryExit - Use "RexxQueryExit()" RxDeregisterExit - Use "RexxDeregisterExit()" Release 1.5 features: RxOpen - open a file with full DosOpen() capabilities RxGetInfoBlocks - get DosGetInfoBlocks() info RxStem2Struct - map values of a stem into a structure (finally implemented) RxQueryAppType - query application type of an executable file RxVioPopUp - Start a VioPopUp display screen RxVioEndPopUp - Close a VioPopUp display screen RxVioWrtCharStrAtt - Write characters to a VioPopUp display screen RxKbCharIn - Get a character from a VioPopUp display screen RxDupHandle - Do a "DosDupHandle()" RxSetFHState - Set file handle state RxQueryFHState - Query file handle state Also, the "RxPstat()" function was reincarnated as "RxQProcStatus()" and is documented herein (it now works properly). In this version (v1.5), "RxQProcStatus()" stores Library, Shared-Memory, and 16-Bit Semaphore information differently. See that section for more information. This function package is 32-bit code and will only work on OS/2 2.x ═══ 4. How to Use It ═══ How to register the functions: In order to use the functions, you have to register them with Rexx like this: call rxfuncadd 'rxuinit','rxu','rxuinit' call rxuinit The .DLL "rxu.dll" must be in your libpath. The program "RXSRS.EXE" must be in your path in order to use the functions "RxStartRexxSession" and "RxDetachRexxPgm". ═══ 5. Available External Functions ═══ The available functions are: Function Package utility functions ---------------------------------- RxuInit - Register all RXU Rexx functions RxuTerm - De-Register all RXU Rexx functions RxuQuery - Query function package version and available external function entry point names UPM/Net Related ----------- RxUpm - Rexx interface to UPM RxNet - Rexx interface to certain NET calls (also some UPM-related calls) System-Info related ------------------- RxTmrQueryFreq - Query frequency of IRQ0 high-resolution timer RxTmrQueryTime - Query snapshot of IRQ0 high-resolution timer value RxProcId - Get process' own PID and TID information RxGetInfoBlocks - Get information about current process/thread RxQueryAppType - Get information about an executable file RxQuerySysInfo - Invoke DosQuerySysInfo RxQProcStatus - Obtain Process Status Information (like PSTAT) RxSetError - Set DosError settings (enable/disable HardError and Exception popups) RxReplaceModule - Replace an active .DLL or .EXE file RxExitList - Use DosExitList RxDevConfig - Obtain device configuration information RxPhysicalDisk - Query information about partitionable disks RxDevIOCtl - Do DosDevIOCtl calls (to talk to character devices directly) Rexx programming and debugging functions ---------------------------------------- RxVlist - List, manipulate Rexx variable pool RxGlobalVar - Put,Get,Delete system-wide global variables RxScount - Count strings (needle) in another string (haystack) RxPmPrintf - Write lines to a PMPrintf Monitor RxCallInStore - Execute a string as a program RxPassByName - Allows rexx program to call another rexx program (external .CMD file), passing rexx variables (including stems) by name (reference or value). RxReturnByName - Allows a called rexx program to return rexx variables (including stems) by name (reference or value) back to a calling rexx program. RxPBNBufSize - Set/Query fetch buffer size (used by RxPassByName) RxTokenize - Tokenize ("Compile") a program string RxPullQueue - Pull items from any Rexx data queue RxAddQueue - Add items to any Rexx data queue RxQueued - Query number of items on any Rexx data queue RxQExists - Query existence of a Rexx Queue RxSearchPath - Find a file in a path RxRegisterFunctionExe - Use "RexxRegisterFunctionExe()" RxRegisterExitDll - Use "RexxRegisterExitDll()" RxRegisterExitExe - Use "RexxRegisterExitExe()" RxQueryExit - Use "RexxQueryExit()" RxDeregisterExit - Use "RexxDeregisterExit()" I/O related ----------- RxRsoe2f - Redirect StdOut/StdErr to a file (by file name) RxRsoe2q - Redirect StdOut/StdErr to a rexx queue (by queue name) RxSoSe2H - Redirect StdOut/StdErr to a file (by file handle) RxSi2H - Redirect StdIn from a file (by file handle) RxRSi2F - Redirect StdIn from a file (by file name) RxOpen - Open a file (with full DosOpen capabilities) RxRead - Read data from a file handle RxDosRead - Alias for "RxRead()" RxWrite - Write data to a file handle RxDosWrite - Alias for "RxWrite()" RxCloseH - Close a file handle RxExecI - Read data into a Rexx queue or stem from a file RxExecO - Write data from a Rexx queue or stem to a file RxVioPopUp - Start a VioPopUp display screen RxVioEndPopUp - Close a VioPopUp display screen RxVioWrtCharStrAtt - Write characters to a VioPopUp display screen RxKbCharIn - Get a character from a VioPopUp display screen RxDupHandle - Do a "DosDupHandle()" RxSetFHState - Set file handle state RxQueryFHState - Query file handle state RxSetMaxFH - Set maximum file handles for process RxSetRelMaxFH - Set max file handles for process (relative to current value) OS/2 Pipes ---------- RxCreateNPipe - Create a named pipe RxConnectNPipe - Connect to a named pipe RxDisConnectNPipe - Disconnect from a named pipe RxCreatePipe - Create an un-named pipe RxDestroyPipe - Destroy a pipe OS/2 Queues ---------- RxCreateQueue - DosCreateQueue RxOpenQueue - DosOpenQueue RxPeekQueue - DosPeekQueue RxReadQueue - DosReadQueue RxWriteQueue - DosWriteQueue RxPurgeQueue - DosPurgeQueue RxQueryQueue - DosQueryQueue RxCloseQueue - DosCloseQueue RxReadQueueStr - Returns data from de-referenced queue pointer NetBios information ------------------- RxNbSessionStatus - Obtain NETBIOS session status information Tasking, threads, etc. ---------------------- RxSetPriority - Set the priority of processes or threads Process - Related RxKillProcess - Kill an OS/2 process by process-id RxExecPgm - Execute a program using DosExecPgm RxWaitChild - Wait for a child process to end RxStartSession - Start a program in another session (DosStartSession) RxStartRexxSession - Start a Rexx program in another session RxDetachRexxPgm - Detach a Rexx program Thread - Related RxCreateRexxThread - Execute a Rexx program on another thread RxSetExceptionExit - Specify the address of a "_System" linkage function which is called when an OS/2 exception occurs on a thread started with "RxCreateRexxThread". RxCreateThread - Call a procedure address on another thread RxKillThread - Kill a thread by thread-id RxResumeThread - Resume thread execution by thread-id RxSuspendThread - Suspend thread execution by thread-id RxCallEntryPoint - Call a (non-Rexx) routine by entry point address OS/2 Memory managment --------------------- RxStructMap - Generate a structure map for RxStruct2Stem() RxStruct2Stem - Map structure elements into a stem RxStem2Struct - Map a stem into structure elements RxStorage - Query/Alter storage by address RxAdd2Ptr - Pointer Arithmetic (Add/Subtract) RxThunkAddr - Thunk an address Flat->Segmented, Segmented->Flat RxAllocMem - Allocate Memory RxFreeMem - Free Memory RxAllocSharedMem - Allocated Shared memory (named or un-named) RxGetSharedMem - Get (gettable) shared memory RxGiveSharedMem - Give (giveable) shared memory RxGetNamedSharedMem - Get named shared memory RxSetMem - Set memory attributes RxQueryMem - Query memory attributes RxSubAllocMem - Suballocate memory RxSubFreeMem - Free suballocated memory RxSubSetMem - Set memory for suballocation RxSubUnsetMem - Unset previously "SubSet" memory OS/2 Semaphores --------------- Event Semaphore RxCreateEventSem - Create an event semaphore RxCloseEventSem - Close an event semaphore RxOpenEventSem - Open an event semaphore RxPostEventSem - Post an event semaphore RxQueryEventSem - Query an event semaphore RxResetEventSem - Reset an event semaphore RxWaitEventSem - Wait on an event semaphore Mutex Semaphore RxCreateMutexSem - Create a Mutex semaphore RxOpenMutexSem - Invoke DosOpenMutexSem RxCloseMutexSem - Invoke DosCloseMutexSem RxQueryMutexSem - Invoke DosQueryMutexSem RxReleaseMutexSem - Invoke DosReleaseMutexSem RxRequestMutexSem - Invoke DosRequestMutexSem MuxWait Semaphore RxCreateMuxWaitSem - Invoke DosCreateMuxWaitSem RxCloseMuxWaitSem - Invoke DosCloseMuxWaitSem RxOpenMuxWaitSem - Invoke DosOpenMuxWaitSem RxWaitMuxWaitSem - Invoke DosWaitMuxWaitSem RxAddMuxWaitSem - Invoke DosAddMuxWaitSem RxDeleteMuxWaitSem - Invoke DosDeleteMuxWaitSem RxQueryMuxWaitSem - Invoke DosQueryMuxWaitSem DLL Handling ------------ RxLoadModule - Load a DLL RxFreeModule - Free a DLL RxQueryModuleName - Query the fully qualified name of a DLL (by handle) RxQueryModuleHandle - Query the module handle of a DLL (by name) RxQueryProcType - Query the addressing mode of an entry point in a DLL RxQueryProcAddr - Query the procedure address of an entry point in a DLL Rexx Macro Space Handling ------------------------- RxAddMacro - Add a particular Macro Space function RxDropMacro - Drop a particular Macro Space function RxClearMacroSpace - Clear the Rexx Macro Space RxSaveMacroSpace - Save a particular Macro Space function to a file RxLoadMacroSpace - Load a particular Macro Space function from a file RxQueryMacro - Query the position of a particular Macro Space function RxReorderMacro - Reorder a function's position in a Macro Space PM / Wp related functions ------------------------- RxWinQueryObject - Query object handle of a WP object RxWinDestroyObject - Destroy a WP object ═══ 6. Miscellaneous Programming Notes ═══ A few things to keep in mind when using the functions in this package. ═══ 6.1. Documentation of Parameter Values ═══ Many functions in this package are meant to provide a "pass-through" to the underlying OS/2 API set. For this reason, in most cases, I did not "simplify" the parameter lists (one man's simplification is often another man's complication anyway). I also did not document the meaning of most of the API parameter values (because of duplication effort, copyright, playing "keep-up", etc.). ═══ 6.2. Binary Parameter Values ═══ Many of the OS/2 API pass-through functions that deal with file-handles, memory addresses, semaphore handles, etc., treat these arguments/returned-values as binary values (i.e. 16-/32-bit values) and do not convert these values to hexadecimal strings. The reason for this is that these values are typically only meant to be used as tokens that are passed back into some relevant function (e.g. a semaphore handle obtained by a create-semaphore API is passed back into some other semaphore function) and not scrutinized by the rexx code itself. In some cases, some functions return an integer value (as a normal rexx integer number), but this number would subsequently be used by some other function as a binary value (e.g. rxcreaterexxthread returns thread-id as a normal rexx integer number, but rxkillthread() takes a binary value for the thread-id argument). The binary values required in these cases are typically 32-bit integers, and also must be in little-endian form (i.e. byte-reversed). A simple way to convert the integer value to the proper binary form is as such: binary_value = reverse(d2c(integer_value,4)) ═══ 6.3. How Functions Return Values ═══ The functions in this package return essentially three categories of values: 1) An unknown number of values (e.g. rxvlist()) 2) A known or fixed number of values that can be strung together as blank-delimited tokens 3) A known or fixed number of values that may contain binary data (i.e. not what we'd consider character strings) For case #1, the values are usually returned either under a stem, or on a queue. For case #2, the values are often (but not always) returned as blank-delimited tokens following the return code of the underlying OS/2 API (thus, the values are most easily obtained by using the PARSE instruction, for instance). For case #3, the function usually requires you to supply a Rexx variable name (or names) in which the binary values will be returned. ═══ 7. UPM Related Functions ═══ Functions which allow certain UPM activities to be performed. ═══ 7.1. RxUpm - Rexx/UPM Interface ═══ This function allows you to make most UPM calls from a Rexx program. Syntax: func = 'Logon' For Process level logon, only usable by that process */ 'Logonp' = 'Logonu' For "User" logon, usable by all processes = 'Logoff' For Process level logoff, undoes a "LOGONP" 'Logoffp' = 'Logoffu' For "User" logoff, undoes a "LOGONU" = 'LogonList' Gets list of current active logons uid = 'Userid' Userid to be logged on/off = 'stemname' Name of Rexx stem variable under which results of "LogonList" are mapped as such: stem.0 - Number of logons reported on stem.n.1 - Userid stem.n.2 - Node/Domain name stem.n.3 - Session-Id stem.n.4 - Logon type (Local/Node/Domain) pw = 'Password' Password to be used with 'Userid' (for logon) type = 'Local' Logs you on/off UPM locally (default is LOCAL if no value supplied) = 'Node' Logs you on/off a node = 'Domain' Logs you on/off a LAN domain = 'dataBase' Logs you on/off the correct node for a database name = 'Name' The name of the node/domain/database, depending on what "TYPE" was chosen check = 'Admin' Checks to see if userid has Admin authority = 'User' Checks to see if userid has User authority = 'Config' Checks to see if logon was done from Config.Sys upmrc = RxUpm(func, uid, pw, type, name, check) ═══ 7.2. RxNet - Rexx/NET Interface ═══ This function allows you to make certain NetApi calls from Rexx. This enables you to do such things as changing passwords, adding and deleting userids, validating a userid/pw, listing users and logons. Syntax: /* General syntax */ netrc = RxNet(func, server, arg3, arg4, arg5, arg6) where: func = 'UserPwSet' /* Change a user's password */ = 'UserAdd' /* Add a user to UPM */ = 'UserDel' /* Delete a user from UPM */ = 'UserVal' /* Validate a userid/password without logging on */ = 'UserEnum' /* List users in UPM */ = 'UserGetInfo' /* Get user information */ = 'LogonEnum' /* List active logons */ = 'FileEnum' /* File usage on the LAN */ = 'UseAdd' /* Do a "Net Use dev \\srv\alias" */ = 'UseDel' /* Do a "Net Use dev /d" */ = 'UseEnum' /* Do a "Net Use" */ server = name of server, or '00'x for local netrc = return code from NetApi call. If netrc < 2100, then it's probably a base OS/2 return code, otherwise, it's defined in NETCONS.H /* Specific calls */ netrc = RxNet('UserPwSet', server, userid, oldpw, newpw) netrc = RxNet('UserAdd', server, userid, password, type, comment) type = 'User', 'Guest', or 'Admin' netrc = RxNet('UserDel', server, userid) netrc = RxNet('UserVal', server, userid, password) netrc = RxNet('UserEnum',server, rexxstem [,uidfilter][,infotype]) uidfilter = userid prefix filter (i.e. only return info on those userids whose leading characters match this prefix). infotype = "FULL" or "USERNAME" which indicates what type of information to return rexxstem = Rexx stem name, under which results are mapped as: stem.0 = if "uidfilter" not supplied: - number of entries returned in stem if "uidfilter" was supplied, two blank delimited integers: - number of entries returned in stem - total number of entries stem.n.1 = userid If infotype = "FULL", the following also: stem.n.2 = privilege level (Guest, User, Admin, ?) stem.n.3 = password age (in seconds) stem.n.4 = comment stem.n.5 = script path stem.n.6 = full name stem.n.7 = user comment stem.n.8 = parms stem.n.9 = logon server netrc = RxNet('UserGetInfo',server, rexxstem ,username) username = username to get information for rexxstem = Rexx stem name, under which results are mapped as: stem.1 = userid stem.2 = privilege level (Guest, User, Admin, ?) stem.3 = password age (in seconds) stem.4 = comment stem.5 = script path stem.6 = full name stem.7 = user comment stem.8 = parms stem.9 = logon server netrc = RxNet('LogonEnum',server, rexxstem) rexxstem = Rexx stem name, under which results are mapped as: stem.0 = number of users stem.n.1 = userid netrc = RxNet('FileEnum',server, basepath, username, rexxstem) basepath = file path/name qualifier username = username qualifier rexxstem = Rexx stem name, under which results are mapped as: stem.0 = number of entries stem.n.1 = file-id stem.n.2 = permissions stem.n.3 = numlocks stem.n.4 = pathname stem.n.5 = username netrc = RxNet('UseAdd', server, device, name, password) device = Local name for resource, such as a drive letter name = server\alias (must be like "\\servname\alias") password = optional password to use resource netrc = RxNet('UseDel', server, device, forcemode) device = Local name for resource, such as a drive letter forcemode = 'F'orce 'N'o force 'M'ax force netrc = RxNet('UseEnum',server, rexxstem) rexxstem = Rexx stem name, under which results are mapped as: stem.0 = number of entries stem.n.1 = device name stem.n.2 = name stem.n.3 = status, values are: Ok Paused Disconnected/SessionLost NetError Connecting Reconnecting ? stem.n.4 = asg_type, values are: WildCard DiskDevice SpooledPrinter SerialDevice IPC (InterProcessCommunication) ? stem.n.5 = refcount stem.n.5 = usecount ═══ 8. Rexx Programming/Debugging ═══ Tools for developing Rexx programs. ═══ 8.1. RxSCount - Count instances of a string ═══ This function returns a count of the number of instances of a string "needle" in a string "haystack", optionally ignoring case. Syntax: numitem = rxscount(needle,haystack[,case]) where: needle = string you want to count instances of haystack = string in which you want to count instances of "needle" case = any character to indicate that case (upper/lower) is to be ignored numitem = number of times "needle" is found in "haystack" ═══ 8.2. RxPmPrintf - Write lines to a PMPrintf Monitor ═══ This function writes data lines to a PMPrintf "Monitor" program. Syntax: bytes = RxPmPrintf(qname, [data1 [,data2 [,data3 [...]]]] ) where: qname = name of PMPrintf queue If blank, uses default PMPrintf Queue (PRINTF32). data1 = data to be written to PMPrintf ... Each argument is written as a separate line datan bytes = number of bytes written in this operation Notes: The PMPrintf tool can be downloaded from the OS/2 Bulletin Board. This Rexx function does work with PMPrintf v2.5, but may not work with earlier versions. You can start the PMPrintf program with a command line argument specifying an alternate queue name for it to use. This queue name can be supplied as the first argument of RxPmPrintf to direct the data to a specific running instance of PMPrintf. If only the queue name is supplied (i.e. args 2-n are not supplied), nothing at all is written to queue. If an argument has zero length, no data will be written to the queue for that argument (i.e. you must supply at least one byte to be written to queue). ═══ 8.3. RxPassByName - Pass variables (by name) to external rexx (.CMD file) program ═══ This function allows one Rexx program to call another Rexx program (i.e. another .CMD file), passing it rexx variables by name. In addition, these variables can be passed "by reference" or "by value." The normal method of invoking a Rexx external function is by the "call" instruction or by function reference. In these cases, arguments can be passed as expressions and are accessed in the called routine by the "parse arg" instruction or the "arg()" built-in function. To pass a variable name "by value" means that the variable's name and value will be placed in the called program's variable pool before that called program begins executing. To pass a variable "by reference" means the same as "by value," but additionally, any changes to the variable in the called program will be reflected in the variable pool of the calling program upon return of control (to the caller). Syntax: result = RxPassByName(yourfunc, varlist [,arg1,arg2,...,arg18]) where: yourfunc = name of rexx program file to be called (as function or subroutine) or a '$' immediately preceding a rexx program source string or a '&' immediately preceding a tokenized program string varlist = list of blank delimited variable names to be passed to "yourfunc" Individual items in the list are passed "by value" unless the item is preceded by an ampersand (&), in which case it is passed by reference. For instance, in the following example, call rxpassbyname 'yourfunc','abc &frank st1. &st2.', date() the variable "abc", and the stem "st1." would be passed "by value" to "yourfunc", whereas the variable "frank" and the stem "st.2" would be passed "by reference" to "yourfunc". That is, "abc" and all values of the stem "st1." would be passed to "yourfunc" (but whatever "yourfunc" does to these variables has no effect on their values in the caller), and "frank" and all values of the stem "st2." would be passed to "yourfunc" (and whatever "yourfunc" does to these variables WILL have an effect on their values in the caller). Note that the called Rexx program ("yourfunc") will receive "arg1" as its first argument, "arg2" as its second argument, and so on. If you want the called routine to know what variables were passed to it, you must supply this variable list as a separate argument. arg1 = subsequent argument(s) to "yourfunc", passed on as-is (i.e. in normal Rexx ... fashion. Note that given the Rexx restriction of 20 arguments, and the argn fact that two arguments are "used up" by the called routine's name and the variable name list, only 18 remain for normal argument passing. result = whatever value is returned by "yourfunc" (independent of what "flows" back from "yourfunc" as a result of "by reference" variables). Notes: When variables are passed "by reference," whatever is done to a variable (or stem) in the called routine will show up back in the calling routine, including dropping the variable ("drop" instruction) with all that this implies for stems. Thus, passing a variable "by reference" to an external Rexx routine should have the same effect that the "expose" option of the "procedure" instruction has on internal Rexx routines. The difference is that "expose" is specified by the called routine, and "by reference" is specified by the calling routine. RxPassByName() is multi-thread safe. It may also be called by nested Rexx programs (i.e. "pgma.cmd" calls "pgmb.cmd" which calls "pgmc.cmd", etc.), as would be expected. ═══ 8.4. RxReturnByName - Return variables (by name) to external calling Rexx program ═══ This function allows a RxPassByName-called Rexx program to return rexx variables (by name) to the calling rexx program (i.e. another .CMD file). These variables are always passed "by value." Values are obtained for return at the time the rexx routine actually terminates (NOT when this function is called). So, this function has the effect of specifying what variables are to be returned (actually, simple variables are specified at this time (i.e. non-stems), but only the stem of compound variables are specified -- the actual tails of a stem are resolved at return time). Syntax: successful = RxReturnByName(varlist) where: varlist = list of blank delimited variable names to be returned to caller Individual variables are passed "by value". successful = boolean (1 or 0) indicating whether items to be returned were noted Notes: When using this function, it is up to you to ensure that the rexx routine from which you call this function was itself invoked via the "RxPassByName()" function. If this is not the case, but some prior rexx routine in the call chain (on current thread) was invoked via "RxPassByName()", that routine's caller will pick up the variable values being passed back, and furthermore that "RxPassByName()"-invoked rexx program's values will be returned, not those values from the current rexx program's variable pool. The upshot is that you must be careful when using this function that you call it only from within a rexx program that was itself invoked (directly) via "RxPassByName()". RxReturnByName() is multi-thread safe. ═══ 8.5. RxPBNBufSize - Set/Query fetch buffer size (used by RxPassByName) ═══ This function allows you to set the working buffer size used by RxPassByName to fetch subsets of the variable pool when passing stem variables between Rexx programs. You do not have to use this function in order to use RxPassByName (working buffer defaults to 32k), but you could use this function if, for instance, many stem values are more than the default size (32k). In this case, you would specify a larger work buffer size to prevent RxPassByName from having to access the variable pool twice for each stem value. The size you specify would ideally be as large as the longest stem value, but doesn't have to be (i.e. RxPassByName will always work, just not as efficiently as it could). As a rule, you should never need to use this function. It is just provided as a means to tune RxPassByName in cases where tuning would matter (memory constrained environment where you can't afford the default of 32k and stem value lengths are usually much less than 32k, stem values longer than 32k, etc.). Also, note that the work buffer size applies to all threads in a process. That is, Rexx programs running on different threads in the same process will all use the current value, so that any changes made to the buffer size will affect all threads. Syntax: oldval = RxPBNBufSize([newsize]) where: newsize = optional, new work buffer size oldval = previous work buffer size ═══ 8.6. RxCallInStore - Execute a string as a program ═══ This function allows the Rexx program developer to execute a string as though it were a Rexx program. This allows you to build the equivalent of a Rexx program's text in a variable, and then execute it from the string. Actually, the Rexx program text can come from anywhere -- a file, over a communications link, from a database. For repeated execution of a program, use "RxTokenize" to "compile" the program, then call "RxCallInStore" with "&" to re-use the tokenized program. Syntax: result = RxCallInStore strtext, arg1, arg2, ..., arg19 where: strtext = text of a Rexx program, complete with crlf and eof markers or a '$' immediately preceding a source program string or a '&' immediately preceding a tokenized program string arg1 = arguments to the called program ... arg19 Note: Example of executing a program string: crlf = '0d0a'x str = '/* Rexx */'crlf str = str 'Do i=1 To Arg()'crlf str = str ' Say "Arg#"i "= {"arg(i)"}"'crlf str = str 'End'crlf str = str||'1a'x /* EOF marker */ call rxcallinstore str, date(), time() ( or ) call rxcallinstore '$'str, date(), time() ( or ) tstr = rxtokenize(str) call rxcallinstore '&'tstr, date(), time() ═══ 8.7. RxTokenize - Tokenize a program source string ═══ This function in effect "compiles" a program source string for re-use with subsequent "RxCallInstore" or "RxCreateRexxThread" calls. This provides better performance when a program string is repeatedly called. Syntax: tokenstr = RxTokenize(progstr) rxrc = RxTokenize(progstr,rexxvar) where: progstr = actual Rexx program source string rexxvar = name of rexx variable in which tokenized version is returned tokenstr = tokenized ("compiled") result of "progstr" rxrc = two blank delimited integers: 1) return code from invoking rexx interpreter 2) rexx return code Note: This function, in conjunction with the "RxCallInstore" and/or "RxCreateRexxThread" functions, can be used to achieve the same effect as the Rexx Macrospace, except that this technique is local to the program using it (whereas the Macrospace is system global). ═══ 8.8. RxVlist - Display/Process Rexx Variables ═══ This function allows the Rexx program developer to view portions of the Rexx variable pool. It also allows you to effectively "pass" variable pools (or subsets thereof) between execs across Rexx queues. Syntax: numvar = RxVlist( [vnamepat] [,func] [,qname] ) where: func = 'V' /* Puts variable name/value pairs on a queue */ = 'N' /* Puts variable names on a queue */ = 'G' /* Gets variable name/value pairs off a queue */ /* and incorporates them into the current variable pool */ = 'D' /* display variables and their values (default) */ vnamepat = variable name prefix (every variable whose name begins with this value is processed according to the specified function) (default is all variables) qname = name of a Rexx queue to use (default is the current queue) ═══ 8.9. RxPullQueue - Pull items off any Rexx queue ═══ This function does what the Rexx "Pull" instruction and "LineIn" functions do, except this function allows you to specify the queue name as part of the call, regardless of what the current queue may be. Syntax: data = RxPullQueue( [qname] [,type] [,rexxvar] ) where: qname = name of Rexx queue to pull from (default is current queue) type = 'Wait' or 'Nowait' (default is 'Wait') rexxvar = name of a Rexx variable into which is put the queue-insertion- timestamp for the retreived element data = data obtained from queue ═══ 8.10. RxGlobalVar - Put,Get,Delete system-wide global variables ═══ This function manages a global variable pool (among all processes). It implements the pool using named Rexx queues (lazy but effective). Each global variable is just a queue whose name is derived from the variable's name and which contains just one element (the variable's value). The queue name is just the variable name bracketed by "RXUGV". For example, the variable name "FRANK" would be implemented with a queue named "RXUGVFRANKRXUGV". This obviously presents the possibility of stepping on queues created for other purposes (that happen to have the same name), but this isn't likely. Syntax: value = RxGlobalVar(action,varname[,newvalue]) where: action = 'Put' 'Get' 'Delete' varname = name of variable to put, get, delete newvalue = value for "varname" (put only) value = value of "varname" (get only) ═══ 8.11. RxPullQueue - Pull items off any Rexx queue ═══ This function does what the Rexx "Pull" instruction and "LineIn" functions do, except this function allows you to specify the queue name as part of the call, regardless of what the current queue may be. Syntax: data = RxPullQueue( [qname] [,type] [,rexxvar] ) where: qname = name of Rexx queue to pull from (default is current queue) type = 'Wait' or 'Nowait' (default is 'Wait') rexxvar = name of a Rexx variable into which is put the queue-insertion- timestamp for the retreived element data = data obtained from queue ═══ 8.12. RxAddQueue - Add items to any Rexx queue ═══ This function does what the Rexx "Queue" and "Push" instructions, and the "LineOut" function do, except this function allows you to specify the queue name as part of the call, regardless of what the current queue may be. Syntax: qrc = RxAddQueue( data [,qname] [,type] ) where: data = data to be placed on queue qname = name of Rexx queue to add to (default is current queue) type = 'Queue' or 'Push' (default is 'Queue') ═══ 8.13. RxQueued - Query number of items on any Rexx queue ═══ This function does what the Rexx "Queued" function does, except this function allows you to specify the queue name as part of the call, regardless of what the current queue may be. Syntax: numq = RxQueued( [qname] ) where: qname = name of Rexx queue to report on (default is current queue) ═══ 8.14. RxQExists - Query existence of a Rexx Queue ═══ This function returns "1" or "0", indicating the existence of the Rexx Queue whose name you supply as an argument. Syntax: bool = RxQExists( [qname] ) where: qname = name of Rexx queue to check for existence of bool = truth value of queue's existence ═══ 8.15. RxSearchPath - Find a file in a path ═══ This function does what REXXUTIL's "SysSearchPath" does, but allows full use of DosSearchPath capabilities. Syntax: info = RxSearchPath(fname,path[,flags]) where: fname = name of file to search for (can contain pattern characters) path = either an actual path string, or the name of an environment variable containing a path string flags = any combination of: V - indicates that "path" is an environment variable name, rather than an actual path string I - ignore network errors when searching through network drives C - search current directory first The default is "Not V, Not I, Not C". info = two blank delimited tokens: 1) return code from DosSearchPath 2) If (1) is zero, the fully qualified name of the file found ═══ 8.16. RxRegisterFunctionExe - Use "RexxRegisterFunctionExe()" ═══ This function allows you to register an external function for the current .EXE only. Syntax: rxrc = RxRegisterFunctionExe(funcname,funcaddr) where: funcname = name of external function funcaddr = address of function implementation (e.g. - could be obtained by RxQueryProcAddr) rxrc = return code from RexxRegisterFunctionExe() ═══ 8.17. RxRegisterExitDll - Use "RexxRegisterExitDll()" ═══ This function allows you to register a Rexx exit handler that resides in a .DLL Syntax: rxrc = RxRegisterExitDll(hname,dllname,procname,udata,dropflag) where: hname = handler name dllname = name of .DLL where handler code resides procname = name of procedure in .DLL that implements handler udata = user data (1-8 bytes) dropflag = D - can be dropped N - cannot be dropped rxrc = return code from RexxRegisterExitDll() ═══ 8.18. RxRegisterExitExe - Use "RexxRegisterExitExe()" ═══ This function allows you to register a Rexx exit handler that resides in a .EXE Syntax: rxrc = RxRegisterExitExe(hname,funcaddr,udata) where: hname = handler name funcaddr = address of handler function implementation (e.g. - could be obtained by RxQueryProcAddr) udata = user data (1-8 bytes) rxrc = return code from RexxRegisterExitExe() ═══ 8.19. RxQueryExit - Use "RexxQueryExit()" ═══ This function allows you to query exit information Syntax: rxrc = RxQueryExit(hname,modname) where: hname = name of handler modname = handler module name rxrc = return code from RexxQueryExit() ═══ 8.20. RxDeregisterExit - Use "RexxDeregisterExit()" ═══ This function allows you to de-register a Rexx exit Syntax: rxrc = RxDeregisterExit(hname,modname) where: hname = name of handler modname = handler module name rxrc = return code from RexxDeregisterExit() ═══ 9. Memory Management/Access ═══ These functions allow Rexx programs to create, access, and manage OS/2 memory objects by address. This includes objects such as shared memory (named and un-named). Note that for named shared memory, the memory name must begin with "\sharemem\". Thus, a valid shared memory name would be "\sharemem\frank" whereas "\frank" would not be valid. ═══ 9.1. RxStructMap - Generate a structure map for RxStruct2Stem() ═══ This function builds a "structure map" which can be used by the function RxStruct2Stem() to map the elements of a structure into a Rexx stem. The elements of the structure must be described by the Rexx program. This can be used to access the elements of a structure whose address is passed to the Rexx program by a compiled program. Syntax: map = RxStructMap(stemname) where stemname = name of Rexx stem under which structure is described as such: stem.0 = Number of elements in structure (1-n) stem.P = Packing mode of structure (default = 1) stem.n.T = Type of element "n" in structure. Valid values are: l = signed long integer (4 bytes) L = unsigned long integer (4 bytes) s = signed short integer (2 bytes) S = unsigned short integer (2 bytes) d = double (8 bytes) D = double (8 bytes) c = character array (stem.n.L bytes) C = character array (stem.n.L bytes) stem.n.L = Length of character array (if type = 'C' or 'c') map = binary structure map used by RxStruct2Stem() ═══ 9.2. RxStruct2Stem - Map structure elements into a stem ═══ This function allows a Rexx program to map the elements of a structure into a Rexx stem. The structure is referred to by its address. The structure is described by the map built with RxStructMap(). This can be used to access the elements of a structure whose address is passed to the Rexx program by a compiled program. Syntax: bytes = RxStruct2Stem(stemname, pointer, map) where stemname = name of Rexx stem under which structure elements' values are returned, as such: stem.0 = Number of elements in structure stem.n = Actual value of element "n" in structure pointer = 32-bit pointer (address) to base of structure map = structure map generated by RxStructMap() bytes = total number of bytes in structure ═══ 9.3. RxStem2Struct - Map a stem into structure elements ═══ This function allows a Rexx program to map a stem variable into the elements of a structure. The structure is referred to by its address. Syntax: bytes = RxStem2Struct(stemname, pointer, map) where stemname = name of Rexx stem under which structure elements' values are provided, as such: stem.n = Actual value of element "n" in structure pointer = 32-bit pointer (address) to base of structure map = structure map generated by RxStructMap() bytes = total number of bytes in structure ═══ 9.4. RxStorage - Access/Alter memory by address ═══ This function allows a Rexx program to access and/or alter storage by address. This could be used to process data passed to it by a program. This could also be used to "Pass By Reference" among Rexx programs when using the RxAllocMem and RxFreeMem functions. Syntax: outdata = RxStorage( pointer [, length] [, indata] ) where pointer = 32-bit pointer (address) length = Length of storage to be queried (defaults to 1) indata = Data to place at address "pointer" for the length of the data (regardless of "length" value) outdata = Data at address "pointer" for length "length" (truncated if "length" takes you beyond allowed storage) Note: A request to query memory out-of-bounds returns a string up to the bound- ary. A request to set memory out-of-bounds, sets memory up to the bound- ary. All memory is allocated in 4k chunks. Therefore, some query or set operations will access memory up to the next 4k boundary. ═══ 9.5. RxAdd2Ptr - Pointer Arithmetic (Add/Subtract) ═══ This function allows a Rexx program to add or subtract from an OS/2 32-bit linear address. Syntax: newptr = RxAdd2Ptr( pointer , [number] ) where: pointer = 32-bit pointer (address) number = amount by which "pointer" is to be incremented/decremented in bytes. Default is zero. newptr = result of addition/subtraction ═══ 9.6. RxThunkAddr - Thunk an address Flat->Segmented, Segmented->Flat ═══ This function allows a Rexx program to "thunk" an address from flat to segmented, or from segmented to flat (i.e. 32->16 bit or 16->32 bit). Syntax: newptr = RxThunkAddr( pointer , type ) where: pointer = input address type = indicates what to convert input address to: S - convert input address from flat to segmented (32->16) F - convert input address from segmented to flat (16->32) newptr = thunked address ═══ 9.7. RxAllocMem - Allocate memory (using DosAllocMem) ═══ This function allows a Rexx program to allocate memory. This memory can then be accessed using RxStorage. Syntax: allocrc = RxAllocMem(rexxvar, length, flags) where rexxvar = name of a rexx variable in which pointer is returned length = a decimal integer indicating amount of storage (in bytes) to allocate flags = any combination of: C - Pag_Commit T - Obj_Tile X - Pag_Execute R - Pag_Read W - Pag_Write G - Pag_Guard allocrc = return code from DosAllocMem() for example: /* Following would get 4k committed read/write */ allocrc = RxAllocMem('pointer', 4096, 'crw') Note: All memory is allocated in 4k chunks. Therefore, even if you allocate 200 bytes, you will get access to 4096 bytes. ═══ 9.8. RxFreeMem - Free memory allocated by RxAllocMem ═══ This function allows a Rexx program to free memory allocated by RxAllocMem. Syntax: freerc = RxFreeMem(pointer) where pointer - A valid 32 bit pointer. Note: Returned value is return code from DosFreeMem ═══ 9.9. RxAllocSharedMem - Allocate shared memory ═══ This function allocates shared (named or un-named) memory. Other processes can access this memory with either RxGetSharedMem (un-named), or RxGetNamedSharedMem (named), or if it is "Given", followed by calls to RxStorage. Syntax: allocrc = RxAllocSharedMem(rexxvar, length, flags [,memname] ) where rexxvar = name of a rexx variable in which pointer is returned length = a decimal integer indicating amount of storage (in bytes) to allocate flags = any combination of: C - Pag_Commit T - Obj_Tile I - Obj_Giveable E - Obj_Gettable (sic) X - Pag_Execute R - Pag_Read W - Pag_Write G - Pag_Guard memname = name of shared memory object, if this is to be named shared memory allocrc = return code from DosAllocSharedMem() for example: /* To allocate an un-named, gettable object */ allocrc = RxAllocSharedMem('pointer', 4096, 'cerw') /* To allocate a named object */ allocrc = RxAllocSharedMem('pointer', 4096, 'crw','\SHAREMEM\TEST.MEM') Note: All memory is allocated in 4k chunks. Therefore, even if you allocate 200 bytes, you will get access to 4096 bytes. ═══ 9.10. RxGiveSharedMem - Give access to shared memory ═══ This function gives access to shared, un-named memory to a process-id Syntax: giverc = RxGiveSharedMem(pointer, pid [,flags]) where pointer = valid 32-bit pointer pid = valid process-id (as a decimal integer) flags = any combination of: X - Pag_Execute R - Pag_Read W - Pag_Write G - Pag_Guard for example: /* To give shared memory */ giverc = RxGiveSharedMem(pointer, 23, 'rw') Note: A valid pointer must be supplied. This is obtained from the process which allocated the shared un-named memory via RxAllocSharedMem. The process-id supplied must be valid (i.e. must currently exist). ═══ 9.11. RxGetSharedMem - Get access to shared memory ═══ This function gets access to shared, un-named, gettable memory. Syntax: getrc = RxGetSharedMem(pointer, flags) where pointer = valid 32-bit pointer flags = any combination of: X - Pag_Execute R - Pag_Read W - Pag_Write G - Pag_Guard for example: /* To get shared memory */ getrc = RxGetSharedMem(pointer, 'rw') Note: A valid pointer must be supplied. This is obtained from the process which allocated the shared un-named memory via RxAllocSharedMem. ═══ 9.12. RxGetNamedSharedMem - Get access to named shared memory ═══ This function gets access to shared, named memory. Syntax: getrc = RxGetNamedSharedMem(rexxvar, memname, flags) where rexxvar = name of a rexx variable in which pointer is returned memname = valid name of a shared memory object flags = any combination of: X - Pag_Execute R - Pag_Read W - Pag_Write G - Pag_Guard getrc = return code from DosGetNamedSharedMem() for example: /* To get named shared memory */ getrc = RxGetNamedSharedMem('pointer', '\SHAREMEM\TEST.MEM', 'rw') ═══ 9.13. RxSetMem - Set memory attributes ═══ This function sets memory attributes using DosSetMem Syntax: setrc = RxSetMem(pointer [,memsize [,flags]]) where pointer = valid 32-bit pointer memsize = size of memory block to set flags = any combination of: C - Pag_Commit D - Pag_Decommit F - Pag_Default X - Pag_Execute R - Pag_Read W - Pag_Write G - Pag_Guard for example: /* To set memory attributes */ setrc = RxSetMem(pointer, 4096, 'crw') Note: Returned value is return code from DosSetMem. ═══ 9.14. RxQueryMem - Query memory attributes ═══ This function queries memory attributes using DosQueryMem Syntax: qinfo = RxQueryMem(pointer [,memsize]) where pointer = valid 32-bit pointer memsize = size of memory block to query qinfo = either one or three blank-delimited tokens: 1) return code from DosQueryMem If #1 is zero: 2) actual memory size 3) memory attribute flags, which can be any combination of: C - Pag_Commit F - Pag_Free S - Pag_Shared B - Pag_Base X - Pag_Execute R - Pag_Read W - Pag_Write G - Pag_Guard for example: /* To query memory attributes */ qinfo = RxQueryMem(pointer, 4096) /* "Say qinfo" might say -> "0 4096 CSRW" for instance */ Note: If first token is not zero, no other information was returned. ═══ 9.15. RxSubSetMem - Set memory for suballocation ═══ This function sets memory for suballocation using DosSubSetMem Syntax: subsetrc = RxSubSetMem(pointer [,memsize [,flags]]) where pointer = valid 32-bit pointer to pool memsize = size of memory block to subset flags = any combination of: I - DosSub_Init G - DosSub_Grow S - DosSub_Sparse R - DosSub_Serialize for example: /* To subset some memory */ subsetrc = RxSubSetMem(pointer, 4096, 'i') Note: Returned value is return code from DosSubSetMem. ═══ 9.16. RxSubUnSetMem - UnSet memory from suballocation ═══ This function unsets memory from suballocation using DosSubUnSetMem Syntax: subunsetrc = RxSubUnSetMem(pointer) where pointer = valid 32-bit pointer to pool for example: /* To subunset some memory */ subunsetrc = RxSubUnSetMem(pointer) Note: Returned value is return code from DosSubUnSetMem. ═══ 9.17. RxSubAllocMem - Suballocate memory ═══ This function suballocates memory. Syntax: subarc = RxSubAllocMem(rexxvar, pointer [,memsize]) where rexxvar = name of a rexx variable in which block offset is returned pointer = valid 32-bit pointer to pool memsize = size of block to suballocate subarc = return code from DosSubAllocMem() for example: /* To suballocate some memory */ subarc = RxSubAllocMem('block_offset', pointer, 4096) ═══ 9.18. RxSubFreeMem - Free suballocated memory ═══ This function frees suballocated memory. Syntax: freerc = RxSubFreeMem(pointer, boffset [,memsize]) where pointer = valid 32-bit pointer to pool boffset = block offset pointer memsize = size of block to free for example: /* To free suballocated memory */ freerc = RxSubFreeMem(pointer, boffset, 4096) Note: Returned value is return code from DosSubFreeMem. ═══ 10. Semaphore handling ═══ These functions allow Rexx programs to make use of OS/2 semaphores for synchronization/serialization purposes. Note that for named semaphores (event, mutex, or mux) the semaphore name must begin with "\sem32\". Thus, a valid semaphore name would be "\sem32\frank" whereas "\frank" would not be valid. ═══ 10.1. RxCreateEventSem - Create an event semaphore ═══ This function creates a (named or un-named) event semaphore. Syntax: semrc = RxCreateEventSem(rexxvar [,type] [,name] [,state] ) where rexxvar = name of a rexx variable in which sem handle is returned type = 'Shared' or 'Private' (default is Private) name = semaphore name (default is un-named) state = 'Reset' or 'Posted' (default is Reset) semrc = return code from DosCreateEventSem() ═══ 10.2. RxOpenEventSem - Open an event semaphore ═══ This function opens an event semaphore for use by a process that did not create the semaphore. Syntax: semrc = RxOpenEventSem(rexxvar, semid) where rexxvar = name of a rexx variable in which sem handle is returned semid = either a semaphore handle, or a semaphore name semrc = return code from DosOpenEventSem() Note: A zero length string is returned if DosOpenEventSem fails. ═══ 10.3. RxPostEventSem - Post an event semaphore ═══ This function posts an event semaphore. Syntax: postrc = RxPostEventSem(hev) where hev = semaphore handle postrc = return code from DosPostEventSem ═══ 10.4. RxQueryEventSem - Query an event semaphore ═══ This function returns the post count for an event semaphore. Syntax: info = RxQueryEventSem(hev) where hev = semaphore handle info = return code from DosQueryEventSem, followed by number of posts Note: Word 1 of info is the return code from DosQueryEventSem Word 2 of info is the actual number of posts to the semaphore ═══ 10.5. RxResetEventSem - Reset an event semaphore ═══ This function resets an event semaphore, returning the number of postings for that semaphore. Syntax: info = RxResetEventSem(hev) where hev = semaphore handle info = return code from DosResetEventSem, followed by number of posts Note: Word 1 of info is the return code from DosResetEventSem Word 2 of info is the actual number of posts to the semaphore before the Reset. ═══ 10.6. RxWaitEventSem - Wait on an event semaphore ═══ This function waits on the posting of an event semaphore. Syntax: semhandle /* A valid semaphore handle */ time = 1000 /* in milliseconds */ waitrc = RxWaitEventSem(hev [,time]) where hev = semaphore handle time = number of miliseconds to wait before returning, or the word 'Indefinite'. Default is 'Indefinite'. waitrc = return code from DosWaitEventSem ═══ 10.7. RxCloseEventSem - Close an event semaphore ═══ This function closes an event semaphore Syntax: closerc = RxCloseEventSem(hev) where hev = semaphore handle closerc = return code from DosCloseEventSem ═══ 10.8. RxCreateMutexSem - Create a Mutex Semaphore ═══ This function creates a mutex semaphore Syntax: semrc = RxCreateMutexSem(rexxvar [,type] [,name] [,state] ) where rexxvar = name of a rexx variable in which sem handle is returned type = 'Shared' or 'Private' (default is 'Private') name = semaphore name (default is un-named) state = 'Owned' or 'Unowned' (default is un-owned) semrc = return code from DosCreateMutexSem() ═══ 10.9. RxOpenMutexSem - Open a Mutex Semaphore ═══ This function opens a mutex semaphore Syntax: semrc = RxOpenMutexSem(rexxvar, semid ) where rexxvar = name of a rexx variable in which sem handle is returned semid = either a semaphore name, or an existing mutex semaphore handle semrc = return code from DosOpenMutexSem() ═══ 10.10. RxCloseMutexSem - Close a Mutex Semaphore ═══ This function closes a mutex semaphore Syntax: mtxrc = RxCloseMutexSem( hmtx ) where hmtx = existing mutex semaphore handle mtxrc = return code from DosCloseMutexSem ═══ 10.11. RxQueryMutexSem - Query Mutex Semaphore ═══ This function queries a mutex semaphore's attributes Syntax: mtxinfo = RxQueryMutexSem( hmtx ) where hmtx = existing mutex semaphore handle mtxinfo = four blank delimited tokens: 1) return code from DosQueryMutexSem 2) Process-Id of semaphore's current owner 3) Thread-Id of semaphore's current owner 4) A count of the number of calls to DosRequestMutexSem, minus the number of calls to DosReleaseMutexSem, that have been made for the semaphore by the owning thread. If the semaphore is unowned, this value will be zero. If the owning thread has ended, the value will be the request count for the ended owner. ═══ 10.12. RxReleaseMutexSem - Release Mutex Semaphore ═══ This function releases a mutex semaphore Syntax: mtxrc = RxReleaseMutexSem( hmtx ) where hmtx = existing mutex semaphore handle mtxrc = return code from DosReleaseMutexSem ═══ 10.13. RxRequestMutexSem - Request Mutex Semaphore ═══ This function requests a mutex semaphore Syntax: mtxrc = RxRequestMutexSem( hmtx [, timeout] ) where hmtx = existing mutex semaphore handle timeout = either a decimal integer (miliseconds to block), or the word 'Indefinite' mtxrc = return code from DosRequestMutexSem ═══ 10.14. RxCreateMuxWaitSem - Create a MuxWait Semaphore ═══ This function creates a muxwait semaphore Syntax: semrc = RxCreateMuxWaitSem(rexxvar, stemname [,type] [,anyall] [,name] ) where rexxvar = name of a rexx variable in which sem handle is returned stemname = a Rexx stem name (ending in a period '.'), under which are supplied the semaphore handles which constitute this muxwait semaphore. The expected structure of the stem is: 1) stem.0 = a decimal integer indicating how many semaphores are supplied 2) stem.n.1 = handle of Nth semaphore 3) stem.n.2 = decimal integer used as an Id for Nth semaphore type = 'Shared' or 'Private' (default is 'Private') anyall = 'anY' or 'alL' (default is 'All') name = semaphore name (default is un-named) semrc = return code from DosCreateMuxWaitSem() ═══ 10.15. RxOpenMuxWaitSem - Open a MuxWait Semaphore ═══ This function opens a muxwait semaphore Syntax: semrc = RxOpenMuxWaitSem(rexxvar, semid ) where rexxvar = name of a rexx variable in which sem handle is returned semid = either a semaphore name, or an existing muxwait semaphore handle semrc = return code from DosOpenMuxWaitSem() ═══ 10.16. RxCloseMuxWaitSem - Close a MuxWait Semaphore ═══ This function closes a muxwait semaphore Syntax: muxrc = RxCloseMuxWaitSem( hmux ) where hmux = existing muxwait semaphore handle muxrc = return code from DosCloseMuxWaitSem ═══ 10.17. RxDeleteMuxWaitSem - Delete from a MuxWait Semaphore ═══ This function deletes a semaphore from a muxwait semaphore list Syntax: muxrc = RxDeleteMuxWaitSem( hmux, hsem ) where hmux = existing muxwait semaphore handle hsem = handle of a semaphore in the muxwait semaphore list muxrc = return code from DosDeleteMuxWaitSem ═══ 10.18. RxAddMuxWaitSem - Add to a MuxWait Semaphore ═══ This function adds a semaphore to a muxwait semaphore list Syntax: muxrc = RxAddMuxWaitSem( hmux, hsem, semid ) where hmux = existing muxwait semaphore handle hsem = handle of a semaphore to add to the muxwait semaphore list semid = decimal integer used as an Id for this semaphore muxrc = return code from DosAddMuxWaitSem ═══ 10.19. RxQueryMuxWaitSem - Query a MuxWait Semaphore ═══ This function queries information about a muxwait semaphore Syntax: muxinfo = RxQueryMuxWaitSem( hmux, stemname ) where hmux = existing muxwait semaphore handle stemname = a Rexx stem name (ending in a period '.'), under which is returned information about the muxwait semaphore. The structure of the returned information is: 1) stem.0 = a decimal integer indicating how many semaphores are listed in this muxwait semaphore 2) stem.n.1 = handle of Nth semaphore 3) stem.n.2 = decimal integer Id of Nth semaphore muxinfo = Two blank delimited tokens: 1) return code from DosQueryMuxWaitSem 2) a string of letters indicating this muxwait semaphore's properties: 'S' if it's shared 'Y' if it's a wait ANY 'L' if it's a wait ALL ═══ 10.20. RxWaitMuxWaitSem - Wait on a MuxWait Semaphore ═══ This function waits on a muxwait semaphore Syntax: muxinfo = RxWaitMuxWaitSem( hmux [,timeout] ) where hmux = existing muxwait semaphore handle timeout = either a decimal integer (miliseconds to block), or the word 'Indefinite' muxinfo = Two blank delimited tokens: 1) return code from DosQueryMuxWaitSem 2) semaphore-id of releaser of muxwait sem (for more info, see details of DosWaitMuxWaitSem) ═══ 11. Rexx Macro Space Functions ═══ These functions allow Rexx programs to query and alter the Rexx MacroSpace. ═══ 11.1. RxAddMacro - Add Entry to MacroSpace ═══ This function adds a Rexx program to the macrospace. Syntax: addrc = RxAddMacro(funcname, sourcefile [,order]) where funcname = name for function in macrospace sourcefile = name of source file where Rexx source code exists order = order in macrospace (Before or After) Note: Returned value is return code from RexxAddMacro. ═══ 11.2. RxDropMacro - Drop Entry from MacroSpace ═══ This function drops a function from the macrospace. Syntax: droprc = RxDropMacro(funcname) where funcname = name of function in macrospace Note: Returned value is return code from RexxDropMacro. ═══ 11.3. RxClearMacroSpace - Clear Entire MacroSpace ═══ This function clears all functions from the macro space. Be careful when using this as it will affect all processes in the system. Syntax: clear_rc = RxClearMacroSpace() Note: Returned value is return code from RexxClearMacroSpace. ═══ 11.4. RxSaveMacroSpace - Save Macro to File ═══ This function saves a macrospace function to a file. Syntax: saverc = RxSaveMacroSpace(funcname, macfile) where funcname = name of function in macrospace macfile = name of file in which to save macro Note: Returned value is return code from RexxSaveMacroSpace. ═══ 11.5. RxLoadMacroSpace - Load a Macro from File ═══ This function loads a macrospace function from a file. Syntax: loadrc = RxLoadMacroSpace(funcname, macfile) where funcname = name of function in macrospace macfile = name of file in which to save macro Note: Returned value is return code from RexxLoadMacroSpace. ═══ 11.6. RxQueryMacro - Query MacroSpace ═══ This function queries the existence/position of a macro in the macrospace. Syntax: qinfo = RxQueryMacro(funcname) where funcname = name of function in macrospace qinfo = blank-delimited tokens: 1) return code from RexxQueryMacro If #1 is zero, then: 2) Before/After/? Note: If first token is not zero, no other information was returned. ═══ 11.7. RxReorderMacro - Reorder Macro Position ═══ This function reorders the position of a macro within the macrospace. Syntax: reorderrc = RxReorderMacro(funcname, position) where funcname = name of function in macrospace position = relative position in macrospace (Before/After) Note: Returned value is return code from RexxReorderMacro ═══ 12. Threads, Tasking, etc. ═══ These functions allow a Rexx program to start and control new threads and processes. ═══ 12.1. RxWaitChild - Wait for child process(es) to end ═══ This function will wait for child process(es) to end Syntax: dosrc = RxWaitChild(childpid,actioncode,waitoption) where childpid = PID of child process (decimal number) actioncode = kill single process, or a process tree: P - single process T - process tree waitoption = whether or not to wait for child to end: W - wait N - no wait dosrc = four blank-delimited tokens: 1) return code from DosWaitChild if (1) is zero, then 2) returned PID 3) result code from terminating process 4) text indicating type of child termination: - NormalExit - HardError - Trap - KillProcess - Exception ═══ 12.2. RxExecPgm - Execute a program ═══ This function starts another program in the same session. Syntax: exrc = RxExecPgm(pgmname [, mode [,argstring]]) where pgmname = name of .EXE file to execute mode = 'S'ync, 'A'sync, async'R'esult, 'T'race, 'B'ackground, 'L'oad, asyncresult'D'b. Default is 'S'ync. argstring = arg string to pass to program exrc = three blank-delimited tokens: 1) return code from DosExecPgm 2) termination code / process-id (for asynchronous) 3) new program's return code ═══ 12.3. RxStartSession - Start Another Session ═══ This function starts a program in another OS/2 session. Syntax: strc = RxStartSession(pgmname [,args [,related [,fgbg [,title [,type [,ctrl] ] ] ] ] ]) where pgmname = name of .EXE file to execute args = arg string to pass to program related = Relation of started session to this session, can be: 'I'ndependent or 'C'hild fgbg = Foreground/Background option, can be: 'F'oreground or 'B'ackground title = Session title (defaults to program name) type = Program type, can be: 'D'efault, 'F'ullscreen, 'P'M, 'V'irtual-Dos, 'W'indowed-Virtual-Dos, vi'O'-windowable ctrl = Program control, can be: 'V'isible, 'I'nvisible, ma'X'imized, mi'N'imized, no'A'utoclose strc = if DosStartSession failed: - return code from DosStartSession followed by error info if DosStartSession got zero rc: - return code from DosStartSession Session-ID Process-ID ═══ 12.4. RxStartRexxSession - Start a Rexx program on another session ═══ This function starts a Rexx program in another OS/2 session. (The program "RXSRS.EXE" must be in your path in order to use this function) Syntax: strc = RxStartRexxSession(execname [,arg1] [,arg2] ... [,argn]) where execname = name of Rexx program to execute or a '$' immediately preceding a source program string or a '&' immediately preceding a tokenized program string (for more info about these, see "RxCallInStore" and "RxTokenize") arg1 = arguments 1-n for target Rexx program ... argn strc = if DosStartSession failed: - return code from DosStartSession followed by error info if DosStartSession worked: - return code from DosStartSession Session-ID Process-ID ═══ 12.5. RxDetachRexxPgm - Detach a Rexx program ═══ This function starts a Rexx program in the detached OS/2 session. (The program "RXSRS.EXE" must be in your path in order to use this function) Syntax: dtrc = RxDetachRexxPgm(execname [,arg1] [,arg2] ... [,argn]) where execname = name of Rexx program to execute or a '$' immediately preceding a source program string or a '&' immediately preceding a tokenized program string (for more info about these, see "RxCallInStore" and "RxTokenize") arg1 = arguments 1-n for target Rexx program ... argn dtrc = if DosExecPgm failed: - return code from DosExecPgm, followed by error info if DosExecPgm worked: - return code from DosExecPgm "codeTerminate" and "codeResult" ═══ 12.6. RxKillProcess - Kill an OS/2 Process ═══ This function kills an OS/2 process by process-id. Syntax: killrc = RxKillProcess(pid [, action]) where pid = process-id (decimal integer) action = 'Process' or 'Tree' (default is 'Process') killrc = return code from DosKillProcess ═══ 12.7. RxCreateThread - Start new thread ═══ This function starts execution at a supplied entry point on a new thread. The entry point is any valid procedure address (e.g. obtained by a call to RxQueryProcAddr, etc.). Syntax: tid = RxCreateThread(procaddr [, dataptr [, linktype [, stacksize [, threadflag]]]]) where procaddr = Procedure Address dataptr = pointer to arguments linktype = 'System' or 'Optlink' If linktype is 'System', then args 4 and 5 are: stacksize = stacksize for thread (default is 8192) threadflag = 'Immediate' or 'Suspend' tid = thread-id of new thread Note: Pointer to arguments is optional, but if supplied must be a valid pointer. ═══ 12.8. RxKillThread - Kill a thread ═══ This function kills a thread by thread-id. Syntax: killrc = RxKillThread(tid) where tid = thread-id killrc = return code from DosKillThread ═══ 12.9. RxSetPriority - Set the priority of processes or threads ═══ This function sets the priority of one or more process and/or threads. Syntax: setrc = RxSetPriority(scope,class,delta,id) where scope = 'P'rocess (default) t'R'ee 'T'hread class = 'N'ochange (default) 'I'dletime 'R'egular 'T'imecritical foreground'S'erver delta = any integer from -31 to +31, or ma'X'imum, or mi'N'imum id = a Process-Id, Thread-Id, or nothing, depending on value of "scope" setrc = return code from DosSetPriority ═══ 12.10. RxResumeThread - Resume thread execution ═══ This function causes a thread to resume execution Syntax: resrc = RxResumeThread(tid) where tid = thread-id resrc = return code from DosResumeThread ═══ 12.11. RxSuspendThread - Suspend thread execution ═══ This function causes a thread to suspend execution Syntax: susrc = RxSuspendThread(tid) where tid = thread-id susrc = return code from DosSuspendThread ═══ 12.12. RxCreateRexxThread - Rexx on another thread ═══ This function executes a Rexx program on another thread of the same process. The started Rexx program has a separate variable pool, and maintains its own "current Rexx queue", indpendently of the starting Rexx program. But all other features of multi-threaded applications apply (i.e. shared file handles, etc.) Syntax: tid = RxCreateRexxThread(execname [,arg1 [,arg2 [, ...]]]) where execname = name of Rexx program to execute or a '$' immediately preceding a source program string or a '&' immediately preceding a tokenized program string (for more info about these, see "RxCallInStore" and "RxTokenize") arg1 = arguments to Rexx program (up to 19 possible) arg2 ... tid = Thread-Id of new thread Note: Example of executing a program string: crlf = '0d0a'x str = '/* Rexx */'crlf str = str 'Do i=1 To Arg()'crlf str = str ' Say "Arg#"i "= {"arg(i)"}"'crlf str = str 'End'crlf str = str||'1a'x /* EOF marker */ call rxcreaterexxthread '$'str, date(), time() ═══ 12.13. RxSetExceptionExit - Specify the address of exception exit ═══ which is called when an OS/2 exception occurs on a thread started with "RxCreateRexxThread". This function specifies the address of a "_System" linkage function which is to be called when an OS/2 exception occurs on a thread which was started with "RxCreateRexxThread". Syntax: rslt = RxSetExceptionExit(pfn) where pfn = 32-bit pointer to a _System linkage exception (i.e. a four byte binary value) rslt = empty string ═══ 13. NETBIOS information ═══ These functions allow a Rexx program to access certain NETBIOS information. ═══ 13.1. RxNbSessionStatus - NetBios Session Status ═══ This function gets NetBios session status information. Syntax: nbname = 'S$SQLDBSERVR1#DB' nbrc = RxNbSessionStatus(nbname,'s.','r') Note: Return code is from NETBIOS api. Second argument is name of a Rexx stem variable under which results are returned as such: stem.0 = number of sessions reported on stem.n.1 = Local session number stem.n.2 = Session state stem.n.3 = Local name stem.n.4 = Remote name stem.n.5 = Number of receive commands pending stem.n.6 = Number of send commands pending Third argument may be supplied to have a NETBIOS "Reset" done before and after obtaining session status. ═══ 14. DLL Handling ═══ These functions allow a Rexx program to load and execute procedures with- in DLL's. Also, certain information about DLL's can be obtained. ═══ 14.1. RxLoadModule - Load a DLL ═══ This function loads a DLL, returning a module handle (or an error code). Syntax: dosrc = RxLoadModule(rexxvar, dllname) where: rexxvar = name of rexx variable in which module handle is returned dllname = name of DLL to load dosrc = return code from DosLoadModule ═══ 14.2. RxFreeModule - Free a DLL ═══ This function frees the DLL whose module handle is supplied. Syntax: dosrc = RxFreeModule(hmod) where: hmod = module handle dosrc = return code from DosFreeModule ═══ 14.3. RxQueryModuleName - Get Module Name ═══ This function returns the name of a module, given the module handle. Syntax: dosrc = RxQueryModuleName(rexxvar,hmod) where: rexxvar = name of rexx variable in which module name is returned hmod = module handle of DLL dosrc = return code from DosQueryModuleName ═══ 14.4. RxQueryModuleHandle - Get Module Handle ═══ This function returns the handle of a module, given the module's name. Syntax: dosrc = RxQueryModuleHandle(rexxvar,modname) where: rexxvar = name of rexx variable in which module handle is returned modname = name of DLL dosrc = return code from DosQueryModuleHandle ═══ 14.5. RxQueryProcType - Query Procedure Type ═══ This function returns the addressing mode (16/32 bit) of a procedure of a DLL. The procedure can be identified either by name, or ordinal number. Syntax: entryname = 'SQLEXEC' ordinal = 3 procinfo = RxQueryProcType(hmod,procid) amode = RxQueryProcType(hmod,entryname) where: hmod = module handle procid = procedure-id (either an ordinal, or a procedure name) procinfo = Two blank-delimited tokens: 1) return code from DosQueryProcType 2) either "16" or "32", indicating 16 or 32 bit ═══ 14.6. RxQueryProcAddr - Query Procedure Address ═══ This function returns the address of an entry point in a DLL. This entry point can then be used in RxCallEntryPoint to call an entry point in a Loaded DLL. Syntax: entryname = 'SQLEXEC' /* Entry name */ 3 /* Entry ordinal */ dosrc = RxQueryProcAddr(rexxvar,hmod,procid) where: rexxvar = name of rexx variable in which procedure address is returned hmod = module handle of DLL procid = procedure-id (either an ordinal, or a procedure name) ═══ 14.7. RxCallEntryPoint - Call an entry point ═══ This function "calls" the code which begins at the ProcAddress supplied. This ProcAddress could be the address obtained by RxQueryProcAddr for the entry point of a DLL. But, it can be any "legal" entry point address of any routine. Syntax: procrc = RxCallEntryPoint(procaddr [,arg1 [, arg2 [,...]]] ) where procaddr = proc-address (could be obtained from RxQueryProcAddr, etc.) parg1 ... parg19 = up to 19 arguments. If an argument is a valid pointer, the pointer will be passed. If not, a copy of the argument's value will be passed by reference. Either way, the procedure must be expecting a pointer for each argument. procrc = return code from the procedure Note: Linkage to the proc-address is type _System. ═══ 15. OS/2 Pipes ═══ An assortment of OS/2 pipe-related functions (not complete). ═══ 15.1. RxCreateNPipe - Create a named pipe ═══ This function creates an OS/2 named pipe. Syntax: dosrc = RxCreateNPipe( rexxvar, pipename, openmode, pipemode, instance_count, outbufsize, inbufsize, timeout) where rexxvar = name of Rexx variable into which read/write handle is placed pipename = name of pipe OpenMode Values W = WriteBehind w = NoWriteBehind I = Inherit i = NoInherit N(n) = Access Inbound O(o) = Access Outbound D(d) = Access Duplex PipeMode Values W = Wait w = NoWait T = Pipe Type "Byte" t = Pipe Type "Message" R = Readmode "Byte" r = Readmode "Message" Instance_Count Integer Outbuf Size Integer Inbuf Size Integer Timeout Integer dosrc = return code from DosCreateNPipe() ═══ 15.2. RxConnectNPipe - Connect to a named pipe ═══ This function connects to a named pipe Syntax: dosrc = RxConnectNPipe(hpipe) where hpipe = pipe handle dosrc = return code from DosConnectNPipe() ═══ 15.3. RxDisConnectNPipe - Disconnect from a named pipe ═══ This function disconnects from a named pipe Syntax: dosrc = RxDisConnectNPipe(hpipe) where hpipe = pipe handle dosrc = return code from DosDisConnectNPipe() ═══ 15.4. RxCreatePipe - Create an un-named pipe ═══ This function creates an OS/2 un-named pipe Syntax: dosrc = RxCreatePipe(rexxstem [,pipesize]) where rexxstem = name of Rexx stem variable under which read handle, write handle, and pipe size are returned as such: stem.1 = read handle stem.2 = write handle stem.3 = pipe size dosrc = return code from DosCreatePipe() ═══ 15.5. RxDestroyPipe - Destroy an un-named pipe ═══ This function destroys an OS/2 un-named pipe Syntax: dosrc = RxDestroyPipe(hread,hwrite) where hread = read handle hwrite = write handle dosrc = return codes from DosClose() ═══ 16. OS/2 Queues ═══ Most of the OS/2 queue APIs are implemented here. ═══ 16.1. RxCreateQueue - Create an OS/2 queue. ═══ This function creates an OS/2 queue. Syntax: dosrc = RxCreateQueue(rexxvar, qname, qflags) where rexxvar = name of Rexx variable into which queue handle is placed qname = name of OS/2 queue qflags = flags for queue creation: F - Fifo L - Lifo P - Priority C - Convert Address N - No-convert Address dosrc = return code from DosCreateQueue() ═══ 16.2. RxOpenQueue - Open an OS/2 queue ═══ This function opens an OS/2 queue Syntax: dosrc = RxOpenQueue(rexxstem,qname) where rexxstem = name of Rexx stem, under which info is returned: stem.1 = queue-owner-pid (integer) stem.2 = queue handle qname = name of queue to open dosrc = return code from DosOpenQueue() ═══ 16.3. RxPeekQueue - Peek at an OS/2 queue ═══ This function peeks at an OS/2 queue without reading it Syntax: dosrc = RxPeekQueue(rexxstem,qhandle,elemcode,waitcode,semhandle) where rexxstem = name of Rexx stem, under which info is returned: stem.1 = data pointer (e.g. for use with RxStorage) stem.2 = data length (of that pointed to by stem.1) stem.3 = PID of process which enqueued element stem.4 = event code (RequestData.ulData) stem.5 = element code stem.6 = element priority qhandle = handle to queue elemcode = element code (integer) waitcode = whether to wait for data in queue W = Wait N = Nowait semhandle = handle of semaphore dosrc = return code from DosPeekQueue() ═══ 16.4. RxReadQueue - Read an OS/2 queue ═══ This function reads an element off an OS/2 Syntax: dosrc = RxReadQueue(rexxstem,qhandle,elemcode,waitcode,semhandle) where rexxstem = name of Rexx stem, under which info is returned: stem.1 = data pointer (e.g. for use with RxStorage) stem.2 = data length (of that pointed to by stem.1) stem.3 = PID of process which enqueued element stem.4 = event code (RequestData.ulData) stem.5 = element priority qhandle = handle to queue elemcode = element code (integer) waitcode = whether to wait for data in queue W = Wait N = Nowait semhandle = handle of semaphore dosrc = return code from DosReadQueue() ═══ 16.5. RxWriteQueue - Write to an OS/2 queue ═══ This function writes an element to an OS/2 Syntax: dosrc = RxWriteQueue(qhandle,pointer,length,reqdata,elemprty) where qhandle = handle to queue pointer = whatever 32 bits you want to put on queue length = integer length associated with "pointer" reqdata = integer request data elemprtry = element priority, if this is a priority queue dosrc = return code from DosWriteQueue() ═══ 16.6. RxPurgeQueue - Purge elements from OS/2 queue ═══ This function purges elements from an OS/2 queue Syntax: dosrc = RxPurgeQueue(qhandle) where qhandle = handle to queue dosrc = return code from DosPurgeQueue() ═══ 16.7. RxQueryQueue - Query info about OS/2 queue ═══ This function returns information about an OS/2 queue Syntax: info = RxQueryQueue(qhandle) where qhandle = handle to queue info = two blank delimited tokens: 1) return code from DosQueryQueue() 2) number of elements on queue (if (1) is zero) ═══ 16.8. RxCloseQueue - Close an OS/2 queue ═══ This function closes an OS/2 queue Syntax: dosrc = RxCloseQueue(qhandle) where qhandle = handle to queue dosrc = return code from DosCloseQueue() ═══ 16.9. RxReadQueueStr - Read data from OS/2 queue ═══ This function returns the de-referenced contents of an OS/2 queue element. That is, it dequeues an element and returns the data pointed to by the dequeued element as the function result. It first does a DosOpenQueue, then a DosReadQueue(wait), but does NOT do a DosCloseQueue. Syntax: datastr = RxReadQueueStr(qid) where qid = name of queue to read, or handle of already-opened queue datastr = data pointed to by dequeued pointer ═══ 17. I/O Related ═══ Miscellaneous functions related to I/O operations. ═══ 17.1. RxOpen - Open a file ═══ This function opens a file. Syntax: dosrc = RxOpen(rexxstem, filename, openflag, openmode [,attr] [,size]) where rexxstem = name of Rexx stem variable under which info is returned: stem.1 = file handle stem.2 = action taken: Existed Created Truncated filename = name of file/pipe/stream to open openflag = flag indicating what to do if file exists: (case does not matter) N - fail if New C - Create if new E - fail if Exists O - Open if exists R - Replace if exists openmode = how to open file, valid combinations of: (case DOES matter) D - Dasd T - write Through F - Fail on error C - no Cache S - Sequential R - Random M - random/sequential (Mixed) H - no inHerit b - (sharemode) deny read/write (both) w - (sharemode) deny write r - (sharemode) deny read n - (sharemode) deny none R - (accessmode) Read only W - (accessmode) Write only B - (accessmode) readwrite (Both) attr = file attribute, valid combinations of: (only if open creates file) A - Archived D - Directory S - System H - Hidden R - Readonly N - Normal (default) size = file size (only if open creates file) dosrc = return code from DosOpen() ═══ 17.2. RxDosRead - Read from File Handle (alias for RxRead) ═══ This alias for "RxRead()" is provided to allow RXU to be used along with other Rexx function packages (such as RXUTILS, etc.) which already use the function name "RxRead". ═══ 17.3. RxRead - Read from File Handle ═══ This function reads a character stream in from a file handle, rather than from a file name. Syntax: dosrc = RxRead( rexxvar, hfile [,length] ) where rexxvar = name of Rexx variable into which read data is placed hfile = handle of file to be read from length = number of bytes to read (defaults to zero) dosrc = two blank-delimited words: 1) return code from DosRead 2) if (1) is zero, an integer indicating number of bytes read (should be same as length of rexx variable's value) ═══ 17.4. RxDosWrite - Write to File Handle (alias for RxWrite) ═══ This alias for "RxWrite()" is provided to allow RXU to be used along with other Rexx function packages (such as RXUTILS, etc.) which already use the function name "RxWrite". ═══ 17.5. RxWrite - Write to File Handle ═══ This function writes a character stream out to a file handle, rather than from a file name. Syntax: dosrc = RxWrite( hfile , data ) where hfile = handle of file to be written to data = data to be written to file dosrc = two blank-delimited words: 1) return code from DosWrite 2) if (1) is zero, an integer indicating number of bytes written (may not be same as length of data supplied) ═══ 17.6. RxCloseH - Close a File Handle ═══ This function closes a file handle. Syntax: closerc = RxCloseH(hfile) where hfile = handle of file to be closed closerc = return code from DosClose() ═══ 17.7. RxSoSe2H - Redirect StdOut/StdErr to a file (by file handle) ═══ This function redirects StdOut/StdErr to a file whose handle you supply. Syntax: dosrc = RxSoSe2H(hfile) where hfile = handle of file dosrc = return code from DosDupHandle() ═══ 17.8. RxSi2H - Redirect StdIn from a file (by file handle) ═══ This function redirects StdIn from a file whose handle you supply. Syntax: dosrc = RxSi2H(hfile) where hfile = handle of file dosrc = return code from DosDupHandle() ═══ 17.9. RxRSi2F - Redirect StdIn from a file (by file name) ═══ This function redirects StdIn from a file whose name you supply. Syntax: dosrc = RxRSi2F(filename) where filename = name of file dosrc = return code from DosOpen() or DosDupHandle() ═══ 17.10. RxExecI - Read data into a Rexx queue or stem from a file ═══ This function reads (text) data into a Rexx queue or stem variable from a file. It is meant to be like EXECIO in TSO and VM, and can be used in a similar fashion for file input. Syntax: info = RxExecI([fname], [qtype], [name], [type]) where: fname = name of file to be read from (default reads from stdin) qtype = 'Lifo' or 'Fifo' (default is 'Fifo') determines how lines are read onto queue (ignored for stems) name = name of Rexx queue from into which data is read (default uses current queue) or name of a Rexx stem variable under which data is to be mapped as stem.0 = number of lines (stem.1 - stem.n) stem.1 stem.2 ... stem.n type = 'Queue' or 'Stem' (default is 'Queue') this tells whether arg 3 is a Rexx Queue name or a stem variable name info = two blank delimited numbers: 1) number of lines read 2) total number of bytes read Example: /* Read a text file into the Rexx stem 's.' */ info = rxexeci('c:\config.sys',,'s.','s') parse var info lines bytes Say lines 'lines were read' Say bytes 'bytes were read' ═══ 17.11. RxExecO - Write data from a Rexx queue or stem to a file ═══ This function writes data from a Rexx queue or stem variable to a file. It is meant to be like EXECIO in TSO and VM, and can be used in a similar fashion for file output. Syntax: info = RxExecO([fname], [action], [name], [type]) where: fname = name of file to be written to (default sends to stdout) action = Replace or Append (default is 'Replace') replaces or appends to 'fname' name = name of Rexx queue from which to get data (default uses current queue) or name of a Rexx stem variable under which data is mapped as stem.1 stem.2 ... stem.n Once an uninitialized value for 'stem.n' is encountered, i/o stops. type = 'Queue' or 'Stem' (default is 'Queue') this tells whether arg 3 is a Rexx Queue name or a stem variable name info = two blank delimited numbers: 1) number of lines written 2) total number of bytes written Example: /* Write 100 lines from current queue to c:\junk.dat (replace file) */ Do 100 Queue i time('l') End info = rxexeco('c:\junk.dat','r') parse var info lines bytes Say lines 'lines were written' Say bytes 'bytes were written' ═══ 17.12. RxVioPopUp - Start a VioPopUp display screen ═══ This function starts a VioPopUp display screen. Syntax: viorc = RxVioPopUp(wait,opaque) where: wait = Wait - wait if a pop-up screen already exists = Nowait - return with error if a pop-up screen already exists opaque = Opaque or Transparent viorc = return code from VioPopUp() ═══ 17.13. RxVioEndPopUp - Close a VioPopUp display screen ═══ This function closes a VioPopUp display screen. Syntax: viorc = RxVioEndPopUp() where: viorc = return code from VioEndPopUp() ═══ 17.14. RxVioWrtCharStrAtt - Write characters to a VioPopUp display screen ═══ This function writes characters to a VioPopUp display screen. Syntax: viorc = RxWrtCharStrAtt(string,rowx,coly,attr) where: string = data to write rowx = row number coly = column number attr = attribute bit string viorc = return code from VioWrtCharStrAtt() ═══ 17.15. RxKbCharIn - Get a character from a VioPopUp display screen ═══ This function gets a character from a VioPopUp display screen Syntax: info = RxKbdCharIn(wait) where: wait = Wait - wait for character Nowait - no wait for character info = return code from KbdCharIn(), and, if zero, followed by these blank delimited values: 1) Character 2) Scan Code (hex) 3) NLS state (hex) 4) NLS shift (hex) 5) Shift Key state (hex) 6) Millisecond timestamp of keystroke ═══ 17.16. Rxrsoe2f - Redirect Std-Out/Err to File ═══ This function redirects Standard Out and Standard Error to a named file (or device name, such as "CON"). Syntax: Call Rxrsoe2f stream,opt where: stream = name of file or device (e.g. 'con', 'nul', 'kbd', etc.) to which standard-out and standard-error are re-directed. opt = either 'Append' or 'Replace' file/device ═══ 17.17. Rxrsoe2q - Redirect Std-Out/Err to Rexx Queue ═══ This function redirects Standard Out and Standard Error to a named queue. Syntax: token = rxrsoe2q(opt,value) where: opt = either 'Enable' or 'Disable' value = queue name - (when opt=Enable) (created if it doesn't exist) token - (when opt=Disable) token = binary token returned when opt=Enable, subsequently supplied as a parameter when opt=Disable ═══ 17.18. RxDupHandle - Do a "DosDupHandle()" ═══ This function allows you to do a "DosDupHandle()" Syntax: dosrc = RxDupHandle(rexxvar,hfile1,hfile2) where: rexxvar = name of Rexx variable in which is return duplicated handle (value returned in arg2 by DosDupHandle) hfile1 = arg1 to DosDupHandle hfile2 = arg2 to DosDupHandle dosrc = return code from DosDupHandle() ═══ 17.19. RxSetFHState - Set file handle state ═══ This function allows you to set a file handle's state Syntax: dosrc = RxSetFHState(hfile,flags) where: hfile = file handle whose state you want to set flags = valid combinations of: (case DOES matter) D - Dasd T - write Through F - Fail on error C - no Cache S - Sequential R - Random M - random/sequential (Mixed) H - no inHerit b - (sharemode) deny read/write (both) w - (sharemode) deny write r - (sharemode) deny read n - (sharemode) deny none R - (accessmode) Read only W - (accessmode) Write only B - (accessmode) readwrite (Both) dosrc = return code from DosSetFHState() ═══ 17.20. RxSetMaxFH - Set maximum file handles for process ═══ This function allows you to set the maximum number of file handles for the calling process. Syntax: dosrc = RxSetMaxFH(numhandles) where: numhandles = maximum number of file handles for calling process dosrc = return code from DosSetMaxFH ═══ 17.21. RxSetRelMaxFH - Set max file handles for process (relative to current value) ═══ This function allows you to set the maximum number of file handles (relative to the current number) for the calling process. Syntax: info = RxSetRelMaxFH(numhandles) where: numhandles = maximum number of file handles for calling process info = two blank delimited integers: 1) return code from DosSetMaxFH 2) new total number of allocated file handles ═══ 17.22. RxQueryFHState - Query file handle state ═══ This function allows you to query a file handle's state Syntax: info = RxQueryFHState(hfile) where: hfile = file handle whose state you want to query info = two blank delimited tokens: 1) return code from DosQueryFHState(), 2) if (1) is zero, then a string of flags indicating state of file, flag values are (case is important): D - OPEN_FLAGS_DASD T - OPEN_FLAGS_WRITE_THROUGH F - OPEN_FLAGS_FAIL_ON_ERROR C - OPEN_FLAGS_NO_CACHE H - OPEN_FLAGS_NOINHERIT b - OPEN_SHARE_DENYREADWRITE w - OPEN_SHARE_DENYWRITE r - OPEN_SHARE_DENYREAD n - OPEN_SHARE_DENYNONE R - OPEN_ACCESS_READONLY W - OPEN_ACCESS_WRITEONLY B - OPEN_ACCESS_READWRITE ═══ 18. System-Info related ═══ Functions returning OS/2 system information. ═══ 18.1. RxQProcstatus - Get Process Status Information ═══ This function returns process status information (like PSTAT). In this version of RXU (v1.5), Library, Shared-Memory and 16-Bit Semaphore information is stored differently than in the previous release (v1.4). In the previous version, if you wanted the name of a module used by a process, for instance, you would have to search through the Library array to match the module index value "stem.0p.n.0l.m", to get the module name "stem.0l.n.2". In this version, you simply get the module name by indexing into the Library array using the index value in "stem.0p.n.0l.m". Syntax: dosrc = RxQProcStatus(stemname [,flags]) where: stemname = a Rexx stem variable name under which results are mapped as such: // System Global Information stem.0G.1 = total number of threads in system stem.0G.2 = undocumented value 1 stem.0G.3 = undocumented value 2 // Process Information stem.0P.0 = number of processes stem.0P.n.1 = process-id (hex) stem.0P.n.2 = parent process-id (hex) stem.0P.n.3 = process type (hex) stem.0P.n.4 = process status (hex, followed by blank, followed by text description) stem.0P.n.5 = process screen-group/session-id (hex) stem.0P.n.6 = process module name (value of "SYSINIT" may indicate a DOS "process") stem.0P.n.0S.0 = number of 16-bit semaphores used by process stem.0P.n.0S.n = 16-bit semaphore index value (use to "hash" into list of "stem.0S.index" values) stem.0P.n.0L.0 = number of libraries statically linked by process stem.0P.n.0L.n = linked library index value (use to "hash" into list of "stem.0L.index" values) stem.0P.n.0M.0 = number of shared memory objects used by process stem.0P.n.0M.n = shared memory index value (use to "hash" into list of "stem.0M.index" values) stem.0P.n.0T.0 = number of threads in this process stem.0P.n.0T.m.1 = thread-id within process (hex) stem.0P.n.0T.m.2 = unique thread slot number (hex, system wide) stem.0P.n.0T.m.3 = sleep-id thread is sleeping on (hex) stem.0P.n.0T.m.4 = thread priority (hex) stem.0P.n.0T.m.5 = system time (# ring 0 time slices) stem.0P.n.0T.m.6 = user time (# ring 3 time slices) stem.0P.n.0T.m.7 = thread state (hex followed by text string) // 16-Bit Semaphore Information stem.0S.0 = number of 16-bit semaphore records stem.0S.0.1 = index of first semaphore (hex) stem.0S.n = semaphore index (hex, hash into using "stem.0P.n.0S.n") stem.0S.index.1 = owning slot-id (hex) stem.0S.index.3 = semaphore flag stem.0S.index.4 = reference count stem.0S.index.5 = request count stem.0S.index.6 = semaphore name // Shared Memory Object Information stem.0M.0 = number of shared memory objects stem.0M.n = memory handle (hex, hash into using "stem.0P.n.0M.n") stem.0M.index.1 = memory selector (hex) stem.0M.index.2 = reference count stem.0M.index.3 = memory name // Statically Linked Library Information stem.0L.0 = number of statically linked libraries/modules stem.0L.n = module handle (hex, hash into using "stem.0P.n.0L.n") stem.0L.index.1 = library name stem.0L.index.0I.0 = number of imported modules stem.0L.index.0I.n = imported module handle (hex, use to "hash" into list of "stem.0L.index" values) flags = flags indicating what kind of information to return, may be any combination of: M - shared memory information S - 16-bit semaphore information L - linked library information dosrc = return code from DosQProcStatus() Example: /* rexx */ /* Find out what modules each process has statically linked (1st level) */ dosrc = rxqprocstatus('q.','l') Say 'There are' q.0p.0 'processes ('q.0g.1 'threads) running right now' do j=1 to q.0p.0 say;say 'Process ('q.0p.j.1')'q.0p.j.6 'statically links the following libraries:' do r=1 to q.0p.j.0l.0 idx = q.0p.j.0l.r say ' ' q.0l.idx.1 end end exit Note: Process/Thread information is always returned, whether or not semaphore, library or shared-memory information is requested. The reason such odd compound variable index values were chosen (such as "0P", "0S", etc.) is because too long a constant index value (such as "PROC") tended to increase processing time for the function call (actual size of variable name pool is larger). The alternative, to use brief constant index values (such as "M") turned out to cause problems when I happened to be using one of these for a variable. The solution was to choose a constant index name which begins with a digit ("0" - i.e. zero), which is an invalid variable name, thus ensuring that no variable could have the same name as the constant index. This made relatively brief names (e.g. - "0M") possible and prevents "collision" with variable names your program may be using. ═══ 18.2. RxSetError - Set DosError settings ═══ This function allows you to turn HardError and Exception popup on or off. This change takes effect for the process in which it is issued, no matter what the previous setting was, by whom, or on what thread. Presently, there is no way (that I know of) to query or "reset" these error settings. Syntax: dosrc = RxSetError(flag) where: flag = any combination of: 'h' to disable HardError popup 'H' to enable HardError popup 'e' to disable Exception popup 'E' to enable Exception popup dosrc = return code from DosError() Example: Call rxseterror 'eh' /* would suppress popups from both harderror */ /* and exception conditions */ ═══ 18.3. RxReplaceModule - Replace an active .DLL or .EXE ═══ This function uses the OS/2 "DosReplaceModule()" API to replace an active .DLL or .EXE (i.e. such a module that is locked because it is currently in use). Syntax: dosrc = RxReplaceModule(oldmodname, newmodname, backupmodname) where: oldmodname = name of locked module newmodname = name of new module to replace old one backupmodname = name of backup module for recoverability dosrc = return code from DosReplaceModule() ═══ 18.4. RxExitList - Use DosExitList ═══ This function uses the OS/2 "DosExitList()" API to work with OS/2 Exit-Handlers (i.e. add/remove/exit). For more information on this function, see the OS/2 developer's reference for "DosExitList()". Syntax: dosrc = RxExitList(funcaddr [,action] [,order] ) where: funcaddr = function pointer (e.g. obtained by RxQueryProcAddr()) action = Add, Remove, Exit order = 1 byte value (0x00-0xff) indicating order for "Add" dosrc = return code from DosExitList() ═══ 18.5. RxProcId - Get process' own PID and TID information ═══ This function returns the process-id, parent process-id, and thread-id of the current thread of the current process. Syntax: procinfo = rxprocid() where: procinfo = three blank delimited integers: 1) process-id 2) parent process-id 3) thread-id ═══ 18.6. RxGetInfoBlocks - Get information about current process/thread ═══ This function returns the various pieces of information which the DosGetInfoBlocks() function returns. Syntax: dosrc = RxGetInfoBlocks(rexxstem) where: rexxstem = name of rexx stem under which information is returned as such: stem.P.1 = process-id stem.P.2 = parent process-id stem.P.3 = our .EXE's module handle stem.P.4 = pointer to command line string stem.P.5 = pointer to environment string stem.P.6 = process status bits stem.P.7 = process type code stem.T.1 = thread-id stem.T.2 = thread priority stem.T.3 = tib2 version stem.T.4 = MustComplete count stem.T.5 = MustComplete Force Flag stem.T.6 = tib version stem.T.7 = thread ordinal stem.T.8 = pointer to head of exception handler chain stem.T.9 = pointer to base of stack stem.T.10 = pointer to end of stack dosrc = return code from DosGetInfoBlocks() Note: for stem.P.4, stem.P.5, stem.T.9, and stem.T.10, you could use RxStorage() to get to the values at these addresses. ═══ 18.7. RxQueryAppType - Get information about an executable file ═══ This function returns information about the type of an executable file as indicated in that file's header. Syntax: info = RxQueryAppType(filename) where: filename = name of executable file whose type you want to know (either fully qualified, or just name and will search path) info = return code from DosQueryAppType, and if zero, followed by any combination of: N - NotSpecified w - NotWindowCompat W - WindowCompat A - WindowApi B - Bound L - DLL D - DOS Y - Physical Device Driver V - Virtual Device Driver P - Protected Memory DLL 3 - 32 Bit ═══ 18.8. RxTmrQueryFreq - Query frequency of IRQ0 high-resolution timer ═══ This function returns the frequency of the IRQ0 high-resolution (8254) timer via the DosTmrQueryFreq() API. Syntax: info = RxTmrQueryFreq() where info = two blank delimited values: 1) return code from DosTmrQueryFreq() and if return code is zero: 2) frequency of high-resolution timer in hertz (timer units/sec). ═══ 18.9. RxTmrQueryTime - Query snapshot of IRQ0 high-resolution timer value ═══ This function returns a snapshot of the value from the IRQ0 high-resolution (8254) timer via the DosTmrQueryTime() API. Syntax: info = RxTmrQueryTime() where info = two blank delimited values: 1) return code from DosTmrQueryTime() and if return code is zero: 2) two period-delimited integers indicating high-order and low-order portions of timer value, as such: high-order.low-order ═══ 18.10. RxQuerySysInfo - Query OS/2 SysInfo ═══ This function returns live system information about OS/2 via the DosQuerySysInfo API. Syntax: dosrc = RxQuerySysInfo( stemname [,startidx [,endidx]]) where stemname = Rexx stem name, under which results are returned. Each DosQuerySysInfo item is returned under the appropriate stem.n For instance, the call "call rxquerysysinfo('s.',3,5)" would set the rexx variables "s.3", "s.4", and "s.5". dosrc = return code from DosQuerySysInfo() startidx = Default is 1 endidx = Default is 23 Index values: 1. Maximum length, in bytes, of a path name. 2. Maximum number of text sessions. 3. Maximum number of PM sessions. 4. Maximum number of DOS sessions. 5. Drive from which the system was started (1 means drive A, 2 means drive B, and so on). 6. Dynamic priority variation flag (0 means absolute priority, 1 means dynamic priority). 7. Maximum wait in seconds. 8. Minimum time slice in milliseconds. 9. Maximum time slice in milliseconds. 10. Memory page size in bytes. This value is 4096 for the 80386 processor. 11. Major version number. 12. Minor version number. 13. Revision letter. 14. Value of a 32-bit, free-running millisecond counter. This value is zero when the system is started. 15. Low-order 32 bits of the time in seconds since January 1, 1970 at 0:00:00. 16. High-order 32 bits of the time in seconds since January 1, 1970 at 0:00:00. 17. Total number of pages of physical memory in the system. One page is 4KB. 18. Total number of pages of resident memory in the system. 19. Maximum number of pages of memory that can be allocated by all processes in the system. This number is advisory and is not guaranteed, since system conditions change constantly. 20. Maximum number of bytes of memory that this process can allocate in its private arena. This number is advisory and is not guaranteed, since system conditions change constantly. 21. Maximum number of bytes of memory that a process can allocate in the shared arena. This number is advisory and is not guaranteed, since system conditions change constantly. 22. Timer interval in tenths of a millisecond. 23. Maximum length, in bytes, of one component in a path name. ═══ 18.11. RxPhysicalDisk - Query information about partitionable disks ═══ This function returns information about physical disks via the DosPhysicalDisk() API. Syntax: dosrc = RxDevConfig(function, rexxvar ,retlen [,parm]) where function = function code (1,2,3) rexxvar = Rexx variable name, in which physical disk information is returned retlen = return buffer length parm = (optional) parameter to be passed to API dosrc = return code from DosPhysicalDisk() ═══ 18.12. RxDevConfig - Obtain device configuration information ═══ This function returns device configuration information using the DosDevConfig() API. Syntax: dosrc = RxDevConfig(rexxvar ,devtype [,infolen]) where rexxvar = Rexx variable name, in which device information is returned devtype = integer (currently 0-6) indicating which device to get info on infolen = if devtype > 6, length of buffer necessary to hold devinfo dosrc = return code from DosDevConfig() ═══ 18.13. RxDevIOCtl - Do DosDevIOCtl calls (to talk to character devices directly) ═══ This function allows direct communication with character devices using the DosDevIOCtl() API. Syntax: dosrc = RxDevIOCtl(rexxstem, devhandle, category, function, parmlist, retparmlen, data, retdatalen) where rexxstem = Rexx stem name, under which data is returned as such: stem.1 = parmlist returned stem.2 = dataarea returned devhandle = device handle (binary) obtained from DosOpen() category = integer indicating category function = integer indicating function parmlist = parmlist data (if zero length or "empty" string, no parmlist is passed to DosDevIOCtl()) retparmlen = length of expected parmlist returned data = dataarea data (if zero length or "empty" string, no dataarea is passed to DosDevIOCtl()) retdatalen = length of expected dataarea returned dosrc = return code from DosDevIOCtl() ═══ 19. PM / Wp related functions ═══ Functions related to PM or Workplace Shell Objects ═══ 19.1. RxWinQueryObject - Query WP-Shell Object Handle ═══ This function returns the object handle of a WorkPlace Shell object. Syntax: hobj = RxWinQueryObject(objname) where objname = name of WorkPlace Shell object hobj = handle to object (or null string if not successful) ═══ 19.2. RxWinDestroyObject - Destroy a WP-Shell Object ═══ This function destroys a WorkPlace Shell object by object handle. Syntax: yorn = RxWinDestroyObject(hobj) where hobj = handle to object yorn = "1" if it worked, "0" if it didn't