systemctl: implement a new "whoami" verb, that just returns unit of caller/PID

This commit is contained in:
Lennart Poettering 2023-07-03 14:36:14 +02:00 committed by Luca Boccassi
parent f2492d39ba
commit c86a95082b
6 changed files with 104 additions and 1 deletions

View file

@ -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.</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>

View file

@ -36,6 +36,7 @@ systemctl_sources = files(
'systemctl-sysv-compat.c',
'systemctl-trivial-method.c',
'systemctl-util.c',
'systemctl-whoami.c',
'systemctl.c',
)

View file

@ -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;
}
}

View file

@ -0,0 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
int verb_whoami(int argc, char *argv[], void *userdata);

View file

@ -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 },
{}
};

View file

@ -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