Skip to content

Commit e57deca

Browse files
committed
Merge branch 'maint'
2 parents f96d9f2 + adb8bb0 commit e57deca

File tree

6 files changed

+93
-28
lines changed

6 files changed

+93
-28
lines changed

lib/kernel/doc/kernel_app.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,10 @@ For more information about configuration parameters, see file
525525
[Escripts and non-interactive I/O in Unicode Usage in Erlang](`e:stdlib:unicode_usage.md#escripts-and-non-interactive-i-o`)
526526
for more details.
527527

528+
- **`os_cmd_shell = string()`{: #os_cmd_shell }** - Specifies which shell to
529+
use when invoking system commands via `os:cmd/2`. By default the shell is detected
530+
automatically.
531+
528532
## Deprecated Configuration Parameters
529533

530534
In Erlang/OTP 21.0, a new API for logging was added. The old `error_logger`

lib/kernel/src/kernel.erl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
start(_, []) ->
3434
%% Setup the logger and configure the kernel logger environment
3535
ok = logger:internal_init_logger(),
36+
ok = os:internal_init_cmd_shell(),
3637
case supervisor:start_link({local, kernel_sup}, kernel, []) of
3738
{ok, Pid} ->
3839
ok = erl_signal_handler:start(),
@@ -48,6 +49,7 @@ stop(_State) ->
4849
%% Some configuration parameters for kernel are changed
4950
%%-------------------------------------------------------------------
5051
config_change(Changed, New, Removed) ->
52+
ok = os:internal_init_cmd_shell(),
5153
do_distribution_change(Changed, New, Removed),
5254
do_global_groups_change(Changed, New, Removed),
5355
ok.

lib/kernel/src/os.erl

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ a program to run on most platforms.
3737

3838
-export([type/0, version/0, cmd/1, cmd/2, find_executable/1, find_executable/2]).
3939

40+
-export([internal_init_cmd_shell/0]).
41+
4042
-include("file.hrl").
4143

4244
-export_type([env_var_name/0, env_var_value/0, env_var_name_value/0]).
@@ -519,6 +521,10 @@ cmd(Cmd) ->
519521
Executes `Command` in a command shell of the target OS, captures the standard
520522
output and standard error of the command, and returns this result as a string.
521523

524+
The command shell can be set using the
525+
[kernel configuration parameter](kernel_app.md#os_cmd_shell), by default the
526+
shell is detected upon system startup.
527+
522528
_Examples:_
523529

524530
```erlang
@@ -582,35 +588,16 @@ get_option(Opt, Options, Default) ->
582588
_ -> throw(badopt)
583589
end.
584590

585-
mk_cmd({win32,Wtype}, Cmd) ->
586-
Command = case {os:getenv("COMSPEC"),Wtype} of
587-
{false,windows} -> lists:concat(["command.com /c", Cmd]);
588-
{false,_} -> lists:concat(["cmd /c", Cmd]);
589-
{Cspec,_} -> lists:concat([Cspec," /c",Cmd])
590-
end,
591+
-define(KERNEL_OS_CMD_SHELL_KEY, kernel_os_cmd_shell).
592+
593+
mk_cmd({win32,_}, Cmd) ->
594+
Shell = persistent_term:get(?KERNEL_OS_CMD_SHELL_KEY),
595+
Command = lists:concat([Shell, " /c", Cmd]),
591596
{Command, [], [], <<>>};
592597
mk_cmd(_,Cmd) ->
593598
%% Have to send command in like this in order to make sh commands like
594599
%% cd and ulimit available.
595-
%%
596-
%% We use an absolute path here because we do not want the path to be
597-
%% searched in case a stale NFS handle is somewhere in the path before
598-
%% the sh command.
599-
%%
600-
%% Check if the default shell is located in /bin/sh as expected usually
601-
%% or in /system/bin/sh as implemented on Android. The raw option is
602-
%% used to bypass the file server and speed up the file access.
603-
Shell = case file:read_file_info("/bin/sh",[raw]) of
604-
{ok,#file_info{type=regular}} ->
605-
"/bin/sh";
606-
_ ->
607-
case file:read_file_info("/system/bin/sh",[raw]) of
608-
{ok,#file_info{type=regular}} ->
609-
"/system/bin/sh";
610-
_ ->
611-
"/bin/sh"
612-
end
613-
end,
600+
Shell = persistent_term:get(?KERNEL_OS_CMD_SHELL_KEY),
614601
{Shell ++ " -s unix:cmd", [out],
615602
%% We insert a new line after the command, in case the command
616603
%% contains a comment character.
@@ -629,6 +616,42 @@ mk_cmd(_,Cmd) ->
629616
["(", unicode:characters_to_binary(Cmd), "\n) </dev/null; echo \"\^D\"\n"],
630617
<<$\^D>>}.
631618

619+
-doc false.
620+
internal_init_cmd_shell() ->
621+
Shell =
622+
case application:get_env(kernel, os_cmd_shell) of
623+
undefined ->
624+
internal_init_cmd_shell(os:type());
625+
{ok, Val} ->
626+
Val
627+
end,
628+
persistent_term:put(?KERNEL_OS_CMD_SHELL_KEY, Shell).
629+
internal_init_cmd_shell({win32,Wtype}) ->
630+
case {os:getenv("COMSPEC"),Wtype} of
631+
{false,windows} -> "command.com";
632+
{false,_} -> "cmd";
633+
{Cspec,_} -> Cspec
634+
end;
635+
internal_init_cmd_shell(_) ->
636+
%% We use an absolute path here because we do not want the path to be
637+
%% searched in case a stale NFS handle is somewhere in the path before
638+
%% the sh command.
639+
%%
640+
%% Check if the default shell is located in /bin/sh as expected usually
641+
%% or in /system/bin/sh as implemented on Android. The raw option is
642+
%% used to bypass the file server.
643+
case file:read_file_info("/bin/sh",[raw]) of
644+
{ok,#file_info{type=regular}} ->
645+
"/bin/sh";
646+
_ ->
647+
case file:read_file_info("/system/bin/sh",[raw]) of
648+
{ok,#file_info{type=regular}} ->
649+
"/system/bin/sh";
650+
_ ->
651+
"/bin/sh"
652+
end
653+
end.
654+
632655
validate(Term) ->
633656
try validate1(Term)
634657
catch error:_ -> throw(badarg)

lib/kernel/test/os_SUITE.erl

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
find_executable/1, unix_comment_in_command/1, deep_list_command/1,
2929
large_output_command/1, background_command/0, background_command/1,
3030
message_leak/1, close_stdin/0, close_stdin/1, max_size_command/1,
31-
perf_counter_api/1, error_info/1]).
31+
perf_counter_api/1, error_info/1, os_cmd_shell/1,os_cmd_shell_peer/1]).
3232

3333
-include_lib("common_test/include/ct.hrl").
3434

@@ -43,7 +43,7 @@ all() ->
4343
find_executable, unix_comment_in_command, deep_list_command,
4444
large_output_command, background_command, message_leak,
4545
close_stdin, max_size_command, perf_counter_api,
46-
error_info].
46+
error_info, os_cmd_shell, os_cmd_shell_peer].
4747

4848
groups() ->
4949
[].
@@ -469,6 +469,30 @@ error_info(Config) ->
469469
],
470470
error_info_lib:test_error_info(os, L).
471471

472+
%% Check that is *not* possible to change shell after startup
473+
os_cmd_shell(_Config) ->
474+
475+
application:set_env(kernel, os_cmd_shell, "broken shell"),
476+
477+
%% os:cmd should continue to work as normal
478+
comp("hello", os:cmd("echo hello")).
479+
480+
%% When started with os_cmd_shell set, we make sure that it is used.
481+
os_cmd_shell_peer(Config) ->
482+
DataDir = proplists:get_value(data_dir, Config),
483+
SysShell = "\"" ++ filename:join(DataDir, "sys_shell") ++ "\"",
484+
{ok, Peer, Node} = ?CT_PEER(["-kernel","os_cmd_shell", SysShell]),
485+
try erpc:call(Node, os, cmd, ["ls"], rtnode:timeout(normal)) of
486+
"sys_shell" -> ok;
487+
Other -> ct:fail({unexpected, Other})
488+
catch
489+
C:R:Stk ->
490+
io:format("~p\n~p\n~p\n", [C,R,Stk]),
491+
ct:fail(failed)
492+
after
493+
peer:stop(Peer)
494+
end.
495+
472496
no_limit_for_opened_files() ->
473497
case os:type() of
474498
{unix, freebsd} ->

lib/kernel/test/os_SUITE_data/Makefile.src

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ LD = @LD@
33
CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@
44
CROSSLDFLAGS = @CROSSLDFLAGS@
55

6-
PROGS = my_echo@exe@ my_fds@exe@
6+
PROGS = my_echo@exe@ my_fds@exe@ sys_shell@exe@
77

88
all: $(PROGS)
99

@@ -18,3 +18,9 @@ my_fds@exe@: my_fds@obj@
1818

1919
my_fds@obj@: my_fds.c
2020
$(CC) -c -o my_fds@obj@ $(CFLAGS) my_fds.c
21+
22+
sys_shell@exe@: sys_shell@obj@
23+
$(LD) $(CROSSLDFLAGS) -o sys_shell sys_shell@obj@ @LIBS@
24+
25+
sys_shell@obj@: sys_shell.c
26+
$(CC) -c -o sys_shell@obj@ $(CFLAGS) sys_shell.c
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <stdio.h>
2+
int main(void)
3+
{
4+
printf("sys_shell");
5+
return 0;
6+
}

0 commit comments

Comments
 (0)