]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-login/sd-login.c
util: rework strappenda(), and rename it strjoina()
[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 <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_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 }