From c86a95082b032fc6a0ff83b732f70ff53e45e4b6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 3 Jul 2023 14:36:14 +0200 Subject: [PATCH] systemctl: implement a new "whoami" verb, that just returns unit of caller/PID --- man/systemctl.xml | 9 ++++ src/systemctl/meson.build | 1 + src/systemctl/systemctl-whoami.c | 70 +++++++++++++++++++++++++++++++ src/systemctl/systemctl-whoami.h | 4 ++ src/systemctl/systemctl.c | 6 ++- test/units/testsuite-23.whoami.sh | 15 +++++++ 6 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/systemctl/systemctl-whoami.c create mode 100644 src/systemctl/systemctl-whoami.h create mode 100755 test/units/testsuite-23.whoami.sh diff --git a/man/systemctl.xml b/man/systemctl.xml index cc7d2ea08a2..2e2daa4526c 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -740,6 +740,15 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err to be started again, use this command to make it startable again. + + + whoami [PID…] + + Returns the units the processes referenced by the given PIDs belong to (one per + line). If no PID is specified returns the unit the systemctl command is invoked + in. + + diff --git a/src/systemctl/meson.build b/src/systemctl/meson.build index 07049ca920f..f45cbc47d30 100644 --- a/src/systemctl/meson.build +++ b/src/systemctl/meson.build @@ -36,6 +36,7 @@ systemctl_sources = files( 'systemctl-sysv-compat.c', 'systemctl-trivial-method.c', 'systemctl-util.c', + 'systemctl-whoami.c', 'systemctl.c', ) diff --git a/src/systemctl/systemctl-whoami.c b/src/systemctl/systemctl-whoami.c new file mode 100644 index 00000000000..4ee65925256 --- /dev/null +++ b/src/systemctl/systemctl-whoami.c @@ -0,0 +1,70 @@ +/* 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; + } +} diff --git a/src/systemctl/systemctl-whoami.h b/src/systemctl/systemctl-whoami.h new file mode 100644 index 00000000000..abdd13b34fc --- /dev/null +++ b/src/systemctl/systemctl-whoami.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +int verb_whoami(int argc, char *argv[], void *userdata); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 143c8b41b28..989318360cf 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -59,6 +59,7 @@ #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" @@ -193,7 +194,9 @@ static int systemctl_help(void) { " 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" @@ -1213,6 +1216,7 @@ static int systemctl_main(int argc, char *argv[]) { { "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 }, {} }; diff --git a/test/units/testsuite-23.whoami.sh b/test/units/testsuite-23.whoami.sh new file mode 100755 index 00000000000..a0c73b85647 --- /dev/null +++ b/test/units/testsuite-23.whoami.sh @@ -0,0 +1,15 @@ +#!/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