[libc-commits] [libc] [libc] Add program_invocation(_short)_name and tweak err.h functions (PR #212448)

Jeff Bailey via libc-commits libc-commits at lists.llvm.org
Mon Aug 3 06:04:33 PDT 2026


================
@@ -0,0 +1,140 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Integration test for program_invocation_name.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/CPP/string_view.h"
+#include "src/errno/program_invocation_name.h"
+#include "src/errno/program_invocation_short_name.h"
+#include "src/unistd/execve.h"
+#include "test/IntegrationTest/test.h"
+
+TEST_MAIN(int argc, char **argv, char **envp) {
+  ASSERT_TRUE(argc >= 1);
+  ASSERT_TRUE(LIBC_NAMESPACE::program_invocation_name != nullptr);
+  ASSERT_TRUE(LIBC_NAMESPACE::program_invocation_short_name != nullptr);
+  ASSERT_TRUE(LIBC_NAMESPACE::program_invocation_name == argv[0]);
+
+  LIBC_NAMESPACE::cpp::string_view arg1 = argc > 1 ? argv[1] : "";
+
+  if (arg1 == "reexec1") {
+    // Step 1: Executed with an absolute path containing slashes.
+    ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name,
+                 "/known/path/to/invocation_name");
+    ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name,
+                 "invocation_name");
+
+    ASSERT_EQ(argc, 3);
+    const char *self_path = argv[2];
+    char *const child_argv[] = {
+        const_cast<char *>("./relative/path/to/invocation_name"),
+        const_cast<char *>("reexec2"),
+        const_cast<char *>(self_path),
+        nullptr,
+    };
+    LIBC_NAMESPACE::execve(self_path, child_argv, envp);
+    ASSERT_TRUE(false);
+  }
+
+  if (arg1 == "reexec2") {
+    // Step 2: Executed with a relative path containing slashes.
+    ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name,
+                 "./relative/path/to/invocation_name");
+    ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name,
+                 "invocation_name");
+
+    ASSERT_EQ(argc, 3);
+    const char *self_path = argv[2];
+    char *const child_argv[] = {
+        const_cast<char *>(""),
+        const_cast<char *>("reexec3"),
+        const_cast<char *>(self_path),
+        nullptr,
+    };
+    LIBC_NAMESPACE::execve(self_path, child_argv, envp);
+    ASSERT_TRUE(false);
+  }
+
+  if (arg1 == "reexec3") {
+    // Step 3: Executed with an empty string.
+    ASSERT_TRUE(LIBC_NAMESPACE::program_invocation_name ==
+                LIBC_NAMESPACE::program_invocation_short_name);
+    ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name, "");
+    ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name, "");
+
+    ASSERT_EQ(argc, 3);
+    const char *self_path = argv[2];
+    char *const child_argv[] = {
+        const_cast<char *>("/known/path/to/dir/"),
+        const_cast<char *>("reexec4"),
+        const_cast<char *>(self_path),
+        nullptr,
+    };
+    LIBC_NAMESPACE::execve(self_path, child_argv, envp);
+    ASSERT_TRUE(false);
+  }
+
+  if (arg1 == "reexec4") {
+    // Step 4: Executed with a path ending in a slash.
+    ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name,
+                 "/known/path/to/dir/");
+    ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name, "");
+
+    ASSERT_EQ(argc, 3);
+    const char *self_path = argv[2];
+    char *const child_argv[] = {
+        const_cast<char *>("invocation_name_no_slash"),
+        const_cast<char *>("reexec5"),
+        const_cast<char *>(self_path),
+        nullptr,
+    };
+    LIBC_NAMESPACE::execve(self_path, child_argv, envp);
+    ASSERT_TRUE(false);
+  }
+
+  if (arg1 == "reexec5") {
+    // Step 5: Executed with a path without slashes.
+    ASSERT_TRUE(LIBC_NAMESPACE::program_invocation_name ==
+                LIBC_NAMESPACE::program_invocation_short_name);
+    ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_name,
+                 "invocation_name_no_slash");
+    ASSERT_STREQ(LIBC_NAMESPACE::program_invocation_short_name,
+                 "invocation_name_no_slash");
+
+    ASSERT_EQ(argc, 3);
+    const char *self_path = argv[2];
+    char *const child_argv[] = {
+        nullptr,
+    };
+    LIBC_NAMESPACE::execve(self_path, child_argv, envp);
+    ASSERT_TRUE(false);
+  }
+
+  if (argc == 1 && LIBC_NAMESPACE::cpp::string_view(argv[0]) == "") {
+    // Step 6: Executed with an empty (zero-length) argv. The kernel changes
----------------
kaladron wrote:

```suggestion
    // Step 6: Executed with an empty (zero-length) argv. The kernel
```

https://github.com/llvm/llvm-project/pull/212448


More information about the libc-commits mailing list