Skip to content

Commit

Permalink
Allow subprocess to use environ for environment
Browse files Browse the repository at this point in the history
Typically allow subprocess to use `$PATH` to find binaries

Signed-off-by: Paul Guyot <pguyot@kallisys.net>
  • Loading branch information
pguyot committed Jan 12, 2025
1 parent ffa26d1 commit f0af941
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
5 changes: 3 additions & 2 deletions libs/eavmlib/src/atomvm.erl
Original file line number Diff line number Diff line change
Expand Up @@ -347,14 +347,15 @@ 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

0 comments on commit f0af941

Please sign in to comment.