]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-user-dbus.c
Make systemctl --root look for files in the proper places
[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>
adacb957 24#include <sys/capability.h>
3f49d45a 25
cc377381
LP
26#include "strv.h"
27#include "bus-util.h"
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,
ebcf1f97
LP
37 void *userdata,
38 sd_bus_error *error) {
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,
ebcf1f97
LP
60 void *userdata,
61 sd_bus_error *error) {
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,
ebcf1f97
LP
78 void *userdata,
79 sd_bus_error *error) {
cc377381
LP
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,
ebcf1f97
LP
119 void *userdata,
120 sd_bus_error *error) {
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,
ebcf1f97
LP
137 void *userdata,
138 sd_bus_error *error) {
cc377381
LP
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,
ebcf1f97
LP
160 void *userdata,
161 sd_bus_error *error) {
3a9f7a30
LP
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
ebcf1f97 175static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 176 User *u = userdata;
3f49d45a
LP
177 int r;
178
cc377381
LP
179 assert(bus);
180 assert(message);
181 assert(u);
3f49d45a 182
9bb69af4 183 r = user_stop(u, true);
3f49d45a 184 if (r < 0)
ebcf1f97 185 return r;
3f49d45a 186
df2d202e 187 return sd_bus_reply_method_return(message, NULL);
3f49d45a
LP
188}
189
ebcf1f97 190static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
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)
ebcf1f97 201 return r;
a185c5aa 202
cc377381 203 if (signo <= 0 || signo >= _NSIG)
ebcf1f97 204 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
a185c5aa 205
cc377381
LP
206 r = user_kill(u, signo);
207 if (r < 0)
ebcf1f97 208 return r;
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
556089dc
LP
216 SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(User, uid), SD_BUS_VTABLE_PROPERTY_CONST),
217 SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(User, gid), SD_BUS_VTABLE_PROPERTY_CONST),
218 SD_BUS_PROPERTY("Name", "s", NULL, offsetof(User, name), SD_BUS_VTABLE_PROPERTY_CONST),
219 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(User, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
220 SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), SD_BUS_VTABLE_PROPERTY_CONST),
221 SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), SD_BUS_VTABLE_PROPERTY_CONST),
222 SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), SD_BUS_VTABLE_PROPERTY_CONST),
223 SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_CONST),
cc377381
LP
224 SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
225 SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
226 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
227 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
228 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3a9f7a30 229 SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0),
cc377381 230
adacb957
LP
231 SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
232 SD_BUS_METHOD("Kill", "i", NULL, method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
cc377381
LP
233
234 SD_BUS_VTABLE_END
235};
3f49d45a 236
f00c3121 237int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
3f49d45a 238 Manager *m = userdata;
cc377381 239 User *user;
3f49d45a
LP
240 int r;
241
cc377381
LP
242 assert(bus);
243 assert(path);
244 assert(interface);
245 assert(found);
246 assert(m);
3f49d45a 247
927b1649 248 if (streq(path, "/org/freedesktop/login1/user/self")) {
5b12334d 249 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
927b1649
LP
250 sd_bus_message *message;
251 pid_t pid;
3f49d45a 252
19befb2d 253 message = sd_bus_get_current_message(bus);
927b1649
LP
254 if (!message)
255 return 0;
256
5b12334d 257 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
927b1649 258 if (r < 0)
5b12334d
LP
259 return r;
260
261 r = sd_bus_creds_get_pid(creds, &pid);
262 if (r < 0)
263 return r;
927b1649
LP
264
265 r = manager_get_user_by_pid(m, pid, &user);
266 if (r <= 0)
267 return 0;
268 } else {
269 unsigned long lu;
270 const char *p;
3f49d45a 271
927b1649
LP
272 p = startswith(path, "/org/freedesktop/login1/user/_");
273 if (!p)
274 return 0;
275
276 r = safe_atolu(p, &lu);
277 if (r < 0)
278 return 0;
279
280 user = hashmap_get(m->users, ULONG_TO_PTR(lu));
281 if (!user)
282 return 0;
283 }
3f49d45a 284
cc377381
LP
285 *found = user;
286 return 1;
3f49d45a
LP
287}
288
3f49d45a
LP
289char *user_bus_path(User *u) {
290 char *s;
291
292 assert(u);
293
9444b1f2 294 if (asprintf(&s, "/org/freedesktop/login1/user/_%llu", (unsigned long long) u->uid) < 0)
3f49d45a
LP
295 return NULL;
296
297 return s;
298}
da119395 299
f00c3121 300int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
cc377381
LP
301 _cleanup_strv_free_ char **l = NULL;
302 Manager *m = userdata;
303 User *user;
304 Iterator i;
305 int r;
da119395 306
cc377381
LP
307 assert(bus);
308 assert(path);
309 assert(nodes);
da119395 310
cc377381
LP
311 HASHMAP_FOREACH(user, m->users, i) {
312 char *p;
da119395 313
cc377381
LP
314 p = user_bus_path(user);
315 if (!p)
316 return -ENOMEM;
da119395 317
6e18964d
ZJS
318 r = strv_consume(&l, p);
319 if (r < 0)
cc377381 320 return r;
cc377381 321 }
da119395 322
cc377381
LP
323 *nodes = l;
324 l = NULL;
da119395 325
cc377381
LP
326 return 1;
327}
328
329int user_send_signal(User *u, bool new_user) {
330 _cleanup_free_ char *p = NULL;
da119395 331
cc377381
LP
332 assert(u);
333
334 p = user_bus_path(u);
335 if (!p)
4654e558 336 return -ENOMEM;
da119395 337
cc377381
LP
338 return sd_bus_emit_signal(
339 u->manager->bus,
340 "/org/freedesktop/login1",
341 "org.freedesktop.login1.Manager",
342 new_user ? "UserNew" : "UserRemoved",
343 "uo", (uint32_t) u->uid, p);
da119395 344}
9418f147 345
cc377381 346int user_send_changed(User *u, const char *properties, ...) {
ce0fc5f5 347 _cleanup_free_ char *p = NULL;
cc377381 348 char **l;
9418f147
LP
349
350 assert(u);
351
ed18b08b
LP
352 if (!u->started)
353 return 0;
354
9418f147
LP
355 p = user_bus_path(u);
356 if (!p)
357 return -ENOMEM;
358
cc377381 359 l = strv_from_stdarg_alloca(properties);
9418f147 360
cc377381 361 return sd_bus_emit_properties_changed_strv(u->manager->bus, p, "org.freedesktop.login1.User", l);
9418f147 362}