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 return parse_boolean(s);
255 _public_ int sd_session_is_remote(const char *session) {
257 _cleanup_free_ char *p = NULL, *s = NULL;
259 r = file_of_session(session, &p);
263 r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL);
270 return parse_boolean(s);
273 _public_ int sd_session_get_state(const char *session, char **state) {
274 _cleanup_free_ char *p = NULL, *s = NULL;
277 assert_return(state, -EINVAL);
279 r = file_of_session(session, &p);
283 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
296 _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
298 _cleanup_free_ char *p = NULL, *s = NULL;
300 assert_return(uid, -EINVAL);
302 r = file_of_session(session, &p);
306 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
313 return parse_uid(s, uid);
316 static int session_get_string(const char *session, const char *field, char **value) {
317 _cleanup_free_ char *p = NULL, *s = NULL;
320 assert_return(value, -EINVAL);
322 r = file_of_session(session, &p);
326 r = parse_env_file(p, NEWLINE, field, &s, NULL);
339 _public_ int sd_session_get_seat(const char *session, char **seat) {
340 return session_get_string(session, "SEAT", seat);
343 _public_ int sd_session_get_tty(const char *session, char **tty) {
344 return session_get_string(session, "TTY", tty);
347 _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
348 _cleanup_free_ char *vtnr_string = NULL;
352 r = session_get_string(session, "VTNR", &vtnr_string);
356 r = safe_atou(vtnr_string, &u);
364 _public_ int sd_session_get_service(const char *session, char **service) {
365 return session_get_string(session, "SERVICE", service);
368 _public_ int sd_session_get_type(const char *session, char **type) {
369 return session_get_string(session, "TYPE", type);
372 _public_ int sd_session_get_class(const char *session, char **class) {
373 return session_get_string(session, "CLASS", class);
376 _public_ int sd_session_get_display(const char *session, char **display) {
377 return session_get_string(session, "DISPLAY", display);
380 _public_ int sd_session_get_remote_user(const char *session, char **remote_user) {
381 return session_get_string(session, "REMOTE_USER", remote_user);
384 _public_ int sd_session_get_remote_host(const char *session, char **remote_host) {
385 return session_get_string(session, "REMOTE_HOST", remote_host);
388 static int file_of_seat(const char *seat, char **_p) {
395 p = strappend("/run/systemd/seats/", seat);
397 _cleanup_free_ char *buf = NULL;
399 r = sd_session_get_seat(NULL, &buf);
403 p = strappend("/run/systemd/seats/", buf);
414 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
415 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
418 assert_return(session || uid, -EINVAL);
420 r = file_of_seat(seat, &p);
424 r = parse_env_file(p, NEWLINE,
438 r = parse_uid(t, uid);
451 _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
452 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
453 _cleanup_strv_free_ char **a = NULL;
454 _cleanup_free_ uid_t *b = NULL;
458 r = file_of_seat(seat, &p);
462 r = parse_env_file(p, NEWLINE,
464 "ACTIVE_SESSIONS", &t,
471 a = strv_split(s, " ");
480 FOREACH_WORD(w, l, t, state)
490 FOREACH_WORD(w, l, t, state) {
491 _cleanup_free_ char *k = NULL;
497 r = parse_uid(k, b + i);
525 static int seat_get_can(const char *seat, const char *variable) {
526 _cleanup_free_ char *p = NULL, *s = NULL;
529 assert_return(variable, -EINVAL);
531 r = file_of_seat(seat, &p);
535 r = parse_env_file(p, NEWLINE,
543 return parse_boolean(s);
546 _public_ int sd_seat_can_multi_session(const char *seat) {
547 return seat_get_can(seat, "CAN_MULTI_SESSION");
550 _public_ int sd_seat_can_tty(const char *seat) {
551 return seat_get_can(seat, "CAN_TTY");
554 _public_ int sd_seat_can_graphical(const char *seat) {
555 return seat_get_can(seat, "CAN_GRAPHICAL");
558 _public_ int sd_get_seats(char ***seats) {
559 return get_files_in_directory("/run/systemd/seats/", seats);
562 _public_ int sd_get_sessions(char ***sessions) {
563 return get_files_in_directory("/run/systemd/sessions/", sessions);
566 _public_ int sd_get_uids(uid_t **users) {
567 _cleanup_closedir_ DIR *d;
570 _cleanup_free_ uid_t *l = NULL;
572 d = opendir("/run/systemd/users/");
583 if (!de && errno != 0)
589 dirent_ensure_type(d, de);
591 if (!dirent_is_file(de))
594 k = parse_uid(de->d_name, &uid);
599 if ((unsigned) r >= n) {
603 t = realloc(l, sizeof(uid_t) * n);
610 assert((unsigned) r < n);
624 _public_ int sd_get_machine_names(char ***machines) {
625 char **l = NULL, **a, **b;
628 assert_return(machines, -EINVAL);
630 r = get_files_in_directory("/run/systemd/machines/", &l);
637 /* Filter out the unit: symlinks */
638 for (a = l, b = l; *a; a++) {
639 if (startswith(*a, "unit:"))
655 _public_ int sd_machine_get_class(const char *machine, char **class) {
656 _cleanup_free_ char *c = NULL;
660 assert_return(filename_is_safe(machine), -EINVAL);
661 assert_return(class, -EINVAL);
663 p = strappenda("/run/systemd/machines/", machine);
664 r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL);
676 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
677 return (int) (unsigned long) m - 1;
680 static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
681 return (sd_login_monitor*) (unsigned long) (fd + 1);
684 _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
688 assert_return(m, -EINVAL);
690 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
694 if (!category || streq(category, "seat")) {
695 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
697 close_nointr_nofail(fd);
704 if (!category || streq(category, "session")) {
705 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
707 close_nointr_nofail(fd);
714 if (!category || streq(category, "uid")) {
715 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
717 close_nointr_nofail(fd);
724 if (!category || streq(category, "machine")) {
725 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
727 close_nointr_nofail(fd);
739 *m = FD_TO_MONITOR(fd);
743 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
746 assert_return(m, NULL);
748 fd = MONITOR_TO_FD(m);
754 _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
756 assert_return(m, -EINVAL);
758 return flush_fd(MONITOR_TO_FD(m));
761 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
763 assert_return(m, -EINVAL);
765 return MONITOR_TO_FD(m);
768 _public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
770 assert_return(m, -EINVAL);
772 /* For now we will only return POLLIN here, since we don't
773 * need anything else ever for inotify. However, let's have
774 * this API to keep our options open should we later on need
779 _public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
781 assert_return(m, -EINVAL);
782 assert_return(timeout_usec, -EINVAL);
784 /* For now we will only return (uint64_t) -1, since we don't
785 * need any timeout. However, let's have this API to keep our
786 * options open should we later on need it. */
787 *timeout_usec = (uint64_t) -1;