Skip to content

Commit e8e2a91

Browse files
committed
Allow subprocess to use environ for environment
Typically allow subprocess to use `$PATH` to find binaries Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent ffa26d1 commit e8e2a91

File tree

4 files changed

+33
-14
lines changed

4 files changed

+33
-14
lines changed

libs/eavmlib/src/atomvm.erl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,14 +347,17 @@ get_creation() ->
347347
%% @param Path path to the command to execute
348348
%% @param Args arguments to pass to the command. First item is the name
349349
%% of the command
350-
%% @param Envp environment variables to pass to the command.
350+
%% @param Envp environment variables to pass to the command or `undefined'
351+
%% to use environ (VM environment variables)
351352
%% @param Options options to run execve. Should be `[stdout]'
352353
%% @returns a tuple with the process id and a fd to the stdout of the process.
353354
%% @doc Fork and execute a program using fork(2) and execve(2). Pipe stdout
354355
%% so output of the program can be read with `atomvm:posix_read/2'.
355356
%% @end
356357
%%-----------------------------------------------------------------------------
357-
-spec subprocess(Path :: iodata(), Args :: [iodata()], Env :: [iodata()], Options :: [stdout]) ->
358+
-spec subprocess(
359+
Path :: iodata(), Args :: [iodata()], Env :: [iodata()] | undefined, Options :: [stdout]
360+
) ->
358361
{ok, non_neg_integer(), posix_fd()} | {error, posix_error()}.
359362
subprocess(_Path, _Args, _Env, _Options) ->
360363
erlang:nif_error(undefined).

src/libAtomVM/posix_nifs.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@
5858
#include "nifs.h"
5959
#include "posix_nifs.h"
6060

61+
#if HAVE_EXECVE
62+
extern char **environ;
63+
#endif
64+
6165
term posix_errno_to_term(int err, GlobalContext *glb)
6266
{
6367
#if HAVE_OPEN && HAVE_CLOSE || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_SETTIMEOFDAY)
@@ -511,6 +515,9 @@ static term nif_atomvm_posix_select_stop(Context *ctx, int argc, term argv[])
511515
#if HAVE_EXECVE
512516
static void free_string_list(char **list)
513517
{
518+
if (IS_NULL_PTR(list)) {
519+
return;
520+
}
514521
char **ptr = list;
515522
while (*ptr) {
516523
char *str = *ptr;
@@ -564,19 +571,26 @@ static term nif_atomvm_subprocess(Context *ctx, int argc, term argv[])
564571
free(path);
565572
RAISE_ERROR(BADARG_ATOM);
566573
}
567-
char **envp = parse_string_list(argv[2]);
568-
if (IS_NULL_PTR(envp)) {
569-
free(path);
570-
free_string_list(args);
571-
RAISE_ERROR(BADARG_ATOM);
574+
char **envp;
575+
char **envp_array = NULL;
576+
if (argv[2] == UNDEFINED_ATOM) {
577+
envp = environ;
578+
} else {
579+
envp_array = parse_string_list(argv[2]);
580+
if (IS_NULL_PTR(envp_array)) {
581+
free(path);
582+
free_string_list(args);
583+
RAISE_ERROR(BADARG_ATOM);
584+
}
585+
envp = envp_array;
572586
}
573587

574588
int pstdout[2];
575589
int r = pipe(pstdout);
576590
if (r < 0) {
577591
free(path);
578592
free_string_list(args);
579-
free_string_list(envp);
593+
free_string_list(envp_array);
580594
return errno_to_error_tuple_maybe_gc(ctx);
581595
}
582596
pid_t pid;
@@ -609,7 +623,7 @@ static term nif_atomvm_subprocess(Context *ctx, int argc, term argv[])
609623
if (UNLIKELY(r != 0)) {
610624
free(path);
611625
free_string_list(args);
612-
free_string_list(envp);
626+
free_string_list(envp_array);
613627
close(pstdout[0]);
614628
close(pstdout[1]);
615629
return error_tuple_maybe_gc(r, ctx);
@@ -620,7 +634,7 @@ static term nif_atomvm_subprocess(Context *ctx, int argc, term argv[])
620634
int err = errno;
621635
free(path);
622636
free_string_list(args);
623-
free_string_list(envp);
637+
free_string_list(envp_array);
624638
close(pstdout[0]);
625639
close(pstdout[1]);
626640
return error_tuple_maybe_gc(err, ctx);
@@ -646,7 +660,7 @@ static term nif_atomvm_subprocess(Context *ctx, int argc, term argv[])
646660
close(pstdout[1]); // close write-end of the pipe
647661
free(path);
648662
free_string_list(args);
649-
free_string_list(envp);
663+
free_string_list(envp_array);
650664

651665
if (UNLIKELY(memory_ensure_free_opt(ctx, TUPLE_SIZE(3) + TERM_BOXED_RESOURCE_SIZE, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
652666
RAISE_ERROR(OUT_OF_MEMORY_ATOM);

tests/libs/eavmlib/test_file.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ test_subprocess(true) ->
322322
ok.
323323

324324
test_subprocess_echo() ->
325-
{ok, _Pid, StdoutFd} = atomvm:subprocess("/bin/echo", ["echo"], [], [stdout]),
325+
{ok, _Pid, StdoutFd} = atomvm:subprocess("/bin/echo", ["echo"], undefined, [stdout]),
326326
{ok, <<"\n">>} = atomvm:posix_read(StdoutFd, 10),
327327
eof = atomvm:posix_read(StdoutFd, 10),
328328
ok = atomvm:posix_close(StdoutFd),

tests/libs/estdlib/test_epmd.erl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ has_command("BEAM", Command) ->
3939
R = os:cmd("command -v " ++ Command),
4040
R =/= [];
4141
has_command("ATOM", Command) ->
42-
{ok, _, Fd} = atomvm:subprocess("/bin/sh", ["sh", "-c", "command -v " ++ Command], [], [stdout]),
42+
{ok, _, Fd} = atomvm:subprocess("/bin/sh", ["sh", "-c", "command -v " ++ Command], undefined, [
43+
stdout
44+
]),
4345
Result =
4446
case atomvm:posix_read(Fd, 200) of
4547
eof -> false;
@@ -52,7 +54,7 @@ ensure_epmd("BEAM") ->
5254
_ = os:cmd("epmd -daemon"),
5355
ok;
5456
ensure_epmd("ATOM") ->
55-
{ok, _, Fd} = atomvm:subprocess("/bin/sh", ["sh", "-c", "epmd -daemon"], [], [stdout]),
57+
{ok, _, Fd} = atomvm:subprocess("/bin/sh", ["sh", "-c", "epmd -daemon"], undefined, [stdout]),
5658
ok = atomvm:posix_close(Fd),
5759
ok.
5860

0 commit comments

Comments
 (0)