From 0527559e7bc73c9153ee837c83e5c0d7ff7ebbe6 Mon Sep 17 00:00:00 2001 From: Brandon Payton Date: Mon, 13 Jul 2026 06:57:36 -0400 Subject: [PATCH] libc: preserve short program invocation names Restore musl's basename derivation in the Wasm __libc_start_main overlay so program_invocation_short_name reflects argv[0] without its directory. Programs such as procps pkill use that standard libc identity to select behavior.\n\nExtend the exec regression fixture to cover both the full and short program invocation names. --- host/test/exec.test.ts | 8 +++++++- libc/musl-overlay/src/env/__libc_start_main.c | 2 ++ programs/exec-caller.c | 2 +- programs/exec-child.c | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/host/test/exec.test.ts b/host/test/exec.test.ts index 5726624ada..fe3222a3e1 100644 --- a/host/test/exec.test.ts +++ b/host/test/exec.test.ts @@ -23,6 +23,7 @@ describe("execve", () => { argv: ["exec-caller"], timeout: 15_000, execPrograms, + useDefaultRootfs: false, }); // exec-child exits with 42 @@ -30,9 +31,13 @@ describe("execve", () => { // exec-child prints its argv expect(result.stdout).toContain("argc=3"); - expect(result.stdout).toContain("argv[0]=exec-child"); + expect(result.stdout).toContain("argv[0]=/opt/kandelo/bin/exec-child"); expect(result.stdout).toContain("argv[1]=hello"); expect(result.stdout).toContain("argv[2]=world"); + expect(result.stdout).toContain( + "program_invocation_name=/opt/kandelo/bin/exec-child", + ); + expect(result.stdout).toContain("program_invocation_short_name=exec-child"); // exec-child prints env vars passed by exec-caller expect(result.stdout).toContain("FOO=bar"); @@ -45,6 +50,7 @@ describe("execve", () => { argv: ["fork-exec"], timeout: 15_000, execPrograms, + useDefaultRootfs: false, }); // Parent exits 0 diff --git a/libc/musl-overlay/src/env/__libc_start_main.c b/libc/musl-overlay/src/env/__libc_start_main.c index 7996193ab4..105030d934 100644 --- a/libc/musl-overlay/src/env/__libc_start_main.c +++ b/libc/musl-overlay/src/env/__libc_start_main.c @@ -31,6 +31,7 @@ int __init_tp(void *); void __init_libc(char **envp, char *pn) { + size_t i; __environ = envp; /* On Wasm, there is no auxv, TLS, or secure-execution mode. @@ -46,6 +47,7 @@ void __init_libc(char **envp, char *pn) if (!pn) pn = ""; __progname = __progname_full = pn; + for (i=0; pn[i]; i++) if (pn[i]=='/') __progname = pn+i+1; /* Initialize the thread pointer for the main thread. * Set __wasm_thread_pointer to point at __wasm_tp_storage, diff --git a/programs/exec-caller.c b/programs/exec-caller.c index 5fff36df05..f4eef9de01 100644 --- a/programs/exec-caller.c +++ b/programs/exec-caller.c @@ -8,7 +8,7 @@ extern char **environ; int main(void) { - char *argv[] = {"exec-child", "hello", "world", NULL}; + char *argv[] = {"/opt/kandelo/bin/exec-child", "hello", "world", NULL}; char *envp[] = {"FOO=bar", "TEST=exec", NULL}; execve("/bin/exec-child", argv, envp); /* If we get here, exec failed */ diff --git a/programs/exec-child.c b/programs/exec-child.c index c54f7a2e67..af4bda2b71 100644 --- a/programs/exec-child.c +++ b/programs/exec-child.c @@ -2,13 +2,17 @@ * exec-child.c — Target program for exec tests. * Prints its argv and selected env vars to verify exec passed them correctly. */ +#define _GNU_SOURCE #include #include +#include int main(int argc, char *argv[]) { printf("argc=%d\n", argc); for (int i = 0; i < argc; i++) printf("argv[%d]=%s\n", i, argv[i]); + printf("program_invocation_name=%s\n", program_invocation_name); + printf("program_invocation_short_name=%s\n", program_invocation_short_name); const char *foo = getenv("FOO"); if (foo) printf("FOO=%s\n", foo);