Changeset 47


Ignore:
Timestamp:
Sep 23, 2019, 5:23:37 AM (6 years ago)
Author:
Alex Taylor
Message:

Add Sys2Exec function (DosExecPgm wrapper)

Location:
rxutilex/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • rxutilex/trunk/rxutilex.c

    r43 r47  
    9494#define SZ_LIBRARY_NAME         "RXUTILEX"  // Name of this library
    9595//#define SZ_ERROR_NAME       "SYS2ERR"   // REXX variable used to store error codes - must be defined in Makefile
    96 #define SZ_VERSION              "0.1.6"     // Current version of this library
     96#define SZ_VERSION              "0.1.7"     // Current version of this library
    9797
    9898// Maximum string lengths...
     
    153153    "Sys2Write",
    154154    "Sys2QuerySysValue",
     155    "Sys2Exec",
    155156    "Sys2Version"
    156157};
     
    174175RexxFunctionHandler Sys2KillProcess;
    175176RexxFunctionHandler Sys2QueryForegroundProcess;
     177RexxFunctionHandler Sys2Exec;
    176178
    177179RexxFunctionHandler Sys2QueryDriveInfo;
     
    27162718
    27172719
     2720/* ------------------------------------------------------------------------- *
     2721 * Sys2Exec                                                                  *
     2722 *                                                                           *
     2723 * Wrapper to DosExecPgm.                                                    *
     2724 *                                                                           *
     2725 * REXX ARGUMENTS:                                                           *
     2726 *   1. Name of executable program                                (REQUIRED) *
     2727 *   2. Arguments to pass to program (default "")                            *
     2728 *   3. Execution mode flag, one of:                                         *
     2729 *       'W' or 'S': Wait for program to return (EXEC_SYNC)                  *
     2730 *       'N' or 'A': No wait (EXEC_ASYNC)                                    *
     2731 *       'D' or 'B': Detach process (EXEC_BACKGROUND)                        *
     2732 *                                                                           *
     2733 * REXX RETURN VALUE:                                                        *
     2734 *   If EXEC_SYNC mode was requested, returns the termination status from    *
     2735 *   the started session.  Otherwise, returns the process ID.                *
     2736 * ------------------------------------------------------------------------- */
     2737ULONG APIENTRY Sys2Exec( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     2738{
     2739    RESULTCODES st_RC = {0};
     2740    CHAR        szLoadErr[ CCHMAXPATH ] = {0},
     2741                szTerminate[ US_INTEGER_MAXZ ];
     2742    PSZ         pszProg,
     2743                pszArgs,
     2744                s;
     2745    ULONG       cbArgs,
     2746                ulExec;
     2747    APIRET      rc;
     2748
     2749    // Reset the error indicator
     2750    WriteErrorCode( 0, NULL );
     2751
     2752    // Make sure we have at least one valid argument
     2753    if (( argc < 1 ) || ( !RXVALIDSTRING( argv[0]) ))
     2754        return ( 40 );
     2755
     2756    // Second argument is optional but must be a valid string if specified
     2757    if (( argc >= 2 ) && ( !RXVALIDSTRING(argv[1]) ))
     2758        return ( 40 );
     2759
     2760    // Third argument: execution mode flag
     2761    if ( argc >= 3 && RXVALIDSTRING(argv[2]) ) {
     2762        strupr( argv[2].strptr );
     2763        switch ( argv[2].strptr[0] ) {
     2764            case 'N':
     2765            case 'A': ulExec = EXEC_ASYNC; break;
     2766            case 'W':
     2767            case 'S': ulExec = EXEC_SYNC; break;
     2768            case 'D':
     2769            case 'B': ulExec = EXEC_BACKGROUND; break;
     2770            default: return ( 40 );
     2771        }
     2772    }
     2773
     2774    // Build the argument strings (first arg must be the program name)
     2775    pszProg = strrchr( argv[0].strptr, '\\');
     2776    if ( pszProg == NULL )
     2777        pszProg = strrchr( argv[0].strptr, ':');
     2778    if ( pszProg == NULL )
     2779        pszProg = argv[0].strptr;
     2780    cbArgs = strlen( pszProg + 1 );
     2781    if ( argc >= 2 ) {
     2782        cbArgs += argv[1].strlength + 1;
     2783    }
     2784    pszArgs = calloc( cbArgs + 1, sizeof(char) );
     2785    if ( pszArgs == NULL ) {
     2786        WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc");
     2787        SaveResultString( prsResult, NULL, 0 );
     2788        return ( 0 );
     2789    }
     2790
     2791    // Concatenate the program and argument strings, null-separated
     2792    // (We use 0x1A while building the string to avoid termination issues)
     2793    if ( argc >= 2 )
     2794        sprintf( pszArgs, "%s\x1A%s\x1A", pszProg, argv[1].strptr );
     2795    else
     2796        sprintf( pszArgs, "%s\x1A", pszProg );
     2797    // Now replace the 0x1A's with nulls (starting from string end)
     2798    while (( s = strrchr( pszArgs, 0x1A )) != NULL )
     2799        *s = 0;
     2800
     2801    // Launch the program
     2802    rc = DosExecPgm( szLoadErr, sizeof( szLoadErr), ulExec,
     2803                     pszArgs, NULL, &st_RC, pszProg );
     2804    if ( rc != NO_ERROR ) {
     2805        WriteErrorCode( rc, "DosExecPgm");
     2806        SaveResultString( prsResult, PSZ_ZERO, 1 );
     2807        return ( 0 );
     2808    }
     2809
     2810    sprintf( szTerminate, "%u", st_RC.codeTerminate );
     2811    SaveResultString( prsResult, szTerminate, strlen(szTerminate) );
     2812    return ( 0 );
     2813}
     2814
    27182815
    27192816// -------------------------------------------------------------------------
  • rxutilex/trunk/rxutilex.def

    r43 r47  
    11LIBRARY     RXUTILEX INITINSTANCE TERMINSTANCE
    22DATA        MULTIPLE NONSHARED
    3 DESCRIPTION '@#Alex Taylor:0.1.6#@##1## 30 Mar 2018 16:11:36     REINFORCE::::::@@Extended REXX Utility Functions'
     3DESCRIPTION '@#Alex Taylor:0.1.7#@##1## 22 Sep 2019 23:22:58     reinforce::::::@@Extended REXX Utility Functions'
    44
    55EXPORTS     Sys2LoadFuncs
     
    3232Sys2BytesRemaining
    3333Sys2QuerySysValue
     34Sys2Exec
    3435
  • rxutilex/trunk/rxutilex.txt

    r44 r47  
    88Sys2DisconnectNamedPipe     - Acknowledge that a named pipe session has ended
    99Sys2DropFuncs               - Deregister all functions
     10Sys2Exec                    - Execute an external program (DosExecPgm wrapper)
    1011Sys2FormatNumber            - Format a number with thousands-grouping characters
    1112Sys2FormatTime              - Format calender time (strftime wrapper)
     
    165166REXX ARGUMENTS:    None
    166167REXX RETURN VALUE: ""
     168
     169
     170-------------------------------------------------------------------------
     171Sys2Exec                                                                 
     172                                                                         
     173Executes an external program and returns the process ID or termination
     174code.  Wrapper to DosExecPgm.  If the called program requires user input,
     175it must be the same type (PM or text mode) as the program which calls this
     176function.
     177                                                                         
     178REXX ARGUMENTS:                                                         
     179  1. Name of executable program to run.                        (REQUIRED)
     180  2. Argument string to pass to the called program.
     181  3. Execution mode flag, one of:
     182      'W' or 'S': Run the program in wait (synchronous) mode (EXEC_SYNC).
     183      'N' or 'A': Run the program in no-wait (asynchronous) mode (EXEC_ASYNC).
     184      'D' or 'B': Run the program detached (EXEC_BACKGROUND).
     185                                                                         
     186REXX RETURN VALUE:                                                       
     187  If EXEC_SYNC mode was requested, returns the termination status (this is
     188  _not_ the same as the return code) from the started program.  Otherwise,
     189  returns the process ID of the started program.
    167190
    168191
  • rxutilex/trunk/testlib.cmd

    r42 r47  
    5555say Sys2FormatNumber('-64583.449286', 5)
    5656
     57pid = Sys2Exec('e.exe', SysBootDrive() || '\config.sys /read', 'd')
     58say 'Started program with PID =' pid
    5759
    5860call Sys2DropFuncs
Note: See TracChangeset for help on using the changeset viewer.