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"
34 #include "login-shared.h"
36 _public_ int sd_pid_get_session(pid_t pid, char **session) {
43 return cg_pid_get_session(pid, session);
46 _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
53 return cg_pid_get_unit(pid, unit);
56 _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
63 return cg_pid_get_user_unit(pid, unit);
66 _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
73 return cg_pid_get_machine_name(pid, name);
76 _public_ int sd_pid_get_slice(pid_t pid, char **slice) {
83 return cg_pid_get_slice(pid, slice);
86 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
94 return cg_pid_get_owner_uid(pid, uid);
97 _public_ int sd_uid_get_state(uid_t uid, char**state) {
104 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
107 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
112 s = strdup("offline");
128 _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
130 _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
133 const char *variable;
138 variable = require_active ? "ACTIVE_UID" : "UIDS";
140 p = strappend("/run/systemd/seats/", seat);
144 r = parse_env_file(p, NEWLINE, variable, &s, NULL);
152 if (asprintf(&t, "%lu", (unsigned long) uid) < 0)
155 FOREACH_WORD(w, l, s, state) {
163 static int uid_get_array(uid_t uid, const char *variable, char ***array) {
164 _cleanup_free_ char *p = NULL, *s = NULL;
168 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
171 r = parse_env_file(p, NEWLINE,
190 a = strv_split(s, " ");
206 _public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
207 return uid_get_array(
209 require_active == 0 ? "ONLINE_SESSIONS" :
210 require_active > 0 ? "ACTIVE_SESSIONS" :
215 _public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
216 return uid_get_array(
218 require_active == 0 ? "ONLINE_SEATS" :
219 require_active > 0 ? "ACTIVE_SEATS" :
224 static int file_of_session(const char *session, char **_p) {
231 if (!session_id_valid(session))
234 p = strappend("/run/systemd/sessions/", session);
236 _cleanup_free_ char *buf = NULL;
238 r = sd_pid_get_session(0, &buf);
242 p = strappend("/run/systemd/sessions/", buf);
252 _public_ int sd_session_is_active(const char *session) {
254 _cleanup_free_ char *p = NULL, *s = NULL;
256 r = file_of_session(session, &p);
260 r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
267 r = parse_boolean(s);
272 _public_ int sd_session_get_state(const char *session, char **state) {
273 _cleanup_free_ char *p = NULL, *s = NULL;
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;
303 r = file_of_session(session, &p);
307 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
315 r = parse_uid(s, uid);
320 static int session_get_string(const char *session, const char *field, char **value) {
321 _cleanup_free_ char *p = NULL, *s = NULL;
327 r = file_of_session(session, &p);
331 r = parse_env_file(p, NEWLINE, field, &s, NULL);
344 _public_ int sd_session_get_seat(const char *session, char **seat) {
345 return session_get_string(session, "SEAT", seat);
348 _public_ int sd_session_get_tty(const char *session, char **tty) {
349 return session_get_string(session, "TTY", tty);
352 _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
353 _cleanup_free_ char *vtnr_string = NULL;
357 r = session_get_string(session, "VTNR", &vtnr_string);
361 r = safe_atou(vtnr_string, &u);
369 _public_ int sd_session_get_service(const char *session, char **service) {
370 return session_get_string(session, "SERVICE", service);
373 _public_ int sd_session_get_type(const char *session, char **type) {
374 return session_get_string(session, "TYPE", type);
377 _public_ int sd_session_get_class(const char *session, char **class) {
378 return session_get_string(session, "CLASS", class);
381 _public_ int sd_session_get_display(const char *session, char **display) {
382 return session_get_string(session, "DISPLAY", display);
385 static int file_of_seat(const char *seat, char **_p) {
392 p = strappend("/run/systemd/seats/", seat);
394 _cleanup_free_ char *buf = NULL;
396 r = sd_session_get_seat(NULL, &buf);
400 p = strappend("/run/systemd/seats/", buf);
411 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
412 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
415 if (!session && !uid)
418 r = file_of_seat(seat, &p);
422 r = parse_env_file(p, NEWLINE,
436 r = parse_uid(t, uid);
449 _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
450 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
451 _cleanup_strv_free_ char **a = NULL;
452 _cleanup_free_ uid_t *b = NULL;
456 r = file_of_seat(seat, &p);
460 r = parse_env_file(p, NEWLINE,
462 "ACTIVE_SESSIONS", &t,
469 a = strv_split(s, " ");
478 FOREACH_WORD(w, l, t, state)
488 FOREACH_WORD(w, l, t, state) {
489 _cleanup_free_ char *k = NULL;
495 r = parse_uid(k, b + i);
523 static int seat_get_can(const char *seat, const char *variable) {
524 _cleanup_free_ char *p = NULL, *s = NULL;
527 r = file_of_seat(seat, &p);
531 r = parse_env_file(p, NEWLINE,
538 r = parse_boolean(s);
545 _public_ int sd_seat_can_multi_session(const char *seat) {
546 return seat_get_can(seat, "CAN_MULTI_SESSION");
549 _public_ int sd_seat_can_tty(const char *seat) {
550 return seat_get_can(seat, "CAN_TTY");
553 _public_ int sd_seat_can_graphical(const char *seat) {
554 return seat_get_can(seat, "CAN_GRAPHICAL");
557 _public_ int sd_get_seats(char ***seats) {
558 return get_files_in_directory("/run/systemd/seats/", seats);
561 _public_ int sd_get_sessions(char ***sessions) {
562 return get_files_in_directory("/run/systemd/sessions/", sessions);
565 _public_ int sd_get_uids(uid_t **users) {
566 _cleanup_closedir_ DIR *d;
569 _cleanup_free_ uid_t *l = NULL;
571 d = opendir("/run/systemd/users/");
577 union dirent_storage buf;
581 k = readdir_r(d, &buf.de, &de);
588 dirent_ensure_type(d, de);
590 if (!dirent_is_file(de))
593 k = parse_uid(de->d_name, &uid);
598 if ((unsigned) r >= n) {
602 t = realloc(l, sizeof(uid_t) * n);
609 assert((unsigned) r < n);
623 _public_ int sd_get_machine_names(char ***machines) {
624 return get_files_in_directory("/run/systemd/machines/", machines);
627 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
628 return (int) (unsigned long) m - 1;
631 static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
632 return (sd_login_monitor*) (unsigned long) (fd + 1);
635 _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
642 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
646 if (!category || streq(category, "seat")) {
647 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
649 close_nointr_nofail(fd);
656 if (!category || streq(category, "session")) {
657 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
659 close_nointr_nofail(fd);
666 if (!category || streq(category, "uid")) {
667 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
669 close_nointr_nofail(fd);
676 if (!category || streq(category, "machine")) {
677 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
679 close_nointr_nofail(fd);
691 *m = FD_TO_MONITOR(fd);
695 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
701 fd = MONITOR_TO_FD(m);
707 _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
712 return flush_fd(MONITOR_TO_FD(m));
715 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
720 return MONITOR_TO_FD(m);
723 _public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
728 /* For now we will only return POLLIN here, since we don't
729 * need anything else ever for inotify. However, let's have
730 * this API to keep our options open should we later on need
735 _public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
742 /* For now we will only return (uint64_t) -1, since we don't
743 * need any timeout. However, let's have this API to keep our
744 * options open should we later on need it. */
745 *timeout_usec = (uint64_t) -1;