Skip to content

Commit

Permalink
Unix.open_process_args*: look up program in PATH (ocaml#10084)
Browse files Browse the repository at this point in the history
The `Unix.open_process_args*` used to treat their first arguments as a file name for the executable to be run, like `execv` does.

This commit ensures that the first argument is searched in the executable path, like `execvp` does.  This is a more useful behavior.

 Closes: ocaml#10083
  • Loading branch information
nojb authored and dbuenzli committed Mar 25, 2021
1 parent 47c2307 commit db22958
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 39 deletions.
6 changes: 6 additions & 0 deletions Changes
Expand Up @@ -26,6 +26,12 @@ Working version

### Other libraries:

* #10084: Unix.open_process_args* functions now look up the program in the PATH.
This was already the case under Windows, but this is now also done under
Unix. Note that previously the program was interpreted relative to the current
directory.
(Nicolás Ojeda Bär, review by Gabriel Scherer and Xavier Leroy)

### Tools:

### Manual and documentation:
Expand Down
10 changes: 5 additions & 5 deletions otherlibs/unix/unix.ml
Expand Up @@ -890,7 +890,7 @@ let system cmd =
let pid = spawn shell [| shell; "-c"; cmd |] None false [| 0; 1; 2 |] in
snd(waitpid_non_intr pid)

let create_process_gen usepath cmd args optenv
let create_process_gen cmd args optenv
new_stdin new_stdout new_stderr =
let toclose = ref [] in
let close_after () =
Expand All @@ -917,13 +917,13 @@ let create_process_gen usepath cmd args optenv
(if new_stderr = 2 then 2 else file_descr_not_standard new_stderr)
|] in
Fun.protect ~finally:close_after
(fun () -> spawn cmd args optenv usepath redirections)
(fun () -> spawn cmd args optenv true (* usepath *) redirections)

let create_process cmd args new_stdin new_stdout new_stderr =
create_process_gen true cmd args None new_stdin new_stdout new_stderr
create_process_gen cmd args None new_stdin new_stdout new_stderr

let create_process_env cmd args env new_stdin new_stdout new_stderr =
create_process_gen true cmd args (Some env) new_stdin new_stdout new_stderr
create_process_gen cmd args (Some env) new_stdin new_stdout new_stderr

type popen_process =
Process of in_channel * out_channel
Expand All @@ -935,7 +935,7 @@ let popen_processes = (Hashtbl.create 7 : (popen_process, int) Hashtbl.t)

let open_proc prog args envopt proc input output error =
let pid =
create_process_gen false prog args envopt input output error in
create_process_gen prog args envopt input output error in
Hashtbl.add popen_processes proc pid

let open_process_args_in prog args =
Expand Down
38 changes: 21 additions & 17 deletions otherlibs/unix/unix.mli
Expand Up @@ -875,38 +875,42 @@ val open_process_full :
{!open_process_full}. *)

val open_process_args_in : string -> string array -> in_channel
(** High-level pipe and process management. The first argument specifies the
command to run, and the second argument specifies the argument array passed
to the command. This function runs the command in parallel with the program.
The standard output of the command is redirected to a pipe, which can be read
via the returned input channel.
(** [open_process_args_in prog args] runs the program [prog] with arguments
[args]. The new process executes concurrently with the current process.
The standard output of the new process is redirected to a pipe, which can be
read via the returned input channel.
The executable file [prog] is searched in the path. This behaviour changed
in 4.12; previously [prog] was looked up only in the current directory.
The new process has the same environment as the current process.
@since 4.08.0 *)

val open_process_args_out : string -> string array -> out_channel
(** Same as {!open_process_args_in}, but redirect the standard input of the
command to a pipe. Data written to the returned output channel is sent to
the standard input of the command. Warning: writes on output channels are
buffered, hence be careful to call {!Stdlib.flush} at the right times to
ensure correct synchronization.
(** Same as {!open_process_args_in}, but redirect the standard input of the new
process to a pipe. Data written to the returned output channel is sent to
the standard input of the program. Warning: writes on output channels are
buffered, hence be careful to call {!Stdlib.flush} at the right times to
ensure correct synchronization.
@since 4.08.0 *)

val open_process_args : string -> string array -> in_channel * out_channel
(** Same as {!open_process_args_out}, but redirects both the standard input
and standard output of the command to pipes connected to the two returned
channels. The input channel is connected to the output of the command, and
the output channel to the input of the command.
(** Same as {!open_process_args_out}, but redirects both the standard input and
standard output of the new process to pipes connected to the two returned
channels. The input channel is connected to the output of the program, and
the output channel to the input of the program.
@since 4.08.0 *)

val open_process_args_full :
string -> string array -> string array ->
in_channel * out_channel * in_channel
(** Similar to {!open_process_args}, but the third argument specifies the
environment passed to the command. The result is a triple of channels
connected respectively to the standard output, standard input, and standard
error of the command.
environment passed to the new process. The result is a triple of channels
connected respectively to the standard output, standard input, and standard
error of the program.
@since 4.08.0 *)

Expand Down
38 changes: 21 additions & 17 deletions otherlibs/unix/unixLabels.mli
Expand Up @@ -875,38 +875,42 @@ val open_process_full :
{!open_process_full}. *)

val open_process_args_in : string -> string array -> in_channel
(** High-level pipe and process management. The first argument specifies the
command to run, and the second argument specifies the argument array passed
to the command. This function runs the command in parallel with the program.
The standard output of the command is redirected to a pipe, which can be read
via the returned input channel.
(** [open_process_args_in prog args] runs the program [prog] with arguments
[args]. The new process executes concurrently with the current process.
The standard output of the new process is redirected to a pipe, which can be
read via the returned input channel.
The executable file [prog] is searched in the path. This behaviour changed
in 4.12; previously [prog] was looked up only in the current directory.
The new process has the same environment as the current process.
@since 4.08.0 *)

val open_process_args_out : string -> string array -> out_channel
(** Same as {!open_process_args_in}, but redirect the standard input of the
command to a pipe. Data written to the returned output channel is sent to
the standard input of the command. Warning: writes on output channels are
buffered, hence be careful to call {!Stdlib.flush} at the right times to
ensure correct synchronization.
(** Same as {!open_process_args_in}, but redirect the standard input of the new
process to a pipe. Data written to the returned output channel is sent to
the standard input of the program. Warning: writes on output channels are
buffered, hence be careful to call {!Stdlib.flush} at the right times to
ensure correct synchronization.
@since 4.08.0 *)

val open_process_args : string -> string array -> in_channel * out_channel
(** Same as {!open_process_args_out}, but redirects both the standard input
and standard output of the command to pipes connected to the two returned
channels. The input channel is connected to the output of the command, and
the output channel to the input of the command.
(** Same as {!open_process_args_out}, but redirects both the standard input and
standard output of the new process to pipes connected to the two returned
channels. The input channel is connected to the output of the program, and
the output channel to the input of the program.
@since 4.08.0 *)

val open_process_args_full :
string -> string array -> string array ->
in_channel * out_channel * in_channel
(** Similar to {!open_process_args}, but the third argument specifies the
environment passed to the command. The result is a triple of channels
connected respectively to the standard output, standard input, and standard
error of the command.
environment passed to the new process. The result is a triple of channels
connected respectively to the standard output, standard input, and standard
error of the program.
@since 4.08.0 *)

Expand Down

0 comments on commit db22958

Please sign in to comment.