I'm trying to capture the output of a command run using Posix.Process.execp
. I ported some C code I found on stackoverflow and can capture output for one execution, but I can't get the output for a second execution.
Here's my function:
(* Runs a command c (command and argument list) using Posix.Process.execp. *)
(* If we successfully run the program, we return the lines output to stdout *)
(* in a list, along with SOME of the exit code. *)
(* If we fail to run the program, we return the error message in the list *)
(* and NONE. *)
fun execpOutput (c : string * string list) : (string list * Posix.Process.exit_status option) =
let fun readAll () = case TextIO.inputLine TextIO.stdIn
of SOME s => s :: (readAll ())
| NONE => []
(* Create a new pipe *)
val { infd = infd, outfd = outfd } = Posix.IO.pipe ()
in case Posix.Process.fork ()
of NONE => (
(* We are the child. First copy outfd to stdout; they will *)
(* point to the same file descriptor and can be used interchangeably. *)
(* See dup(2) for details. Then close infd: we don't need it and don't *)
(* want to block because we have open file descriptors laying around *)
(* when we want to exit. *)
( Posix.IO.dup2 { old = outfd, new = Posix.FileSys.stdout }
; Posix.IO.close infd
; Posix.Process.execp c )
handle OS.SysErr (err, _) => ([err], NONE) )
| SOME pid =>
(* We are the parent. This time, copy infd to stdin, and get rid of the *)
(* outfd we don't need. *)
let val _ = ( Posix.IO.dup2 { old = infd, new = Posix.FileSys.stdin }
; Posix.IO.close outfd )
val (_, status) = Posix.Process.waitpid (Posix.Process.W_CHILD pid, [])
in (readAll (), SOME status) end
end
val lsls = (#1 (execpOutput ("ls", ["ls"]))) @ (#1 (execpOutput ("ls", ["ls"])))
val _ = app print lsls
and here's the corresponding output:
rak@zeta:/tmp/test$ ls
a b c
rak@zeta:/tmp/test$ echo 'use "/tmp/mwe.sml";' | sml
Standard ML of New Jersey v110.79 [built: Tue Aug 8 16:57:33 2017]
- [opening /tmp/mwe.sml]
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[library $SMLNJ-BASIS/(basis.cm):basis-common.cm is stable]
[autoloading done]
a
b
c
val execpOutput = fn
: string * string list -> string list * ?.POSIX_Process.exit_status option
val lsls = ["a\n","b\n","c\n"] : string list
val it = () : unit
-
Any suggestions on what I'm doing wrong?