]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-user-dbus.c
hostnamed: modernizations
[thirdparty/systemd.git] / src / login / logind-user-dbus.c
CommitLineData
3f49d45a
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
3f49d45a
LP
11 (at your option) any later version.
12
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
5430f7f2 16 Lesser General Public License for more details.
3f49d45a 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
3f49d45a
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
a185c5aa 23#include <string.h>
3f49d45a 24
cc377381
LP
25#include "strv.h"
26#include "bus-util.h"
27
3f49d45a
LP
28#include "logind.h"
29#include "logind-user.h"
3f49d45a 30
cc377381
LP
31static int property_get_display(
32 sd_bus *bus,
33 const char *path,
34 const char *interface,
35 const char *property,
36 sd_bus_message *reply,
37 sd_bus_error *error,
38 void *userdata) {
3f49d45a 39
cc377381
LP
40 _cleanup_free_ char *p = NULL;
41 User *u = userdata;
3f49d45a 42
cc377381
LP
43 assert(bus);
44 assert(reply);
45 assert(u);
3f49d45a 46
cc377381
LP
47 p = u->display ? session_bus_path(u->display) : strdup("/");
48 if (!p)
3f49d45a
LP
49 return -ENOMEM;
50
cc377381 51 return sd_bus_message_append(reply, "(so)", u->display ? u->display->id : "", p);
3f49d45a
LP
52}
53
cc377381
LP
54static int property_get_state(
55 sd_bus *bus,
56 const char *path,
57 const char *interface,
58 const char *property,
59 sd_bus_message *reply,
60 sd_bus_error *error,
61 void *userdata) {
3f49d45a 62
cc377381 63 User *u = userdata;
3f49d45a 64
cc377381
LP
65 assert(bus);
66 assert(reply);
67 assert(u);
3f49d45a 68
cc377381 69 return sd_bus_message_append(reply, "s", user_state_to_string(user_get_state(u)));
3f49d45a
LP
70}
71
cc377381
LP
72static int property_get_sessions(
73 sd_bus *bus,
74 const char *path,
75 const char *interface,
76 const char *property,
77 sd_bus_message *reply,
78 sd_bus_error *error,
79 void *userdata) {
80
81 User *u = userdata;
3f49d45a 82 Session *session;
cc377381 83 int r;
3f49d45a 84
cc377381
LP
85 assert(bus);
86 assert(reply);
3f49d45a
LP
87 assert(u);
88
cc377381
LP
89 r = sd_bus_message_open_container(reply, 'a', "(so)");
90 if (r < 0)
91 return r;
3f49d45a
LP
92
93 LIST_FOREACH(sessions_by_user, session, u->sessions) {
cc377381 94 _cleanup_free_ char *p = NULL;
3f49d45a
LP
95
96 p = session_bus_path(session);
97 if (!p)
98 return -ENOMEM;
99
cc377381
LP
100 r = sd_bus_message_append(reply, "(so)", session->id, p);
101 if (r < 0)
102 return r;
3f49d45a 103
3f49d45a
LP
104 }
105
cc377381
LP
106 r = sd_bus_message_close_container(reply);
107 if (r < 0)
108 return r;
3f49d45a 109
cc377381 110 return 1;
3f49d45a
LP
111}
112
cc377381
LP
113static int property_get_idle_hint(
114 sd_bus *bus,
115 const char *path,
116 const char *interface,
117 const char *property,
118 sd_bus_message *reply,
119 sd_bus_error *error,
120 void *userdata) {
a185c5aa 121
cc377381 122 User *u = userdata;
77527da0 123
cc377381
LP
124 assert(bus);
125 assert(reply);
126 assert(u);
a185c5aa 127
cc377381 128 return sd_bus_message_append(reply, "b", user_get_idle_hint(u, NULL) > 0);
a185c5aa
LP
129}
130
cc377381
LP
131static int property_get_idle_since_hint(
132 sd_bus *bus,
133 const char *path,
134 const char *interface,
135 const char *property,
136 sd_bus_message *reply,
137 sd_bus_error *error,
138 void *userdata) {
139
140 User *u = userdata;
a185c5aa
LP
141 dual_timestamp t;
142 uint64_t k;
143
cc377381
LP
144 assert(bus);
145 assert(reply);
a185c5aa
LP
146 assert(u);
147
148 user_get_idle_hint(u, &t);
149 k = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
150
cc377381 151 return sd_bus_message_append(reply, "t", k);
a185c5aa
LP
152}
153
3a9f7a30
LP
154static int property_get_linger(
155 sd_bus *bus,
156 const char *path,
157 const char *interface,
158 const char *property,
159 sd_bus_message *reply,
160 sd_bus_error *error,
161 void *userdata) {
162
163 User *u = userdata;
164 int r;
165
166 assert(bus);
167 assert(reply);
168 assert(u);
169
170 r = user_check_linger_file(u);
171
172 return sd_bus_message_append(reply, "b", r > 0);
173}
174
cc377381
LP
175static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata) {
176 User *u = userdata;
3f49d45a
LP
177 int r;
178
cc377381
LP
179 assert(bus);
180 assert(message);
181 assert(u);
3f49d45a 182
cc377381 183 r = user_stop(u);
3f49d45a 184 if (r < 0)
df2d202e 185 return sd_bus_reply_method_errno(message, r, NULL);
3f49d45a 186
df2d202e 187 return sd_bus_reply_method_return(message, NULL);
3f49d45a
LP
188}
189
cc377381
LP
190static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata) {
191 User *u = userdata;
192 int32_t signo;
a185c5aa
LP
193 int r;
194
cc377381 195 assert(bus);
3f49d45a 196 assert(message);
cc377381 197 assert(u);
3f49d45a 198
cc377381
LP
199 r = sd_bus_message_read(message, "i", &signo);
200 if (r < 0)
df2d202e 201 return sd_bus_reply_method_errno(message, r, NULL);
a185c5aa 202
cc377381 203 if (signo <= 0 || signo >= _NSIG)
df2d202e 204 return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
a185c5aa 205
cc377381
LP
206 r = user_kill(u, signo);
207 if (r < 0)
df2d202e 208 return sd_bus_reply_method_errno(message, r, NULL);
a185c5aa 209
df2d202e 210 return sd_bus_reply_method_return(message, NULL);
3f49d45a
LP
211}
212
cc377381
LP
213const sd_bus_vtable user_vtable[] = {
214 SD_BUS_VTABLE_START(0),
215
216 SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(User, uid), 0),
217 SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(User, gid), 0),
218 SD_BUS_PROPERTY("Name", "s", NULL, offsetof(User, name), 0),
219 SD_BUS_PROPERTY("Timestamp", "t", NULL, offsetof(User, timestamp.realtime), 0),
220 SD_BUS_PROPERTY("TimestampMonotonic", "t", NULL, offsetof(User, timestamp.monotonic), 0),
221 SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), 0),
222 SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), 0),
223 SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), 0),
224 SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, 0),
225 SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
226 SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
227 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
228 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
229 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3a9f7a30 230 SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0),
cc377381
LP
231
232 SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, 0),
233 SD_BUS_METHOD("Kill", "i", NULL, method_kill, 0),
234
235 SD_BUS_VTABLE_END
236};
3f49d45a 237
cc377381 238int user_object_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
3f49d45a 239 Manager *m = userdata;
cc377381 240 User *user;
3f49d45a
LP
241 int r;
242
cc377381
LP
243 assert(bus);
244 assert(path);
245 assert(interface);
246 assert(found);
247 assert(m);
3f49d45a 248
927b1649
LP
249 if (streq(path, "/org/freedesktop/login1/user/self")) {
250 sd_bus_message *message;
251 pid_t pid;
3f49d45a 252
927b1649
LP
253 message = sd_bus_get_current(bus);
254 if (!message)
255 return 0;
256
257 r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
258 if (r < 0)
259 return 0;
260
261 r = manager_get_user_by_pid(m, pid, &user);
262 if (r <= 0)
263 return 0;
264 } else {
265 unsigned long lu;
266 const char *p;
3f49d45a 267
927b1649
LP
268 p = startswith(path, "/org/freedesktop/login1/user/_");
269 if (!p)
270 return 0;
271
272 r = safe_atolu(p, &lu);
273 if (r < 0)
274 return 0;
275
276 user = hashmap_get(m->users, ULONG_TO_PTR(lu));
277 if (!user)
278 return 0;
279 }
3f49d45a 280
cc377381
LP
281 *found = user;
282 return 1;
3f49d45a
LP
283}
284
3f49d45a
LP
285char *user_bus_path(User *u) {
286 char *s;
287
288 assert(u);
289
9444b1f2 290 if (asprintf(&s, "/org/freedesktop/login1/user/_%llu", (unsigned long long) u->uid) < 0)
3f49d45a
LP
291 return NULL;
292
293 return s;
294}
da119395 295
cc377381
LP
296int user_node_enumerator(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
297 _cleanup_strv_free_ char **l = NULL;
298 Manager *m = userdata;
299 User *user;
300 Iterator i;
301 int r;
da119395 302
cc377381
LP
303 assert(bus);
304 assert(path);
305 assert(nodes);
da119395 306
cc377381
LP
307 HASHMAP_FOREACH(user, m->users, i) {
308 char *p;
da119395 309
cc377381
LP
310 p = user_bus_path(user);
311 if (!p)
312 return -ENOMEM;
da119395 313
cc377381
LP
314 r = strv_push(&l, p);
315 if (r < 0) {
316 free(p);
317 return r;
318 }
319 }
da119395 320
cc377381
LP
321 *nodes = l;
322 l = NULL;
da119395 323
cc377381
LP
324 return 1;
325}
326
327int user_send_signal(User *u, bool new_user) {
328 _cleanup_free_ char *p = NULL;
da119395 329
cc377381
LP
330 assert(u);
331
332 p = user_bus_path(u);
333 if (!p)
4654e558 334 return -ENOMEM;
da119395 335
cc377381
LP
336 return sd_bus_emit_signal(
337 u->manager->bus,
338 "/org/freedesktop/login1",
339 "org.freedesktop.login1.Manager",
340 new_user ? "UserNew" : "UserRemoved",
341 "uo", (uint32_t) u->uid, p);
da119395 342}
9418f147 343
cc377381 344int user_send_changed(User *u, const char *properties, ...) {
ce0fc5f5 345 _cleanup_free_ char *p = NULL;
cc377381 346 char **l;
9418f147
LP
347
348 assert(u);
349
ed18b08b
LP
350 if (!u->started)
351 return 0;
352
9418f147
LP
353 p = user_bus_path(u);
354 if (!p)
355 return -ENOMEM;
356
cc377381 357 l = strv_from_stdarg_alloca(properties);
9418f147 358
cc377381 359 return sd_bus_emit_properties_changed_strv(u->manager->bus, p, "org.freedesktop.login1.User", l);
9418f147 360}