In an environment where qemu (user-mode) is used to execute binaries, I'm seeing these test failures:
$ cat test-execle.sh.log qemu-riscv64: Could not open '/lib/ld-linux-riscv64-lp64d.so.1': No such file or directory FAIL test-execle.sh (exit status: 1) $ cat test-execve.sh.log qemu-riscv64: Could not open '/lib/ld-linux-riscv64-lp64d.so.1': No such file or directory FAIL test-execve.sh (exit status: 1) $ cat test-execvpe.sh.log qemu-riscv64: Could not open '/lib/ld-linux-riscv64-lp64d.so.1': No such file or directory FAIL test-execvpe.sh (exit status: 1) The cause is that the QEMU_LD_PREFIX environment variable is not passed to the program to be executed. This patch fixes it. 2021-08-28 Bruno Haible <br...@clisp.org> execle, execve, execvpe tests: Fix test failures under qemu user-mode. * test-execle-main.c: Include <string.h>. (get_environ_assignment, create_minimal_env): New functions. (main): Call create_minimal_env. * test-execve-main.c: Likewise. * test-execvpe-main.c: Likewise. diff --git a/tests/test-execle-main.c b/tests/test-execle-main.c index 2c085f630..f738293c3 100644 --- a/tests/test-execle-main.c +++ b/tests/test-execle-main.c @@ -25,22 +25,53 @@ SIGNATURE_CHECK (execle, int, (const char *, const char *, ...)); #include <stdio.h> +#include <string.h> + +/* Looks up the NAME=VALUE assignment among the environment variables. + Returns it, or NULL if not found. */ +static const char * +get_environ_assignment (const char *name) +{ + size_t name_len = strlen (name); + char **p; + for (p = environ; *p != NULL; p++) + { + const char *assignment = *p; + if (strncmp (assignment, name, name_len) == 0 + && assignment[name_len] == '=') + return assignment; + } + return NULL; +} + +/* Creates a minimal environment. */ +static void +create_minimal_env (const char *env[5]) +{ + const char **p = env; + *p++ = + #ifdef __CYGWIN__ + /* The Cygwin DLLs needed by the program are in /bin. */ + "PATH=.:/bin"; + #else + "PATH=."; + #endif + *p = get_environ_assignment ("QEMU_LD_PREFIX"); + if (*p != NULL) + p++; + *p = get_environ_assignment ("QEMU_CPU"); + if (*p != NULL) + p++; + *p++ = "Hommingberg=Gepardenforelle"; + *p = NULL; +} int main () { const char *progname = "./test-exec-child"; - const char *env[3] = - { - #ifdef __CYGWIN__ - /* The Cygwin DLLs needed by the program are in /bin. */ - "PATH=.:/bin", - #else - "PATH=.", - #endif - "Hommingberg=Gepardenforelle", - NULL - }; + const char *env[5]; + create_minimal_env (env); execle (progname, progname, "abc def", diff --git a/tests/test-execve-main.c b/tests/test-execve-main.c index 970372da1..6199a7d50 100644 --- a/tests/test-execve-main.c +++ b/tests/test-execve-main.c @@ -25,22 +25,51 @@ SIGNATURE_CHECK (execve, int, (const char *, char * const *, char * const *)); #include <stdio.h> +#include <string.h> + +/* Looks up the NAME=VALUE assignment among the environment variables. + Returns it, or NULL if not found. */ +static const char * +get_environ_assignment (const char *name) +{ + size_t name_len = strlen (name); + char **p; + for (p = environ; *p != NULL; p++) + { + const char *assignment = *p; + if (strncmp (assignment, name, name_len) == 0 + && assignment[name_len] == '=') + return assignment; + } + return NULL; +} + +/* Creates a minimal environment. */ +static void +create_minimal_env (const char *env[5]) +{ + const char **p = env; + *p++ = + #ifdef __CYGWIN__ + /* The Cygwin DLLs needed by the program are in /bin. */ + "PATH=.:/bin"; + #else + "PATH=."; + #endif + *p = get_environ_assignment ("QEMU_LD_PREFIX"); + if (*p != NULL) + p++; + *p = get_environ_assignment ("QEMU_CPU"); + if (*p != NULL) + p++; + *p++ = "Hommingberg=Gepardenforelle"; + *p = NULL; +} int main () { const char *progname = "./test-exec-child"; - const char *env[3] = - { - #ifdef __CYGWIN__ - /* The Cygwin DLLs needed by the program are in /bin. */ - "PATH=.:/bin", - #else - "PATH=.", - #endif - "Hommingberg=Gepardenforelle", - NULL - }; const char *argv[12] = { progname, @@ -56,6 +85,8 @@ main () "", NULL }; + const char *env[5]; + create_minimal_env (env); execve (progname, (char * const *) argv, (char * const *) env); perror ("execve"); diff --git a/tests/test-execvpe-main.c b/tests/test-execvpe-main.c index 560ae8e69..c7aa0a3a2 100644 --- a/tests/test-execvpe-main.c +++ b/tests/test-execvpe-main.c @@ -25,22 +25,51 @@ SIGNATURE_CHECK (execvpe, int, (const char *, char * const *, char * const *)); #include <stdio.h> +#include <string.h> + +/* Looks up the NAME=VALUE assignment among the environment variables. + Returns it, or NULL if not found. */ +static const char * +get_environ_assignment (const char *name) +{ + size_t name_len = strlen (name); + char **p; + for (p = environ; *p != NULL; p++) + { + const char *assignment = *p; + if (strncmp (assignment, name, name_len) == 0 + && assignment[name_len] == '=') + return assignment; + } + return NULL; +} + +/* Creates a minimal environment. */ +static void +create_minimal_env (const char *env[5]) +{ + const char **p = env; + *p++ = + #ifdef __CYGWIN__ + /* The Cygwin DLLs needed by the program are in /bin. */ + "PATH=.:/bin"; + #else + "PATH=."; + #endif + *p = get_environ_assignment ("QEMU_LD_PREFIX"); + if (*p != NULL) + p++; + *p = get_environ_assignment ("QEMU_CPU"); + if (*p != NULL) + p++; + *p++ = "Hommingberg=Gepardenforelle"; + *p = NULL; +} int main () { const char *progname = "test-exec-child"; - const char *env[3] = - { - #ifdef __CYGWIN__ - /* The Cygwin DLLs needed by the program are in /bin. */ - "PATH=.:/bin", - #else - "PATH=.", - #endif - "Hommingberg=Gepardenforelle", - NULL - }; const char *argv[12] = { progname, @@ -56,6 +85,8 @@ main () "", NULL }; + const char *env[5]; + create_minimal_env (env); execvpe (progname, (char * const *) argv, (char * const *) env); perror ("execvpe");