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