2020-11-09 05:23:58 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
2011-05-26 02:21:16 +02:00
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2020-06-28 16:43:29 +02:00
|
|
|
#include "bus-get-properties.h"
|
2020-01-22 11:39:22 +01:00
|
|
|
#include "bus-polkit.h"
|
2013-11-05 01:10:21 +01:00
|
|
|
#include "bus-util.h"
|
2016-11-07 16:14:59 +01:00
|
|
|
#include "format-util.h"
|
2019-04-30 15:05:14 +02:00
|
|
|
#include "logind-dbus.h"
|
|
|
|
#include "logind-session-dbus.h"
|
|
|
|
#include "logind-user-dbus.h"
|
2015-10-25 22:32:30 +01:00
|
|
|
#include "logind-user.h"
|
|
|
|
#include "logind.h"
|
2018-12-04 08:26:09 +01:00
|
|
|
#include "missing_capability.h"
|
2016-04-08 11:27:28 +02:00
|
|
|
#include "signal-util.h"
|
2015-10-25 22:32:30 +01:00
|
|
|
#include "strv.h"
|
|
|
|
#include "user-util.h"
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2019-08-07 16:22:35 +02:00
|
|
|
static int property_get_uid(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
|
|
|
|
|
|
|
User *u = userdata;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
|
|
|
|
|
|
|
return sd_bus_message_append(reply, "u", (uint32_t) u->user_record->uid);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int property_get_gid(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
|
|
|
|
|
|
|
User *u = userdata;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
|
|
|
|
|
|
|
return sd_bus_message_append(reply, "u", (uint32_t) u->user_record->gid);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int property_get_name(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
|
|
|
|
|
|
|
User *u = userdata;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
|
|
|
|
|
|
|
return sd_bus_message_append(reply, "s", u->user_record->user_name);
|
|
|
|
}
|
|
|
|
|
2018-05-14 03:02:55 +02:00
|
|
|
static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", User, user_get_state, user_state_to_string);
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
static int property_get_display(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
_cleanup_free_ char *p = NULL;
|
|
|
|
User *u = userdata;
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
p = u->display ? session_bus_path(u->display) : strdup("/");
|
|
|
|
if (!p)
|
2011-05-26 02:21:16 +02:00
|
|
|
return -ENOMEM;
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
return sd_bus_message_append(reply, "(so)", u->display ? u->display->id : "", p);
|
2011-05-26 02:21:16 +02:00
|
|
|
}
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
static int property_get_sessions(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-11-05 01:10:21 +01:00
|
|
|
|
|
|
|
User *u = userdata;
|
2011-05-26 02:21:16 +02:00
|
|
|
Session *session;
|
2013-11-05 01:10:21 +01:00
|
|
|
int r;
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2011-05-26 02:21:16 +02:00
|
|
|
assert(u);
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
r = sd_bus_message_open_container(reply, 'a', "(so)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2011-05-26 02:21:16 +02:00
|
|
|
|
|
|
|
LIST_FOREACH(sessions_by_user, session, u->sessions) {
|
2013-11-05 01:10:21 +01:00
|
|
|
_cleanup_free_ char *p = NULL;
|
2011-05-26 02:21:16 +02:00
|
|
|
|
|
|
|
p = session_bus_path(session);
|
|
|
|
if (!p)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
r = sd_bus_message_append(reply, "(so)", session->id, p);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2011-05-26 02:21:16 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-07-08 14:35:32 +02:00
|
|
|
return sd_bus_message_close_container(reply);
|
2011-05-26 02:21:16 +02:00
|
|
|
}
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
static int property_get_idle_hint(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2011-06-17 15:59:18 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
User *u = userdata;
|
2011-06-21 22:29:25 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
2011-06-17 15:59:18 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
return sd_bus_message_append(reply, "b", user_get_idle_hint(u, NULL) > 0);
|
2011-06-17 15:59:18 +02:00
|
|
|
}
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
static int property_get_idle_since_hint(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-11-05 01:10:21 +01:00
|
|
|
|
|
|
|
User *u = userdata;
|
2015-06-16 01:08:12 +02:00
|
|
|
dual_timestamp t = DUAL_TIMESTAMP_NULL;
|
2011-06-17 15:59:18 +02:00
|
|
|
uint64_t k;
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2011-06-17 15:59:18 +02:00
|
|
|
assert(u);
|
|
|
|
|
2018-08-06 19:04:49 +02:00
|
|
|
(void) user_get_idle_hint(u, &t);
|
2011-06-17 15:59:18 +02:00
|
|
|
k = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
return sd_bus_message_append(reply, "t", k);
|
2011-06-17 15:59:18 +02:00
|
|
|
}
|
|
|
|
|
2013-11-05 01:27:27 +01:00
|
|
|
static int property_get_linger(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-11-05 01:27:27 +01:00
|
|
|
|
|
|
|
User *u = userdata;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
|
|
|
assert(u);
|
|
|
|
|
|
|
|
r = user_check_linger_file(u);
|
|
|
|
|
|
|
|
return sd_bus_message_append(reply, "b", r > 0);
|
|
|
|
}
|
|
|
|
|
2015-04-29 18:35:10 +02:00
|
|
|
int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
2013-11-05 01:10:21 +01:00
|
|
|
User *u = userdata;
|
2011-05-26 02:21:16 +02:00
|
|
|
int r;
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
assert(message);
|
|
|
|
assert(u);
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2015-02-18 12:55:25 +01:00
|
|
|
r = bus_verify_polkit_async(
|
|
|
|
message,
|
|
|
|
CAP_KILL,
|
|
|
|
"org.freedesktop.login1.manage",
|
2015-09-05 16:07:16 +02:00
|
|
|
NULL,
|
2015-02-18 12:55:25 +01:00
|
|
|
false,
|
2019-08-07 16:22:35 +02:00
|
|
|
u->user_record->uid,
|
2015-02-18 12:55:25 +01:00
|
|
|
&u->manager->polkit_registry,
|
|
|
|
error);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
if (r == 0)
|
|
|
|
return 1; /* Will call us back */
|
|
|
|
|
2020-09-11 17:59:39 +02:00
|
|
|
r = user_stop(u, /* force */ true);
|
2011-05-26 02:21:16 +02:00
|
|
|
if (r < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return r;
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2013-11-21 01:51:16 +01:00
|
|
|
return sd_bus_reply_method_return(message, NULL);
|
2011-05-26 02:21:16 +02:00
|
|
|
}
|
|
|
|
|
2015-04-29 18:35:10 +02:00
|
|
|
int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
2013-11-05 01:10:21 +01:00
|
|
|
User *u = userdata;
|
|
|
|
int32_t signo;
|
2011-06-17 15:59:18 +02:00
|
|
|
int r;
|
|
|
|
|
2011-05-26 02:21:16 +02:00
|
|
|
assert(message);
|
2013-11-05 01:10:21 +01:00
|
|
|
assert(u);
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2015-02-18 12:55:25 +01:00
|
|
|
r = bus_verify_polkit_async(
|
|
|
|
message,
|
|
|
|
CAP_KILL,
|
|
|
|
"org.freedesktop.login1.manage",
|
2015-09-05 16:07:16 +02:00
|
|
|
NULL,
|
2015-02-18 12:55:25 +01:00
|
|
|
false,
|
2019-08-07 16:22:35 +02:00
|
|
|
u->user_record->uid,
|
2015-02-18 12:55:25 +01:00
|
|
|
&u->manager->polkit_registry,
|
|
|
|
error);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
if (r == 0)
|
|
|
|
return 1; /* Will call us back */
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
r = sd_bus_message_read(message, "i", &signo);
|
|
|
|
if (r < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return r;
|
2011-06-17 15:59:18 +02:00
|
|
|
|
2016-04-08 11:27:28 +02:00
|
|
|
if (!SIGNAL_VALID(signo))
|
2013-11-21 19:34:37 +01:00
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
|
2011-06-17 15:59:18 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
r = user_kill(u, signo);
|
|
|
|
if (r < 0)
|
2013-11-21 19:34:37 +01:00
|
|
|
return r;
|
2011-06-17 15:59:18 +02:00
|
|
|
|
2013-11-21 01:51:16 +01:00
|
|
|
return sd_bus_reply_method_return(message, NULL);
|
2011-05-26 02:21:16 +02:00
|
|
|
}
|
|
|
|
|
2020-04-23 01:00:07 +02:00
|
|
|
static int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
|
2011-05-26 02:21:16 +02:00
|
|
|
Manager *m = userdata;
|
2015-01-09 16:14:19 +01:00
|
|
|
uid_t uid;
|
2013-11-05 01:10:21 +01:00
|
|
|
User *user;
|
2011-05-26 02:21:16 +02:00
|
|
|
int r;
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(path);
|
|
|
|
assert(interface);
|
|
|
|
assert(found);
|
|
|
|
assert(m);
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2013-11-05 20:52:39 +01:00
|
|
|
if (streq(path, "/org/freedesktop/login1/user/self")) {
|
|
|
|
sd_bus_message *message;
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2014-05-15 01:15:30 +02:00
|
|
|
message = sd_bus_get_current_message(bus);
|
2013-11-05 20:52:39 +01:00
|
|
|
|
logind: "self" objects which do not apply - return specific error messages
It's confusing that the bus API has aliases like "session/self" that return
an error based on ENXIO, when it also has methods that return e.g.
NO_SESSION_FOR_PID for the same problem. The latter kind of error includes
more specifically helpful messages.
"user/self" is the odd one out; it returns a generic UnknownObject error
when it is not applicable to the caller. It's not clear whether this was
intentional, but at first I thought it was more correct. More
specifically, user_object_find() was returning 0 for "user/self", in the
same situations (more or less) where user_node_enumerator() was omitting
"user/self". I thought that was a good idea, because returning e.g. -ENXIO instead
suggested that there _is_ something specific on that path. And it could be
confused with errors of the method being called.
Therefore I suggested changing the enumerator, always admitting that there
is a handler for the path "foo/self", but returning a specific error when
queried. However this interacts poorly with tools like D-Feet or `busctl`.
In either tool, looking at logind would show an error message, and then go
on to omit "user/self" in the normal listing. These tools are very useful,
so we don't want to interfere with them.
I think we can change the error codes without causing problems. The self
objects were not listed in the documentation. They have been suggested to
other projects - but without reference to error reporting. "seat/self" is
used by various Wayland compositors for VT switching, but they don't appear
to reference specific errors.
We _could_ insist on the link between enumeration and UnknownObject, and
standardize on that as the error for the aliases. But I'm not aware of any
practical complaints, that we returned an error from an object that didn't
exist.
Instead, let's unify the codepaths for "user/self" vs GetUserByPid(0) etc.
We will return the most helpful error message we can think of, if the
object does not exist. E.g. for "session/self", we might return an error
that the caller does not belong to a session. If one of the compositors is
ever simplified to use "session/self" in initialization, users would be
able to trigger such errors (e.g. run `gnome-shell` inside gnome-terminal).
The message text will most likely be logged. The user might not know what
the "session" is, but at least we'll be pointing towards the right
questions. I think it should also be clearer for development / debugging.
Unifying the code paths is also slightly helpful for auditing / marking
calls to sd_bus_creds_get_session() in subsequent commits.
2017-10-14 10:25:56 +02:00
|
|
|
r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
|
2019-04-30 13:48:34 +02:00
|
|
|
if (r == -ENXIO) {
|
|
|
|
sd_bus_error_free(error);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-11-05 20:52:39 +01:00
|
|
|
if (r < 0)
|
2013-11-28 17:50:02 +01:00
|
|
|
return r;
|
2013-11-05 20:52:39 +01:00
|
|
|
} else {
|
|
|
|
const char *p;
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2013-11-05 20:52:39 +01:00
|
|
|
p = startswith(path, "/org/freedesktop/login1/user/_");
|
|
|
|
if (!p)
|
|
|
|
return 0;
|
|
|
|
|
2015-01-09 16:14:19 +01:00
|
|
|
r = parse_uid(p, &uid);
|
2018-01-04 11:36:35 +01:00
|
|
|
if (r < 0)
|
|
|
|
return 0;
|
2015-01-09 16:14:19 +01:00
|
|
|
|
2018-01-04 11:36:35 +01:00
|
|
|
user = hashmap_get(m->users, UID_TO_PTR(uid));
|
|
|
|
if (!user)
|
|
|
|
return 0;
|
|
|
|
}
|
2011-05-26 02:21:16 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
*found = user;
|
|
|
|
return 1;
|
2011-05-26 02:21:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
char *user_bus_path(User *u) {
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
assert(u);
|
|
|
|
|
2019-08-07 16:22:35 +02:00
|
|
|
if (asprintf(&s, "/org/freedesktop/login1/user/_"UID_FMT, u->user_record->uid) < 0)
|
2011-05-26 02:21:16 +02:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
2011-06-21 20:43:34 +02:00
|
|
|
|
2020-04-23 01:00:07 +02:00
|
|
|
static int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
|
2013-11-05 01:10:21 +01:00
|
|
|
_cleanup_strv_free_ char **l = NULL;
|
2015-01-18 12:59:39 +01:00
|
|
|
sd_bus_message *message;
|
2013-11-05 01:10:21 +01:00
|
|
|
Manager *m = userdata;
|
|
|
|
User *user;
|
|
|
|
int r;
|
2011-06-21 20:43:34 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(path);
|
|
|
|
assert(nodes);
|
2011-06-21 20:43:34 +02:00
|
|
|
|
2020-09-08 11:58:29 +02:00
|
|
|
HASHMAP_FOREACH(user, m->users) {
|
2013-11-05 01:10:21 +01:00
|
|
|
char *p;
|
2011-06-21 20:43:34 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
p = user_bus_path(user);
|
|
|
|
if (!p)
|
|
|
|
return -ENOMEM;
|
2011-06-21 20:43:34 +02:00
|
|
|
|
2014-03-04 15:20:51 +01:00
|
|
|
r = strv_consume(&l, p);
|
|
|
|
if (r < 0)
|
2013-11-05 01:10:21 +01:00
|
|
|
return r;
|
|
|
|
}
|
2011-06-21 20:43:34 +02:00
|
|
|
|
2015-01-18 12:59:39 +01:00
|
|
|
message = sd_bus_get_current_message(bus);
|
|
|
|
if (message) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
2015-01-18 12:59:39 +01:00
|
|
|
|
|
|
|
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
|
|
|
|
if (r >= 0) {
|
2019-04-30 13:48:34 +02:00
|
|
|
uid_t uid;
|
|
|
|
|
2015-01-18 12:59:39 +01:00
|
|
|
r = sd_bus_creds_get_owner_uid(creds, &uid);
|
|
|
|
if (r >= 0) {
|
|
|
|
user = hashmap_get(m->users, UID_TO_PTR(uid));
|
|
|
|
if (user) {
|
|
|
|
r = strv_extend(&l, "/org/freedesktop/login1/user/self");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-09 01:44:40 +01:00
|
|
|
|
2018-04-05 07:26:26 +02:00
|
|
|
*nodes = TAKE_PTR(l);
|
2011-06-21 20:43:34 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-04-23 01:00:07 +02:00
|
|
|
static const sd_bus_vtable user_vtable[] = {
|
|
|
|
SD_BUS_VTABLE_START(0),
|
|
|
|
|
|
|
|
SD_BUS_PROPERTY("UID", "u", property_get_uid, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("GID", "u", property_get_gid, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(User, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
|
|
|
|
SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, 0),
|
|
|
|
SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0),
|
|
|
|
|
|
|
|
SD_BUS_METHOD("Terminate", NULL, NULL, bus_user_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
SD_BUS_METHOD_WITH_NAMES("Kill",
|
|
|
|
"i",
|
|
|
|
SD_BUS_PARAM(signal_number),
|
|
|
|
NULL,,
|
|
|
|
bus_user_method_kill,
|
|
|
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
|
|
|
|
|
|
|
SD_BUS_VTABLE_END
|
|
|
|
};
|
|
|
|
|
|
|
|
const BusObjectImplementation user_object = {
|
|
|
|
"/org/freedesktop/login1/user",
|
|
|
|
"org.freedesktop.login1.User",
|
|
|
|
.fallback_vtables = BUS_FALLBACK_VTABLES({user_vtable, user_object_find}),
|
|
|
|
.node_enumerator = user_node_enumerator,
|
|
|
|
};
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
int user_send_signal(User *u, bool new_user) {
|
|
|
|
_cleanup_free_ char *p = NULL;
|
2011-06-21 20:43:34 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
assert(u);
|
|
|
|
|
|
|
|
p = user_bus_path(u);
|
|
|
|
if (!p)
|
2013-03-19 01:31:21 +01:00
|
|
|
return -ENOMEM;
|
2011-06-21 20:43:34 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
return sd_bus_emit_signal(
|
|
|
|
u->manager->bus,
|
|
|
|
"/org/freedesktop/login1",
|
|
|
|
"org.freedesktop.login1.Manager",
|
|
|
|
new_user ? "UserNew" : "UserRemoved",
|
2019-08-07 16:22:35 +02:00
|
|
|
"uo", (uint32_t) u->user_record->uid, p);
|
2011-06-21 20:43:34 +02:00
|
|
|
}
|
2011-06-21 21:46:13 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
int user_send_changed(User *u, const char *properties, ...) {
|
2013-03-18 19:38:48 +01:00
|
|
|
_cleanup_free_ char *p = NULL;
|
2013-11-05 01:10:21 +01:00
|
|
|
char **l;
|
2011-06-21 21:46:13 +02:00
|
|
|
|
|
|
|
assert(u);
|
|
|
|
|
2011-06-24 19:42:45 +02:00
|
|
|
if (!u->started)
|
|
|
|
return 0;
|
|
|
|
|
2011-06-21 21:46:13 +02:00
|
|
|
p = user_bus_path(u);
|
|
|
|
if (!p)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
l = strv_from_stdarg_alloca(properties);
|
2011-06-21 21:46:13 +02:00
|
|
|
|
2013-11-05 01:10:21 +01:00
|
|
|
return sd_bus_emit_properties_changed_strv(u->manager->bus, p, "org.freedesktop.login1.User", l);
|
2011-06-21 21:46:13 +02:00
|
|
|
}
|