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>
28 #include "cgroup-util.h"
34 _public_ int sd_pid_get_session(pid_t pid, char **session) {
44 r = cg_pid_get_cgroup(pid, NULL, &cgroup);
48 if (!startswith(cgroup, "/user/")) {
53 p = strchr(cgroup + 6, '/');
60 if (startswith(p, "shared/") || streq(p, "shared")) {
65 p = strndup(p, strcspn(p, "/"));
75 _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
83 return cg_pid_get_unit(pid, unit);
86 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
88 char *root, *cgroup, *p, *cc;
97 r = cg_pid_get_cgroup(pid, &root, &cgroup);
101 if (!startswith(cgroup, "/user/")) {
107 p = strchr(cgroup + 6, '/');
114 p += strcspn(p, "/");
117 r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, cgroup, &cc);
130 if (!S_ISDIR(st.st_mode))
137 _public_ int sd_uid_get_state(uid_t uid, char**state) {
144 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
147 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
152 s = strdup("offline");
168 _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
169 char *p, *w, *t, *state, *s = NULL;
172 const char *variable;
177 variable = require_active ? "ACTIVE_UID" : "UIDS";
179 p = strappend("/run/systemd/seats/", seat);
183 r = parse_env_file(p, NEWLINE, variable, &s, NULL);
194 if (asprintf(&t, "%lu", (unsigned long) uid) < 0) {
199 FOREACH_WORD(w, l, s, state) {
200 if (strneq(t, w, l)) {
214 static int uid_get_array(uid_t uid, const char *variable, char ***array) {
219 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
222 r = parse_env_file(p, NEWLINE,
245 a = strv_split(s, " ");
262 _public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
263 return uid_get_array(
265 require_active == 0 ? "ONLINE_SESSIONS" :
266 require_active > 0 ? "ACTIVE_SESSIONS" :
271 _public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
272 return uid_get_array(
274 require_active == 0 ? "ONLINE_SEATS" :
275 require_active > 0 ? "ACTIVE_SEATS" :
280 static int file_of_session(const char *session, char **_p) {
287 p = strappend("/run/systemd/sessions/", session);
291 r = sd_pid_get_session(0, &buf);
295 p = strappend("/run/systemd/sessions/", buf);
306 _public_ int sd_session_is_active(const char *session) {
310 r = file_of_session(session, &p);
314 r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
325 r = parse_boolean(s);
331 _public_ int sd_session_get_state(const char *session, char **state) {
338 r = file_of_session(session, &p);
342 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
355 _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
362 r = file_of_session(session, &p);
366 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
377 r = parse_uid(s, uid);
383 static int session_get_string(const char *session, const char *field, char **value) {
390 r = file_of_session(session, &p);
394 r = parse_env_file(p, NEWLINE, field, &s, NULL);
409 _public_ int sd_session_get_seat(const char *session, char **seat) {
410 return session_get_string(session, "SEAT", seat);
413 _public_ int sd_session_get_tty(const char *session, char **tty) {
414 return session_get_string(session, "TTY", tty);
417 _public_ int sd_session_get_service(const char *session, char **service) {
418 return session_get_string(session, "SERVICE", service);
421 _public_ int sd_session_get_type(const char *session, char **type) {
422 return session_get_string(session, "TYPE", type);
425 _public_ int sd_session_get_class(const char *session, char **class) {
426 return session_get_string(session, "CLASS", class);
429 _public_ int sd_session_get_display(const char *session, char **display) {
430 return session_get_string(session, "DISPLAY", display);
433 static int file_of_seat(const char *seat, char **_p) {
440 p = strappend("/run/systemd/seats/", seat);
444 r = sd_session_get_seat(NULL, &buf);
448 p = strappend("/run/systemd/seats/", buf);
459 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
460 char *p, *s = NULL, *t = NULL;
463 if (!session && !uid)
466 r = file_of_seat(seat, &p);
470 r = parse_env_file(p, NEWLINE,
493 r = parse_uid(t, uid);
511 _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
512 char *p, *s = NULL, *t = NULL, **a = NULL;
517 r = file_of_seat(seat, &p);
521 r = parse_env_file(p, NEWLINE,
523 "ACTIVE_SESSIONS", &t,
534 a = strv_split(s, " ");
548 FOREACH_WORD(w, l, t, state)
562 FOREACH_WORD(w, l, t, state) {
573 r = parse_uid(k, b + i);
601 static int seat_get_can(const char *seat, const char *variable) {
605 r = file_of_seat(seat, &p);
609 r = parse_env_file(p, NEWLINE,
620 r = parse_boolean(s);
628 _public_ int sd_seat_can_multi_session(const char *seat) {
629 return seat_get_can(seat, "CAN_MULTI_SESSION");
632 _public_ int sd_seat_can_tty(const char *seat) {
633 return seat_get_can(seat, "CAN_TTY");
636 _public_ int sd_seat_can_graphical(const char *seat) {
637 return seat_get_can(seat, "CAN_GRAPHICAL");
640 _public_ int sd_get_seats(char ***seats) {
641 return get_files_in_directory("/run/systemd/seats/", seats);
644 _public_ int sd_get_sessions(char ***sessions) {
645 return get_files_in_directory("/run/systemd/sessions/", sessions);
648 _public_ int sd_get_uids(uid_t **users) {
654 d = opendir("/run/systemd/users/");
660 union dirent_storage buf;
664 k = readdir_r(d, &buf.de, &de);
673 dirent_ensure_type(d, de);
675 if (!dirent_is_file(de))
678 k = parse_uid(de->d_name, &uid);
683 if ((unsigned) r >= n) {
687 t = realloc(l, sizeof(uid_t) * n);
696 assert((unsigned) r < n);
715 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
716 return (int) (unsigned long) m - 1;
719 static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
720 return (sd_login_monitor*) (unsigned long) (fd + 1);
723 _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
730 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
734 if (!category || streq(category, "seat")) {
735 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
737 close_nointr_nofail(fd);
744 if (!category || streq(category, "session")) {
745 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
747 close_nointr_nofail(fd);
754 if (!category || streq(category, "uid")) {
755 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
757 close_nointr_nofail(fd);
769 *m = FD_TO_MONITOR(fd);
773 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
779 fd = MONITOR_TO_FD(m);
785 _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
790 return flush_fd(MONITOR_TO_FD(m));
793 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
798 return MONITOR_TO_FD(m);