saleyn / erlexec

Execute and control OS processes from Erlang/OTP
https://hexdocs.pm/erlexec/readme.html
Other
527 stars 139 forks source link

fix controlling terminal in pty #95

Closed noelbk closed 7 years ago

noelbk commented 7 years ago

First, thanks for this module! It's perfect for my project running remote shells. Just one problem though... the :pty option like :exec,run([:pid]) fails to set the controlling terminal of the child process, so child processes like sudo will fail. This fixes that by opening the slave pty in the child process, not the parent.

Currently, sudo fails in subshells

Interactive Elixir (1.4.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> {:ok, pid, ospid} = :exec.run(['/bin/bash'], [:stdout, :stderr, :stdin, :monitor, :pty])
{:ok, #PID<0.227.0>, 28675}
iex(2)> flush()
{:stdout, 28675,
 "bash: cannot set terminal process group (-1): Inappropriate ioctl for device\r\nbash: no job control in this shell\r\n"}
{:stdout, 28675,
 "\r\n$ "}
:ok
iex(3)> :exec.send(pid, "sudo id\n")
:ok
iex(4)> flush()
{:stdout, 28675, "sudo: no tty present and no askpass program specified\r\n"}
{:stdout, 28675, "\r\n$ "}
:ok

With this fix, sudo works:

Interactive Elixir (1.4.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> {:ok, pid, ospid} = :exec.run(['/bin/bash'], [:stdout, :stderr, :stdin, :monitor, :pty])
{:ok, #PID<0.227.0>, 28907}
iex(2)> flush()
{:stdout, 28907,
 "\r\n$ "}
:ok
iex(3)> :exec.send(pid, "sudo id\n")
:ok
iex(4)> flush()
{:stdout, 28907, "[sudo] password for user: "}
:ok
iex(5)> :exec.send(pid, "XXXXXXXX\n")
:ok
iex(6)> flush()
{:stdout, 28907, "\r\n"}
{:stdout, 28907, "uid=0(root) gid=0(root) groups=0(root)\r\n"}
{:stdout, 28907, "\r\n$ "}
:ok

Cheers! ~~ Noel