Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow subprocess to use environ for environment #1469

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions libs/eavmlib/src/atomvm.erl
Original file line number Diff line number Diff line change
Expand Up @@ -347,14 +347,17 @@ get_creation() ->
%% @param Path path to the command to execute
%% @param Args arguments to pass to the command. First item is the name
%% of the command
%% @param Envp environment variables to pass to the command.
%% @param Envp environment variables to pass to the command or `undefined'
%% to use environ (VM environment variables)
%% @param Options options to run execve. Should be `[stdout]'
%% @returns a tuple with the process id and a fd to the stdout of the process.
%% @doc Fork and execute a program using fork(2) and execve(2). Pipe stdout
%% so output of the program can be read with `atomvm:posix_read/2'.
%% @end
%%-----------------------------------------------------------------------------
-spec subprocess(Path :: iodata(), Args :: [iodata()], Env :: [iodata()], Options :: [stdout]) ->
-spec subprocess(
Path :: iodata(), Args :: [iodata()], Env :: [iodata()] | undefined, Options :: [stdout]
) ->
{ok, non_neg_integer(), posix_fd()} | {error, posix_error()}.
subprocess(_Path, _Args, _Env, _Options) ->
erlang:nif_error(undefined).
32 changes: 23 additions & 9 deletions src/libAtomVM/posix_nifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
#include "nifs.h"
#include "posix_nifs.h"

#if HAVE_EXECVE
extern char **environ;
#endif

term posix_errno_to_term(int err, GlobalContext *glb)
{
#if HAVE_OPEN && HAVE_CLOSE || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_SETTIMEOFDAY)
Expand Down Expand Up @@ -511,6 +515,9 @@ static term nif_atomvm_posix_select_stop(Context *ctx, int argc, term argv[])
#if HAVE_EXECVE
static void free_string_list(char **list)
{
if (IS_NULL_PTR(list)) {
return;
}
char **ptr = list;
while (*ptr) {
char *str = *ptr;
Expand Down Expand Up @@ -564,19 +571,26 @@ static term nif_atomvm_subprocess(Context *ctx, int argc, term argv[])
free(path);
RAISE_ERROR(BADARG_ATOM);
}
char **envp = parse_string_list(argv[2]);
if (IS_NULL_PTR(envp)) {
free(path);
free_string_list(args);
RAISE_ERROR(BADARG_ATOM);
char **envp;
char **envp_array = NULL;
if (argv[2] == UNDEFINED_ATOM) {
envp = environ;
} else {
envp_array = parse_string_list(argv[2]);
if (IS_NULL_PTR(envp_array)) {
free(path);
free_string_list(args);
RAISE_ERROR(BADARG_ATOM);
}
envp = envp_array;
}

int pstdout[2];
int r = pipe(pstdout);
if (r < 0) {
free(path);
free_string_list(args);
free_string_list(envp);
free_string_list(envp_array);
return errno_to_error_tuple_maybe_gc(ctx);
}
pid_t pid;
Expand Down Expand Up @@ -609,7 +623,7 @@ static term nif_atomvm_subprocess(Context *ctx, int argc, term argv[])
if (UNLIKELY(r != 0)) {
free(path);
free_string_list(args);
free_string_list(envp);
free_string_list(envp_array);
close(pstdout[0]);
close(pstdout[1]);
return error_tuple_maybe_gc(r, ctx);
Expand All @@ -620,7 +634,7 @@ static term nif_atomvm_subprocess(Context *ctx, int argc, term argv[])
int err = errno;
free(path);
free_string_list(args);
free_string_list(envp);
free_string_list(envp_array);
close(pstdout[0]);
close(pstdout[1]);
return error_tuple_maybe_gc(err, ctx);
Expand All @@ -646,7 +660,7 @@ static term nif_atomvm_subprocess(Context *ctx, int argc, term argv[])
close(pstdout[1]); // close write-end of the pipe
free(path);
free_string_list(args);
free_string_list(envp);
free_string_list(envp_array);

if (UNLIKELY(memory_ensure_free_opt(ctx, TUPLE_SIZE(3) + TERM_BOXED_RESOURCE_SIZE, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
Expand Down
2 changes: 1 addition & 1 deletion tests/libs/eavmlib/test_file.erl
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ test_subprocess(true) ->
ok.

test_subprocess_echo() ->
{ok, _Pid, StdoutFd} = atomvm:subprocess("/bin/echo", ["echo"], [], [stdout]),
{ok, _Pid, StdoutFd} = atomvm:subprocess("/bin/echo", ["echo"], undefined, [stdout]),
{ok, <<"\n">>} = atomvm:posix_read(StdoutFd, 10),
eof = atomvm:posix_read(StdoutFd, 10),
ok = atomvm:posix_close(StdoutFd),
Expand Down
6 changes: 4 additions & 2 deletions tests/libs/estdlib/test_epmd.erl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ has_command("BEAM", Command) ->
R = os:cmd("command -v " ++ Command),
R =/= [];
has_command("ATOM", Command) ->
{ok, _, Fd} = atomvm:subprocess("/bin/sh", ["sh", "-c", "command -v " ++ Command], [], [stdout]),
{ok, _, Fd} = atomvm:subprocess("/bin/sh", ["sh", "-c", "command -v " ++ Command], undefined, [
stdout
]),
Result =
case atomvm:posix_read(Fd, 200) of
eof -> false;
Expand All @@ -52,7 +54,7 @@ ensure_epmd("BEAM") ->
_ = os:cmd("epmd -daemon"),
ok;
ensure_epmd("ATOM") ->
{ok, _, Fd} = atomvm:subprocess("/bin/sh", ["sh", "-c", "epmd -daemon"], [], [stdout]),
{ok, _, Fd} = atomvm:subprocess("/bin/sh", ["sh", "-c", "epmd -daemon"], undefined, [stdout]),
ok = atomvm:posix_close(Fd),
ok.

Expand Down
Loading