diff options
author | Fred Hebert <mononcqc@ferd.ca> | 2016-01-06 15:20:34 -0500 |
---|---|---|
committer | Fred Hebert <mononcqc@ferd.ca> | 2016-01-06 15:20:34 -0500 |
commit | f7047073358ceedfc1bc61d6df01f4d6710ad8b1 (patch) | |
tree | 0923f963e3356d83714299867f8461dd92786e8f | |
parent | 814d18a31fdd58bb796c068e7c927e35fd9322f6 (diff) |
Correct TTY type detection
This reuses the trick used within OTP to pick within old and new shell.
The 'user' structure is the same for all cases (escript, escript + dumb
TERM, unstable install, unstable install + dumb TERM), so we take it
down first.
Then we boot the TTY driver, which fails if TERM=dumb, in which case we
boot the retro-style usr. If it worked, we shut down the driver again,
and boot a modern shell structure.
This avoids all warnings and seems to work in all cases.
-rw-r--r-- | src/rebar_prv_shell.erl | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl index b2479f1..824293f 100644 --- a/src/rebar_prv_shell.erl +++ b/src/rebar_prv_shell.erl @@ -112,36 +112,42 @@ info() -> "Start a shell with project and deps preloaded similar to~n'erl -pa ebin -pa deps/*/ebin'.~n". setup_shell() -> - case process_info(whereis(user), current_function) of - {_,{user,_,_}} -> setup_old_shell(); - _ -> setup_new_shell() - end. + OldUser = kill_old_user(), + %% Test for support here + NewUser = try erlang:open_port({spawn,'tty_sl -c -e'}, []) of + Port when is_port(Port) -> + true = port_close(Port), + setup_new_shell() + catch + error:_ -> + setup_old_shell() + end, + rewrite_leaders(OldUser, NewUser). -setup_new_shell() -> - %% scan all processes for any with references to the old user and save them to - %% update later +kill_old_user() -> OldUser = whereis(user), - %% terminate the current user + %% terminate the current user's port, in a way that makes it shut down, + %% but without taking down the supervision tree so that the escript doesn't + %% fully die + [P] = [P || P <- element(2,process_info(whereis(user), links)), is_port(P)], + user ! {'EXIT', P, normal}, % pretend the port died, then the port can die! + OldUser. + +setup_new_shell() -> + %% terminate the current user supervision structure ok = supervisor:terminate_child(kernel_sup, user), %% start a new shell (this also starts a new user under the correct group) _ = user_drv:start(), %% wait until user_drv and user have been registered (max 3 seconds) ok = wait_until_user_started(3000), - NewUser = whereis(user), - rewrite_leaders(OldUser, NewUser). + whereis(user). setup_old_shell() -> %% scan all processes for any with references to the old user and save them to %% update later - OldUser = whereis(user), - %% terminate the current user's port, in a way that makes it shut down, - %% but without taking down the supervision tree so that the escript doesn't - %% fully die - [P] = [P || P <- element(2,process_info(whereis(user), links)), is_port(P)], - user ! {'EXIT', P, normal}, % pretend the port died, then the port can die! NewUser = rebar_user:start(), % hikack IO stuff with fake user NewUser = whereis(user), - rewrite_leaders(OldUser, NewUser). + NewUser. rewrite_leaders(OldUser, NewUser) -> %% set any process that had a reference to the old user's group leader to the |