GAP can call other programs, such programs are called processes. There are two kinds of processes: first there are processes that are started, run and return a result, while GAP is suspended until the process terminates. Then there are processes that will run in parallel to GAP as subprocesses and GAP can communicate and control the processes using streams (see InputOutputLocalProcess (10.8-2)).
‣ Process( dir, prg, stream-in, stream-out, options ) | ( operation ) |
Process runs a new process and returns when the process terminates. It returns the return value of the process if the operating system supports such a concept.
The first argument dir is a directory object (see 9.4) which will be the current directory (in the usual UNIX or MS-DOS sense) when the program is run. This will only matter if the program accesses files (including running other programs) via relative path names. In particular, it has nothing to do with finding the binary to run.
In general the directory will either be the current directory, which is returned by DirectoryCurrent (9.4-4) –this was the behaviour of GAP 3– or a temporary directory returned by DirectoryTemporary (9.4-3). If one expects that the process creates temporary or log files the latter should be used because GAP will attempt to remove these directories together with all the files in them when quitting.
If a program of a GAP package which does not only consist of GAP code needs to be launched in a directory relative to certain data libraries, then the first entry of DirectoriesPackageLibrary (76.3-7) should be used. The argument of DirectoriesPackageLibrary (76.3-7) should be the path to the data library relative to the package directory.
If a program calls other programs and needs to be launched in a directory containing the executables for such a GAP package then the first entry of DirectoriesPackagePrograms (76.3-8) should be used.
The latter two alternatives should only be used if absolutely necessary because otherwise one risks accumulating log or core files in the package directory.
gap> ls := PathSystemProgram( "ls" );; gap> stdin := InputTextUser();; gap> stdout := OutputTextUser();; gap> path := DirectoriesSystemPrograms();; gap> Process( path[1], ls, stdin, stdout, ["-c"] );; awk ls mkdir gap> # current directory, here the root directory gap> Process( DirectoryCurrent(), ls, stdin, stdout, ["-c"] );; bin lib trans tst CVS grp prim thr two src dev etc tbl doc pkg small tom gap> # create a temporary directory gap> tmpdir := DirectoryTemporary();; gap> Process( tmpdir, ls, stdin, stdout, ["-c"] );; gap> PrintTo( Filename( tmpdir, "emil" ) ); gap> Process( tmpdir, ls, stdin, stdout, ["-c"] );; emil
prg is the filename of the program to launch, for portability it should be the result of Filename (9.5-1) and should pass IsExecutableFile (9.7-4). Note that Process does no searching through a list of directories, this is done by Filename (9.5-1).
stream-in is the input stream that delivers the characters to the process. For portability it should either be InputTextNone (10.9-1) (if the process reads no characters), InputTextUser (10.6-1), the result of a call to InputTextFile (10.5-1) from which no characters have been read, or the result of a call to InputTextString (10.7-1).
Process is free to consume all the input even if the program itself does not require any input at all.
stream-out is the output stream which receives the characters from the process. For portability it should either be OutputTextNone (10.9-2) (if the process writes no characters), OutputTextUser (10.6-2), the result of a call to OutputTextFile (10.5-2) to which no characters have been written, or the result of a call to OutputTextString (10.7-2).
options is a list of strings which are passed to the process as command line argument. Note that no substitutions are performed on the strings, i.e., they are passed immediately to the process and are not processed by a command interpreter (shell). Further note that each string is passed as one argument, even if it contains space characters. Note that input/output redirection commands are not allowed as options.
In order to find a system program use PathSystemProgram (9.5-2).
gap> date := PathSystemProgram( "date" ); "/bin/date"
The next example shows how to execute date with no argument and no input, and collect the output into a string stream.
gap> str := "";; a := OutputTextString(str,true);; gap> Process( DirectoryCurrent(), date, InputTextNone(), a, [] ); 0 gap> CloseStream(a); gap> Print(str); Fri Jul 11 09:04:23 MET DST 1997
‣ Exec( cmd, option1, ..., optionN ) | ( function ) |
Exec runs a shell in the current directory to execute the command given by the string cmd with options option1, ..., optionN.
gap> Exec( "date" ); Thu Jul 24 10:04:13 BST 1997
cmd is interpreted by the shell and therefore we can make use of the various features that a shell offers as in following example.
gap> Exec( "echo \"GAP is great!\" > foo" ); gap> Exec( "cat foo" ); GAP is great! gap> Exec( "rm foo" );
Because cmd is interpreted by a shell, it is difficult to pass arguments containing spaces or quotes reliably, and the exit code of the command is not available. For new code RunProcess (11.1-3) is therefore usually the better choice.
Exec calls the more general operation Process (11.1-1). The function Edit (6.10-1) should be used to call an editor from within GAP.
‣ RunProcess( cmd[, arg1, ..., argN][, options] ) | ( function ) |
RunProcess runs the program cmd with the arguments arg1, ..., argN, waits for it to terminate, and returns a record describing the outcome.
If cmd contains no path separator, it is looked up with PathSystemProgram (9.5-2), that is, the first executable file of that name in one of the directories returned by DirectoriesSystemPrograms (9.4-7) is used; otherwise cmd is used as a path as-is, resolved relative to GAP's current directory rather than to the directory option below. Each argument must be a string or an integer, the latter being converted via String (27.7-6).
No shell is involved: the arguments are handed to the program verbatim. There is thus no need to quote or escape arguments containing spaces or other special characters, and the behaviour does not depend on which shell happens to be installed. The flip side is that shell features are not available, so unlike Exec (11.1-2) one cannot use redirections such as >/dev/null, pipes, or wildcard expansion.
The returned record always has the component status: the exit code of the program, or fail if it could not be executed at all. A nonzero exit code is not treated as an error by RunProcess; it is up to the caller to check it. Note that Process (11.1-1), and hence RunProcess, reports fail also for a program that exits with the code 255, and thus cannot tell the two apart.
gap> res := RunProcess("echo", "GAP is great!"); rec( output := "GAP is great!\n", status := 0 ) gap> RunProcess("false").status; 1
The optional final argument options is a record which may have the following components.
directorythe directory in which the program is run, as a directory object (see 9.4); it defaults to DirectoryCurrent (9.4-4).
inputan input stream serving as the standard input of the program. By default the program receives no input at all; note that this differs from Exec (11.1-2), which passes on whatever the user types.
outputan output stream receiving the standard output of the program. By default the output is captured and returned in the output component of the result record; if this option is given, the result record has no output component.
gap> input := InputTextString("hello\n");; gap> RunProcess("sort", rec(input := input, output := OutputTextUser())); hello rec( status := 0 )
The standard error stream of the program is currently inherited from GAP and cannot be redirected or captured, since GAP has no support for this yet.
RunProcess calls the more general operation Process (11.1-1).
generated by GAPDoc2HTML