chiark / gitweb /
95cb6ff5812c1dd95119377d24ac8e7839b982b2
[elogind.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 <sys/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_display(const char *session, char **display) {
489         return session_get_string(session, "DISPLAY", display);
490 }
491
492 _public_ int sd_session_get_remote_user(const char *session, char **remote_user) {
493         return session_get_string(session, "REMOTE_USER", remote_user);
494 }
495
496 _public_ int sd_session_get_remote_host(const char *session, char **remote_host) {
497         return session_get_string(session, "REMOTE_HOST", remote_host);
498 }
499
500 static int file_of_seat(const char *seat, char **_p) {
501         char *p;
502         int r;
503
504         assert(_p);
505
506         if (seat)
507                 p = strappend("/run/systemd/seats/", seat);
508         else {
509                 _cleanup_free_ char *buf = NULL;
510
511                 r = sd_session_get_seat(NULL, &buf);
512                 if (r < 0)
513                         return r;
514
515                 p = strappend("/run/systemd/seats/", buf);
516         }
517
518         if (!p)
519                 return -ENOMEM;
520
521         *_p = p;
522         p = NULL;
523         return 0;
524 }
525
526 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
527         _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
528         int r;
529
530         assert_return(session || uid, -EINVAL);
531
532         r = file_of_seat(seat, &p);
533         if (r < 0)
534                 return r;
535
536         r = parse_env_file(p, NEWLINE,
537                            "ACTIVE", &s,
538                            "ACTIVE_UID", &t,
539                            NULL);
540         if (r < 0)
541                 return r;
542
543         if (session && !s)
544                 return -ENOENT;
545
546         if (uid && !t)
547                 return -ENOENT;
548
549         if (uid && t) {
550                 r = parse_uid(t, uid);
551                 if (r < 0)
552                         return r;
553         }
554
555         if (session && s) {
556                 *session = s;
557                 s = NULL;
558         }
559
560         return 0;
561 }
562
563 _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
564         _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
565         _cleanup_strv_free_ char **a = NULL;
566         _cleanup_free_ uid_t *b = NULL;
567         unsigned n = 0;
568         int r;
569
570         r = file_of_seat(seat, &p);
571         if (r < 0)
572                 return r;
573
574         r = parse_env_file(p, NEWLINE,
575                            "SESSIONS", &s,
576                            "ACTIVE_SESSIONS", &t,
577                            NULL);
578
579         if (r < 0)
580                 return r;
581
582         if (s) {
583                 a = strv_split(s, " ");
584                 if (!a)
585                         return -ENOMEM;
586         }
587
588         if (uids && t) {
589                 const char *word, *state;
590                 size_t l;
591
592                 FOREACH_WORD(word, l, t, state)
593                         n++;
594
595                 if (n > 0) {
596                         unsigned i = 0;
597
598                         b = new(uid_t, n);
599                         if (!b)
600                                 return -ENOMEM;
601
602                         FOREACH_WORD(word, l, t, state) {
603                                 _cleanup_free_ char *k = NULL;
604
605                                 k = strndup(word, l);
606                                 if (!k)
607                                         return -ENOMEM;
608
609                                 r = parse_uid(k, b + i);
610
611                                 if (r < 0)
612                                         continue;
613
614                                 i++;
615                         }
616                 }
617         }
618
619         r = strv_length(a);
620
621         if (sessions) {
622                 *sessions = a;
623                 a = NULL;
624         }
625
626         if (uids) {
627                 *uids = b;
628                 b = NULL;
629         }
630
631         if (n_uids)
632                 *n_uids = n;
633
634         return r;
635 }
636
637 static int seat_get_can(const char *seat, const char *variable) {
638         _cleanup_free_ char *p = NULL, *s = NULL;
639         int r;
640
641         assert_return(variable, -EINVAL);
642
643         r = file_of_seat(seat, &p);
644         if (r < 0)
645                 return r;
646
647         r = parse_env_file(p, NEWLINE,
648                            variable, &s,
649                            NULL);
650         if (r < 0)
651                 return r;
652         if (!s)
653                 return 0;
654
655         return parse_boolean(s);
656 }
657
658 _public_ int sd_seat_can_multi_session(const char *seat) {
659         return seat_get_can(seat, "CAN_MULTI_SESSION");
660 }
661
662 _public_ int sd_seat_can_tty(const char *seat) {
663         return seat_get_can(seat, "CAN_TTY");
664 }
665
666 _public_ int sd_seat_can_graphical(const char *seat) {
667         return seat_get_can(seat, "CAN_GRAPHICAL");
668 }
669
670 _public_ int sd_get_seats(char ***seats) {
671         return get_files_in_directory("/run/systemd/seats/", seats);
672 }
673
674 _public_ int sd_get_sessions(char ***sessions) {
675         return get_files_in_directory("/run/systemd/sessions/", sessions);
676 }
677
678 _public_ int sd_get_uids(uid_t **users) {
679         _cleanup_closedir_ DIR *d;
680         int r = 0;
681         unsigned n = 0;
682         _cleanup_free_ uid_t *l = NULL;
683
684         d = opendir("/run/systemd/users/");
685         if (!d)
686                 return -errno;
687
688         for (;;) {
689                 struct dirent *de;
690                 int k;
691                 uid_t uid;
692
693                 errno = 0;
694                 de = readdir(d);
695                 if (!de && errno != 0)
696                         return -errno;
697
698                 if (!de)
699                         break;
700
701                 dirent_ensure_type(d, de);
702
703                 if (!dirent_is_file(de))
704                         continue;
705
706                 k = parse_uid(de->d_name, &uid);
707                 if (k < 0)
708                         continue;
709
710                 if (users) {
711                         if ((unsigned) r >= n) {
712                                 uid_t *t;
713
714                                 n = MAX(16, 2*r);
715                                 t = realloc(l, sizeof(uid_t) * n);
716                                 if (!t)
717                                         return -ENOMEM;
718
719                                 l = t;
720                         }
721
722                         assert((unsigned) r < n);
723                         l[r++] = uid;
724                 } else
725                         r++;
726         }
727
728         if (users) {
729                 *users = l;
730                 l = NULL;
731         }
732
733         return r;
734 }
735
736 _public_ int sd_get_machine_names(char ***machines) {
737         char **l = NULL, **a, **b;
738         int r;
739
740         assert_return(machines, -EINVAL);
741
742         r = get_files_in_directory("/run/systemd/machines/", &l);
743         if (r < 0)
744                 return r;
745
746         if (l) {
747                 r = 0;
748
749                 /* Filter out the unit: symlinks */
750                 for (a = l, b = l; *a; a++) {
751                         if (startswith(*a, "unit:"))
752                                 free(*a);
753                         else {
754                                 *b = *a;
755                                 b++;
756                                 r++;
757                         }
758                 }
759
760                 *b = NULL;
761         }
762
763         *machines = l;
764         return r;
765 }
766
767 _public_ int sd_machine_get_class(const char *machine, char **class) {
768         _cleanup_free_ char *c = NULL;
769         const char *p;
770         int r;
771
772         assert_return(machine_name_is_valid(machine), -EINVAL);
773         assert_return(class, -EINVAL);
774
775         p = strappenda("/run/systemd/machines/", machine);
776         r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL);
777         if (r < 0)
778                 return r;
779         if (!c)
780                 return -EIO;
781
782         *class = c;
783         c = NULL;
784
785         return 0;
786 }
787
788 _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
789         _cleanup_free_ char *netif = NULL;
790         size_t l, allocated = 0, nr = 0;
791         int *ni = NULL;
792         const char *p, *word, *state;
793         int r;
794
795         assert_return(machine_name_is_valid(machine), -EINVAL);
796         assert_return(ifindices, -EINVAL);
797
798         p = strappenda("/run/systemd/machines/", machine);
799         r = parse_env_file(p, NEWLINE, "NETIF", &netif, NULL);
800         if (r < 0)
801                 return r;
802         if (!netif) {
803                 *ifindices = NULL;
804                 return 0;
805         }
806
807         FOREACH_WORD(word, l, netif, state) {
808                 char buf[l+1];
809                 int ifi;
810
811                 *(char*) (mempcpy(buf, word, l)) = 0;
812
813                 if (safe_atoi(buf, &ifi) < 0)
814                         continue;
815                 if (ifi <= 0)
816                         continue;
817
818                 if (!GREEDY_REALLOC(ni, allocated, nr+1)) {
819                         free(ni);
820                         return -ENOMEM;
821                 }
822
823                 ni[nr++] = ifi;
824         }
825
826         *ifindices = ni;
827         return nr;
828 }
829
830 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
831         return (int) (unsigned long) m - 1;
832 }
833
834 static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
835         return (sd_login_monitor*) (unsigned long) (fd + 1);
836 }
837
838 _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
839         int fd, k;
840         bool good = false;
841
842         assert_return(m, -EINVAL);
843
844         fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
845         if (fd < 0)
846                 return -errno;
847
848         if (!category || streq(category, "seat")) {
849                 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
850                 if (k < 0) {
851                         safe_close(fd);
852                         return -errno;
853                 }
854
855                 good = true;
856         }
857
858         if (!category || streq(category, "session")) {
859                 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
860                 if (k < 0) {
861                         safe_close(fd);
862                         return -errno;
863                 }
864
865                 good = true;
866         }
867
868         if (!category || streq(category, "uid")) {
869                 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
870                 if (k < 0) {
871                         safe_close(fd);
872                         return -errno;
873                 }
874
875                 good = true;
876         }
877
878         if (!category || streq(category, "machine")) {
879                 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
880                 if (k < 0) {
881                         safe_close(fd);
882                         return -errno;
883                 }
884
885                 good = true;
886         }
887
888         if (!good) {
889                 close_nointr(fd);
890                 return -EINVAL;
891         }
892
893         *m = FD_TO_MONITOR(fd);
894         return 0;
895 }
896
897 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
898         int fd;
899
900         assert_return(m, NULL);
901
902         fd = MONITOR_TO_FD(m);
903         close_nointr(fd);
904
905         return NULL;
906 }
907
908 _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
909
910         assert_return(m, -EINVAL);
911
912         return flush_fd(MONITOR_TO_FD(m));
913 }
914
915 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
916
917         assert_return(m, -EINVAL);
918
919         return MONITOR_TO_FD(m);
920 }
921
922 _public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
923
924         assert_return(m, -EINVAL);
925
926         /* For now we will only return POLLIN here, since we don't
927          * need anything else ever for inotify.  However, let's have
928          * this API to keep our options open should we later on need
929          * it. */
930         return POLLIN;
931 }
932
933 _public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
934
935         assert_return(m, -EINVAL);
936         assert_return(timeout_usec, -EINVAL);
937
938         /* For now we will only return (uint64_t) -1, since we don't
939          * need any timeout. However, let's have this API to keep our
940          * options open should we later on need it. */
941         *timeout_usec = (uint64_t) -1;
942         return 0;
943 }