Current section
Files
Jump to
Current section
Files
src/restrict_remsh_mod.erl
-module(restrict_remsh_mod).
-moduledoc """
Sample restricted remote shell module disabling `q/0` (from the `c` module) and
`init:stop/{0,1}` commands. The shell introduces a replacement command to stop
remote node:
`remote_node_stop/1` equivalent to `init:stop/1`.
To activate restricted shell, run the server node like this: `erl -sname
node@host +Bi -shell restricted_shell restrict_remsh_mod`
Then you can connect to it with: `erl -sname a@myhost -remsh node@host`
See: [http://www.erlang.org/doc/man/shell.html#start_restricted-1]
""".
-author('saleyn@gmail.com').
%% Restricted shell callbacks
-export([local_allowed/3, non_local_allowed/3]).
%% Internal API
-export([remote_node_stop/1]).
%% @private
-spec local_allowed(Func::atom(), Args::list(), State::term()) ->
{boolean(), NewState::term()}.
local_allowed(q, _Args, State) -> {false, State};
local_allowed(halt, _Args, State) -> {false, State};
local_allowed(_Cmd, _Args, State) -> {true, State}.
%% @private
-type funspec() :: {Mod::atom(), Fun::atom()}.
-spec non_local_allowed(FunSpec::funspec(), Args::list(), State::term()) ->
{true,NewState::term()} | {false,NewState::term()} |
{{redirect, NewFuncSpec::funspec(), NewArgs::list()}, NewState::term()}.
non_local_allowed({erlang, halt}, _Args, State) -> {false, State};
non_local_allowed({init, stop}, _Args, State) -> {false, State};
non_local_allowed({remote, stop}, [A], State) -> {{redirect, {?MODULE, remote_node_stop}, [A]}, State};
non_local_allowed({_M, _F}, _Args, State) -> {true, State}.
-doc """
Replaces `init:stop/1` with `remote_node_stop/1` to avoid accidental exit of
remote shell.
""".
-spec remote_node_stop(Status::integer()) -> ok.
remote_node_stop(Status) ->
init:stop(Status).