1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "logind-user.h"
30 static int property_get_display(
33 const char *interface,
35 sd_bus_message *reply,
37 sd_bus_error *error) {
39 _cleanup_free_ char *p = NULL;
46 p = u->display ? session_bus_path(u->display) : strdup("/");
50 return sd_bus_message_append(reply, "(so)", u->display ? u->display->id : "", p);
53 static int property_get_state(
56 const char *interface,
58 sd_bus_message *reply,
60 sd_bus_error *error) {
68 return sd_bus_message_append(reply, "s", user_state_to_string(user_get_state(u)));
71 static int property_get_sessions(
74 const char *interface,
76 sd_bus_message *reply,
78 sd_bus_error *error) {
88 r = sd_bus_message_open_container(reply, 'a', "(so)");
92 LIST_FOREACH(sessions_by_user, session, u->sessions) {
93 _cleanup_free_ char *p = NULL;
95 p = session_bus_path(session);
99 r = sd_bus_message_append(reply, "(so)", session->id, p);
105 r = sd_bus_message_close_container(reply);
112 static int property_get_idle_hint(
115 const char *interface,
116 const char *property,
117 sd_bus_message *reply,
119 sd_bus_error *error) {
127 return sd_bus_message_append(reply, "b", user_get_idle_hint(u, NULL) > 0);
130 static int property_get_idle_since_hint(
133 const char *interface,
134 const char *property,
135 sd_bus_message *reply,
137 sd_bus_error *error) {
147 user_get_idle_hint(u, &t);
148 k = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
150 return sd_bus_message_append(reply, "t", k);
153 static int property_get_linger(
156 const char *interface,
157 const char *property,
158 sd_bus_message *reply,
160 sd_bus_error *error) {
169 r = user_check_linger_file(u);
171 return sd_bus_message_append(reply, "b", r > 0);
174 static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
182 r = user_stop(u, true);
186 return sd_bus_reply_method_return(message, NULL);
189 static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
198 r = sd_bus_message_read(message, "i", &signo);
202 if (signo <= 0 || signo >= _NSIG)
203 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
205 r = user_kill(u, signo);
209 return sd_bus_reply_method_return(message, NULL);
212 const sd_bus_vtable user_vtable[] = {
213 SD_BUS_VTABLE_START(0),
215 SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(User, uid), SD_BUS_VTABLE_PROPERTY_CONST),
216 SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(User, gid), SD_BUS_VTABLE_PROPERTY_CONST),
217 SD_BUS_PROPERTY("Name", "s", NULL, offsetof(User, name), SD_BUS_VTABLE_PROPERTY_CONST),
218 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(User, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
219 SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), SD_BUS_VTABLE_PROPERTY_CONST),
220 SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), SD_BUS_VTABLE_PROPERTY_CONST),
221 SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), SD_BUS_VTABLE_PROPERTY_CONST),
222 SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
223 SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
224 SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
225 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
226 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
227 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
228 SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0),
230 SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
231 SD_BUS_METHOD("Kill", "i", NULL, method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
236 int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
237 Manager *m = userdata;
247 if (streq(path, "/org/freedesktop/login1/user/self")) {
248 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
249 sd_bus_message *message;
252 message = sd_bus_get_current_message(bus);
256 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
260 r = sd_bus_creds_get_pid(creds, &pid);
264 r = manager_get_user_by_pid(m, pid, &user);
271 p = startswith(path, "/org/freedesktop/login1/user/_");
275 r = safe_atolu(p, &lu);
279 user = hashmap_get(m->users, ULONG_TO_PTR(lu));
288 char *user_bus_path(User *u) {
293 if (asprintf(&s, "/org/freedesktop/login1/user/_"UID_FMT, u->uid) < 0)
299 int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
300 _cleanup_strv_free_ char **l = NULL;
301 Manager *m = userdata;
310 HASHMAP_FOREACH(user, m->users, i) {
313 p = user_bus_path(user);
317 r = strv_consume(&l, p);
328 int user_send_signal(User *u, bool new_user) {
329 _cleanup_free_ char *p = NULL;
333 p = user_bus_path(u);
337 return sd_bus_emit_signal(
339 "/org/freedesktop/login1",
340 "org.freedesktop.login1.Manager",
341 new_user ? "UserNew" : "UserRemoved",
342 "uo", (uint32_t) u->uid, p);
345 int user_send_changed(User *u, const char *properties, ...) {
346 _cleanup_free_ char *p = NULL;
354 p = user_bus_path(u);
358 l = strv_from_stdarg_alloca(properties);
360 return sd_bus_emit_properties_changed_strv(u->manager->bus, p, "org.freedesktop.login1.User", l);