1 %%%-------------------------------------------------------------------
2 %%% File : os_shell.erl
4 %%% Description : Module abstracting os shell
6 %%% Created : 22 Mar 2011 by <>
7 %%%-------------------------------------------------------------------
8 -module(mkrl_os_shell
).
9 -include("makerl.hrl").
16 _
-> Cmd
%% Bash o algo? usar os:find_executable?
20 sh(os_filter_cmd(Command
)).
22 sh(os_filter_cmd(Command
), Opts
).
27 %% Options = [Option] -- defaults to [use_stdout, abort_on_error]
28 %% Option = ErrorOption | OutputOption | {cd, string()} | {env, Env}
29 %% ErrorOption = return_on_error | abort_on_error | {abort_on_error, string()}
30 %% OutputOption = use_stdout | {use_stdout, bool()}
31 %% Env = [{string(), Val}]
32 %% Val = string() | false
34 sh(Command
, Options0
) ->
35 ?
INFO("sh: ~s\n~p\n", [Command
, Options0
]),
37 DefaultOptions
= [use_stdout
, abort_on_error
],
38 Options
= lists:map(fun expand_sh_flag
/1,
39 proplists:compact(Options0
++ DefaultOptions
)),
41 ErrorHandler
= proplists:get_value(error_handler
, Options
),
42 OutputHandler
= proplists:get_value(output_handler
, Options
),
44 PortSettings
= proplists:get_all_values(port_settings
, Options
) ++
45 [exit_status
, {line
, 16384}, use_stdio
, stderr_to_stdout
, hide
],
46 Port
= open_port({spawn, Command
}, PortSettings
),
48 case sh_loop(Port
, OutputHandler
, []) of
52 ErrorHandler(Command
, Rc
)
58 expand_sh_flag(return_on_error
) ->
63 expand_sh_flag({abort_on_error
, Message
}) ->
65 log_and_abort(Message
)};
66 expand_sh_flag(abort_on_error
) ->
68 fun log_w_rc_and_abort
/2};
69 expand_sh_flag(use_stdout
) ->
72 ?
CONSOLE("~s", [Line
]),
75 expand_sh_flag({use_stdout
, false
}) ->
80 expand_sh_flag({cd
, Dir
}) ->
81 {port_settings
, {cd
, Dir
}};
82 expand_sh_flag({env
, Env
}) ->
83 {port_settings
, {env
, Env
}}.
86 -spec
log_and_abort(string()) -> fun((string(), integer()) -> no_return()).
87 log_and_abort(Message
) ->
93 -spec
log_w_rc_and_abort(string(), integer()) -> no_return().
94 log_w_rc_and_abort(Command
, Rc
) ->
95 ?
ERROR("~s failed with error: ~w\n", [Command
, Rc
]),
98 sh_loop(Port
, Fun
, Acc
) ->
100 {Port
, {data
, {_
, "_port_cmd_status_ " ++ Status
}}} ->
101 (catch erlang:port_close(Port
)), % sigh () for indentation
102 case list_to_integer(Status
) of
103 0 -> {ok
, lists:flatten(Acc
)};
106 {Port
, {data
, {eol
, Line
}}} ->
107 sh_loop(Port
, Fun
, Fun(Line
++ "\n", Acc
));
108 {Port
, {data
, {noeol
, Line
}}} ->
109 sh_loop(Port
, Fun
, Fun(Line
, Acc
));
110 {Port
, {exit_status
, 0}} ->
111 {ok
, lists:flatten(Acc
)};
112 {Port
, {exit_status
, Rc
}} ->