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