]> git.proxmox.com Git - systemd.git/blame - src/libsystemd/sd-login/sd-login.c
Imported Upstream version 219
[systemd.git] / src / libsystemd / sd-login / sd-login.c
CommitLineData
663996b3
MS
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
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.
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
16 Lesser General Public License for more details.
17
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/>.
20***/
21
22#include <unistd.h>
23#include <string.h>
24#include <errno.h>
25#include <sys/inotify.h>
e735f4d4 26#include <poll.h>
663996b3
MS
27
28#include "util.h"
29#include "cgroup-util.h"
30#include "macro.h"
663996b3
MS
31#include "strv.h"
32#include "fileio.h"
14228c0d 33#include "login-shared.h"
60f067b4 34#include "sd-login.h"
663996b3
MS
35
36_public_ int sd_pid_get_session(pid_t pid, char **session) {
663996b3 37
60f067b4
JS
38 assert_return(pid >= 0, -EINVAL);
39 assert_return(session, -EINVAL);
663996b3
MS
40
41 return cg_pid_get_session(pid, session);
42}
43
44_public_ int sd_pid_get_unit(pid_t pid, char **unit) {
45
60f067b4
JS
46 assert_return(pid >= 0, -EINVAL);
47 assert_return(unit, -EINVAL);
663996b3
MS
48
49 return cg_pid_get_unit(pid, unit);
50}
51
52_public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
53
60f067b4
JS
54 assert_return(pid >= 0, -EINVAL);
55 assert_return(unit, -EINVAL);
663996b3
MS
56
57 return cg_pid_get_user_unit(pid, unit);
58}
59
60_public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
61
60f067b4
JS
62 assert_return(pid >= 0, -EINVAL);
63 assert_return(name, -EINVAL);
663996b3
MS
64
65 return cg_pid_get_machine_name(pid, name);
66}
67
14228c0d
MB
68_public_ int sd_pid_get_slice(pid_t pid, char **slice) {
69
60f067b4
JS
70 assert_return(pid >= 0, -EINVAL);
71 assert_return(slice, -EINVAL);
14228c0d
MB
72
73 return cg_pid_get_slice(pid, slice);
74}
75
663996b3
MS
76_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
77
60f067b4
JS
78 assert_return(pid >= 0, -EINVAL);
79 assert_return(uid, -EINVAL);
663996b3
MS
80
81 return cg_pid_get_owner_uid(pid, uid);
82}
83
60f067b4
JS
84_public_ int sd_peer_get_session(int fd, char **session) {
85 struct ucred ucred;
663996b3
MS
86 int r;
87
60f067b4
JS
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);
663996b3 132
60f067b4
JS
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
168static int file_of_uid(uid_t uid, char **p) {
169 assert(p);
170
171 if (asprintf(p, "/run/systemd/users/" UID_FMT, uid) < 0)
663996b3
MS
172 return -ENOMEM;
173
60f067b4
JS
174 return 0;
175}
176
177_public_ int sd_uid_get_state(uid_t uid, char**state) {
178 _cleanup_free_ char *p = NULL;
179 char *s = NULL;
180 int r;
181
182 assert_return(state, -EINVAL);
183
184 r = file_of_uid(uid, &p);
185 if (r < 0)
186 return r;
663996b3 187
60f067b4 188 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
663996b3
MS
189 if (r == -ENOENT) {
190 free(s);
191 s = strdup("offline");
192 if (!s)
193 return -ENOMEM;
194
663996b3
MS
195 } else if (r < 0) {
196 free(s);
197 return r;
198 } else if (!s)
199 return -EIO;
200
201 *state = s;
202 return 0;
203}
204
60f067b4
JS
205_public_ int sd_uid_get_display(uid_t uid, char **session) {
206 _cleanup_free_ char *p = NULL, *s = NULL;
207 int r;
208
209 assert_return(session, -EINVAL);
210
211 r = file_of_uid(uid, &p);
212 if (r < 0)
213 return r;
214
215 r = parse_env_file(p, NEWLINE, "DISPLAY", &s, NULL);
216 if (r < 0)
217 return r;
218
219 if (isempty(s))
220 return -ENOENT;
221
222 *session = s;
223 s = NULL;
224
225 return 0;
226}
227
663996b3 228_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
663996b3
MS
229 _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
230 size_t l;
231 int r;
5eef597e 232 const char *word, *variable, *state;
663996b3 233
60f067b4 234 assert_return(seat, -EINVAL);
663996b3
MS
235
236 variable = require_active ? "ACTIVE_UID" : "UIDS";
237
238 p = strappend("/run/systemd/seats/", seat);
239 if (!p)
240 return -ENOMEM;
241
242 r = parse_env_file(p, NEWLINE, variable, &s, NULL);
243
244 if (r < 0)
245 return r;
246
247 if (!s)
248 return -EIO;
249
60f067b4 250 if (asprintf(&t, UID_FMT, uid) < 0)
663996b3
MS
251 return -ENOMEM;
252
5eef597e
MP
253 FOREACH_WORD(word, l, s, state) {
254 if (strneq(t, word, l))
663996b3
MS
255 return 1;
256 }
257
258 return 0;
259}
260
261static int uid_get_array(uid_t uid, const char *variable, char ***array) {
262 _cleanup_free_ char *p = NULL, *s = NULL;
263 char **a;
264 int r;
265
60f067b4
JS
266 r = file_of_uid(uid, &p);
267 if (r < 0)
268 return r;
663996b3
MS
269
270 r = parse_env_file(p, NEWLINE,
271 variable, &s,
272 NULL);
273 if (r < 0) {
274 if (r == -ENOENT) {
275 if (array)
276 *array = NULL;
277 return 0;
278 }
279
280 return r;
281 }
282
283 if (!s) {
284 if (array)
285 *array = NULL;
286 return 0;
287 }
288
289 a = strv_split(s, " ");
290
291 if (!a)
292 return -ENOMEM;
293
294 strv_uniq(a);
295 r = strv_length(a);
296
297 if (array)
298 *array = a;
299 else
300 strv_free(a);
301
302 return r;
303}
304
305_public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
306 return uid_get_array(
307 uid,
308 require_active == 0 ? "ONLINE_SESSIONS" :
309 require_active > 0 ? "ACTIVE_SESSIONS" :
310 "SESSIONS",
311 sessions);
312}
313
314_public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
315 return uid_get_array(
316 uid,
317 require_active == 0 ? "ONLINE_SEATS" :
318 require_active > 0 ? "ACTIVE_SEATS" :
319 "SEATS",
320 seats);
321}
322
323static int file_of_session(const char *session, char **_p) {
324 char *p;
325 int r;
326
327 assert(_p);
328
14228c0d
MB
329 if (session) {
330 if (!session_id_valid(session))
331 return -EINVAL;
332
663996b3 333 p = strappend("/run/systemd/sessions/", session);
14228c0d
MB
334 } else {
335 _cleanup_free_ char *buf = NULL;
663996b3
MS
336
337 r = sd_pid_get_session(0, &buf);
338 if (r < 0)
339 return r;
340
341 p = strappend("/run/systemd/sessions/", buf);
663996b3
MS
342 }
343
344 if (!p)
345 return -ENOMEM;
346
347 *_p = p;
348 return 0;
349}
350
351_public_ int sd_session_is_active(const char *session) {
352 int r;
353 _cleanup_free_ char *p = NULL, *s = NULL;
354
355 r = file_of_session(session, &p);
356 if (r < 0)
357 return r;
358
359 r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
663996b3
MS
360 if (r < 0)
361 return r;
362
363 if (!s)
364 return -EIO;
365
60f067b4
JS
366 return parse_boolean(s);
367}
368
369_public_ int sd_session_is_remote(const char *session) {
370 int r;
371 _cleanup_free_ char *p = NULL, *s = NULL;
663996b3 372
60f067b4
JS
373 r = file_of_session(session, &p);
374 if (r < 0)
375 return r;
376
377 r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL);
378 if (r < 0)
379 return r;
380
381 if (!s)
382 return -EIO;
383
384 return parse_boolean(s);
663996b3
MS
385}
386
387_public_ int sd_session_get_state(const char *session, char **state) {
388 _cleanup_free_ char *p = NULL, *s = NULL;
389 int r;
390
60f067b4 391 assert_return(state, -EINVAL);
663996b3
MS
392
393 r = file_of_session(session, &p);
394 if (r < 0)
395 return r;
396
397 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
663996b3
MS
398 if (r < 0)
399 return r;
400 else if (!s)
401 return -EIO;
402
403 *state = s;
404 s = NULL;
405
406 return 0;
407}
408
409_public_ int sd_session_get_uid(const char *session, uid_t *uid) {
410 int r;
411 _cleanup_free_ char *p = NULL, *s = NULL;
412
60f067b4 413 assert_return(uid, -EINVAL);
663996b3
MS
414
415 r = file_of_session(session, &p);
416 if (r < 0)
417 return r;
418
419 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
663996b3
MS
420 if (r < 0)
421 return r;
422
423 if (!s)
424 return -EIO;
425
60f067b4 426 return parse_uid(s, uid);
663996b3
MS
427}
428
429static int session_get_string(const char *session, const char *field, char **value) {
430 _cleanup_free_ char *p = NULL, *s = NULL;
431 int r;
432
60f067b4 433 assert_return(value, -EINVAL);
663996b3
MS
434
435 r = file_of_session(session, &p);
436 if (r < 0)
437 return r;
438
439 r = parse_env_file(p, NEWLINE, field, &s, NULL);
663996b3
MS
440 if (r < 0)
441 return r;
442
443 if (isempty(s))
444 return -ENOENT;
445
446 *value = s;
447 s = NULL;
448 return 0;
449}
450
451_public_ int sd_session_get_seat(const char *session, char **seat) {
452 return session_get_string(session, "SEAT", seat);
453}
454
455_public_ int sd_session_get_tty(const char *session, char **tty) {
456 return session_get_string(session, "TTY", tty);
457}
458
14228c0d 459_public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
60f067b4 460 _cleanup_free_ char *vtnr_string = NULL;
14228c0d
MB
461 unsigned u;
462 int r;
463
60f067b4 464 r = session_get_string(session, "VTNR", &vtnr_string);
14228c0d
MB
465 if (r < 0)
466 return r;
467
468 r = safe_atou(vtnr_string, &u);
469 if (r < 0)
470 return r;
471
472 *vtnr = u;
473 return 0;
474}
475
663996b3
MS
476_public_ int sd_session_get_service(const char *session, char **service) {
477 return session_get_string(session, "SERVICE", service);
478}
479
480_public_ int sd_session_get_type(const char *session, char **type) {
481 return session_get_string(session, "TYPE", type);
482}
483
484_public_ int sd_session_get_class(const char *session, char **class) {
485 return session_get_string(session, "CLASS", class);
486}
487
5eef597e
MP
488_public_ int sd_session_get_desktop(const char *session, char **desktop) {
489 _cleanup_free_ char *escaped = NULL;
490 char *t;
491 int r;
492
493 assert_return(desktop, -EINVAL);
494
495 r = session_get_string(session, "DESKTOP", &escaped);
496 if (r < 0)
497 return r;
498
499 t = cunescape(escaped);
500 if (!t)
501 return -ENOMEM;
502
503 *desktop = t;
504 return 0;
505}
506
663996b3
MS
507_public_ int sd_session_get_display(const char *session, char **display) {
508 return session_get_string(session, "DISPLAY", display);
509}
510
60f067b4
JS
511_public_ int sd_session_get_remote_user(const char *session, char **remote_user) {
512 return session_get_string(session, "REMOTE_USER", remote_user);
513}
514
515_public_ int sd_session_get_remote_host(const char *session, char **remote_host) {
516 return session_get_string(session, "REMOTE_HOST", remote_host);
517}
518
663996b3
MS
519static int file_of_seat(const char *seat, char **_p) {
520 char *p;
521 int r;
522
523 assert(_p);
524
525 if (seat)
526 p = strappend("/run/systemd/seats/", seat);
527 else {
528 _cleanup_free_ char *buf = NULL;
529
530 r = sd_session_get_seat(NULL, &buf);
531 if (r < 0)
532 return r;
533
534 p = strappend("/run/systemd/seats/", buf);
535 }
536
537 if (!p)
538 return -ENOMEM;
539
540 *_p = p;
541 p = NULL;
542 return 0;
543}
544
545_public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
546 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
547 int r;
548
60f067b4 549 assert_return(session || uid, -EINVAL);
663996b3
MS
550
551 r = file_of_seat(seat, &p);
552 if (r < 0)
553 return r;
554
555 r = parse_env_file(p, NEWLINE,
556 "ACTIVE", &s,
557 "ACTIVE_UID", &t,
558 NULL);
559 if (r < 0)
560 return r;
561
562 if (session && !s)
563 return -ENOENT;
564
565 if (uid && !t)
566 return -ENOENT;
567
568 if (uid && t) {
569 r = parse_uid(t, uid);
570 if (r < 0)
571 return r;
572 }
573
574 if (session && s) {
575 *session = s;
576 s = NULL;
577 }
578
579 return 0;
580}
581
582_public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
583 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
584 _cleanup_strv_free_ char **a = NULL;
585 _cleanup_free_ uid_t *b = NULL;
586 unsigned n = 0;
587 int r;
588
589 r = file_of_seat(seat, &p);
590 if (r < 0)
591 return r;
592
593 r = parse_env_file(p, NEWLINE,
594 "SESSIONS", &s,
595 "ACTIVE_SESSIONS", &t,
596 NULL);
597
598 if (r < 0)
599 return r;
600
601 if (s) {
602 a = strv_split(s, " ");
603 if (!a)
604 return -ENOMEM;
605 }
606
607 if (uids && t) {
5eef597e 608 const char *word, *state;
663996b3
MS
609 size_t l;
610
5eef597e 611 FOREACH_WORD(word, l, t, state)
663996b3
MS
612 n++;
613
614 if (n > 0) {
615 unsigned i = 0;
616
617 b = new(uid_t, n);
618 if (!b)
619 return -ENOMEM;
620
5eef597e 621 FOREACH_WORD(word, l, t, state) {
663996b3
MS
622 _cleanup_free_ char *k = NULL;
623
5eef597e 624 k = strndup(word, l);
663996b3
MS
625 if (!k)
626 return -ENOMEM;
627
628 r = parse_uid(k, b + i);
629
630 if (r < 0)
631 continue;
632
633 i++;
634 }
635 }
636 }
637
638 r = strv_length(a);
639
640 if (sessions) {
641 *sessions = a;
642 a = NULL;
643 }
644
645 if (uids) {
646 *uids = b;
647 b = NULL;
648 }
649
650 if (n_uids)
651 *n_uids = n;
652
653 return r;
654}
655
656static int seat_get_can(const char *seat, const char *variable) {
657 _cleanup_free_ char *p = NULL, *s = NULL;
658 int r;
659
60f067b4
JS
660 assert_return(variable, -EINVAL);
661
663996b3
MS
662 r = file_of_seat(seat, &p);
663 if (r < 0)
664 return r;
665
666 r = parse_env_file(p, NEWLINE,
667 variable, &s,
668 NULL);
669 if (r < 0)
670 return r;
60f067b4
JS
671 if (!s)
672 return 0;
663996b3 673
60f067b4 674 return parse_boolean(s);
663996b3
MS
675}
676
677_public_ int sd_seat_can_multi_session(const char *seat) {
678 return seat_get_can(seat, "CAN_MULTI_SESSION");
679}
680
681_public_ int sd_seat_can_tty(const char *seat) {
682 return seat_get_can(seat, "CAN_TTY");
683}
684
685_public_ int sd_seat_can_graphical(const char *seat) {
686 return seat_get_can(seat, "CAN_GRAPHICAL");
687}
688
689_public_ int sd_get_seats(char ***seats) {
690 return get_files_in_directory("/run/systemd/seats/", seats);
691}
692
693_public_ int sd_get_sessions(char ***sessions) {
694 return get_files_in_directory("/run/systemd/sessions/", sessions);
695}
696
697_public_ int sd_get_uids(uid_t **users) {
698 _cleanup_closedir_ DIR *d;
699 int r = 0;
700 unsigned n = 0;
701 _cleanup_free_ uid_t *l = NULL;
702
703 d = opendir("/run/systemd/users/");
704 if (!d)
705 return -errno;
706
707 for (;;) {
708 struct dirent *de;
663996b3
MS
709 int k;
710 uid_t uid;
711
60f067b4
JS
712 errno = 0;
713 de = readdir(d);
714 if (!de && errno != 0)
715 return -errno;
663996b3
MS
716
717 if (!de)
718 break;
719
720 dirent_ensure_type(d, de);
721
722 if (!dirent_is_file(de))
723 continue;
724
725 k = parse_uid(de->d_name, &uid);
726 if (k < 0)
727 continue;
728
729 if (users) {
730 if ((unsigned) r >= n) {
731 uid_t *t;
732
733 n = MAX(16, 2*r);
734 t = realloc(l, sizeof(uid_t) * n);
735 if (!t)
736 return -ENOMEM;
737
738 l = t;
739 }
740
741 assert((unsigned) r < n);
742 l[r++] = uid;
743 } else
744 r++;
745 }
746
747 if (users) {
748 *users = l;
749 l = NULL;
750 }
751
752 return r;
753}
754
755_public_ int sd_get_machine_names(char ***machines) {
60f067b4
JS
756 char **l = NULL, **a, **b;
757 int r;
758
759 assert_return(machines, -EINVAL);
760
761 r = get_files_in_directory("/run/systemd/machines/", &l);
762 if (r < 0)
763 return r;
764
765 if (l) {
766 r = 0;
767
768 /* Filter out the unit: symlinks */
769 for (a = l, b = l; *a; a++) {
770 if (startswith(*a, "unit:"))
771 free(*a);
772 else {
773 *b = *a;
774 b++;
775 r++;
776 }
777 }
778
779 *b = NULL;
780 }
781
782 *machines = l;
783 return r;
784}
785
786_public_ int sd_machine_get_class(const char *machine, char **class) {
787 _cleanup_free_ char *c = NULL;
788 const char *p;
789 int r;
790
e842803a 791 assert_return(machine_name_is_valid(machine), -EINVAL);
60f067b4
JS
792 assert_return(class, -EINVAL);
793
e735f4d4 794 p = strjoina("/run/systemd/machines/", machine);
60f067b4
JS
795 r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL);
796 if (r < 0)
797 return r;
798 if (!c)
799 return -EIO;
800
801 *class = c;
802 c = NULL;
803
804 return 0;
663996b3
MS
805}
806
5eef597e
MP
807_public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
808 _cleanup_free_ char *netif = NULL;
809 size_t l, allocated = 0, nr = 0;
810 int *ni = NULL;
811 const char *p, *word, *state;
812 int r;
813
814 assert_return(machine_name_is_valid(machine), -EINVAL);
815 assert_return(ifindices, -EINVAL);
816
e735f4d4 817 p = strjoina("/run/systemd/machines/", machine);
5eef597e
MP
818 r = parse_env_file(p, NEWLINE, "NETIF", &netif, NULL);
819 if (r < 0)
820 return r;
821 if (!netif) {
822 *ifindices = NULL;
823 return 0;
824 }
825
826 FOREACH_WORD(word, l, netif, state) {
827 char buf[l+1];
828 int ifi;
829
830 *(char*) (mempcpy(buf, word, l)) = 0;
831
832 if (safe_atoi(buf, &ifi) < 0)
833 continue;
834 if (ifi <= 0)
835 continue;
836
837 if (!GREEDY_REALLOC(ni, allocated, nr+1)) {
838 free(ni);
839 return -ENOMEM;
840 }
841
842 ni[nr++] = ifi;
843 }
844
845 *ifindices = ni;
846 return nr;
847}
848
663996b3
MS
849static inline int MONITOR_TO_FD(sd_login_monitor *m) {
850 return (int) (unsigned long) m - 1;
851}
852
853static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
854 return (sd_login_monitor*) (unsigned long) (fd + 1);
855}
856
857_public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
858 int fd, k;
859 bool good = false;
860
60f067b4 861 assert_return(m, -EINVAL);
663996b3
MS
862
863 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
864 if (fd < 0)
865 return -errno;
866
867 if (!category || streq(category, "seat")) {
868 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
869 if (k < 0) {
60f067b4 870 safe_close(fd);
663996b3
MS
871 return -errno;
872 }
873
874 good = true;
875 }
876
877 if (!category || streq(category, "session")) {
878 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
879 if (k < 0) {
60f067b4 880 safe_close(fd);
663996b3
MS
881 return -errno;
882 }
883
884 good = true;
885 }
886
887 if (!category || streq(category, "uid")) {
888 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
889 if (k < 0) {
60f067b4 890 safe_close(fd);
663996b3
MS
891 return -errno;
892 }
893
894 good = true;
895 }
896
897 if (!category || streq(category, "machine")) {
14228c0d 898 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
663996b3 899 if (k < 0) {
60f067b4 900 safe_close(fd);
663996b3
MS
901 return -errno;
902 }
903
904 good = true;
905 }
906
907 if (!good) {
908 close_nointr(fd);
909 return -EINVAL;
910 }
911
912 *m = FD_TO_MONITOR(fd);
913 return 0;
914}
915
916_public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
917 int fd;
918
60f067b4 919 assert_return(m, NULL);
663996b3
MS
920
921 fd = MONITOR_TO_FD(m);
922 close_nointr(fd);
923
924 return NULL;
925}
926
927_public_ int sd_login_monitor_flush(sd_login_monitor *m) {
928
60f067b4 929 assert_return(m, -EINVAL);
663996b3
MS
930
931 return flush_fd(MONITOR_TO_FD(m));
932}
933
934_public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
935
60f067b4 936 assert_return(m, -EINVAL);
663996b3
MS
937
938 return MONITOR_TO_FD(m);
939}
940
941_public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
942
60f067b4 943 assert_return(m, -EINVAL);
663996b3
MS
944
945 /* For now we will only return POLLIN here, since we don't
946 * need anything else ever for inotify. However, let's have
947 * this API to keep our options open should we later on need
948 * it. */
949 return POLLIN;
950}
951
952_public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
953
60f067b4
JS
954 assert_return(m, -EINVAL);
955 assert_return(timeout_usec, -EINVAL);
663996b3
MS
956
957 /* For now we will only return (uint64_t) -1, since we don't
958 * need any timeout. However, let's have this API to keep our
959 * options open should we later on need it. */
960 *timeout_usec = (uint64_t) -1;
961 return 0;
962}