[erlang-questions] Escript using old i/o server still?

Alex Wilson alex@REDACTED
Tue Apr 14 04:35:57 CEST 2015


On Mon, 2015-04-13 at 12:38 -0500, Tristan Sloughter wrote:
> Attempting to accept a password input from an escript led me to discover
> this issue from 2009 is still the case:

Changing this behaviour is actually fairly complicated, if you want to
do it without compromising the ability of escripts to accept input from
non-terminal sources (eg from a shell pipeline). So I'm not sure it's
going to happen any time soon...

If you're desperate you can use a really horrible workaround, something
like this:

-define(OP_PUTC,0).
getpw() ->
  case io:setopts([binary, {echo, false}]) of
    ok ->
      PwLine = io:get_line(<<"Password:">>),
      ok = io:setopts([binary, {echo, true}]),
      io:format("\n"),
      [Pw | _] = binary:split(PwLine, <<"\n">>),
      Pw;
    _ ->
      Port = open_port({spawn, 'tty_sl -e'}, [binary, eof]),
      port_command(Port, <<?OP_PUTC, "Password:">>),
      receive
        {Port, {data, PwLine}} ->
          [Pw | _] = binary:split(PwLine, <<"\n">>),
          port_command(Port, <<?OP_PUTC, $\n>>),
          port_close(Port),
          Pw
      end
  end.

This uses the tty_sl port driver that's only for internal use inside the
new I/O server, which is private API and could disappear at any time.
However, in practice it's been very stable since it was introduced,
so...

It should be safe for tty_sl to just temporarily hijack the terminal
like this as long as nothing else in your program causes the old I/O
server to talk to it at the same time. If there are any other processes
running that could cause io: functions to be called during this, things
could possibly get hairy.

I'd only recommend it from an escript main/1 or similar, before starting
any other processes, and probably after turning off the error_logger or
putting it in silent mode.




More information about the erlang-questions mailing list