1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <sys/inotify.h>
9 #include "alloc-util.h"
10 #include "cgroup-util.h"
11 #include "dirent-util.h"
13 #include "extract-word.h"
15 #include "format-util.h"
17 #include "hostname-util.h"
19 #include "login-util.h"
20 #include "parse-util.h"
21 #include "path-util.h"
22 #include "pidfd-util.h"
24 #include "socket-util.h"
25 #include "string-util.h"
27 #include "user-util.h"
31 * invalid input parameters → -EINVAL
33 * process does not exist → -ESRCH
34 * cgroup does not exist → -ENOENT
35 * machine, session does not exist → -ENXIO
36 * requested metadata on object is missing → -ENODATA
39 _public_
int sd_pid_get_session(pid_t pid
, char **ret_session
) {
42 assert_return(pid
>= 0, -EINVAL
);
44 r
= cg_pid_get_session(pid
, ret_session
);
45 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
48 _public_
int sd_pid_get_unit(pid_t pid
, char **ret_unit
) {
51 assert_return(pid
>= 0, -EINVAL
);
53 r
= cg_pid_get_unit(pid
, ret_unit
);
54 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
57 _public_
int sd_pid_get_user_unit(pid_t pid
, char **ret_unit
) {
60 assert_return(pid
>= 0, -EINVAL
);
62 r
= cg_pid_get_user_unit(pid
, ret_unit
);
63 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
66 _public_
int sd_pid_get_machine_name(pid_t pid
, char **ret_name
) {
69 assert_return(pid
>= 0, -EINVAL
);
71 r
= cg_pid_get_machine_name(pid
, ret_name
);
72 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
75 _public_
int sd_pid_get_slice(pid_t pid
, char **ret_slice
) {
78 assert_return(pid
>= 0, -EINVAL
);
80 r
= cg_pid_get_slice(pid
, ret_slice
);
81 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
84 _public_
int sd_pid_get_user_slice(pid_t pid
, char **ret_slice
) {
87 assert_return(pid
>= 0, -EINVAL
);
89 r
= cg_pid_get_user_slice(pid
, ret_slice
);
90 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
93 _public_
int sd_pid_get_owner_uid(pid_t pid
, uid_t
*ret_uid
) {
96 assert_return(pid
>= 0, -EINVAL
);
98 r
= cg_pid_get_owner_uid(pid
, ret_uid
);
99 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
102 _public_
int sd_pid_get_cgroup(pid_t pid
, char **ret_cgroup
) {
105 assert_return(pid
>= 0, -EINVAL
);
107 _cleanup_free_
char *c
= NULL
;
108 r
= cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER
, pid
, &c
);
113 /* The internal APIs return the empty string for the root cgroup, let's return the "/" in the
114 * public APIs instead, as that's easier and less ambiguous for people to grok. */
116 r
= free_and_strdup(&c
, "/");
121 *ret_cgroup
= TAKE_PTR(c
);
127 _public_
int sd_pidfd_get_session(int pidfd
, char **ret_session
) {
128 _cleanup_free_
char *session
= NULL
;
132 assert_return(pidfd
>= 0, -EBADF
);
134 r
= pidfd_get_pid(pidfd
, &pid
);
138 r
= sd_pid_get_session(pid
, &session
);
142 r
= pidfd_verify_pid(pidfd
, pid
);
147 *ret_session
= TAKE_PTR(session
);
151 _public_
int sd_pidfd_get_unit(int pidfd
, char **ret_unit
) {
152 _cleanup_free_
char *unit
= NULL
;
156 assert_return(pidfd
>= 0, -EBADF
);
158 r
= pidfd_get_pid(pidfd
, &pid
);
162 r
= sd_pid_get_unit(pid
, &unit
);
166 r
= pidfd_verify_pid(pidfd
, pid
);
171 *ret_unit
= TAKE_PTR(unit
);
175 _public_
int sd_pidfd_get_user_unit(int pidfd
, char **ret_unit
) {
176 _cleanup_free_
char *unit
= NULL
;
180 assert_return(pidfd
>= 0, -EBADF
);
182 r
= pidfd_get_pid(pidfd
, &pid
);
186 r
= sd_pid_get_user_unit(pid
, &unit
);
190 r
= pidfd_verify_pid(pidfd
, pid
);
195 *ret_unit
= TAKE_PTR(unit
);
199 _public_
int sd_pidfd_get_machine_name(int pidfd
, char **ret_name
) {
200 _cleanup_free_
char *name
= NULL
;
204 assert_return(pidfd
>= 0, -EBADF
);
206 r
= pidfd_get_pid(pidfd
, &pid
);
210 r
= sd_pid_get_machine_name(pid
, &name
);
214 r
= pidfd_verify_pid(pidfd
, pid
);
219 *ret_name
= TAKE_PTR(name
);
223 _public_
int sd_pidfd_get_slice(int pidfd
, char **ret_slice
) {
224 _cleanup_free_
char *slice
= NULL
;
228 assert_return(pidfd
>= 0, -EBADF
);
230 r
= pidfd_get_pid(pidfd
, &pid
);
234 r
= sd_pid_get_slice(pid
, &slice
);
238 r
= pidfd_verify_pid(pidfd
, pid
);
243 *ret_slice
= TAKE_PTR(slice
);
247 _public_
int sd_pidfd_get_user_slice(int pidfd
, char **ret_slice
) {
248 _cleanup_free_
char *slice
= NULL
;
252 assert_return(pidfd
>= 0, -EBADF
);
254 r
= pidfd_get_pid(pidfd
, &pid
);
258 r
= sd_pid_get_user_slice(pid
, &slice
);
262 r
= pidfd_verify_pid(pidfd
, pid
);
267 *ret_slice
= TAKE_PTR(slice
);
271 _public_
int sd_pidfd_get_owner_uid(int pidfd
, uid_t
*ret_uid
) {
276 assert_return(pidfd
>= 0, -EBADF
);
278 r
= pidfd_get_pid(pidfd
, &pid
);
282 r
= sd_pid_get_owner_uid(pid
, &uid
);
286 r
= pidfd_verify_pid(pidfd
, pid
);
295 _public_
int sd_pidfd_get_cgroup(int pidfd
, char **ret_cgroup
) {
296 _cleanup_free_
char *cgroup
= NULL
;
300 assert_return(pidfd
>= 0, -EBADF
);
302 r
= pidfd_get_pid(pidfd
, &pid
);
306 r
= sd_pid_get_cgroup(pid
, &cgroup
);
310 r
= pidfd_verify_pid(pidfd
, pid
);
315 *ret_cgroup
= TAKE_PTR(cgroup
);
319 _public_
int sd_peer_get_session(int fd
, char **ret_session
) {
322 assert_return(fd
>= 0, -EBADF
);
324 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
325 r
= getpeerpidref(fd
, &pidref
);
329 return cg_pidref_get_session(&pidref
, ret_session
);
332 _public_
int sd_peer_get_owner_uid(int fd
, uid_t
*ret_uid
) {
335 assert_return(fd
>= 0, -EBADF
);
337 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
338 r
= getpeerpidref(fd
, &pidref
);
342 return cg_pidref_get_owner_uid(&pidref
, ret_uid
);
345 _public_
int sd_peer_get_unit(int fd
, char **ret_unit
) {
348 assert_return(fd
>= 0, -EBADF
);
350 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
351 r
= getpeerpidref(fd
, &pidref
);
355 return cg_pidref_get_unit(&pidref
, ret_unit
);
358 _public_
int sd_peer_get_user_unit(int fd
, char **ret_unit
) {
362 assert_return(fd
>= 0, -EBADF
);
364 r
= getpeercred(fd
, &ucred
);
368 return cg_pid_get_user_unit(ucred
.pid
, ret_unit
);
371 _public_
int sd_peer_get_machine_name(int fd
, char **ret_machine
) {
375 assert_return(fd
>= 0, -EBADF
);
377 r
= getpeercred(fd
, &ucred
);
381 return cg_pid_get_machine_name(ucred
.pid
, ret_machine
);
384 _public_
int sd_peer_get_slice(int fd
, char **ret_slice
) {
388 assert_return(fd
>= 0, -EBADF
);
390 r
= getpeercred(fd
, &ucred
);
394 return cg_pid_get_slice(ucred
.pid
, ret_slice
);
397 _public_
int sd_peer_get_user_slice(int fd
, char **ret_slice
) {
401 assert_return(fd
>= 0, -EBADF
);
403 r
= getpeercred(fd
, &ucred
);
407 return cg_pid_get_user_slice(ucred
.pid
, ret_slice
);
410 _public_
int sd_peer_get_cgroup(int fd
, char **ret_cgroup
) {
413 assert_return(fd
>= 0, -EBADF
);
415 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
416 r
= getpeerpidref(fd
, &pidref
);
420 _cleanup_free_
char *c
= NULL
;
421 r
= cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER
, &pidref
, &c
);
426 /* The internal APIs return the empty string for the root cgroup, let's return the "/" in the
427 * public APIs instead, as that's easier and less ambiguous for people to grok. */
429 r
= free_and_strdup(&c
, "/");
434 *ret_cgroup
= TAKE_PTR(c
);
440 static int file_of_uid(uid_t uid
, char **ret
) {
442 assert_return(uid_is_valid(uid
), -EINVAL
);
445 if (asprintf(ret
, "/run/systemd/users/" UID_FMT
, uid
) < 0)
451 _public_
int sd_uid_get_state(uid_t uid
, char **ret_state
) {
452 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
455 r
= file_of_uid(uid
, &p
);
459 r
= parse_env_file(/* f= */ NULL
, p
, "STATE", &s
);
461 r
= free_and_strdup(&s
, "offline");
468 *ret_state
= TAKE_PTR(s
);
472 _public_
int sd_uid_get_display(uid_t uid
, char **ret_session
) {
473 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
476 r
= file_of_uid(uid
, &p
);
480 r
= parse_env_file(/* f= */ NULL
, p
, "DISPLAY", &s
);
489 *ret_session
= TAKE_PTR(s
);
493 _public_
int sd_uid_get_login_time(uid_t uid
, uint64_t *ret_usec
) {
494 _cleanup_free_
char *p
= NULL
, *s
= NULL
, *rt
= NULL
;
497 r
= file_of_uid(uid
, &p
);
501 r
= parse_env_file(/* f= */ NULL
, p
, "STATE", &s
, "REALTIME", &rt
);
506 if (isempty(s
) || isempty(rt
))
509 if (!STR_IN_SET(s
, "active", "online"))
512 return safe_atou64(rt
, ret_usec
);
515 static int file_of_seat(const char *seat
, char **ret
) {
522 if (!filename_is_valid(seat
))
525 p
= path_join("/run/systemd/seats", seat
);
527 _cleanup_free_
char *buf
= NULL
;
529 r
= sd_session_get_seat(NULL
, &buf
);
533 p
= path_join("/run/systemd/seats", buf
);
542 _public_
int sd_uid_is_on_seat(uid_t uid
, int require_active
, const char *seat
) {
543 _cleanup_free_
char *filename
= NULL
, *content
= NULL
;
546 assert_return(uid_is_valid(uid
), -EINVAL
);
548 r
= file_of_seat(seat
, &filename
);
552 r
= parse_env_file(/* f= */ NULL
, filename
,
553 require_active
? "ACTIVE_UID" : "UIDS",
559 if (isempty(content
))
562 return string_contains_word(content
, NULL
, FORMAT_UID(uid
));
565 static int uid_get_array(uid_t uid
, const char *variable
, char ***ret_array
) {
566 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
571 r
= file_of_uid(uid
, &p
);
575 r
= parse_env_file(/* f= */ NULL
, p
, variable
, &s
);
576 if (r
== -ENOENT
|| (r
>= 0 && isempty(s
))) {
584 _cleanup_strv_free_
char **a
= strv_split(s
, NULL
);
589 r
= (int) strv_length(a
);
592 *ret_array
= TAKE_PTR(a
);
597 _public_
int sd_uid_get_sessions(uid_t uid
, int require_active
, char ***ret_sessions
) {
598 return uid_get_array(
600 require_active
== 0 ? "ONLINE_SESSIONS" :
601 require_active
> 0 ? "ACTIVE_SESSIONS" :
606 _public_
int sd_uid_get_seats(uid_t uid
, int require_active
, char ***ret_seats
) {
607 return uid_get_array(
609 require_active
== 0 ? "ONLINE_SEATS" :
610 require_active
> 0 ? "ACTIVE_SEATS" :
615 static int file_of_session(const char *session
, char **ret
) {
622 if (!session_id_valid(session
))
625 p
= path_join("/run/systemd/sessions", session
);
627 _cleanup_free_
char *buf
= NULL
;
629 r
= sd_pid_get_session(0, &buf
);
633 p
= path_join("/run/systemd/sessions", buf
);
642 _public_
int sd_session_is_active(const char *session
) {
643 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
646 r
= file_of_session(session
, &p
);
650 r
= parse_env_file(/* f= */ NULL
, p
, "ACTIVE", &s
);
658 return parse_boolean(s
);
661 _public_
int sd_session_is_remote(const char *session
) {
662 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
665 r
= file_of_session(session
, &p
);
669 r
= parse_env_file(/* f= */ NULL
, p
, "REMOTE", &s
);
677 return parse_boolean(s
);
680 _public_
int sd_session_get_state(const char *session
, char **ret_state
) {
681 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
684 r
= file_of_session(session
, &p
);
688 r
= parse_env_file(/* f= */ NULL
, p
, "STATE", &s
);
697 *ret_state
= TAKE_PTR(s
);
701 _public_
int sd_session_get_uid(const char *session
, uid_t
*ret_uid
) {
703 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
705 r
= file_of_session(session
, &p
);
709 r
= parse_env_file(/* f= */ NULL
, p
, "UID", &s
);
717 return parse_uid(s
, ret_uid
);
720 static int session_get_string(const char *session
, const char *field
, char **ret_value
) {
721 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
726 r
= file_of_session(session
, &p
);
730 r
= parse_env_file(/* f= */ NULL
, p
, field
, &s
);
739 *ret_value
= TAKE_PTR(s
);
743 _public_
int sd_session_get_username(const char *session
, char **ret_username
) {
744 return session_get_string(session
, "USER", ret_username
);
747 _public_
int sd_session_get_seat(const char *session
, char **ret_seat
) {
748 return session_get_string(session
, "SEAT", ret_seat
);
751 _public_
int sd_session_get_start_time(const char *session
, uint64_t *ret_usec
) {
752 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
755 r
= file_of_session(session
, &p
);
759 r
= parse_env_file(/* f= */ NULL
, p
, "REALTIME", &s
);
767 return safe_atou64(s
, ret_usec
);
770 _public_
int sd_session_get_tty(const char *session
, char **ret_tty
) {
771 return session_get_string(session
, "TTY", ret_tty
);
774 _public_
int sd_session_get_vt(const char *session
, unsigned *ret_vtnr
) {
775 _cleanup_free_
char *vtnr_string
= NULL
;
778 r
= session_get_string(session
, "VTNR", &vtnr_string
);
782 return safe_atou(vtnr_string
, ret_vtnr
);
785 _public_
int sd_session_get_service(const char *session
, char **ret_service
) {
786 return session_get_string(session
, "SERVICE", ret_service
);
789 _public_
int sd_session_get_type(const char *session
, char **ret_type
) {
790 return session_get_string(session
, "TYPE", ret_type
);
793 _public_
int sd_session_get_class(const char *session
, char **ret_class
) {
794 return session_get_string(session
, "CLASS", ret_class
);
797 _public_
int sd_session_get_desktop(const char *session
, char **ret_desktop
) {
798 return session_get_string(session
, "DESKTOP", ret_desktop
);
801 _public_
int sd_session_get_display(const char *session
, char **ret_display
) {
802 return session_get_string(session
, "DISPLAY", ret_display
);
805 _public_
int sd_session_get_remote_user(const char *session
, char **ret_remote_user
) {
806 return session_get_string(session
, "REMOTE_USER", ret_remote_user
);
809 _public_
int sd_session_get_remote_host(const char *session
, char **ret_remote_host
) {
810 return session_get_string(session
, "REMOTE_HOST", ret_remote_host
);
813 _public_
int sd_session_get_leader(const char *session
, pid_t
*ret_leader
) {
814 _cleanup_free_
char *leader_string
= NULL
;
817 r
= session_get_string(session
, "LEADER", &leader_string
);
821 return parse_pid(leader_string
, ret_leader
);
824 _public_
int sd_seat_get_active(const char *seat
, char **ret_session
, uid_t
*ret_uid
) {
825 _cleanup_free_
char *p
= NULL
, *s
= NULL
, *t
= NULL
;
828 r
= file_of_seat(seat
, &p
);
832 r
= parse_env_file(/* f= */ NULL
, p
,
840 if (ret_session
&& !s
)
847 r
= parse_uid(t
, ret_uid
);
852 if (ret_session
&& s
)
853 *ret_session
= TAKE_PTR(s
);
858 _public_
int sd_seat_get_sessions(
860 char ***ret_sessions
,
862 unsigned *ret_n_uids
) {
864 _cleanup_free_
char *fname
= NULL
, *session_line
= NULL
, *uid_line
= NULL
;
865 _cleanup_strv_free_
char **sessions
= NULL
;
866 _cleanup_free_ uid_t
*uids
= NULL
;
867 unsigned n_sessions
= 0;
870 r
= file_of_seat(seat
, &fname
);
874 r
= parse_env_file(/* f= */ NULL
, fname
,
875 "SESSIONS", &session_line
,
883 sessions
= strv_split(session_line
, NULL
);
887 n_sessions
= strv_length(sessions
);
890 if (ret_uids
&& uid_line
) {
891 uids
= new(uid_t
, n_sessions
);
896 for (const char *p
= uid_line
;;) {
897 _cleanup_free_
char *word
= NULL
;
899 r
= extract_first_word(&p
, &word
, NULL
, 0);
905 r
= parse_uid(word
, &uids
[n
++]);
915 *ret_sessions
= TAKE_PTR(sessions
);
917 *ret_uids
= TAKE_PTR(uids
);
919 *ret_n_uids
= n_sessions
;
924 static int seat_get_can(const char *seat
, const char *variable
) {
925 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
930 r
= file_of_seat(seat
, &p
);
934 r
= parse_env_file(/* f= */ NULL
, p
,
943 return parse_boolean(s
);
946 _public_
int sd_seat_can_multi_session(const char *seat
) {
950 _public_
int sd_seat_can_tty(const char *seat
) {
951 return seat_get_can(seat
, "CAN_TTY");
954 _public_
int sd_seat_can_graphical(const char *seat
) {
955 return seat_get_can(seat
, "CAN_GRAPHICAL");
958 _public_
int sd_get_seats(char ***ret_seats
) {
961 r
= get_files_in_directory("/run/systemd/seats/", ret_seats
);
970 _public_
int sd_get_sessions(char ***ret_sessions
) {
973 r
= get_files_in_directory("/run/systemd/sessions/", ret_sessions
);
976 *ret_sessions
= NULL
;
982 _public_
int sd_get_uids(uid_t
**ret_users
) {
983 _cleanup_closedir_
DIR *d
= NULL
;
984 _cleanup_free_ uid_t
*l
= NULL
;
987 d
= opendir("/run/systemd/users/");
989 if (errno
== ENOENT
) {
997 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
1000 if (!dirent_is_file(de
))
1003 if (parse_uid(de
->d_name
, &uid
) < 0)
1007 if (!GREEDY_REALLOC(l
, n
+ 1))
1020 *ret_users
= TAKE_PTR(l
);
1025 _public_
int sd_get_machine_names(char ***ret_machines
) {
1026 _cleanup_strv_free_
char **l
= NULL
;
1030 r
= get_files_in_directory("/run/systemd/machines/", &l
);
1033 *ret_machines
= NULL
;
1042 /* Filter out the unit: symlinks */
1043 for (a
= b
= l
; *a
; a
++) {
1044 if (startswith(*a
, "unit:") || !hostname_is_valid(*a
, 0))
1057 *ret_machines
= TAKE_PTR(l
);
1062 _public_
int sd_machine_get_class(const char *machine
, char **ret_class
) {
1063 _cleanup_free_
char *c
= NULL
;
1066 if (streq_ptr(machine
, ".host")) {
1071 if (!hostname_is_valid(machine
, 0))
1074 _cleanup_free_
char *p
= path_join("/run/systemd/machines/", machine
);
1078 r
= parse_env_file(/* f= */ NULL
, p
, "CLASS", &c
);
1088 *ret_class
= TAKE_PTR(c
);
1093 _public_
int sd_machine_get_ifindices(const char *machine
, int **ret_ifindices
) {
1094 _cleanup_free_
char *netif_line
= NULL
, *p
= NULL
;
1097 assert_return(hostname_is_valid(machine
, 0), -EINVAL
);
1099 p
= path_join("/run/systemd/machines/", machine
);
1103 r
= parse_env_file(/* f= */ NULL
, p
, "NETIF", &netif_line
);
1110 *ret_ifindices
= NULL
;
1114 _cleanup_strv_free_
char **tt
= strv_split(netif_line
, NULL
);
1118 _cleanup_free_
int *ifindices
= NULL
;
1119 if (ret_ifindices
) {
1120 ifindices
= new(int, strv_length(tt
));
1126 for (size_t i
= 0; tt
[i
]; i
++) {
1129 ind
= parse_ifindex(tt
[i
]);
1131 /* Return -EUCLEAN to distinguish from -EINVAL for invalid args */
1132 return ind
== -EINVAL
? -EUCLEAN
: ind
;
1140 *ret_ifindices
= TAKE_PTR(ifindices
);
1145 static int MONITOR_TO_FD(sd_login_monitor
*m
) {
1146 return (int) (unsigned long) m
- 1;
1149 static sd_login_monitor
* FD_TO_MONITOR(int fd
) {
1150 return (sd_login_monitor
*) (unsigned long) (fd
+ 1);
1153 _public_
int sd_login_monitor_new(const char *category
, sd_login_monitor
**ret
) {
1154 _cleanup_close_
int fd
= -EBADF
;
1156 assert_return(ret
, -EINVAL
);
1158 fd
= inotify_init1(IN_NONBLOCK
|IN_CLOEXEC
);
1162 static const struct {
1166 { "seat", "/run/systemd/seats/" },
1167 { "session", "/run/systemd/sessions/" },
1168 { "uid", "/run/systemd/users/" },
1169 { "machine", "/run/systemd/machines/" },
1173 FOREACH_ELEMENT(c
, categories
) {
1174 if (category
&& !streq(category
, c
->name
))
1177 if (inotify_add_watch(fd
, c
->path
, IN_MOVED_TO
|IN_DELETE
) < 0)
1186 *ret
= FD_TO_MONITOR(TAKE_FD(fd
));
1190 _public_ sd_login_monitor
* sd_login_monitor_unref(sd_login_monitor
*m
) {
1192 (void) close(MONITOR_TO_FD(m
));
1197 _public_
int sd_login_monitor_flush(sd_login_monitor
*m
) {
1200 assert_return(m
, -EINVAL
);
1202 r
= flush_fd(MONITOR_TO_FD(m
));
1209 _public_
int sd_login_monitor_get_fd(sd_login_monitor
*m
) {
1211 assert_return(m
, -EINVAL
);
1213 return MONITOR_TO_FD(m
);
1216 _public_
int sd_login_monitor_get_events(sd_login_monitor
*m
) {
1218 assert_return(m
, -EINVAL
);
1220 /* For now we will only return POLLIN here, since we don't
1221 * need anything else ever for inotify. However, let's have
1222 * this API to keep our options open should we later on need
1227 _public_
int sd_login_monitor_get_timeout(sd_login_monitor
*m
, uint64_t *ret_timeout_usec
) {
1229 assert_return(m
, -EINVAL
);
1230 assert_return(ret_timeout_usec
, -EINVAL
);
1232 /* For now we will only return UINT64_MAX, since we don't
1233 * need any timeout. However, let's have this API to keep our
1234 * options open should we later on need it. */
1235 *ret_timeout_usec
= UINT64_MAX
;