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"
33 _public_ int sd_pid_get_session(pid_t pid, char **session) {
43 r = cg_pid_get_cgroup(pid, NULL, &cgroup);
47 if (!startswith(cgroup, "/user/")) {
52 p = strchr(cgroup + 6, '/');
59 if (startswith(p, "shared/") || streq(p, "shared")) {
64 p = strndup(p, strcspn(p, "/"));
74 _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
82 return cg_pid_get_unit(pid, unit);
85 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
87 char *root, *cgroup, *p, *cc;
96 r = cg_pid_get_cgroup(pid, &root, &cgroup);
100 if (!startswith(cgroup, "/user/")) {
106 p = strchr(cgroup + 6, '/');
113 p += strcspn(p, "/");
116 r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, cgroup, &cc);
129 if (!S_ISDIR(st.st_mode))
136 _public_ int sd_uid_get_state(uid_t uid, char**state) {
143 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
146 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
151 s = strdup("offline");
167 _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
168 char *p, *w, *t, *state, *s = NULL;
171 const char *variable;
176 variable = require_active ? "ACTIVE_UID" : "UIDS";
178 p = strappend("/run/systemd/seats/", seat);
182 r = parse_env_file(p, NEWLINE, variable, &s, NULL);
193 if (asprintf(&t, "%lu", (unsigned long) uid) < 0) {
198 FOREACH_WORD(w, l, s, state) {
199 if (strncmp(t, w, l) == 0) {
213 static int uid_get_array(uid_t uid, const char *variable, char ***array) {
218 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
221 r = parse_env_file(p, NEWLINE,
244 a = strv_split(s, " ");
261 _public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
262 return uid_get_array(
264 require_active == 0 ? "ONLINE_SESSIONS" :
265 require_active > 0 ? "ACTIVE_SESSIONS" :
270 _public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
271 return uid_get_array(
273 require_active == 0 ? "ONLINE_SEATS" :
274 require_active > 0 ? "ACTIVE_SEATS" :
279 static int file_of_session(const char *session, char **_p) {
286 p = strappend("/run/systemd/sessions/", session);
290 r = sd_pid_get_session(0, &buf);
294 p = strappend("/run/systemd/sessions/", buf);
305 _public_ int sd_session_is_active(const char *session) {
309 r = file_of_session(session, &p);
313 r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
324 r = parse_boolean(s);
330 _public_ int sd_session_get_state(const char *session, char **state) {
337 r = file_of_session(session, &p);
341 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
354 _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
361 r = file_of_session(session, &p);
365 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
376 r = parse_uid(s, uid);
382 static int session_get_string(const char *session, const char *field, char **value) {
389 r = file_of_session(session, &p);
393 r = parse_env_file(p, NEWLINE, field, &s, NULL);
408 _public_ int sd_session_get_seat(const char *session, char **seat) {
409 return session_get_string(session, "SEAT", seat);
412 _public_ int sd_session_get_service(const char *session, char **service) {
413 return session_get_string(session, "SERVICE", service);
416 _public_ int sd_session_get_type(const char *session, char **type) {
417 return session_get_string(session, "TYPE", type);
420 _public_ int sd_session_get_class(const char *session, char **class) {
421 return session_get_string(session, "CLASS", class);
424 _public_ int sd_session_get_display(const char *session, char **display) {
425 return session_get_string(session, "DISPLAY", display);
428 static int file_of_seat(const char *seat, char **_p) {
435 p = strappend("/run/systemd/seats/", seat);
439 r = sd_session_get_seat(NULL, &buf);
443 p = strappend("/run/systemd/seats/", buf);
454 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
455 char *p, *s = NULL, *t = NULL;
458 if (!session && !uid)
461 r = file_of_seat(seat, &p);
465 r = parse_env_file(p, NEWLINE,
488 r = parse_uid(t, uid);
506 _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
507 char *p, *s = NULL, *t = NULL, **a = NULL;
512 r = file_of_seat(seat, &p);
516 r = parse_env_file(p, NEWLINE,
518 "ACTIVE_SESSIONS", &t,
529 a = strv_split(s, " ");
543 FOREACH_WORD(w, l, t, state)
557 FOREACH_WORD(w, l, t, state) {
568 r = parse_uid(k, b + i);
596 static int seat_get_can(const char *seat, const char *variable) {
600 r = file_of_seat(seat, &p);
604 r = parse_env_file(p, NEWLINE,
615 r = parse_boolean(s);
623 _public_ int sd_seat_can_multi_session(const char *seat) {
624 return seat_get_can(seat, "CAN_MULTI_SESSION");
627 _public_ int sd_seat_can_tty(const char *seat) {
628 return seat_get_can(seat, "CAN_TTY");
631 _public_ int sd_seat_can_graphical(const char *seat) {
632 return seat_get_can(seat, "CAN_GRAPHICAL");
635 _public_ int sd_get_seats(char ***seats) {
636 return get_files_in_directory("/run/systemd/seats/", seats);
639 _public_ int sd_get_sessions(char ***sessions) {
640 return get_files_in_directory("/run/systemd/sessions/", sessions);
643 _public_ int sd_get_uids(uid_t **users) {
649 d = opendir("/run/systemd/users/");
655 union dirent_storage buf;
659 k = readdir_r(d, &buf.de, &de);
668 dirent_ensure_type(d, de);
670 if (!dirent_is_file(de))
673 k = parse_uid(de->d_name, &uid);
678 if ((unsigned) r >= n) {
682 t = realloc(l, sizeof(uid_t) * n);
691 assert((unsigned) r < n);
710 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
711 return (int) (unsigned long) m - 1;
714 static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
715 return (sd_login_monitor*) (unsigned long) (fd + 1);
718 _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
725 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
729 if (!category || streq(category, "seat")) {
730 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
732 close_nointr_nofail(fd);
739 if (!category || streq(category, "session")) {
740 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
742 close_nointr_nofail(fd);
749 if (!category || streq(category, "uid")) {
750 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
752 close_nointr_nofail(fd);
764 *m = FD_TO_MONITOR(fd);
768 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
774 fd = MONITOR_TO_FD(m);
780 _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
785 return flush_fd(MONITOR_TO_FD(m));
788 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
793 return MONITOR_TO_FD(m);