]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-login/sd-login.c
logind: fix Display property of user objects
[thirdparty/systemd.git] / src / libsystemd / sd-login / sd-login.c
CommitLineData
74b91131
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
74b91131
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.
74b91131 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
74b91131
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <unistd.h>
23#include <string.h>
24#include <errno.h>
034a2a52 25#include <sys/inotify.h>
dace83cb 26#include <sys/poll.h>
74b91131
LP
27
28#include "util.h"
29#include "cgroup-util.h"
30#include "macro.h"
034a2a52 31#include "strv.h"
a5c32cff 32#include "fileio.h"
4b549144 33#include "login-shared.h"
80514f9c 34#include "sd-login.h"
74b91131 35
034a2a52 36_public_ int sd_pid_get_session(pid_t pid, char **session) {
ba1261bc 37
1ae464e0
TA
38 assert_return(pid >= 0, -EINVAL);
39 assert_return(session, -EINVAL);
034a2a52 40
7027ff61 41 return cg_pid_get_session(pid, session);
74b91131
LP
42}
43
94fb446e 44_public_ int sd_pid_get_unit(pid_t pid, char **unit) {
9847946e 45
1ae464e0
TA
46 assert_return(pid >= 0, -EINVAL);
47 assert_return(unit, -EINVAL);
9847946e 48
ba1261bc 49 return cg_pid_get_unit(pid, unit);
9847946e
LP
50}
51
97e13058
LP
52_public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
53
1ae464e0
TA
54 assert_return(pid >= 0, -EINVAL);
55 assert_return(unit, -EINVAL);
97e13058
LP
56
57 return cg_pid_get_user_unit(pid, unit);
58}
59
7027ff61
LP
60_public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
61
1ae464e0
TA
62 assert_return(pid >= 0, -EINVAL);
63 assert_return(name, -EINVAL);
7027ff61
LP
64
65 return cg_pid_get_machine_name(pid, name);
66}
67
1021b21b
LP
68_public_ int sd_pid_get_slice(pid_t pid, char **slice) {
69
1ae464e0
TA
70 assert_return(pid >= 0, -EINVAL);
71 assert_return(slice, -EINVAL);
1021b21b
LP
72
73 return cg_pid_get_slice(pid, slice);
74}
75
034a2a52 76_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
034a2a52 77
1ae464e0
TA
78 assert_return(pid >= 0, -EINVAL);
79 assert_return(uid, -EINVAL);
034a2a52 80
ae018d9b 81 return cg_pid_get_owner_uid(pid, uid);
034a2a52
LP
82}
83
bf34ab14
LP
84_public_ int sd_peer_get_session(int fd, char **session) {
85 struct ucred ucred;
86 int r;
87
88 assert_return(fd >= 0, -EINVAL);
89 assert_return(session, -EINVAL);
90
91 r = getpeercred(fd, &ucred);
92 if (r < 0)
93 return r;
94
95 return cg_pid_get_session(ucred.pid, session);
96}
97
98_public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) {
99 struct ucred ucred;
100 int r;
101
102 assert_return(fd >= 0, -EINVAL);
103 assert_return(uid, -EINVAL);
104
105 r = getpeercred(fd, &ucred);
106 if (r < 0)
107 return r;
108
109 return cg_pid_get_owner_uid(ucred.pid, uid);
110}
111
112_public_ int sd_peer_get_unit(int fd, char **unit) {
113 struct ucred ucred;
114 int r;
115
116 assert_return(fd >= 0, -EINVAL);
117 assert_return(unit, -EINVAL);
118
119 r = getpeercred(fd, &ucred);
120 if (r < 0)
121 return r;
122
123 return cg_pid_get_unit(ucred.pid, unit);
124}
125
126_public_ int sd_peer_get_user_unit(int fd, char **unit) {
127 struct ucred ucred;
128 int r;
129
130 assert_return(fd >= 0, -EINVAL);
131 assert_return(unit, -EINVAL);
132
133 r = getpeercred(fd, &ucred);
134 if (r < 0)
135 return r;
136
137 return cg_pid_get_user_unit(ucred.pid, unit);
138}
139
140_public_ int sd_peer_get_machine_name(int fd, char **machine) {
141 struct ucred ucred;
142 int r;
143
144 assert_return(fd >= 0, -EINVAL);
145 assert_return(machine, -EINVAL);
146
147 r = getpeercred(fd, &ucred);
148 if (r < 0)
149 return r;
150
151 return cg_pid_get_machine_name(ucred.pid, machine);
152}
153
154_public_ int sd_peer_get_slice(int fd, char **slice) {
155 struct ucred ucred;
156 int r;
157
158 assert_return(fd >= 0, -EINVAL);
159 assert_return(slice, -EINVAL);
160
161 r = getpeercred(fd, &ucred);
162 if (r < 0)
163 return r;
164
165 return cg_pid_get_slice(ucred.pid, slice);
166}
167
74b91131 168_public_ int sd_uid_get_state(uid_t uid, char**state) {
bf34ab14
LP
169 _cleanup_free_ char *p = NULL;
170 char *s = NULL;
74b91131
LP
171 int r;
172
1ae464e0 173 assert_return(state, -EINVAL);
74b91131 174
de0671ee 175 if (asprintf(&p, "/run/systemd/users/"UID_FMT, uid) < 0)
74b91131
LP
176 return -ENOMEM;
177
178 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
74b91131
LP
179 if (r == -ENOENT) {
180 free(s);
181 s = strdup("offline");
182 if (!s)
183 return -ENOMEM;
184
74b91131
LP
185 } else if (r < 0) {
186 free(s);
187 return r;
188 } else if (!s)
189 return -EIO;
190
191 *state = s;
192 return 0;
193}
194
034a2a52 195_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
d70964d0
HH
196 char *w, *state;
197 _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
74b91131
LP
198 size_t l;
199 int r;
034a2a52 200 const char *variable;
74b91131 201
1ae464e0 202 assert_return(seat, -EINVAL);
74b91131 203
034a2a52
LP
204 variable = require_active ? "ACTIVE_UID" : "UIDS";
205
74b91131
LP
206 p = strappend("/run/systemd/seats/", seat);
207 if (!p)
208 return -ENOMEM;
209
034a2a52 210 r = parse_env_file(p, NEWLINE, variable, &s, NULL);
74b91131 211
d70964d0 212 if (r < 0)
74b91131 213 return r;
74b91131
LP
214
215 if (!s)
216 return -EIO;
217
de0671ee 218 if (asprintf(&t, UID_FMT, uid) < 0)
74b91131 219 return -ENOMEM;
74b91131
LP
220
221 FOREACH_WORD(w, l, s, state) {
d70964d0 222 if (strneq(t, w, l))
74b91131 223 return 1;
74b91131
LP
224 }
225
74b91131
LP
226 return 0;
227}
228
034a2a52 229static int uid_get_array(uid_t uid, const char *variable, char ***array) {
d70964d0 230 _cleanup_free_ char *p = NULL, *s = NULL;
034a2a52
LP
231 char **a;
232 int r;
233
de0671ee 234 if (asprintf(&p, "/run/systemd/users/"UID_FMT, uid) < 0)
034a2a52
LP
235 return -ENOMEM;
236
237 r = parse_env_file(p, NEWLINE,
238 variable, &s,
239 NULL);
034a2a52 240 if (r < 0) {
034a2a52 241 if (r == -ENOENT) {
d60ef526
LP
242 if (array)
243 *array = NULL;
034a2a52
LP
244 return 0;
245 }
246
247 return r;
248 }
249
250 if (!s) {
d60ef526
LP
251 if (array)
252 *array = NULL;
034a2a52
LP
253 return 0;
254 }
255
256 a = strv_split(s, " ");
034a2a52
LP
257
258 if (!a)
259 return -ENOMEM;
260
d60ef526
LP
261 strv_uniq(a);
262 r = strv_length(a);
263
264 if (array)
265 *array = a;
266 else
267 strv_free(a);
268
269 return r;
034a2a52
LP
270}
271
272_public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
d18dff43
LP
273 return uid_get_array(
274 uid,
275 require_active == 0 ? "ONLINE_SESSIONS" :
276 require_active > 0 ? "ACTIVE_SESSIONS" :
277 "SESSIONS",
278 sessions);
74b91131
LP
279}
280
034a2a52 281_public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
d18dff43
LP
282 return uid_get_array(
283 uid,
284 require_active == 0 ? "ONLINE_SEATS" :
285 require_active > 0 ? "ACTIVE_SEATS" :
286 "SEATS",
287 seats);
74b91131
LP
288}
289
50b1678a
LP
290static int file_of_session(const char *session, char **_p) {
291 char *p;
74b91131 292 int r;
74b91131 293
50b1678a
LP
294 assert(_p);
295
4b549144
ZJS
296 if (session) {
297 if (!session_id_valid(session))
298 return -EINVAL;
299
50b1678a 300 p = strappend("/run/systemd/sessions/", session);
4b549144
ZJS
301 } else {
302 _cleanup_free_ char *buf = NULL;
50b1678a
LP
303
304 r = sd_pid_get_session(0, &buf);
305 if (r < 0)
306 return r;
307
308 p = strappend("/run/systemd/sessions/", buf);
50b1678a 309 }
74b91131 310
74b91131
LP
311 if (!p)
312 return -ENOMEM;
313
50b1678a
LP
314 *_p = p;
315 return 0;
316}
317
318_public_ int sd_session_is_active(const char *session) {
319 int r;
d70964d0 320 _cleanup_free_ char *p = NULL, *s = NULL;
50b1678a
LP
321
322 r = file_of_session(session, &p);
323 if (r < 0)
324 return r;
325
74b91131 326 r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
d70964d0 327 if (r < 0)
74b91131 328 return r;
74b91131
LP
329
330 if (!s)
331 return -EIO;
332
0325941f 333 return parse_boolean(s);
74b91131
LP
334}
335
5b04fe60
MM
336_public_ int sd_session_is_remote(const char *session) {
337 int r;
338 _cleanup_free_ char *p = NULL, *s = NULL;
339
340 r = file_of_session(session, &p);
341 if (r < 0)
342 return r;
343
344 r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL);
345 if (r < 0)
346 return r;
347
348 if (!s)
349 return -EIO;
350
0325941f 351 return parse_boolean(s);
5b04fe60
MM
352}
353
0604381b 354_public_ int sd_session_get_state(const char *session, char **state) {
d70964d0 355 _cleanup_free_ char *p = NULL, *s = NULL;
0604381b
LP
356 int r;
357
1ae464e0 358 assert_return(state, -EINVAL);
0604381b
LP
359
360 r = file_of_session(session, &p);
361 if (r < 0)
362 return r;
363
364 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
0604381b 365
d70964d0 366 if (r < 0)
0604381b 367 return r;
d70964d0 368 else if (!s)
0604381b
LP
369 return -EIO;
370
371 *state = s;
d70964d0
HH
372 s = NULL;
373
0604381b
LP
374 return 0;
375}
376
74b91131
LP
377_public_ int sd_session_get_uid(const char *session, uid_t *uid) {
378 int r;
d70964d0 379 _cleanup_free_ char *p = NULL, *s = NULL;
74b91131 380
1ae464e0 381 assert_return(uid, -EINVAL);
74b91131 382
50b1678a
LP
383 r = file_of_session(session, &p);
384 if (r < 0)
385 return r;
74b91131
LP
386
387 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
d70964d0 388 if (r < 0)
74b91131 389 return r;
74b91131
LP
390
391 if (!s)
392 return -EIO;
393
0325941f 394 return parse_uid(s, uid);
74b91131
LP
395}
396
51f58f08 397static int session_get_string(const char *session, const char *field, char **value) {
d70964d0 398 _cleanup_free_ char *p = NULL, *s = NULL;
74b91131
LP
399 int r;
400
1ae464e0 401 assert_return(value, -EINVAL);
74b91131 402
50b1678a
LP
403 r = file_of_session(session, &p);
404 if (r < 0)
405 return r;
74b91131 406
51f58f08 407 r = parse_env_file(p, NEWLINE, field, &s, NULL);
74b91131 408
d70964d0 409 if (r < 0)
74b91131 410 return r;
74b91131
LP
411
412 if (isempty(s))
413 return -ENOENT;
414
51f58f08 415 *value = s;
d70964d0 416 s = NULL;
74b91131
LP
417 return 0;
418}
419
51f58f08
LP
420_public_ int sd_session_get_seat(const char *session, char **seat) {
421 return session_get_string(session, "SEAT", seat);
422}
eff40633 423
c84f5e4a
LP
424_public_ int sd_session_get_tty(const char *session, char **tty) {
425 return session_get_string(session, "TTY", tty);
426}
427
44ded3ab 428_public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
3f4fee03 429 _cleanup_free_ char *vtnr_string = NULL;
44ded3ab
GC
430 unsigned u;
431 int r;
432
0581dac2 433 r = session_get_string(session, "VTNR", &vtnr_string);
44ded3ab
GC
434 if (r < 0)
435 return r;
436
437 r = safe_atou(vtnr_string, &u);
438 if (r < 0)
439 return r;
440
441 *vtnr = u;
442 return 0;
443}
444
51f58f08
LP
445_public_ int sd_session_get_service(const char *session, char **service) {
446 return session_get_string(session, "SERVICE", service);
447}
eff40633 448
51f58f08
LP
449_public_ int sd_session_get_type(const char *session, char **type) {
450 return session_get_string(session, "TYPE", type);
451}
eff40633 452
51f58f08
LP
453_public_ int sd_session_get_class(const char *session, char **class) {
454 return session_get_string(session, "CLASS", class);
eff40633
LP
455}
456
fc8af9ff
LP
457_public_ int sd_session_get_display(const char *session, char **display) {
458 return session_get_string(session, "DISPLAY", display);
459}
460
5b04fe60
MM
461_public_ int sd_session_get_remote_user(const char *session, char **remote_user) {
462 return session_get_string(session, "REMOTE_USER", remote_user);
463}
464
465_public_ int sd_session_get_remote_host(const char *session, char **remote_host) {
466 return session_get_string(session, "REMOTE_HOST", remote_host);
467}
468
50b1678a
LP
469static int file_of_seat(const char *seat, char **_p) {
470 char *p;
471 int r;
472
473 assert(_p);
474
475 if (seat)
476 p = strappend("/run/systemd/seats/", seat);
477 else {
d70964d0 478 _cleanup_free_ char *buf = NULL;
50b1678a
LP
479
480 r = sd_session_get_seat(NULL, &buf);
481 if (r < 0)
482 return r;
483
484 p = strappend("/run/systemd/seats/", buf);
50b1678a
LP
485 }
486
487 if (!p)
488 return -ENOMEM;
489
490 *_p = p;
d70964d0 491 p = NULL;
50b1678a
LP
492 return 0;
493}
494
74b91131 495_public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
d70964d0 496 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
74b91131
LP
497 int r;
498
1ae464e0 499 assert_return(session || uid, -EINVAL);
74b91131 500
50b1678a
LP
501 r = file_of_seat(seat, &p);
502 if (r < 0)
503 return r;
74b91131
LP
504
505 r = parse_env_file(p, NEWLINE,
506 "ACTIVE", &s,
507 "ACTIVE_UID", &t,
508 NULL);
d70964d0 509 if (r < 0)
74b91131 510 return r;
74b91131 511
d70964d0 512 if (session && !s)
034a2a52 513 return -ENOENT;
74b91131 514
d70964d0 515 if (uid && !t)
034a2a52 516 return -ENOENT;
74b91131
LP
517
518 if (uid && t) {
034a2a52 519 r = parse_uid(t, uid);
d70964d0 520 if (r < 0)
74b91131 521 return r;
74b91131
LP
522 }
523
d70964d0 524 if (session && s) {
74b91131 525 *session = s;
d70964d0
HH
526 s = NULL;
527 }
74b91131
LP
528
529 return 0;
530}
034a2a52
LP
531
532_public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
d70964d0
HH
533 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
534 _cleanup_strv_free_ char **a = NULL;
535 _cleanup_free_ uid_t *b = NULL;
034a2a52
LP
536 unsigned n = 0;
537 int r;
538
50b1678a
LP
539 r = file_of_seat(seat, &p);
540 if (r < 0)
541 return r;
034a2a52
LP
542
543 r = parse_env_file(p, NEWLINE,
544 "SESSIONS", &s,
545 "ACTIVE_SESSIONS", &t,
546 NULL);
034a2a52 547
d70964d0 548 if (r < 0)
034a2a52 549 return r;
034a2a52 550
d60ef526 551 if (s) {
034a2a52 552 a = strv_split(s, " ");
d70964d0 553 if (!a)
034a2a52 554 return -ENOMEM;
034a2a52
LP
555 }
556
034a2a52
LP
557 if (uids && t) {
558 char *w, *state;
559 size_t l;
034a2a52
LP
560
561 FOREACH_WORD(w, l, t, state)
562 n++;
563
d70964d0 564 if (n > 0) {
de3756ab 565 unsigned i = 0;
034a2a52 566
de3756ab 567 b = new(uid_t, n);
d70964d0 568 if (!b)
034a2a52 569 return -ENOMEM;
034a2a52 570
de3756ab 571 FOREACH_WORD(w, l, t, state) {
d70964d0 572 _cleanup_free_ char *k = NULL;
034a2a52 573
de3756ab 574 k = strndup(w, l);
d70964d0 575 if (!k)
de3756ab 576 return -ENOMEM;
de3756ab
LP
577
578 r = parse_uid(k, b + i);
d70964d0 579
de3756ab
LP
580 if (r < 0)
581 continue;
582
583 i++;
584 }
034a2a52
LP
585 }
586 }
587
d60ef526
LP
588 r = strv_length(a);
589
d70964d0 590 if (sessions) {
034a2a52 591 *sessions = a;
d70964d0
HH
592 a = NULL;
593 }
034a2a52 594
d70964d0 595 if (uids) {
034a2a52 596 *uids = b;
d70964d0
HH
597 b = NULL;
598 }
034a2a52
LP
599
600 if (n_uids)
601 *n_uids = n;
602
d60ef526 603 return r;
034a2a52
LP
604}
605
20747498 606static int seat_get_can(const char *seat, const char *variable) {
d70964d0 607 _cleanup_free_ char *p = NULL, *s = NULL;
add30678
LP
608 int r;
609
0325941f
LP
610 assert_return(variable, -EINVAL);
611
50b1678a
LP
612 r = file_of_seat(seat, &p);
613 if (r < 0)
614 return r;
add30678
LP
615
616 r = parse_env_file(p, NEWLINE,
20747498 617 variable, &s,
add30678 618 NULL);
d70964d0 619 if (r < 0)
add30678 620 return r;
0325941f
LP
621 if (!s)
622 return 0;
add30678 623
0325941f 624 return parse_boolean(s);
add30678
LP
625}
626
20747498
LP
627_public_ int sd_seat_can_multi_session(const char *seat) {
628 return seat_get_can(seat, "CAN_MULTI_SESSION");
629}
630
631_public_ int sd_seat_can_tty(const char *seat) {
632 return seat_get_can(seat, "CAN_TTY");
633}
634
635_public_ int sd_seat_can_graphical(const char *seat) {
636 return seat_get_can(seat, "CAN_GRAPHICAL");
637}
638
034a2a52 639_public_ int sd_get_seats(char ***seats) {
034a2a52
LP
640 return get_files_in_directory("/run/systemd/seats/", seats);
641}
642
643_public_ int sd_get_sessions(char ***sessions) {
034a2a52
LP
644 return get_files_in_directory("/run/systemd/sessions/", sessions);
645}
646
647_public_ int sd_get_uids(uid_t **users) {
d70964d0 648 _cleanup_closedir_ DIR *d;
034a2a52
LP
649 int r = 0;
650 unsigned n = 0;
d70964d0 651 _cleanup_free_ uid_t *l = NULL;
034a2a52 652
034a2a52 653 d = opendir("/run/systemd/users/");
8ea913b2
LP
654 if (!d)
655 return -errno;
656
034a2a52 657 for (;;) {
7d5e9c0f 658 struct dirent *de;
034a2a52
LP
659 int k;
660 uid_t uid;
661
66c7a533
FW
662 errno = 0;
663 de = readdir(d);
664 if (!de && errno != 0)
665 return -errno;
034a2a52
LP
666
667 if (!de)
668 break;
669
670 dirent_ensure_type(d, de);
671
672 if (!dirent_is_file(de))
673 continue;
674
675 k = parse_uid(de->d_name, &uid);
676 if (k < 0)
677 continue;
678
d60ef526
LP
679 if (users) {
680 if ((unsigned) r >= n) {
681 uid_t *t;
034a2a52 682
d60ef526
LP
683 n = MAX(16, 2*r);
684 t = realloc(l, sizeof(uid_t) * n);
d70964d0
HH
685 if (!t)
686 return -ENOMEM;
034a2a52 687
d60ef526
LP
688 l = t;
689 }
034a2a52 690
d60ef526
LP
691 assert((unsigned) r < n);
692 l[r++] = uid;
693 } else
694 r++;
034a2a52
LP
695 }
696
d70964d0
HH
697 if (users) {
698 *users = l;
699 l = NULL;
700 }
034a2a52
LP
701
702 return r;
703}
704
4d5fb962 705_public_ int sd_get_machine_names(char ***machines) {
89f7c846
LP
706 char **l = NULL, **a, **b;
707 int r;
708
0325941f
LP
709 assert_return(machines, -EINVAL);
710
89f7c846
LP
711 r = get_files_in_directory("/run/systemd/machines/", &l);
712 if (r < 0)
713 return r;
714
715 if (l) {
716 r = 0;
717
718 /* Filter out the unit: symlinks */
719 for (a = l, b = l; *a; a++) {
720 if (startswith(*a, "unit:"))
721 free(*a);
722 else {
723 *b = *a;
724 b++;
725 r++;
726 }
727 }
728
729 *b = NULL;
730 }
731
732 *machines = l;
733 return r;
a20affe2
LP
734}
735
0325941f
LP
736_public_ int sd_machine_get_class(const char *machine, char **class) {
737 _cleanup_free_ char *c = NULL;
738 const char *p;
739 int r;
740
741 assert_return(filename_is_safe(machine), -EINVAL);
742 assert_return(class, -EINVAL);
743
744 p = strappenda("/run/systemd/machines/", machine);
745 r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL);
746 if (r < 0)
747 return r;
748 if (!c)
749 return -EIO;
750
751 *class = c;
752 c = NULL;
753
754 return 0;
755}
756
034a2a52
LP
757static inline int MONITOR_TO_FD(sd_login_monitor *m) {
758 return (int) (unsigned long) m - 1;
759}
760
761static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
762 return (sd_login_monitor*) (unsigned long) (fd + 1);
763}
764
765_public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
034a2a52
LP
766 int fd, k;
767 bool good = false;
768
1ae464e0 769 assert_return(m, -EINVAL);
034a2a52
LP
770
771 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
772 if (fd < 0)
bcb161b0 773 return -errno;
034a2a52
LP
774
775 if (!category || streq(category, "seat")) {
776 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
777 if (k < 0) {
03e334a1 778 safe_close(fd);
034a2a52
LP
779 return -errno;
780 }
781
782 good = true;
783 }
784
785 if (!category || streq(category, "session")) {
786 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
787 if (k < 0) {
03e334a1 788 safe_close(fd);
034a2a52
LP
789 return -errno;
790 }
791
792 good = true;
793 }
794
795 if (!category || streq(category, "uid")) {
796 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
797 if (k < 0) {
03e334a1 798 safe_close(fd);
034a2a52
LP
799 return -errno;
800 }
801
802 good = true;
803 }
804
e10375f2 805 if (!category || streq(category, "machine")) {
ba73ed85 806 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
e10375f2 807 if (k < 0) {
03e334a1 808 safe_close(fd);
e10375f2
LP
809 return -errno;
810 }
811
812 good = true;
813 }
814
034a2a52
LP
815 if (!good) {
816 close_nointr(fd);
817 return -EINVAL;
818 }
819
820 *m = FD_TO_MONITOR(fd);
821 return 0;
822}
823
824_public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
825 int fd;
826
1ae464e0 827 assert_return(m, NULL);
034a2a52
LP
828
829 fd = MONITOR_TO_FD(m);
830 close_nointr(fd);
831
832 return NULL;
833}
834
835_public_ int sd_login_monitor_flush(sd_login_monitor *m) {
836
1ae464e0 837 assert_return(m, -EINVAL);
034a2a52
LP
838
839 return flush_fd(MONITOR_TO_FD(m));
840}
841
842_public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
843
1ae464e0 844 assert_return(m, -EINVAL);
034a2a52
LP
845
846 return MONITOR_TO_FD(m);
847}
dace83cb
LP
848
849_public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
850
1ae464e0 851 assert_return(m, -EINVAL);
dace83cb 852
667c24a6
LP
853 /* For now we will only return POLLIN here, since we don't
854 * need anything else ever for inotify. However, let's have
855 * this API to keep our options open should we later on need
856 * it. */
dace83cb
LP
857 return POLLIN;
858}
667c24a6
LP
859
860_public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
861
1ae464e0
TA
862 assert_return(m, -EINVAL);
863 assert_return(timeout_usec, -EINVAL);
667c24a6
LP
864
865 /* For now we will only return (uint64_t) -1, since we don't
866 * need any timeout. However, let's have this API to keep our
867 * options open should we later on need it. */
868 *timeout_usec = (uint64_t) -1;
869 return 0;
870}