]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Add $SYSTEMD_INVOKED_AS
authorZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Mon, 25 May 2026 09:07:01 +0000 (11:07 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Mon, 25 May 2026 10:37:36 +0000 (12:37 +0200)
This allows multi-call binaries to be easily invoked with a different
name. After installation, the name is set by creating a symlink. But in
build directories, we don't create the symlinks. (There are also other
ways to achieve the same thing, e.g. zsh supports $ARGV0, and exec -a
can be used, but those are either non-portable or are more complicated
to use.)  The primary use-case for me is to test --help output for
multicall binaries.

Also reorder the help for env vars to group the more generic ones near
the top.

This was initially proposed in https://github.com/systemd/systemd/pull/24054,
but there were some comments about the implementation. I had a branch
with the patch, but I don't think I ever actually submitted it as a
pull request.

docs/ENVIRONMENT.md
src/basic/argv-util.c
src/shared/help-util.c
src/test/test-process-util.c

index 53f4a1a60c8967907da48d95a09ca758277f7e37..a55e91ff203d206e415d566d5ca42d361d3cadaa 100644 (file)
@@ -35,11 +35,15 @@ All tools:
   no-ops. If that's what's explicitly desired, you might consider setting
   `$SYSTEMD_OFFLINE=1`.
 
+* `$SYSTEMD_IN_INITRD` — takes a boolean. If set, overrides initrd detection.
+  This is useful for debugging and testing initrd-only programs in the main
+  system.
+
 * `$SYSTEMD_FIRST_BOOT=0|1` — if set, assume "first boot" condition to be false
   or true, instead of checking the flag file created by PID 1.
 
-* `$SD_EVENT_PROFILE_DELAYS=1` — if set, the sd-event event loop implementation
-  will print latency information at runtime.
+* `$SYSTEMD_INVOKED_AS=name` — override argv[0] for detection of a multicall
+  binary. E.g. `SYSTEMD_INVOKED_AS=systemd-udevd build/udevadm`.
 
 * `$SYSTEMD_PROC_CMDLINE` — if set, the contents are used as the kernel command
   line instead of the actual one in `/proc/cmdline`. This is useful for
@@ -76,9 +80,8 @@ All tools:
   (relevant in particular for the system manager and `systemd-hostnamed`).
   Must be a valid hostname (either a single label or a FQDN).
 
-* `$SYSTEMD_IN_INITRD` — takes a boolean. If set, overrides initrd detection.
-  This is useful for debugging and testing initrd-only programs in the main
-  system.
+* `$SD_EVENT_PROFILE_DELAYS=1` — if set, the sd-event event loop implementation
+  will print latency information at runtime.
 
 * `$SYSTEMD_BUS_TIMEOUT=SECS` — specifies the maximum time to wait for method call
   completion. If no time unit is specified, assumes seconds. The usual other units
index 10f8cd86f4aad5bf54a574013eebb253db881af9..cefe6900bedaff4930d50d582e87f38e0a877eca 100644 (file)
@@ -29,13 +29,15 @@ void save_argc_argv(int argc, char **argv) {
 }
 
 bool invoked_as(char *argv[], const char *token) {
-        if (!argv || isempty(argv[0]))
-                return false;
+        const char *progname = secure_getenv("SYSTEMD_INVOKED_AS");
+
+        if (!progname && argv)
+                progname = argv[0];
 
-        if (isempty(token))
+        if (isempty(progname) || isempty(token))
                 return false;
 
-        return strstr(last_path_component(argv[0]), token);
+        return strstr(last_path_component(progname), token);
 }
 
 bool invoked_by_systemd(void) {
index 7b67bb58f1a21d88267e8fe4ac58411276f9f35a..8968ba13771518394a83fd5a5dd59dcbc1dad9cf 100644 (file)
@@ -1,8 +1,11 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include <stdlib.h>
+
 #include "alloc-util.h"
 #include "ansi-color.h"
 #include "help-util.h"
+#include "path-util.h"
 #include "pretty-print.h"
 
 /* These are helpers for putting together --help texts in a uniform way with a common output style. Each
  *   options.[ch] APIs. */
 
 void help_cmdline(const char *arguments) {
+        const char *progname =
+                last_path_component(secure_getenv("SYSTEMD_INVOKED_AS"))
+                ?: program_invocation_short_name;
+
         assert(arguments);
 
         printf("%s>%s %s %s\n",
                ansi_grey(),
                ansi_normal(),
-               program_invocation_short_name,
+               progname,
                arguments);
 }
 
index 4c803fbbd9c38dca09142b0016fb7ad456b58656..63458117cb9378a41a8398cea9c5f980137f1979 100644 (file)
@@ -1125,6 +1125,21 @@ TEST(getenv_for_pid) {
         }
 }
 
+TEST(invoked_as) {
+        ASSERT_FALSE(invoked_as(NULL, "foobar"));
+        ASSERT_FALSE(invoked_as(NULL, "barbar"));
+
+        ASSERT_EQ(setenv("SYSTEMD_INVOKED_AS", "/usr/bin/foobar", 1), 0);
+
+        ASSERT_TRUE(invoked_as(NULL, "foobar"));
+        ASSERT_FALSE(invoked_as(NULL, "barbar"));
+        ASSERT_TRUE(invoked_as(NULL, "foo"));
+        ASSERT_TRUE(invoked_as(STRV_MAKE("barbar", "barbar", "y"), "foobar"));
+        ASSERT_FALSE(invoked_as(STRV_MAKE("barbar", "barbar", "y"), "barbar"));
+
+        ASSERT_EQ(unsetenv("SYSTEMD_INVOKED_AS"), 0);
+}
+
 static int intro(void) {
         log_show_color(true);
         return EXIT_SUCCESS;