system_exec

Definition: integer exit_code = system_exec(string st, integer mode=2)
Description: Execute the specified command string.
Comments: Any path or filename containing spaces should be enclosed in quotation marks, as shown in example 3.

The system_exec() routine can actually be run in four different ways, depending on whether you want a result and whether a command shell is required.

The system(st) routine is in fact a simple wrapper of system_exec that creates a new shell and does not wait for a return value.

In contrast res = system_exec(st), ie using the default mode, does not create a new shell and waits for a return value.

The bit settings of the mode parameter are designed to implement the above (default) behaviours, and in a backwards-compatible manner, but as a result are slightly unusual and easiest to explain using the table below.

The legacy mode parameter values of 0, 1, and 2, which controlled the restoration of the graphics mode, are now completely ignored, as the fullscreen video mode of an MS_DOS window has not been available since the release of Windows Vista (Jan 2007). Bit #04 controls whether a new shell is created (1=yes) and bit #08 controls whether to wait for a (meaningful) return value (1=no). The opposing on/off meanings of a set bit are a potential source of confusion, however all legacy code should continue to work unaltered.

If bit #04 in mode is set, a new shell is started, using %COMSPEC% /C, which means it has the same features (redirection, wildcards, etc) and is subject to the same limitations (eg it was 126 chars on Win98, but has grown to 8000 chars on Win7) as manually using an MS-DOS console window. This is the (non-overrideable) behaviour of system().

If bit #04 in mode is not set, no new shell is started, in which case st must be a .exe or .com program. Attempts to run .bat files, built-in DOS commands, or use command-line redirection will fail (unless you have manually prefixed the command with %COMSPEC% /C). Some commands, such as DEL, are not programs, they are actually built-in to the command interpreter. This is the default behaviour for system_exec().

If bit #08 in mode is set, this routine does not wait for the command to finish (though it does allow it up to about 0.4s to get going) and the return value will be meaningless (except for -1). This is the (non-overrideable) behaviour of system().

If bit #08 in mode is not set, this routine waits for the command to finish and returns the appropriate exit code, typically in the range 0 to 255, with 0 indicating success. This is the default behaviour for system_exec().

If it is not possible to run the program, system_exec() returns -1 (whether bit #08 was set or not).

The following table shows the four possible ways that system_exec can be used, one of which is the same as "system() plus -1":

result/wait redirect/builtin invoke aka
no yes system(st) res1 = system_exec(st,12)
no no res1 = system_exec(st,8)
yes yes res = system_exec(st,4)
yes no system_exec(st) res = system_exec(st[,0])
1 -1 if the command could not be invoked, all other values are meaningless. In the first case (system/12) a non-(-1) result only means it successfully created a shell, as opposed to the shell being able to make any sense of the rest of the line.

Note that the bit 4/8 settings of the mode parameter have no known equivalents on RDS Eu or OpenEuphoria, though otherwise system() and system_exec() work the same.

For example if you want to run DEL or a batch file or the command string contains "< input" or "> output", then you need system_exec(st,4) (if you want a result) or system (if you do not), and both of those come with that "ugly black box" thing as part and parcel of the deal for the extra functionality.

If however you want to run an exe file then system_exec(st,8) (no result, returns immediately), or system_exec (result, does not return until the invoked executable terminates) may be more appropriate, and without an "ugly black box" - unless triggered by something like ?, puts(1,xx) or getc(0).

You can run a phix program using system_exec(), and it can return an exit code using abort().

system_exec() does not by default start a new DOS shell.
Example 1:
integer exit_code
exit_code = system_exec("xcopy temp1.dat temp2.dat")
if exit_code=-1 then
    puts(2, "\n couldn't run xcopy.exe\n")
elsif exit_code=0 then
    puts(2, "\n xcopy succeeded\n")
else
    printf(2, "\n xcopy failed with code %d\n", exit_code)
end if
Example 2:
-- executes myprog with two file names as arguments
-- note use of double backslash in literal string to get a single backslash
if system_exec("p.exe \\test\\myprog.ex indata.csv outdata.csv") then
    puts(2, "failure!\n")
end if
Example 3:
-- execute myprog with redirected standard input and output, and wait for the result
-- note the use of quotation marks around any path/filename that contains spaces
if system_exec("\"C:Program Files (x86)\\Phix\\p.exe\" myprog.ex < indata > outdata",4)
    puts(2, "failure!\n")
end if
See Also: system, abort, get_interpreter