to be started again, use this command to make it startable again.</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><command>whoami [<replaceable>PID</replaceable>…]</command></term>
+
+ <listitem><para>Returns the units the processes referenced by the given PIDs belong to (one per
+ line). If no PID is specified returns the unit the <command>systemctl</command> command is invoked
+ in.</para></listitem>
+ </varlistentry>
+
</variablelist>
</refsect2>
'systemctl-sysv-compat.c',
'systemctl-trivial-method.c',
'systemctl-util.c',
+ 'systemctl-whoami.c',
'systemctl.c',
)
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "systemctl.h"
+#include "systemctl-util.h"
+#include "systemctl-whoami.h"
+#include "parse-util.h"
+
+static int lookup_pid(sd_bus *bus, pid_t pid) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_free_ char *unit = NULL;
+ const char *path;
+ int r;
+
+ r = bus_call_method(bus, bus_systemd_mgr, "GetUnitByPID", &error, &reply, "u", (uint32_t) pid);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get unit for ourselves: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_read(reply, "o", &path);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = unit_name_from_dbus_path(path, &unit);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract unit name from D-Bus object path '%s': %m", path);
+
+ printf("%s\n", unit);
+ return 0;
+}
+
+int verb_whoami(int argc, char *argv[], void *userdata) {
+ sd_bus *bus;
+ int r;
+
+ r = acquire_bus(BUS_FULL, &bus);
+ if (r < 0)
+ return r;
+
+ char **pids = strv_skip(argv, 1);
+
+ if (strv_isempty(pids)) {
+
+ if (arg_transport != BUS_TRANSPORT_LOCAL)
+ return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "Refusing to look up local PID on remote host.");
+
+ return lookup_pid(bus, 0);
+ } else {
+ int ret = 0;
+
+ STRV_FOREACH(p, pids) {
+ pid_t pid;
+
+ r = parse_pid(*p, &pid);
+ if (r < 0) {
+ log_error_errno(r, "Failed to parse PID: %s", *p);
+ if (ret >= 0)
+ ret = r;
+ continue;
+ }
+
+ r = lookup_pid(bus, pid);
+ if (r < 0 && ret >= 0)
+ ret = r;
+ }
+
+ return ret;
+ }
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+int verb_whoami(int argc, char *argv[], void *userdata);
#include "systemctl-sysv-compat.h"
#include "systemctl-trivial-method.h"
#include "systemctl-util.h"
+#include "systemctl-whoami.h"
#include "systemctl.h"
#include "terminal-util.h"
#include "time-util.h"
" service-log-level SERVICE [LEVEL] Get/set logging threshold for service\n"
" service-log-target SERVICE [TARGET] Get/set logging target for service\n"
" reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
- " units"
+ " units\n"
+ " whoami [PID...] Return unit caller or specified PIDs are\n"
+ " part of\n"
"\n%3$sUnit File Commands:%4$s\n"
" list-unit-files [PATTERN...] List installed unit files\n"
" enable [UNIT...|PATH...] Enable one or more unit files\n"
{ "edit", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_edit },
{ "bind", 3, 4, VERB_ONLINE_ONLY, verb_bind },
{ "mount-image", 4, 5, VERB_ONLINE_ONLY, verb_mount_image },
+ { "whoami", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_whoami },
{}
};
--- /dev/null
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+set -eux
+set -o pipefail
+
+test "$(systemctl whoami)" = testsuite-23.service
+test "$(systemctl whoami $$)" = testsuite-23.service
+
+systemctl whoami 1 $$ 1 | cmp - /dev/fd/3 3<<'EOF'
+init.scope
+testsuite-23.service
+init.scope
+EOF