1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
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.
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.
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/>.
25 #include <sys/inotify.h>
29 #include "cgroup-util.h"
33 #include "login-shared.h"
34 #include "formats-util.h"
37 _public_ int sd_pid_get_session(pid_t pid, char **session) {
39 assert_return(pid >= 0, -EINVAL);
40 assert_return(session, -EINVAL);
42 return cg_pid_get_session(pid, session);
45 _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
47 assert_return(pid >= 0, -EINVAL);
48 assert_return(unit, -EINVAL);
53 _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
55 assert_return(pid >= 0, -EINVAL);
56 assert_return(unit, -EINVAL);
61 _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
63 assert_return(pid >= 0, -EINVAL);
64 assert_return(name, -EINVAL);
69 _public_ int sd_pid_get_slice(pid_t pid, char **slice) {
71 assert_return(pid >= 0, -EINVAL);
72 assert_return(slice, -EINVAL);
77 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
79 assert_return(pid >= 0, -EINVAL);
80 assert_return(uid, -EINVAL);
85 _public_ int sd_peer_get_session(int fd, char **session) {
86 struct ucred ucred = {};
89 assert_return(fd >= 0, -EINVAL);
90 assert_return(session, -EINVAL);
92 r = getpeercred(fd, &ucred);
96 return cg_pid_get_session(ucred.pid, session);
99 _public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) {
103 assert_return(fd >= 0, -EINVAL);
104 assert_return(uid, -EINVAL);
106 r = getpeercred(fd, &ucred);
113 _public_ int sd_peer_get_unit(int fd, char **unit) {
117 assert_return(fd >= 0, -EINVAL);
118 assert_return(unit, -EINVAL);
120 r = getpeercred(fd, &ucred);
127 _public_ int sd_peer_get_user_unit(int fd, char **unit) {
131 assert_return(fd >= 0, -EINVAL);
132 assert_return(unit, -EINVAL);
134 r = getpeercred(fd, &ucred);
141 _public_ int sd_peer_get_machine_name(int fd, char **machine) {
145 assert_return(fd >= 0, -EINVAL);
146 assert_return(machine, -EINVAL);
148 r = getpeercred(fd, &ucred);
155 _public_ int sd_peer_get_slice(int fd, char **slice) {
159 assert_return(fd >= 0, -EINVAL);
160 assert_return(slice, -EINVAL);
162 r = getpeercred(fd, &ucred);
169 static int file_of_uid(uid_t uid, char **p) {
172 if (asprintf(p, "/run/systemd/users/" UID_FMT, uid) < 0)
178 _public_ int sd_uid_get_state(uid_t uid, char**state) {
179 _cleanup_free_ char *p = NULL;
183 assert_return(state, -EINVAL);
185 r = file_of_uid(uid, &p);
189 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
192 s = strdup("offline");
206 _public_ int sd_uid_get_display(uid_t uid, char **session) {
207 _cleanup_free_ char *p = NULL, *s = NULL;
210 assert_return(session, -EINVAL);
212 r = file_of_uid(uid, &p);
216 r = parse_env_file(p, NEWLINE, "DISPLAY", &s, NULL);
229 _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
230 _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
233 const char *word, *variable, *state;
235 assert_return(seat, -EINVAL);
237 variable = require_active ? "ACTIVE_UID" : "UIDS";
239 p = strappend("/run/systemd/seats/", seat);
243 r = parse_env_file(p, NEWLINE, variable, &s, NULL);
251 if (asprintf(&t, UID_FMT, uid) < 0)
254 FOREACH_WORD(word, l, s, state) {
255 if (strneq(t, word, l))
262 static int uid_get_array(uid_t uid, const char *variable, char ***array) {
263 _cleanup_free_ char *p = NULL, *s = NULL;
267 r = file_of_uid(uid, &p);
271 r = parse_env_file(p, NEWLINE,
290 a = strv_split(s, " ");
306 _public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
307 return uid_get_array(
309 require_active == 0 ? "ONLINE_SESSIONS" :
310 require_active > 0 ? "ACTIVE_SESSIONS" :
315 _public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
316 return uid_get_array(
318 require_active == 0 ? "ONLINE_SEATS" :
319 require_active > 0 ? "ACTIVE_SEATS" :
324 static int file_of_session(const char *session, char **_p) {
331 if (!session_id_valid(session))
334 p = strappend("/run/systemd/sessions/", session);
336 _cleanup_free_ char *buf = NULL;
338 r = sd_pid_get_session(0, &buf);
342 p = strappend("/run/systemd/sessions/", buf);
352 _public_ int sd_session_is_active(const char *session) {
354 _cleanup_free_ char *p = NULL, *s = NULL;
356 r = file_of_session(session, &p);
360 r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
367 return parse_boolean(s);
370 _public_ int sd_session_is_remote(const char *session) {
372 _cleanup_free_ char *p = NULL, *s = NULL;
374 r = file_of_session(session, &p);
378 r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL);
385 return parse_boolean(s);
388 _public_ int sd_session_get_state(const char *session, char **state) {
389 _cleanup_free_ char *p = NULL, *s = NULL;
392 assert_return(state, -EINVAL);
394 r = file_of_session(session, &p);
398 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
410 _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
412 _cleanup_free_ char *p = NULL, *s = NULL;
414 assert_return(uid, -EINVAL);
416 r = file_of_session(session, &p);
420 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
427 return parse_uid(s, uid);
430 static int session_get_string(const char *session, const char *field, char **value) {
431 _cleanup_free_ char *p = NULL, *s = NULL;
434 assert_return(value, -EINVAL);
436 r = file_of_session(session, &p);
440 r = parse_env_file(p, NEWLINE, field, &s, NULL);
452 _public_ int sd_session_get_seat(const char *session, char **seat) {
453 return session_get_string(session, "SEAT", seat);
456 _public_ int sd_session_get_tty(const char *session, char **tty) {
457 return session_get_string(session, "TTY", tty);
460 _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
461 _cleanup_free_ char *vtnr_string = NULL;
465 r = session_get_string(session, "VTNR", &vtnr_string);
469 r = safe_atou(vtnr_string, &u);
477 _public_ int sd_session_get_service(const char *session, char **service) {
478 return session_get_string(session, "SERVICE", service);
481 _public_ int sd_session_get_type(const char *session, char **type) {
482 return session_get_string(session, "TYPE", type);
485 _public_ int sd_session_get_class(const char *session, char **class) {
486 return session_get_string(session, "CLASS", class);
489 _public_ int sd_session_get_desktop(const char *session, char **desktop) {
490 _cleanup_free_ char *escaped = NULL;
494 assert_return(desktop, -EINVAL);
496 r = session_get_string(session, "DESKTOP", &escaped);
500 r = cunescape(escaped, 0, &t);
508 _public_ int sd_session_get_display(const char *session, char **display) {
509 return session_get_string(session, "DISPLAY", display);
512 _public_ int sd_session_get_remote_user(const char *session, char **remote_user) {
513 return session_get_string(session, "REMOTE_USER", remote_user);
516 _public_ int sd_session_get_remote_host(const char *session, char **remote_host) {
517 return session_get_string(session, "REMOTE_HOST", remote_host);
520 static int file_of_seat(const char *seat, char **_p) {
527 p = strappend("/run/systemd/seats/", seat);
529 _cleanup_free_ char *buf = NULL;
531 r = sd_session_get_seat(NULL, &buf);
535 p = strappend("/run/systemd/seats/", buf);
546 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
547 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
550 assert_return(session || uid, -EINVAL);
552 r = file_of_seat(seat, &p);
556 r = parse_env_file(p, NEWLINE,
570 r = parse_uid(t, uid);
583 _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
584 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
585 _cleanup_strv_free_ char **a = NULL;
586 _cleanup_free_ uid_t *b = NULL;
590 r = file_of_seat(seat, &p);
594 r = parse_env_file(p, NEWLINE,
596 "ACTIVE_SESSIONS", &t,
603 a = strv_split(s, " ");
609 const char *word, *state;
612 FOREACH_WORD(word, l, t, state)
622 FOREACH_WORD(word, l, t, state) {
623 _cleanup_free_ char *k = NULL;
625 k = strndup(word, l);
629 r = parse_uid(k, b + i);
657 static int seat_get_can(const char *seat, const char *variable) {
658 _cleanup_free_ char *p = NULL, *s = NULL;
661 assert_return(variable, -EINVAL);
663 r = file_of_seat(seat, &p);
667 r = parse_env_file(p, NEWLINE,
675 return parse_boolean(s);
678 _public_ int sd_seat_can_multi_session(const char *seat) {
679 return seat_get_can(seat, "CAN_MULTI_SESSION");
682 _public_ int sd_seat_can_tty(const char *seat) {
683 return seat_get_can(seat, "CAN_TTY");
686 _public_ int sd_seat_can_graphical(const char *seat) {
687 return seat_get_can(seat, "CAN_GRAPHICAL");
690 _public_ int sd_get_seats(char ***seats) {
691 return get_files_in_directory("/run/systemd/seats/", seats);
694 _public_ int sd_get_sessions(char ***sessions) {
695 return get_files_in_directory("/run/systemd/sessions/", sessions);
698 _public_ int sd_get_uids(uid_t **users) {
699 _cleanup_closedir_ DIR *d;
702 _cleanup_free_ uid_t *l = NULL;
704 d = opendir("/run/systemd/users/");
715 if (!de && errno != 0)
721 dirent_ensure_type(d, de);
723 if (!dirent_is_file(de))
726 k = parse_uid(de->d_name, &uid);
731 if ((unsigned) r >= n) {
735 t = realloc(l, sizeof(uid_t) * n);
742 assert((unsigned) r < n);
756 _public_ int sd_get_machine_names(char ***machines) {
757 char **l = NULL, **a, **b;
760 assert_return(machines, -EINVAL);
762 r = get_files_in_directory("/run/systemd/machines/", &l);
769 /* Filter out the unit: symlinks */
770 for (a = l, b = l; *a; a++) {
771 if (startswith(*a, "unit:"))
787 _public_ int sd_machine_get_class(const char *machine, char **class) {
788 _cleanup_free_ char *c = NULL;
792 assert_return(machine_name_is_valid(machine), -EINVAL);
793 assert_return(class, -EINVAL);
795 p = strjoina("/run/systemd/machines/", machine);
796 r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL);
808 _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
809 _cleanup_free_ char *netif = NULL;
810 size_t l, allocated = 0, nr = 0;
812 const char *p, *word, *state;
815 assert_return(machine_name_is_valid(machine), -EINVAL);
816 assert_return(ifindices, -EINVAL);
818 p = strjoina("/run/systemd/machines/", machine);
819 r = parse_env_file(p, NEWLINE, "NETIF", &netif, NULL);
827 FOREACH_WORD(word, l, netif, state) {
831 *(char*) (mempcpy(buf, word, l)) = 0;
833 if (safe_atoi(buf, &ifi) < 0)
838 if (!GREEDY_REALLOC(ni, allocated, nr+1)) {
850 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
851 return (int) (unsigned long) m - 1;
854 static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
855 return (sd_login_monitor*) (unsigned long) (fd + 1);
858 _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
862 assert_return(m, -EINVAL);
864 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
868 if (!category || streq(category, "seat")) {
869 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
878 if (!category || streq(category, "session")) {
879 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
888 if (!category || streq(category, "uid")) {
889 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
898 if (!category || streq(category, "machine")) {
899 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
913 *m = FD_TO_MONITOR(fd);
917 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
920 assert_return(m, NULL);
922 fd = MONITOR_TO_FD(m);
928 _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
930 assert_return(m, -EINVAL);
932 return flush_fd(MONITOR_TO_FD(m));
935 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
937 assert_return(m, -EINVAL);
939 return MONITOR_TO_FD(m);
942 _public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
944 assert_return(m, -EINVAL);
946 /* For now we will only return POLLIN here, since we don't
947 * need anything else ever for inotify. However, let's have
948 * this API to keep our options open should we later on need
953 _public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
955 assert_return(m, -EINVAL);
956 assert_return(timeout_usec, -EINVAL);
958 /* For now we will only return (uint64_t) -1, since we don't
959 * need any timeout. However, let's have this API to keep our
960 * options open should we later on need it. */
961 *timeout_usec = (uint64_t) -1;