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"
36 _public_ int sd_pid_get_session(pid_t pid, char **session) {
38 assert_return(pid >= 0, -EINVAL);
39 assert_return(session, -EINVAL);
41 return cg_pid_get_session(pid, session);
44 _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
46 assert_return(pid >= 0, -EINVAL);
47 assert_return(unit, -EINVAL);
49 return cg_pid_get_unit(pid, unit);
52 _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
54 assert_return(pid >= 0, -EINVAL);
55 assert_return(unit, -EINVAL);
57 return cg_pid_get_user_unit(pid, unit);
60 _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
62 assert_return(pid >= 0, -EINVAL);
63 assert_return(name, -EINVAL);
65 return cg_pid_get_machine_name(pid, name);
68 _public_ int sd_pid_get_slice(pid_t pid, char **slice) {
70 assert_return(pid >= 0, -EINVAL);
71 assert_return(slice, -EINVAL);
73 return cg_pid_get_slice(pid, slice);
76 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
78 assert_return(pid >= 0, -EINVAL);
79 assert_return(uid, -EINVAL);
81 return cg_pid_get_owner_uid(pid, uid);
84 _public_ int sd_uid_get_state(uid_t uid, char**state) {
88 assert_return(state, -EINVAL);
90 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
93 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
98 s = strdup("offline");
114 _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
116 _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
119 const char *variable;
121 assert_return(seat, -EINVAL);
123 variable = require_active ? "ACTIVE_UID" : "UIDS";
125 p = strappend("/run/systemd/seats/", seat);
129 r = parse_env_file(p, NEWLINE, variable, &s, NULL);
137 if (asprintf(&t, "%lu", (unsigned long) uid) < 0)
140 FOREACH_WORD(w, l, s, state) {
148 static int uid_get_array(uid_t uid, const char *variable, char ***array) {
149 _cleanup_free_ char *p = NULL, *s = NULL;
153 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
156 r = parse_env_file(p, NEWLINE,
175 a = strv_split(s, " ");
191 _public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
192 return uid_get_array(
194 require_active == 0 ? "ONLINE_SESSIONS" :
195 require_active > 0 ? "ACTIVE_SESSIONS" :
200 _public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
201 return uid_get_array(
203 require_active == 0 ? "ONLINE_SEATS" :
204 require_active > 0 ? "ACTIVE_SEATS" :
209 static int file_of_session(const char *session, char **_p) {
216 if (!session_id_valid(session))
219 p = strappend("/run/systemd/sessions/", session);
221 _cleanup_free_ char *buf = NULL;
223 r = sd_pid_get_session(0, &buf);
227 p = strappend("/run/systemd/sessions/", buf);
237 _public_ int sd_session_is_active(const char *session) {
239 _cleanup_free_ char *p = NULL, *s = NULL;
241 r = file_of_session(session, &p);
245 r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
252 r = parse_boolean(s);
257 _public_ int sd_session_is_remote(const char *session) {
259 _cleanup_free_ char *p = NULL, *s = NULL;
261 r = file_of_session(session, &p);
265 r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL);
272 r = parse_boolean(s);
277 _public_ int sd_session_get_state(const char *session, char **state) {
278 _cleanup_free_ char *p = NULL, *s = NULL;
281 assert_return(state, -EINVAL);
283 r = file_of_session(session, &p);
287 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
300 _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
302 _cleanup_free_ char *p = NULL, *s = NULL;
304 assert_return(uid, -EINVAL);
306 r = file_of_session(session, &p);
310 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
318 r = parse_uid(s, uid);
323 static int session_get_string(const char *session, const char *field, char **value) {
324 _cleanup_free_ char *p = NULL, *s = NULL;
327 assert_return(value, -EINVAL);
329 r = file_of_session(session, &p);
333 r = parse_env_file(p, NEWLINE, field, &s, NULL);
346 _public_ int sd_session_get_seat(const char *session, char **seat) {
347 return session_get_string(session, "SEAT", seat);
350 _public_ int sd_session_get_tty(const char *session, char **tty) {
351 return session_get_string(session, "TTY", tty);
354 _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
355 _cleanup_free_ char *vtnr_string = NULL;
359 r = session_get_string(session, "VTNR", &vtnr_string);
363 r = safe_atou(vtnr_string, &u);
371 _public_ int sd_session_get_service(const char *session, char **service) {
372 return session_get_string(session, "SERVICE", service);
375 _public_ int sd_session_get_type(const char *session, char **type) {
376 return session_get_string(session, "TYPE", type);
379 _public_ int sd_session_get_class(const char *session, char **class) {
380 return session_get_string(session, "CLASS", class);
383 _public_ int sd_session_get_display(const char *session, char **display) {
384 return session_get_string(session, "DISPLAY", display);
387 _public_ int sd_session_get_remote_user(const char *session, char **remote_user) {
388 return session_get_string(session, "REMOTE_USER", remote_user);
391 _public_ int sd_session_get_remote_host(const char *session, char **remote_host) {
392 return session_get_string(session, "REMOTE_HOST", remote_host);
395 static int file_of_seat(const char *seat, char **_p) {
402 p = strappend("/run/systemd/seats/", seat);
404 _cleanup_free_ char *buf = NULL;
406 r = sd_session_get_seat(NULL, &buf);
410 p = strappend("/run/systemd/seats/", buf);
421 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
422 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
425 assert_return(session || uid, -EINVAL);
427 r = file_of_seat(seat, &p);
431 r = parse_env_file(p, NEWLINE,
445 r = parse_uid(t, uid);
458 _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
459 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
460 _cleanup_strv_free_ char **a = NULL;
461 _cleanup_free_ uid_t *b = NULL;
465 r = file_of_seat(seat, &p);
469 r = parse_env_file(p, NEWLINE,
471 "ACTIVE_SESSIONS", &t,
478 a = strv_split(s, " ");
487 FOREACH_WORD(w, l, t, state)
497 FOREACH_WORD(w, l, t, state) {
498 _cleanup_free_ char *k = NULL;
504 r = parse_uid(k, b + i);
532 static int seat_get_can(const char *seat, const char *variable) {
533 _cleanup_free_ char *p = NULL, *s = NULL;
536 r = file_of_seat(seat, &p);
540 r = parse_env_file(p, NEWLINE,
547 r = parse_boolean(s);
554 _public_ int sd_seat_can_multi_session(const char *seat) {
555 return seat_get_can(seat, "CAN_MULTI_SESSION");
558 _public_ int sd_seat_can_tty(const char *seat) {
559 return seat_get_can(seat, "CAN_TTY");
562 _public_ int sd_seat_can_graphical(const char *seat) {
563 return seat_get_can(seat, "CAN_GRAPHICAL");
566 _public_ int sd_get_seats(char ***seats) {
567 return get_files_in_directory("/run/systemd/seats/", seats);
570 _public_ int sd_get_sessions(char ***sessions) {
571 return get_files_in_directory("/run/systemd/sessions/", sessions);
574 _public_ int sd_get_uids(uid_t **users) {
575 _cleanup_closedir_ DIR *d;
578 _cleanup_free_ uid_t *l = NULL;
580 d = opendir("/run/systemd/users/");
591 if (!de && errno != 0)
597 dirent_ensure_type(d, de);
599 if (!dirent_is_file(de))
602 k = parse_uid(de->d_name, &uid);
607 if ((unsigned) r >= n) {
611 t = realloc(l, sizeof(uid_t) * n);
618 assert((unsigned) r < n);
632 _public_ int sd_get_machine_names(char ***machines) {
633 char **l = NULL, **a, **b;
636 r = get_files_in_directory("/run/systemd/machines/", &l);
643 /* Filter out the unit: symlinks */
644 for (a = l, b = l; *a; a++) {
645 if (startswith(*a, "unit:"))
661 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
662 return (int) (unsigned long) m - 1;
665 static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
666 return (sd_login_monitor*) (unsigned long) (fd + 1);
669 _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
673 assert_return(m, -EINVAL);
675 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
679 if (!category || streq(category, "seat")) {
680 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
682 close_nointr_nofail(fd);
689 if (!category || streq(category, "session")) {
690 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
692 close_nointr_nofail(fd);
699 if (!category || streq(category, "uid")) {
700 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
702 close_nointr_nofail(fd);
709 if (!category || streq(category, "machine")) {
710 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
712 close_nointr_nofail(fd);
724 *m = FD_TO_MONITOR(fd);
728 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
731 assert_return(m, NULL);
733 fd = MONITOR_TO_FD(m);
739 _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
741 assert_return(m, -EINVAL);
743 return flush_fd(MONITOR_TO_FD(m));
746 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
748 assert_return(m, -EINVAL);
750 return MONITOR_TO_FD(m);
753 _public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
755 assert_return(m, -EINVAL);
757 /* For now we will only return POLLIN here, since we don't
758 * need anything else ever for inotify. However, let's have
759 * this API to keep our options open should we later on need
764 _public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
766 assert_return(m, -EINVAL);
767 assert_return(timeout_usec, -EINVAL);
769 /* For now we will only return (uint64_t) -1, since we don't
770 * need any timeout. However, let's have this API to keep our
771 * options open should we later on need it. */
772 *timeout_usec = (uint64_t) -1;