Os.PtyExecuting commands in pseudoterminals.
This module provides a convenience abstraction to interact with commands spawned in pseudoterminals. It can be used to script terminal interactions. See an example.
The TTY demystified is a good read to clear up the mind about terminals.
TODO
The type for pseudoterminals.
These values encapsulate a pseudoterminal device pair returned by Fd.openpty and a process identifiers of a command spawn.
val open_with_spawn :
?env:Env.assignments ->
?cwd:Fpath.t ->
?stdin:Cmd.stdi ->
?stdout:Cmd.stdo ->
?stderr:Cmd.stdo ->
Cmd.t ->
(t, string) Stdlib.resultopen_with_spawn cmd is like Cmd.spawn, except it allocates a pseudoterminal device pair and uses its terminal device for the spawn's stdin, stdout and stderr (unless differently specified). The returned pseudoterminal value can be used to interact with the process and must eventually be closed.
val close_noerr : t -> unitclose_noerr pty closes pty and in particular, all file descriptors held by it.
FIXME The function does not wait on the underlying the spawn. FIXME Should it kill and reap the process ?
val with_spawn :
?env:Env.assignments ->
?cwd:Fpath.t ->
?stdin:Cmd.stdi ->
?stdout:Cmd.stdo ->
?stderr:Cmd.stdo ->
Cmd.t ->
(t -> 'a) ->
('a, string) Stdlib.resultwith_spawn cmd f does open_with_spawn cmd to get a pty and calls f pty. The function guarantees that when it returns pty was closed by close_noerr.
val write : t -> string -> (unit, string) Stdlib.resultwrite pty s writes s on the pseudoterminal device of pty.
val read :
?timeout:Mtime.Span.t ->
?max:int ->
t ->
(string option, string) Stdlib.resultread pty reads a string None is returned if eof or timeout, if timeout is unspecified then blocks forever.
val seek :
?log:bool ->
?timeout:Mtime.Span.t ->
t ->
string ->
(unit, string) Stdlib.resultseek pty mark reads and drops pty input until the mark is seen. The next read returns the bytes after the mark.
val interact : t -> (unit, string) Stdlib.resultinteract pty, connects the current process stdin and stdout to the pseudo terminal device of pty.
Note. This sets Unix.stdin to raw mode for the duration of the call.
WARNING/TODO. For now you you need to Fd.close_noerr tty for that to return when the child exits.
Warning. Performing operations on the the returned values here may have effects on the pty operations (for good or bad).
val pty : t -> Unix.file_descrpty pty is the (controlling) pseudoterminal device of pty.
val tty : t -> Unix.file_descrtty pty is the (controlled) terminal device of pty.
pid pty is the process identifier of the process to which the terminal device of pty is connected.
val set_echo : t -> bool -> (unit, string) Stdlib.resultset_echo pty flag sets echoing to flag.
let session ~user ~password =
Result.join @@ Os.Pty.with_spawn (Cmd.tool "login") @@ fun pty ->
Os.Fd.close_noerr (Os.Pty.tty pty);
let* () = Os.Pty.seek pty "login:" in
let* () = Os.Pty.write pty (user ^ "\n") in
let* () = Os.Pty.seek pty "Password:" in
let* () = Os.Pty.write pty (password ^ "\n") in
print_endline "Login successful, have fun, use Ctrl-D to exit";
Os.Pty.interact pty