chiark / gitweb /
Rename more things to elogind
[elogind.git] / src / libelogind / 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-shared.h"
34 #include "sd-login.h"
35
36 _public_ int sd_pid_get_session(pid_t pid, char **session) {
37
38         assert_return(pid >= 0, -EINVAL);
39         assert_return(session, -EINVAL);
40
41         return cg_pid_get_session(pid, session);
42 }
43
44 _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
45
46         assert_return(pid >= 0, -EINVAL);
47         assert_return(unit, -EINVAL);
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
54         assert_return(pid >= 0, -EINVAL);
55         assert_return(unit, -EINVAL);
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
62         assert_return(pid >= 0, -EINVAL);
63         assert_return(name, -EINVAL);
64
65         return cg_pid_get_machine_name(pid, name);
66 }
67
68 _public_ int sd_pid_get_slice(pid_t pid, char **slice) {
69
70         assert_return(pid >= 0, -EINVAL);
71         assert_return(slice, -EINVAL);
72
73         return cg_pid_get_slice(pid, slice);
74 }
75
76 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
77
78         assert_return(pid >= 0, -EINVAL);
79         assert_return(uid, -EINVAL);
80
81         return cg_pid_get_owner_uid(pid, uid);
82 }
83
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
168 static int file_of_uid(uid_t uid, char **p) {
169         assert(p);
170
171         if (asprintf(p, "/run/systemd/users/" UID_FMT, uid) < 0)
172                 return -ENOMEM;
173
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;
187
188         r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
189         if (r == -ENOENT) {
190                 free(s);
191                 s = strdup("offline");
192                 if (!s)
193                         return -ENOMEM;
194
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
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
228 _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
229         _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
230         size_t l;
231         int r;
232         const char *word, *variable, *state;
233
234         assert_return(seat, -EINVAL);
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
250         if (asprintf(&t, UID_FMT, uid) < 0)
251                 return -ENOMEM;
252
253         FOREACH_WORD(word, l, s, state) {
254                 if (strneq(t, word, l))
255                         return 1;
256         }
257
258         return 0;
259 }
260
261 static 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
266         r = file_of_uid(uid, &p);
267         if (r < 0)
268                 return r;
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
323 static int file_of_session(const char *session, char **_p) {
324         char *p;
325         int r;
326
327         assert(_p);
328
329         if (session) {
330                 if (!session_id_valid(session))
331                         return -EINVAL;
332
333                 p = strappend("/run/systemd/sessions/", session);
334         } else {
335                 _cleanup_free_ char *buf = NULL;
336
337                 r = sd_pid_get_session(0, &buf);
338                 if (r < 0)
339                         return r;
340
341                 p = strappend("/run/systemd/sessions/", buf);
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);
360         if (r < 0)
361                 return r;
362
363         if (!s)
364                 return -EIO;
365
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;
372
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);
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
391         assert_return(state, -EINVAL);
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);
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
413         assert_return(uid, -EINVAL);
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);
420         if (r < 0)
421                 return r;
422
423         if (!s)
424                 return -EIO;
425
426         return parse_uid(s, uid);
427 }
428
429 static int session_get_string(const char *session, const char *field, char **value) {
430         _cleanup_free_ char *p = NULL, *s = NULL;
431         int r;
432
433         assert_return(value, -EINVAL);
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);
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
459 _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
460         _cleanup_free_ char *vtnr_string = NULL;
461         unsigned u;
462         int r;
463
464         r = session_get_string(session, "VTNR", &vtnr_string);
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
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
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
507 _public_ int sd_session_get_display(const char *session, char **display) {
508         return session_get_string(session, "DISPLAY", display);
509 }
510
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
519 static 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
549         assert_return(session || uid, -EINVAL);
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) {
608                 const char *word, *state;
609                 size_t l;
610
611                 FOREACH_WORD(word, l, t, state)
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
621                         FOREACH_WORD(word, l, t, state) {
622                                 _cleanup_free_ char *k = NULL;
623
624                                 k = strndup(word, l);
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
656 static int seat_get_can(const char *seat, const char *variable) {
657         _cleanup_free_ char *p = NULL, *s = NULL;
658         int r;
659
660         assert_return(variable, -EINVAL);
661
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;
671         if (!s)
672                 return 0;
673
674         return parse_boolean(s);
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;
709                 int k;
710                 uid_t uid;
711
712                 errno = 0;
713                 de = readdir(d);
714                 if (!de && errno != 0)
715                         return -errno;
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) {
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
791         assert_return(machine_name_is_valid(machine), -EINVAL);
792         assert_return(class, -EINVAL);
793
794         p = strjoina("/run/systemd/machines/", machine);
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;
805 }
806
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
817         p = strjoina("/run/systemd/machines/", machine);
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
849 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
850         return (int) (unsigned long) m - 1;
851 }
852
853 static 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
861         assert_return(m, -EINVAL);
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) {
870                         safe_close(fd);
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) {
880                         safe_close(fd);
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) {
890                         safe_close(fd);
891                         return -errno;
892                 }
893
894                 good = true;
895         }
896
897         if (!category || streq(category, "machine")) {
898                 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
899                 if (k < 0) {
900                         safe_close(fd);
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
919         assert_return(m, NULL);
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
929         assert_return(m, -EINVAL);
930
931         return flush_fd(MONITOR_TO_FD(m));
932 }
933
934 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
935
936         assert_return(m, -EINVAL);
937
938         return MONITOR_TO_FD(m);
939 }
940
941 _public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
942
943         assert_return(m, -EINVAL);
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
954         assert_return(m, -EINVAL);
955         assert_return(timeout_usec, -EINVAL);
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 }