Changeset 16


Ignore:
Timestamp:
Sep 20, 2014, 1:17:51 PM (11 years ago)
Author:
Alex Taylor
Message:

Added named-pipe and I/O functions (not yet fully tested).

Location:
rxutilex/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • rxutilex/trunk/FUNCTIONS

    r4 r16  
    33(See file 'TODO' for functions which are under consideration to be added.)
    44
     5Sys2CheckNamedPipe          - Check the status of a named pipe
     6Sys2ConnectNamedPipe        - Enable client sessions on a named pipe
     7Sys2CreateNamedPipe         - Create a named pipe
     8Sys2DisconnectNamedPipe     - Acknowledge that a named pipe session has ended
    59Sys2DropFuncs               - Deregister all functions
    610Sys2FormatTime              - Format calender time (strftime wrapper)
     
    1519Sys2QueryProcess            - Get information about a process
    1620Sys2QueryProcessList        - Get the list of running processes
     21Sys2Read                    -
    1722Sys2ReplaceModule           - Unlock a DLL (DosReplaceModule wrapper)
    1823Sys2Version                 - Get the version of this library
     
    2025
    2126If an internal error occurs in any function, the variable SYS2ERR will contain
    22 an error message of the form "RC: description" where RC is a non-zero error 
     27an error message of the form "RC: description" where RC is a non-zero error
    2328code, and description indicates the internal function call that failed.  If
    2429no error occurs, SYS2ERR will be "0".
     30
     31
     32-------------------------------------------------------------------------
     33Sys2CheckNamedPipe
     34
     35Check the status of a named pipe.
     36
     37REXX ARGUMENTS:
     38  1. The pipe handle (from Sys2CreateNamedPipe or DosOpen).  (REQUIRED)
     39
     40REXX RETURN VALUE:
     41  String of the format "bytes status", where bytes is the number of bytes
     42  currently waiting in the pipe, and status is one of: DISCONNECTED,
     43  LISTENING, CONNECTED, or CLOSING.
     44
     45
     46-------------------------------------------------------------------------
     47Sys2ConnectNamedPipe
     48
     49Start 'listening' by allowing clients to connect to a previously-created
     50named pipe.
     51
     52REXX ARGUMENTS:
     53  1. The pipe handle, as returned by Sys2CreateNamedPipe.  (REQUIRED)
     54
     55REXX RETURN VALUE:
     56  1 on success, or 0 if an error occurred.
     57
     58
     59-------------------------------------------------------------------------
     60Sys2CreateNamedPipe
     61
     62Creates a named pipe with the specified name and parameters.
     63
     64Note that the standard REXX functions such as CHARIN/OUT, which operate
     65directly on file names, are not capable of using the pipe handle returned
     66from this function. While the client end can use such functions after
     67using STREAM to issue an OPEN WRITE or OPEN READ command, the host end
     68needs to use the pipe handle from this function, and must therefore use
     69Sys2Read/Sys2Write in order to read and write data from the pipe.
     70
     71REXX ARGUMENTS:
     72  1. The name of the pipe, in the form "\PIPE\something".  (REQUIRED)
     73  2. The size of the outbound buffer, in bytes.  (REQUIRED)
     74  3. The size of the inbound buffer, in bytes.  (REQUIRED)
     75  4. The pipe's timeout value, in milliseconds.  (DEFAULT: 3000)
     76  5. The number of simultaneous instances of this pipe which are allowed.
     77     Must be between 1 and 254, or 0 indicating no limit.  (DEFAULT: 1)
     78  6. Pipe blocking mode, one of:
     79       W = WAIT mode, read and write block waiting for data  (DEFAULT)
     80       N = NOWAIT mode, read and write return immediately
     81  7. Pipe mode, one of:
     82       I = Inbound pipe  (DEFAULT)
     83       O = Outbound pipe
     84       D = Duplex (inbound/outbound) pipe
     85  8. Privacy/inheritance flag, one of:
     86       0 = The pipe handle is inherited by child processes (DEFAULT)
     87       1 = The pipe handle is private to the current process
     88  9. Write-through flag, one of:
     89       0 = Allow delayed writes (write-behind) to remote pipes (DEFAULT)
     90       1 = Force immediate writes (write-through) to remote pipes
     91
     92REXX RETURN VALUE:  A four-byte pipe handle.
     93
     94
     95-------------------------------------------------------------------------
     96Sys2DisconnectNamedPipe
     97
     98Unlocks a named pipe after a client has closed its connection.
     99
     100REXX ARGUMENTS:
     101  1. The pipe handle, as returned by Sys2CreateNamedPipe.      (REQUIRED)
     102
     103REXX RETURN VALUE:
     104  1 on success, or 0 if an error occurred.
    25105
    26106
     
    91171     Years prior to 1970 or later than 2037 cannot be supported due to the
    92172     limitations in how the C library calculates epoch time.  Specifying
    93      1969 or earlier will generate a REXX error.  Any date later than 2037 
     173     1969 or earlier will generate a REXX error.  Any date later than 2037
    94174     will return a value of 0 (and SYS2ERR will report an error in 'mktime').
    95175     NOTE: A 2-digit year can be specified, in which case the number will be
    96            added to 1900 if it is 70 or higher, or to 2000 otherwise. 
     176           added to 1900 if it is 70 or higher, or to 2000 otherwise.
    97177           e.g. '20' ==> 2020
    98178                '75' ==> 1975
     
    134214
    135215-------------------------------------------------------------------------
    136 Sys2LocateDLL                                                         
    137                                                                      
    138 Searches for a DLL by name and returns its fully-qualified path. 
     216Sys2LocateDLL
     217
     218Searches for a DLL by name and returns its fully-qualified path.
    139219
    140220If a DLL with the given name is currently loaded, that instance of the
    141221DLL will be returned.  Otherwise, standard DLL loading rules (according
    142222to the current LIBPATH and/or extended LIBPATH configuration) are used to
    143 search for a DLL whose module name matches the one specified. 
    144                                                                      
    145 REXX ARGUMENTS:                                                       
    146   1. The name of the DLL to search for.  (REQUIRED)                   
    147 
    148                                                                      
    149 REXX RETURN VALUE:                                                   
    150   The fully-qualified path of the DLL, if found; "" otherwise. 
     223search for a DLL whose module name matches the one specified.
     224
     225REXX ARGUMENTS:
     226  1. The name of the DLL to search for.  (REQUIRED)
     227
     228
     229REXX RETURN VALUE:
     230  The fully-qualified path of the DLL, if found; "" otherwise.
    151231
    152232
     
    219299
    220300Gets a list of running processes.  The results will be returned in a stem
    221 variable, where stem.0 contains number of items, and each stem item is a 
     301variable, where stem.0 contains number of items, and each stem item is a
    222302string of the form:
    223303    pid parent-pid process-type priority cpu-time executable-name
     
    241321
    242322-------------------------------------------------------------------------
     323Sys2Read
     324
     325Read bytes from a previously-opened stream (wrapper to DosRead).  The
     326format of file handles supported by this function is currently limited
     327to those returned by Sys2CreateNamedPipe.
     328
     329REXX ARGUMENTS:
     330  1. File handle (as returned by Sys2CreateNamedPipe).  (REQUIRED)
     331  2. Number of bytes to read.  (REQUIRED)
     332
     333REXX RETURN VALUE:
     334  String containing the bytes read, or "" in case of error.
     335
     336
     337-------------------------------------------------------------------------
    243338Sys2ReplaceModule
    244339
  • rxutilex/trunk/Makefile

    r4 r16  
    1515
    1616$(NAME).dll : $(NAME).obj
    17                 @makedesc -D"Extra REXX Utility Functions" -N"Alex Taylor" -V"^#define=SZ_VERSION,rxutilex.c" $(NAME).def
     17                makedesc -D"Extra REXX Utility Functions" -N"Alex Taylor" -V"^#define=SZ_VERSION,rxutilex.c" $(NAME).def
    1818                $(LINK) $(LFLAGS) $(NAME).obj $(NAME).def $(LIBS) /O:$@
    1919                @dllrname.exe $@ CPPOM30=OS2OM30 /Q /R
  • rxutilex/trunk/TODO

    r4 r16  
    66 - Sys2FormatCurrency - A strfmon wrapper
    77 - Sys2GetResource - DosGetResource wrapper
    8  - Sys2PrintFile - print a file to a port or queue
     8 - Sys2PrintFile - Print a file to a port or queue
     9 - Sys2IsDirectory - Determine if filespec is a directory
    910
    1011Under consideration:
  • rxutilex/trunk/rxutilex.c

    r4 r16  
    11/******************************************************************************
    22 * REXX Utility Functions - Extended (RXUTILEX.DLL)                           *
    3  * (C) 2011 Alex Taylor.                                                      *
     3 * (C) 2011, 2014 Alex Taylor.                                                *
    44 *                                                                            *
    55 * LICENSE:                                                                   *
     
    4343#define INCL_WINCLIPBOARD
    4444#define INCL_WINERRORS
     45#define INCL_DOSERRORS
    4546#define INCL_DOSMISC
     47#define INCL_DOSMODULEMGR
     48#define INCL_DOSNMPIPES
    4649#define INCL_DOSPROCESS
    4750#define INCL_DOSPROFILE
    48 #define INCL_DOSERRORS
    49 #define INCL_DOSMODULEMGR
    5051#ifndef OS2_INCLUDED
    5152    #include <os2.h>
     
    7273#define SZ_LIBRARY_NAME         "RXUTILEX"  // Name of this library
    7374#define SZ_ERROR_NAME           "SYS2ERR"   // REXX variable used to store error codes
    74 #define SZ_VERSION              "0.0.4"     // Current version of this library
     75#define SZ_VERSION              "0.0.5"     // Current version of this library
    7576
    7677// Maximum string lengths...
    7778#define US_COMPOUND_MAXZ        250                                  // ...of a compound variable
    78 #define US_INTEGER_MAXZ         12                                   // ...of an integer string
     79#define US_INTEGER_MAXZ         12                                   // ...of a 32-bit integer string
     80#define US_LONGLONG_MAXZ        21                                   // ...of a 64-bit integer string
    7981#define US_STEM_MAXZ          ( US_COMPOUND_MAXZ - US_INTEGER_MAXZ ) // ...of a stem
    8082#define US_ERRSTR_MAXZ          250                                  // ...of an error string
    8183#define US_PIDSTR_MAXZ        ( CCHMAXPATH + 100 )                   // ...of a process information string
    8284#define US_TIMESTR_MAXZ         256                                  // ...of a formatted time string
     85#define US_PIPESTATUS_MAXZ      128                                  // ...of a pipe status string
    8386
    8487#define UL_SSBUFSIZE            0xFFFF      // Buffer size for the DosQuerySysState() data
     
    104107    "Sys2ReplaceModule",
    105108    "Sys2LocateDLL",
     109    "Sys2CreateNamedPipe",
     110    "Sys2ConnectNamedPipe",
     111    "Sys2DisconnectNamedPipe",
     112    "Sys2CheckNamedPipe",
     113    "Sys2Open",
     114    "Sys2Close",
     115    "Sys2Seek",
     116    "Sys2Read",
     117    "Sys2Write",
    106118    "Sys2Version"
    107119};
     
    120132RexxFunctionHandler Sys2GetClipboardText;
    121133RexxFunctionHandler Sys2PutClipboardText;
    122 // RexxFunctionHandler Sys2GetClipboardData;
    123 // RexxFunctionHandler Sys2PutClipboardData;
    124134
    125135RexxFunctionHandler Sys2QueryProcess;
     
    133143RexxFunctionHandler Sys2ReplaceModule;
    134144
    135 RexxFunctionHandler Sys2ReplaceObjectClass;
     145// RexxFunctionHandler Sys2ReplaceObjectClass;
     146
     147RexxFunctionHandler Sys2CreateNamedPipe;
     148RexxFunctionHandler Sys2ConnectNamedPipe;
     149RexxFunctionHandler Sys2DisconnectNamedPipe;
     150RexxFunctionHandler Sys2CheckNamedPipe;
     151
     152RexxFunctionHandler Sys2Open;
     153RexxFunctionHandler Sys2Close;
     154RexxFunctionHandler Sys2Seek;
     155RexxFunctionHandler Sys2Read;
     156RexxFunctionHandler Sys2Write;
    136157
    137158
     
    301322        if ( ulRC == 0 ) {
    302323            memset( pszShareMem, 0, ulBytes );
    303             strncpy( pszShareMem, argv[0].strptr , ulBytes - 1 );
     324            strncpy( pszShareMem, argv[0].strptr, ulBytes - 1 );
    304325            if ( ! WinSetClipbrdData( hab, (ULONG) pszShareMem, CF_TEXT, CFI_POINTER ))
    305326                WriteErrorCode( ERRORIDERROR(WinGetLastError(hab)), "WinSetClipbrdData");
     
    11371158            WriteErrorCode( timeval, "time");
    11381159            MAKERXSTRING( *prsResult, "0", 1 );
     1160            free( pszSetTZ );
    11391161            return 0;
    11401162        }
     
    11531175            WriteErrorCode( timeval, "mktime");
    11541176            MAKERXSTRING( *prsResult, "0", 1 );
     1177            free( pszSetTZ );
    11551178            return 0;
    11561179        }
     
    12241247}
    12251248
     1249
     1250/* ------------------------------------------------------------------------- *
     1251 * Sys2CreateNamedPipe                                                       *
     1252 *                                                                           *
     1253 * Create a named pipe with the specified name and parameters.  Only byte    *
     1254 * mode is supported; message mode is not.                                   *
     1255 *                                                                           *
     1256 * REXX ARGUMENTS:                                                           *
     1257 *   1. The name of the pipe, in the form "\PIPE\something".      (REQUIRED) *
     1258 *   2. The size of the outbound buffer, in bytes.                (REQUIRED) *
     1259 *   3. The size of the inbound buffer, in bytes.                 (REQUIRED) *
     1260 *   4. The pipe's timeout value, in milliseconds.           (DEFAULT: 3000) *
     1261 *   5. The number of simultaneous instances of this pipe which are allowed. *
     1262 *      Must be between 1 and 254, or 0 indicating no limit.    (DEFAULT: 1) *
     1263 *   6. Pipe blocking mode, one of:                                          *
     1264 *        W = WAIT mode, read and write block waiting for data.    (DEFAULT) *
     1265 *        N = NOWAIT mode, read and write return immediately.                *
     1266 *   7. Pipe mode, one of:                                                   *
     1267 *        I = Inbound pipe                                         (DEFAULT) *
     1268 *        O = Outbound pipe                                                  *
     1269 *        D = Duplex (inbound/outbound) pipe                                 *
     1270 *   8. Privacy/inheritance flag, one of:                                    *
     1271 *        0 = The pipe handle is inherited by child processes.     (DEFAULT) *
     1272 *        1 = The pipe handle is private to the current process.             *
     1273 *   9. Write-through flag, one of:                                          *
     1274 *        0 = Allow delayed writes (write-behind) to remote pipes. (DEFAULT) *
     1275 *        1 = Force immediate writes (write-through) to remote pipes.        *
     1276 *                                                                           *
     1277 * REXX RETURN VALUE:                                                        *
     1278 *   A four-byte pipe handle.                                                *
     1279 * ------------------------------------------------------------------------- */
     1280ULONG APIENTRY Sys2CreateNamedPipe( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     1281{
     1282    HPIPE   hp;
     1283    PSZ     pszNPName;
     1284    LONG    iLimit;
     1285    ULONG   ulBufOut,
     1286            ulBufIn,
     1287            ulTimeout = 3000,
     1288            flOpen    = 0,
     1289            flPipe    = 1;
     1290    CHAR    achHandle[ 9 ];
     1291    APIRET  rc;
     1292
     1293    // Reset the error indicator
     1294    WriteErrorCode( 0, NULL );
     1295
     1296    // Make sure we have at least three valid arguments (pipe name and sizes)
     1297    if ( argc < 3  || ( !RXVALIDSTRING(argv[0]) ) ||
     1298        ( !RXVALIDSTRING(argv[1]) ) || ( !RXVALIDSTRING(argv[2]) ))
     1299        return ( 40 );
     1300
     1301    // (Validate the first argument last to simplify error processing)
     1302
     1303    // Second argument: pipe outbound buffer size
     1304    if (( sscanf( argv[1].strptr, "%u", &ulBufOut )) != 1 ) return ( 40 );
     1305
     1306    // Third argument: pipe outbound buffer size
     1307    if (( sscanf( argv[2].strptr, "%u", &ulBufIn )) != 1 ) return ( 40 );
     1308
     1309    // Fourth argument: pipe timeout value
     1310    if ( argc >= 4 && RXVALIDSTRING(argv[3]) ) {
     1311        if (( sscanf( argv[3].strptr, "%u", &ulTimeout )) != 1 ) return ( 40 );
     1312    }
     1313
     1314    // Fifth argument: instances limit
     1315    if ( argc >= 5 && RXVALIDSTRING(argv[4]) ) {
     1316        if (( sscanf( argv[4].strptr, "%d", &iLimit )) != 1 ) return ( 40 );
     1317        if (( iLimit > 1 ) && ( iLimit < 255 ))
     1318            flPipe = iLimit;
     1319        else if ( !iLimit || ( iLimit == -1 ))
     1320            flPipe = NP_UNLIMITED_INSTANCES;
     1321        else
     1322            return ( 40 );
     1323    }
     1324
     1325    // Sixth argument: blocking mode
     1326    if ( argc >= 6 && RXVALIDSTRING(argv[5]) ) {
     1327        strupr( argv[5].strptr );
     1328        if ( argv[5].strptr[0] == 'N' )
     1329            flPipe |= NP_NOWAIT;
     1330        else if ( argv[5].strptr[0] != 'W' )
     1331            return ( 40 );
     1332    }
     1333
     1334    // Seventh argument: pipe mode (direction)
     1335    if ( argc >= 7 && RXVALIDSTRING(argv[6]) ) {
     1336        strupr( argv[6].strptr );
     1337        if (strcspn(argv[6].strptr, "IOD") > 0 ) return ( 40 );
     1338        switch ( argv[6].strptr[0] ) {
     1339            case 'O': flOpen |= NP_ACCESS_OUTBOUND; break;
     1340            case 'D': flOpen |= NP_ACCESS_DUPLEX;   break;
     1341            default : break;            // default is 0
     1342        }
     1343    }
     1344
     1345    // Eighth argument: inheritance mode
     1346    if ( argc >= 8 && RXVALIDSTRING(argv[7]) ) {
     1347        strupr( argv[7].strptr );
     1348        if ( argv[7].strptr[0] == '1' )
     1349            flOpen |= NP_NOINHERIT;
     1350        else if ( argv[7].strptr[0] != '0' )
     1351            return ( 40 );
     1352    }
     1353
     1354    // Ninth argument: write mode
     1355    if ( argc >= 9 && RXVALIDSTRING(argv[8]) ) {
     1356        strupr( argv[8].strptr );
     1357        if ( argv[8].strptr[0] == '1' )
     1358            flOpen |= NP_NOWRITEBEHIND;
     1359        else if ( argv[8].strptr[0] != '0' )
     1360            return ( 40 );
     1361    }
     1362
     1363    // Now the first argument: pipe name
     1364    pszNPName = (PSZ) calloc( RXSTRLEN(argv[0]) + 1, sizeof(UCHAR) );
     1365    if ( pszNPName == NULL ) {
     1366        WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "calloc");
     1367        MAKERXSTRING( *prsResult, "0", 1 );
     1368        return ( 0 );
     1369    }
     1370    strncpy( pszNPName, argv[0].strptr, RXSTRLEN(argv[0]) );
     1371
     1372    // All good, now create the pipe
     1373    rc = DosCreateNPipe( pszNPName, &hp, flOpen, flPipe, ulBufOut, ulBufIn, ulTimeout );
     1374    if (rc) {
     1375        WriteErrorCode( rc, "DosCreateNPipe");
     1376        MAKERXSTRING( *prsResult, "", 0 );
     1377        return 0;
     1378    }
     1379
     1380    // Return the handle as the REXX result string
     1381    sprintf( achHandle, "%8X", hp );
     1382    MAKERXSTRING( *prsResult, achHandle, strlen( achHandle ));
     1383
     1384    free( pszNPName );
     1385    return ( 0 );
     1386}
     1387
     1388
     1389/* ------------------------------------------------------------------------- *
     1390 * Sys2ConnectNamedPipe                                                      *
     1391 *                                                                           *
     1392 * Start 'listening' by allowing clients to connect to a previously-created  *
     1393 * named pipe.                                                               *
     1394 *                                                                           *
     1395 * REXX ARGUMENTS:                                                           *
     1396 *   1. The pipe handle, as returned by Sys2CreateNamedPipe.      (REQUIRED) *
     1397 *                                                                           *
     1398 * REXX RETURN VALUE:                                                        *
     1399 *   1 on success, or 0 if an error occurred.                                *
     1400 * ------------------------------------------------------------------------- */
     1401ULONG APIENTRY Sys2ConnectNamedPipe( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     1402{
     1403    HPIPE   hp;
     1404    APIRET  rc;
     1405
     1406    // Reset the error indicator
     1407    WriteErrorCode( 0, NULL );
     1408
     1409    // Parse the handle
     1410    if ( !(argc == 1 && RXVALIDSTRING(argv[0])) ) return ( 40 );
     1411    if (( sscanf( argv[0].strptr, "%8X", &hp )) != 1 ) return ( 40 );
     1412
     1413    // Connect the pipe
     1414    rc = DosConnectNPipe( hp );
     1415    if ( rc != NO_ERROR ) {
     1416        WriteErrorCode( rc, "DosConnectNPipe");
     1417        MAKERXSTRING( *prsResult, "0", 1 );
     1418        return ( 0 );
     1419    }
     1420
     1421    // Return 1 on success
     1422    MAKERXSTRING( *prsResult, "1", 1 );
     1423    return ( 0 );
     1424}
     1425
     1426
     1427/* ------------------------------------------------------------------------- *
     1428 * Sys2DisconnectNamedPipe                                                   *
     1429 *                                                                           *
     1430 * Unlocks a named pipe after a client has closed its connection.            *
     1431 *                                                                           *
     1432 * REXX ARGUMENTS:                                                           *
     1433 *   1. The pipe handle, as returned by Sys2CreateNamedPipe.      (REQUIRED) *
     1434 *                                                                           *
     1435 * REXX RETURN VALUE:                                                        *
     1436 *   1 on success, or 0 if an error occurred.                                *
     1437 * ------------------------------------------------------------------------- */
     1438ULONG APIENTRY Sys2DisconnectNamedPipe( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     1439{
     1440    HPIPE   hp;
     1441    APIRET  rc;
     1442
     1443    // Reset the error indicator
     1444    WriteErrorCode( 0, NULL );
     1445
     1446    // Parse the handle
     1447    if ( !(argc == 1 && RXVALIDSTRING(argv[0])) ) return ( 40 );
     1448    if (( sscanf( argv[0].strptr, "%8X", &hp )) != 1 ) return ( 40 );
     1449
     1450    // Connect the pipe
     1451    rc = DosDisConnectNPipe( hp );
     1452    if ( rc != NO_ERROR ) {
     1453        WriteErrorCode( rc, "DosDisConnectNPipe");
     1454        MAKERXSTRING( *prsResult, "0", 1 );
     1455        return ( 0 );
     1456    }
     1457
     1458    // Return 1 on success
     1459    MAKERXSTRING( *prsResult, "1", 1 );
     1460    return ( 0 );
     1461}
     1462
     1463
     1464/* ------------------------------------------------------------------------- *
     1465 * Sys2CheckNamedPipe                                                        *
     1466 *                                                                           *
     1467 * Check the status of a named pipe.                                         *
     1468 *                                                                           *
     1469 * REXX ARGUMENTS:                                                           *
     1470 *   1. The pipe handle (from Sys2CreateNamedPipe or DosOpen).    (REQUIRED) *
     1471 *                                                                           *
     1472 * REXX RETURN VALUE:                                                        *
     1473 *   String of the format "bytes status", where bytes is the number of bytes *
     1474 *   currently waiting in the pipe, and status is one of: DISCONNECTED,      *
     1475 *   LISTENING, CONNECTED, or CLOSING.                                       *
     1476 * ------------------------------------------------------------------------- */
     1477ULONG APIENTRY Sys2CheckNamedPipe( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     1478{
     1479    HPIPE     hp;
     1480    ULONG     cbActual, ulState;
     1481    AVAILDATA avd;
     1482    CHAR      szStatus[ US_PIPESTATUS_MAXZ ];
     1483    APIRET    rc;
     1484
     1485    // Reset the error indicator
     1486    WriteErrorCode( 0, NULL );
     1487
     1488    // Parse the handle
     1489    if ( !(argc == 1 && RXVALIDSTRING(argv[0])) ) return ( 40 );
     1490    if (( sscanf( argv[0].strptr, "%8X", &hp )) != 1 ) return ( 40 );
     1491
     1492    rc = DosPeekNPipe( hp, NULL, 0, &cbActual, &avd, &ulState );
     1493    if ( rc != NO_ERROR ) {
     1494        WriteErrorCode( rc, "DosPeekNPipe");
     1495        MAKERXSTRING( *prsResult, "", 0 );
     1496        return ( 0 );
     1497    }
     1498    sprintf( szStatus, "%u ", avd.cbpipe );
     1499    switch ( ulState ) {
     1500        case NP_STATE_DISCONNECTED: strncat( szStatus, "DISCONNECTED", US_PIPESTATUS_MAXZ-1 ); break;
     1501        case NP_STATE_LISTENING:    strncat( szStatus, "LISTENING",    US_PIPESTATUS_MAXZ-1 ); break;
     1502        case NP_STATE_CONNECTED:    strncat( szStatus, "CONNECTED",    US_PIPESTATUS_MAXZ-1 ); break;
     1503        case NP_STATE_CLOSING:      strncat( szStatus, "CLOSING",      US_PIPESTATUS_MAXZ-1 ); break;
     1504        default:                    strncat( szStatus, "UNKNOWN",      US_PIPESTATUS_MAXZ-1 ); break;
     1505    }
     1506
     1507    if ( ! SaveResultString( prsResult, szStatus, strlen( szStatus ))) {
     1508        MAKERXSTRING( *prsResult, "", 0 );
     1509    }
     1510    return ( 0 );
     1511}
     1512
     1513
     1514/* ------------------------------------------------------------------------- *
     1515 * Sys2Open                                                                  *
     1516 *                                                                           *
     1517 * Wrapper to DosOpenL: open a file or stream (with >2GB support).           *
     1518 * Direct-DASD mode is not supported by this function, nor is setting the    *
     1519 * initial extended attributes.                                              *
     1520 *                                                                           *
     1521 * REXX ARGUMENTS:                                                           *
     1522 *   1. Name of file or stream to open.                           (REQUIRED) *
     1523 *   2. Open action flags, must be either "O" (open if exists), "R" (replace *
     1524 *      if exists), or nothing (fail if exists), optionally followed by "C"  *
     1525 *      (create if file does not exist).  If "C" is not specified, the       *
     1526 *      operation will fail if the file does not exist.  Note that a value   *
     1527 *      of "" alone will therefore fail automatically.        (DEFAULT: "O") *
     1528 *      In summary, the possible combinations are:                           *
     1529 *        O = Open only (if file exists, open it; if not, fail)              *
     1530 *        OC= Open/create (if file exists, open it; if not, create it)       *
     1531 *        R = Replace only (if file exists, replace it; if not, fail)        *
     1532 *        RC= Replace/create (if file exists, replace it; if not, create it) *
     1533 *        C = Create only (if file exists, fail; if not, create it)          *
     1534 *        (empty) = No-op (if file exists, fail; if not, fail)               *
     1535 *   3. Access mode flags, one or both of:                   (DEFAULT: "RW") *
     1536 *        R = Open file with read access.                                    *
     1537 *        W = Open file with write access.                                   *
     1538 *   4. Sharing mode flags, any combination of:               (DEFAULT: "W") *
     1539 *        R = Deny read access to other processes                            *
     1540 *        W = Deny write access to other processes                           *
     1541 *   5. Deny legacy DosOpen access, one of:                                  *
     1542 *        0 = Allow DosOpen to access the file                     (DEFAULT) *
     1543 *        1 = Deny access using the DosOpen API                              *
     1544 *   6. Privacy/inheritance flag, one of:                                    *
     1545 *        0 = The file handle is inherited by child processes.     (DEFAULT) *
     1546 *        1 = The file handle is private to the current process.             *
     1547 *   7. Initial file attributes when creating a file:          (DEFAULT: "") *
     1548 *        A = Archive attribute set                                          *
     1549 *        D = Directory attribute set                                        *
     1550 *        S = System attribute set                                           *
     1551 *        H = Hidden attribute set                                           *
     1552 *        R = Read-only attribute set                                        *
     1553 *   8. Initial file size when creating or replacing a file; ignored if      *
     1554 *      access mode is read-only.                               (DEFAULT: 0) *
     1555 *   9. I/O mode flags, any or all of:                         (DEFAULT: "") *
     1556 *       T = Write-through mode (default is normal write)                    *
     1557 *       N = No-cache mode (default is to use filesystem cache)              *
     1558 *       S = Sequential access                                               *
     1559 *       R = Random access                                                   *
     1560 *          * S and R can combine as follows:                                *
     1561 *              Neither: No locality known (default)                         *
     1562 *              S only:  Mainly sequential access                            *
     1563 *              R only:  Mainly random access                                *
     1564 *              Both:    Random/sequential (i.e. random with some locality)  *
     1565 *                                                                           *
     1566 * REXX RETURN VALUE:                                                        *
     1567 *   File handle, or "" in case of error.                                    *
     1568 * ------------------------------------------------------------------------- */
     1569ULONG APIENTRY Sys2Open( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     1570{
     1571    PSZ      pszFile;
     1572    HFILE    hf;
     1573    ULONG    fsAction = 0,
     1574             fsMode   = 0,
     1575             ulResult = 0,
     1576             ulAttr   = FILE_NORMAL;
     1577    LONGLONG llSize   = {0};
     1578    CHAR     achHandle[ 9 ];
     1579    APIRET   rc;
     1580
     1581
     1582    // Reset the error indicator
     1583    WriteErrorCode( 0, NULL );
     1584
     1585    // Make sure we have at least one valid argument (the file name)
     1586    if ( argc < 1  || ( !RXVALIDSTRING(argv[0]) ))
     1587        return ( 40 );
     1588
     1589    // (Validate the first argument last to simplify error processing)
     1590
     1591    // Second argument: open action
     1592    if ( argc >= 2 && RXVALIDSTRING(argv[1]) ) {
     1593        strupr( argv[1].strptr );
     1594        if ( strcspn(argv[1].strptr, "OCR") > 0 ) return ( 40 );
     1595        if ( strchr(argv[1].strptr, 'O'))
     1596            fsAction |= OPEN_ACTION_OPEN_IF_EXISTS;
     1597        else if ( strchr(argv[1].strptr, 'R'))
     1598            fsAction |= OPEN_ACTION_REPLACE_IF_EXISTS;
     1599        if ( strchr(argv[1].strptr, 'C'))
     1600            fsAction |= OPEN_ACTION_CREATE_IF_NEW;
     1601    }
     1602    else
     1603        fsAction = OPEN_ACTION_OPEN_IF_EXISTS;
     1604
     1605    // Third argument: access mode
     1606    if ( argc >= 3 && RXVALIDSTRING(argv[2]) ) {
     1607        strupr( argv[2].strptr );
     1608        if ( strcspn(argv[2].strptr, "RW") > 0 ) return ( 40 );
     1609        if ( strchr(argv[2].strptr, 'R')) {
     1610            if (strchr(argv[2].strptr, 'W'))
     1611                fsMode = OPEN_ACCESS_READWRITE;
     1612            else
     1613                fsMode = OPEN_ACCESS_READONLY;
     1614        }
     1615        else if (strchr(argv[2].strptr, 'W'))
     1616            fsMode = OPEN_ACCESS_WRITEONLY;
     1617        else
     1618            return ( 40 );
     1619    }
     1620    else
     1621        fsMode = OPEN_ACCESS_READWRITE;
     1622
     1623    // Fourth argument: sharing mode
     1624    if ( argc >= 4 && RXVALIDSTRING(argv[3]) ) {
     1625        strupr( argv[3].strptr );
     1626        if ( strcspn(argv[3].strptr, "RW") > 0 ) return ( 40 );
     1627        if ( strchr(argv[3].strptr, 'R')) {
     1628            if (strchr(argv[3].strptr, 'W'))
     1629                fsMode |= OPEN_SHARE_DENYREADWRITE;
     1630            else
     1631                fsMode |= OPEN_SHARE_DENYREAD;
     1632        }
     1633        else if (strchr(argv[3].strptr, 'W'))
     1634            fsMode |= OPEN_SHARE_DENYWRITE;
     1635        else
     1636            fsMode |= OPEN_SHARE_DENYNONE;
     1637    }
     1638    else
     1639        fsMode |= OPEN_SHARE_DENYWRITE;
     1640
     1641    // Fifth argument: deny legacy mode
     1642    if ( argc >= 5 && RXVALIDSTRING(argv[4]) ) {
     1643        strupr( argv[4].strptr );
     1644        if ( argv[4].strptr[0] == '1' )
     1645            fsMode |= OPEN_SHARE_DENYLEGACY;
     1646        else if ( argv[4].strptr[0] != '0' )
     1647            return ( 40 );
     1648    }
     1649
     1650    // Sixth argument: inheritance mode
     1651    if ( argc >= 6 && RXVALIDSTRING(argv[5]) ) {
     1652        strupr( argv[5].strptr );
     1653        if ( argv[5].strptr[0] == '1' )
     1654            fsMode |= OPEN_FLAGS_NOINHERIT;
     1655        else if ( argv[5].strptr[0] != '0' )
     1656            return ( 40 );
     1657    }
     1658
     1659    // Seventh argument: attributes
     1660    if ( argc >= 7 && RXVALIDSTRING(argv[6]) ) {
     1661        strupr( argv[6].strptr );
     1662        if (strcspn(argv[6].strptr, "ADSHR") > 0 ) return ( 40 );
     1663        if ( strchr(argv[6].strptr, 'A')) ulAttr |= FILE_ARCHIVED;
     1664        if ( strchr(argv[6].strptr, 'D')) ulAttr |= FILE_DIRECTORY;
     1665        if ( strchr(argv[6].strptr, 'S')) ulAttr |= FILE_SYSTEM;
     1666        if ( strchr(argv[6].strptr, 'H')) ulAttr |= FILE_HIDDEN;
     1667        if ( strchr(argv[6].strptr, 'R')) ulAttr |= FILE_READONLY;
     1668    }
     1669
     1670    // Eighth argument: initial size
     1671    if ( argc >= 8 && RXVALIDSTRING(argv[7]) ) {
     1672        if (( sscanf( argv[7].strptr, "%lld", &llSize )) != 1 ) return ( 40 );
     1673    }
     1674
     1675    // Ninth argument: I/O mode flags
     1676    if ( argc >= 9 && RXVALIDSTRING(argv[8]) ) {
     1677        strupr( argv[8].strptr );
     1678        if (strcspn(argv[8].strptr, "TNSR") > 0 ) return ( 40 );
     1679        if ( strchr(argv[8].strptr, 'T')) fsMode |= OPEN_FLAGS_WRITE_THROUGH;
     1680        if ( strchr(argv[8].strptr, 'N')) fsMode |= OPEN_FLAGS_NO_CACHE;
     1681        if ( strchr(argv[8].strptr, 'S')) fsMode |= OPEN_FLAGS_SEQUENTIAL;
     1682        if ( strchr(argv[8].strptr, 'R')) fsMode |= OPEN_FLAGS_RANDOM;
     1683    }
     1684
     1685    // Now the first argument: file name
     1686    pszFile = (PSZ) calloc( RXSTRLEN(argv[0]) + 1, sizeof(UCHAR) );
     1687    if ( pszFile == NULL ) {
     1688        WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "calloc");
     1689        MAKERXSTRING( *prsResult, "0", 1 );
     1690        return ( 0 );
     1691    }
     1692    strncpy( pszFile, argv[0].strptr, RXSTRLEN(argv[0]) );
     1693
     1694    // Try and open the file
     1695    rc = DosOpenL( pszFile, &hf, &ulResult, llSize, ulAttr, fsAction, fsMode, NULL );
     1696    if (rc) {
     1697        WriteErrorCode( rc, "DosOpenL");
     1698        MAKERXSTRING( *prsResult, "", 0 );
     1699        free( pszFile );
     1700        return ( 0 );
     1701    }
     1702
     1703    // Return the handle as the REXX result string
     1704    sprintf( achHandle, "%8X", hf );
     1705    MAKERXSTRING( *prsResult, achHandle, strlen( achHandle ));
     1706
     1707    free( pszFile );
     1708    return ( 0 );
     1709}
     1710
     1711
     1712/* ------------------------------------------------------------------------- *
     1713 * Sys2Close                                                                 *
     1714 *                                                                           *
     1715 * Wrapper to DosWrite: write bytes to a previously-opened stream.           *
     1716 *                                                                           *
     1717 * REXX ARGUMENTS:                                                           *
     1718 *   1. File handle (returned by Sys2Open)                        (REQUIRED) *
     1719 *                                                                           *
     1720 * REXX RETURN VALUE:                                                        *
     1721 *   1 on success, or 0 if an error occurred.                                *
     1722 * ------------------------------------------------------------------------- */
     1723ULONG APIENTRY Sys2Close( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     1724{
     1725    HFILE  hf;
     1726    APIRET rc;
     1727
     1728    // Reset the error indicator
     1729    WriteErrorCode( 0, NULL );
     1730
     1731    // Make sure we have exactly one valid argument (the file handle)
     1732    if ( argc != 1  || ( !RXVALIDSTRING(argv[0]) ))
     1733        return ( 40 );
     1734    if (( sscanf( argv[0].strptr, "%8X", &hf )) != 1 ) return ( 40 );
     1735
     1736    // Close the file
     1737    rc = DosClose( hf );
     1738    if ( rc != NO_ERROR ) {
     1739        WriteErrorCode( rc, "DosClose");
     1740        MAKERXSTRING( *prsResult, "0", 1 );
     1741    }
     1742    else {
     1743        MAKERXSTRING( *prsResult, "1", 1 );
     1744    }
     1745
     1746    return ( 0 );
     1747}
     1748
     1749
     1750/* ------------------------------------------------------------------------- *
     1751 * Sys2Seek                                                                  *
     1752 *                                                                           *
     1753 * Wrapper to DosSetFilePtrL: move the read/write pointer to the specified   *
     1754 * location in a stream.                                                     *
     1755 *                                                                           *
     1756 * REXX ARGUMENTS:                                                           *
     1757 *   1. File handle (returned by Sys2Open)                        (REQUIRED) *
     1758 *   2. The signed distance in bytes to move                      (REQUIRED) *
     1759 *   3. Move method, one of:                                                 *
     1760 *        B = Beginning of file                                              *
     1761 *        C = Current position (DEFAULT)                                     *
     1762 *        E = End of file                                                    *
     1763 *                                                                           *
     1764 * REXX RETURN VALUE:                                                        *
     1765 *   The new file position, in bytes.                                        *
     1766 * ------------------------------------------------------------------------- */
     1767ULONG APIENTRY Sys2Seek( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     1768{
     1769    HFILE    hf;
     1770    LONGLONG llPos,
     1771             llActual;
     1772    ULONG    ulMethod = FILE_CURRENT;
     1773    CHAR     achActual[ US_LONGLONG_MAXZ ];
     1774    APIRET   rc;
     1775
     1776    // Reset the error indicator
     1777    WriteErrorCode( 0, NULL );
     1778
     1779    // Make sure we have at least two valid arguments
     1780    if ( argc < 2 || ( !RXVALIDSTRING(argv[0]) ) || ( !RXVALIDSTRING(argv[1]) ))
     1781        return ( 40 );
     1782
     1783    // First argument: file handle
     1784    if (( sscanf( argv[0].strptr, "%8X", &hf )) != 1 ) return ( 40 );
     1785
     1786    // Second argument: requested offset
     1787    if (( sscanf( argv[1].strptr, "%lld", &llPos )) != 1 ) return ( 40 );
     1788
     1789    // Third argument: starting position
     1790    if ( argc >= 3 && RXVALIDSTRING(argv[2]) ) {
     1791        strupr( argv[2].strptr );
     1792        if ( strcspn(argv[2].strptr, "BCE") > 0 ) return ( 40 );
     1793        switch ( argv[1].strptr[0] ) {
     1794            case 'B': ulMethod = FILE_BEGIN;   break;
     1795            case 'E': ulMethod = FILE_END;     break;
     1796            default : ulMethod = FILE_CURRENT; break;
     1797        }
     1798    }
     1799
     1800    rc = DosSetFilePtrL( hf, llPos, ulMethod, &llActual );
     1801    if ( rc != NO_ERROR ) {
     1802        WriteErrorCode( rc, "DosSetFilePtrL");
     1803        MAKERXSTRING( *prsResult, "", 0 );
     1804        return ( 0 );
     1805    }
     1806
     1807    // Return the new position as the REXX result string
     1808    sprintf( achActual, "%lld", llActual );
     1809    MAKERXSTRING( *prsResult, achActual, strlen( achActual ));
     1810
     1811    return ( 0 );
     1812}
     1813
     1814
     1815/* ------------------------------------------------------------------------- *
     1816 * Sys2Read                                                                  *
     1817 *                                                                           *
     1818 * Wrapper to DosRead: read bytes from a previously-opened stream.           *
     1819 *                                                                           *
     1820 * REXX ARGUMENTS:                                                           *
     1821 *   1. File handle (returned by Sys2Open or Sys2CreateNamedPipe) (REQUIRED) *
     1822 *   2. Number of bytes to read                                   (REQUIRED) *
     1823 *                                                                           *
     1824 * REXX RETURN VALUE:                                                        *
     1825 *   String containing the bytes read, or "" in case of error.               *
     1826 * ------------------------------------------------------------------------- */
     1827ULONG APIENTRY Sys2Read( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     1828{
     1829    HFILE  hf;
     1830    ULONG  cb,
     1831           cbActual;
     1832    PSZ    pszData;
     1833    APIRET rc;
     1834
     1835    // Reset the error indicator
     1836    WriteErrorCode( 0, NULL );
     1837
     1838    // Make sure we have two valid arguments
     1839    if ( argc != 2  || ( !RXVALIDSTRING(argv[0]) ) || ( !RXVALIDSTRING(argv[1]) ))
     1840        return ( 40 );
     1841
     1842    // First argument: handle
     1843    if (( sscanf( argv[0].strptr, "%8X", &hf )) != 1 ) return ( 40 );
     1844
     1845    // Second argument: number of bytes to read
     1846    if (( sscanf( argv[1].strptr, "%u", &cb )) != 1 ) return ( 40 );
     1847    if ( cb < 1 ) return ( 40 );
     1848    pszData = (PSZ) malloc( cb );
     1849
     1850    rc = DosRead( hf, pszData, cb, &cbActual );
     1851    if ( rc || !cbActual ) {
     1852        WriteErrorCode( rc, "DosRead");
     1853        MAKERXSTRING( *prsResult, "", 0 );
     1854        goto cleanup;
     1855    }
     1856    if ( ! SaveResultString( prsResult, pszData, cbActual )) {
     1857        MAKERXSTRING( *prsResult, "", 0 );
     1858    }
     1859
     1860cleanup:
     1861    free( pszData );
     1862    return ( 0 );
     1863}
     1864
     1865
     1866/* ------------------------------------------------------------------------- *
     1867 * Sys2Write                                                                 *
     1868 *                                                                           *
     1869 * Wrapper to DosWrite: write bytes to a previously-opened stream.           *
     1870 *                                                                           *
     1871 * REXX ARGUMENTS:                                                           *
     1872 *   1. File handle (returned by Sys2Open or Sys2CreateNamedPipe) (REQUIRED) *
     1873 *   2. Data to be written                                        (REQUIRED) *
     1874 *                                                                           *
     1875 * REXX RETURN VALUE:                                                        *
     1876 *   1 on success, or 0 if an error occurred.                                *
     1877 * ------------------------------------------------------------------------- */
     1878ULONG APIENTRY Sys2Write( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     1879{
     1880    HFILE  hf;
     1881    ULONG  cbActual;
     1882    APIRET rc;
     1883
     1884    // Reset the error indicator
     1885    WriteErrorCode( 0, NULL );
     1886
     1887    // Make sure we have two valid arguments
     1888    if ( argc != 2  || ( !RXVALIDSTRING(argv[0]) ) || ( !RXVALIDSTRING(argv[1]) ))
     1889        return ( 40 );
     1890
     1891    // First argument: handle
     1892    if (( sscanf( argv[0].strptr, "%8X", &hf )) != 1 ) return ( 40 );
     1893
     1894    // (Second argument can be left in standard RXSTRING form)
     1895
     1896    rc = DosWrite( hf, argv[0].strptr, argv[0].strlength, &cbActual );
     1897    if ( rc != NO_ERROR ) {
     1898        WriteErrorCode( rc, "DosWrite");
     1899        MAKERXSTRING( *prsResult, "0", 1 );
     1900    }
     1901    else {
     1902        MAKERXSTRING( *prsResult, "1", 1 );
     1903    }
     1904
     1905    return ( 0 );
     1906}
    12261907
    12271908
  • rxutilex/trunk/rxutilex.def

    r4 r16  
    11LIBRARY     RXUTILEX INITINSTANCE TERMINSTANCE
    22DATA        MULTIPLE NONSHARED
    3 DESCRIPTION '@#Alex Taylor:0.0.4#@##1## 3 Apr 2013 22:02:22      REINFORCE::::::@@Extra REXX Utility Functions'
     3DESCRIPTION '@#Alex Taylor:0.0.5#@##1## 20 Sep 2014 20:12:24     REINFORCE::::::@@Extra REXX Utility Functions'
    44
    55EXPORTS     Sys2LoadFuncs
     
    1717Sys2ReplaceModule
    1818Sys2LocateDLL
     19Sys2CreateNamedPipe
     20Sys2ConnectNamedPipe
     21Sys2DisconnectNamedPipe
     22Sys2CheckNamedPipe
     23Sys2Open
     24Sys2Close
     25Sys2Seek
     26Sys2Read
     27Sys2Write
    1928
  • rxutilex/trunk/testlib.cmd

    r4 r16  
    3535say Sys2LocateDLL('ehxdlmri')
    3636
     37hp = Sys2CreateNamedPipe("\PIPE\RNPTEST", 0, 100 )
     38if hp == "" then say SYS2ERR
     39else do
     40    ok = Sys2ConnectNamedPipe( hp )
     41    if ok == 0 then say SYS2ERR
     42    else do
     43        PARSE VALUE Sys2CheckNamedPipe( hp ) WITH _cb _state
     44        say _cb 'bytes waiting'
     45        /*data = Sys2Read( hp, _cb )*/
     46        data = charin("\PIPE\RNPTEST",, _cb)
     47        say 'Data: "'c2x(data)'"'
     48    end
     49    ok = Sys2DisconnectNamedPipe( hp )
     50    if ok == 0 then say SYS2ERR
     51end
     52
    3753call Sys2DropFuncs
    3854return 0
Note: See TracChangeset for help on using the changeset viewer.