Changeset 16
- Timestamp:
- Sep 20, 2014, 1:17:51 PM (11 years ago)
- Location:
- rxutilex/trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
rxutilex/trunk/FUNCTIONS
r4 r16 3 3 (See file 'TODO' for functions which are under consideration to be added.) 4 4 5 Sys2CheckNamedPipe - Check the status of a named pipe 6 Sys2ConnectNamedPipe - Enable client sessions on a named pipe 7 Sys2CreateNamedPipe - Create a named pipe 8 Sys2DisconnectNamedPipe - Acknowledge that a named pipe session has ended 5 9 Sys2DropFuncs - Deregister all functions 6 10 Sys2FormatTime - Format calender time (strftime wrapper) … … 15 19 Sys2QueryProcess - Get information about a process 16 20 Sys2QueryProcessList - Get the list of running processes 21 Sys2Read - 17 22 Sys2ReplaceModule - Unlock a DLL (DosReplaceModule wrapper) 18 23 Sys2Version - Get the version of this library … … 20 25 21 26 If 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 27 an error message of the form "RC: description" where RC is a non-zero error 23 28 code, and description indicates the internal function call that failed. If 24 29 no error occurs, SYS2ERR will be "0". 30 31 32 ------------------------------------------------------------------------- 33 Sys2CheckNamedPipe 34 35 Check the status of a named pipe. 36 37 REXX ARGUMENTS: 38 1. The pipe handle (from Sys2CreateNamedPipe or DosOpen). (REQUIRED) 39 40 REXX 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 ------------------------------------------------------------------------- 47 Sys2ConnectNamedPipe 48 49 Start 'listening' by allowing clients to connect to a previously-created 50 named pipe. 51 52 REXX ARGUMENTS: 53 1. The pipe handle, as returned by Sys2CreateNamedPipe. (REQUIRED) 54 55 REXX RETURN VALUE: 56 1 on success, or 0 if an error occurred. 57 58 59 ------------------------------------------------------------------------- 60 Sys2CreateNamedPipe 61 62 Creates a named pipe with the specified name and parameters. 63 64 Note that the standard REXX functions such as CHARIN/OUT, which operate 65 directly on file names, are not capable of using the pipe handle returned 66 from this function. While the client end can use such functions after 67 using STREAM to issue an OPEN WRITE or OPEN READ command, the host end 68 needs to use the pipe handle from this function, and must therefore use 69 Sys2Read/Sys2Write in order to read and write data from the pipe. 70 71 REXX 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 92 REXX RETURN VALUE: A four-byte pipe handle. 93 94 95 ------------------------------------------------------------------------- 96 Sys2DisconnectNamedPipe 97 98 Unlocks a named pipe after a client has closed its connection. 99 100 REXX ARGUMENTS: 101 1. The pipe handle, as returned by Sys2CreateNamedPipe. (REQUIRED) 102 103 REXX RETURN VALUE: 104 1 on success, or 0 if an error occurred. 25 105 26 106 … … 91 171 Years prior to 1970 or later than 2037 cannot be supported due to the 92 172 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 94 174 will return a value of 0 (and SYS2ERR will report an error in 'mktime'). 95 175 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. 97 177 e.g. '20' ==> 2020 98 178 '75' ==> 1975 … … 134 214 135 215 ------------------------------------------------------------------------- 136 Sys2LocateDLL 137 138 Searches for a DLL by name and returns its fully-qualified path. 216 Sys2LocateDLL 217 218 Searches for a DLL by name and returns its fully-qualified path. 139 219 140 220 If a DLL with the given name is currently loaded, that instance of the 141 221 DLL will be returned. Otherwise, standard DLL loading rules (according 142 222 to 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. 223 search for a DLL whose module name matches the one specified. 224 225 REXX ARGUMENTS: 226 1. The name of the DLL to search for. (REQUIRED) 227 228 229 REXX RETURN VALUE: 230 The fully-qualified path of the DLL, if found; "" otherwise. 151 231 152 232 … … 219 299 220 300 Gets 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 301 variable, where stem.0 contains number of items, and each stem item is a 222 302 string of the form: 223 303 pid parent-pid process-type priority cpu-time executable-name … … 241 321 242 322 ------------------------------------------------------------------------- 323 Sys2Read 324 325 Read bytes from a previously-opened stream (wrapper to DosRead). The 326 format of file handles supported by this function is currently limited 327 to those returned by Sys2CreateNamedPipe. 328 329 REXX ARGUMENTS: 330 1. File handle (as returned by Sys2CreateNamedPipe). (REQUIRED) 331 2. Number of bytes to read. (REQUIRED) 332 333 REXX RETURN VALUE: 334 String containing the bytes read, or "" in case of error. 335 336 337 ------------------------------------------------------------------------- 243 338 Sys2ReplaceModule 244 339 -
rxutilex/trunk/Makefile
r4 r16 15 15 16 16 $(NAME).dll : $(NAME).obj 17 @makedesc -D"Extra REXX Utility Functions" -N"Alex Taylor" -V"^#define=SZ_VERSION,rxutilex.c" $(NAME).def17 makedesc -D"Extra REXX Utility Functions" -N"Alex Taylor" -V"^#define=SZ_VERSION,rxutilex.c" $(NAME).def 18 18 $(LINK) $(LFLAGS) $(NAME).obj $(NAME).def $(LIBS) /O:$@ 19 19 @dllrname.exe $@ CPPOM30=OS2OM30 /Q /R -
rxutilex/trunk/TODO
r4 r16 6 6 - Sys2FormatCurrency - A strfmon wrapper 7 7 - 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 9 10 10 11 Under consideration: -
rxutilex/trunk/rxutilex.c
r4 r16 1 1 /****************************************************************************** 2 2 * REXX Utility Functions - Extended (RXUTILEX.DLL) * 3 * (C) 2011 Alex Taylor.*3 * (C) 2011, 2014 Alex Taylor. * 4 4 * * 5 5 * LICENSE: * … … 43 43 #define INCL_WINCLIPBOARD 44 44 #define INCL_WINERRORS 45 #define INCL_DOSERRORS 45 46 #define INCL_DOSMISC 47 #define INCL_DOSMODULEMGR 48 #define INCL_DOSNMPIPES 46 49 #define INCL_DOSPROCESS 47 50 #define INCL_DOSPROFILE 48 #define INCL_DOSERRORS49 #define INCL_DOSMODULEMGR50 51 #ifndef OS2_INCLUDED 51 52 #include <os2.h> … … 72 73 #define SZ_LIBRARY_NAME "RXUTILEX" // Name of this library 73 74 #define SZ_ERROR_NAME "SYS2ERR" // REXX variable used to store error codes 74 #define SZ_VERSION "0.0. 4" // Current version of this library75 #define SZ_VERSION "0.0.5" // Current version of this library 75 76 76 77 // Maximum string lengths... 77 78 #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 79 81 #define US_STEM_MAXZ ( US_COMPOUND_MAXZ - US_INTEGER_MAXZ ) // ...of a stem 80 82 #define US_ERRSTR_MAXZ 250 // ...of an error string 81 83 #define US_PIDSTR_MAXZ ( CCHMAXPATH + 100 ) // ...of a process information string 82 84 #define US_TIMESTR_MAXZ 256 // ...of a formatted time string 85 #define US_PIPESTATUS_MAXZ 128 // ...of a pipe status string 83 86 84 87 #define UL_SSBUFSIZE 0xFFFF // Buffer size for the DosQuerySysState() data … … 104 107 "Sys2ReplaceModule", 105 108 "Sys2LocateDLL", 109 "Sys2CreateNamedPipe", 110 "Sys2ConnectNamedPipe", 111 "Sys2DisconnectNamedPipe", 112 "Sys2CheckNamedPipe", 113 "Sys2Open", 114 "Sys2Close", 115 "Sys2Seek", 116 "Sys2Read", 117 "Sys2Write", 106 118 "Sys2Version" 107 119 }; … … 120 132 RexxFunctionHandler Sys2GetClipboardText; 121 133 RexxFunctionHandler Sys2PutClipboardText; 122 // RexxFunctionHandler Sys2GetClipboardData;123 // RexxFunctionHandler Sys2PutClipboardData;124 134 125 135 RexxFunctionHandler Sys2QueryProcess; … … 133 143 RexxFunctionHandler Sys2ReplaceModule; 134 144 135 RexxFunctionHandler Sys2ReplaceObjectClass; 145 // RexxFunctionHandler Sys2ReplaceObjectClass; 146 147 RexxFunctionHandler Sys2CreateNamedPipe; 148 RexxFunctionHandler Sys2ConnectNamedPipe; 149 RexxFunctionHandler Sys2DisconnectNamedPipe; 150 RexxFunctionHandler Sys2CheckNamedPipe; 151 152 RexxFunctionHandler Sys2Open; 153 RexxFunctionHandler Sys2Close; 154 RexxFunctionHandler Sys2Seek; 155 RexxFunctionHandler Sys2Read; 156 RexxFunctionHandler Sys2Write; 136 157 137 158 … … 301 322 if ( ulRC == 0 ) { 302 323 memset( pszShareMem, 0, ulBytes ); 303 strncpy( pszShareMem, argv[0].strptr 324 strncpy( pszShareMem, argv[0].strptr, ulBytes - 1 ); 304 325 if ( ! WinSetClipbrdData( hab, (ULONG) pszShareMem, CF_TEXT, CFI_POINTER )) 305 326 WriteErrorCode( ERRORIDERROR(WinGetLastError(hab)), "WinSetClipbrdData"); … … 1137 1158 WriteErrorCode( timeval, "time"); 1138 1159 MAKERXSTRING( *prsResult, "0", 1 ); 1160 free( pszSetTZ ); 1139 1161 return 0; 1140 1162 } … … 1153 1175 WriteErrorCode( timeval, "mktime"); 1154 1176 MAKERXSTRING( *prsResult, "0", 1 ); 1177 free( pszSetTZ ); 1155 1178 return 0; 1156 1179 } … … 1224 1247 } 1225 1248 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 * ------------------------------------------------------------------------- */ 1280 ULONG 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 * ------------------------------------------------------------------------- */ 1401 ULONG 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 * ------------------------------------------------------------------------- */ 1438 ULONG 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 * ------------------------------------------------------------------------- */ 1477 ULONG 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 * ------------------------------------------------------------------------- */ 1569 ULONG 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 * ------------------------------------------------------------------------- */ 1723 ULONG 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 * ------------------------------------------------------------------------- */ 1767 ULONG 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 * ------------------------------------------------------------------------- */ 1827 ULONG 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 1860 cleanup: 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 * ------------------------------------------------------------------------- */ 1878 ULONG 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 } 1226 1907 1227 1908 -
rxutilex/trunk/rxutilex.def
r4 r16 1 1 LIBRARY RXUTILEX INITINSTANCE TERMINSTANCE 2 2 DATA MULTIPLE NONSHARED 3 DESCRIPTION '@#Alex Taylor:0.0. 4#@##1## 3 Apr 2013 22:02:22REINFORCE::::::@@Extra REXX Utility Functions'3 DESCRIPTION '@#Alex Taylor:0.0.5#@##1## 20 Sep 2014 20:12:24 REINFORCE::::::@@Extra REXX Utility Functions' 4 4 5 5 EXPORTS Sys2LoadFuncs … … 17 17 Sys2ReplaceModule 18 18 Sys2LocateDLL 19 Sys2CreateNamedPipe 20 Sys2ConnectNamedPipe 21 Sys2DisconnectNamedPipe 22 Sys2CheckNamedPipe 23 Sys2Open 24 Sys2Close 25 Sys2Seek 26 Sys2Read 27 Sys2Write 19 28 -
rxutilex/trunk/testlib.cmd
r4 r16 35 35 say Sys2LocateDLL('ehxdlmri') 36 36 37 hp = Sys2CreateNamedPipe("\PIPE\RNPTEST", 0, 100 ) 38 if hp == "" then say SYS2ERR 39 else 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 51 end 52 37 53 call Sys2DropFuncs 38 54 return 0
Note:
See TracChangeset
for help on using the changeset viewer.