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