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"
35 _public_ int sd_pid_get_session(pid_t pid, char **session) {
42 return cg_pid_get_session(pid, session);
45 _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
52 return cg_pid_get_unit(pid, unit);
55 _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
62 return cg_pid_get_user_unit(pid, unit);
65 _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
72 return cg_pid_get_machine_name(pid, name);
75 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
83 return cg_pid_get_owner_uid(pid, uid);
86 _public_ int sd_uid_get_state(uid_t uid, char**state) {
93 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
96 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
101 s = strdup("offline");
117 _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
119 _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
122 const char *variable;
127 variable = require_active ? "ACTIVE_UID" : "UIDS";
129 p = strappend("/run/systemd/seats/", seat);
133 r = parse_env_file(p, NEWLINE, variable, &s, NULL);
141 if (asprintf(&t, "%lu", (unsigned long) uid) < 0)
144 FOREACH_WORD(w, l, s, state) {
152 static int uid_get_array(uid_t uid, const char *variable, char ***array) {
153 _cleanup_free_ char *p = NULL, *s = NULL;
157 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
160 r = parse_env_file(p, NEWLINE,
179 a = strv_split(s, " ");
195 _public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
196 return uid_get_array(
198 require_active == 0 ? "ONLINE_SESSIONS" :
199 require_active > 0 ? "ACTIVE_SESSIONS" :
204 _public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
205 return uid_get_array(
207 require_active == 0 ? "ONLINE_SEATS" :
208 require_active > 0 ? "ACTIVE_SEATS" :
213 static int file_of_session(const char *session, char **_p) {
220 p = strappend("/run/systemd/sessions/", session);
224 r = sd_pid_get_session(0, &buf);
228 p = strappend("/run/systemd/sessions/", buf);
239 _public_ int sd_session_is_active(const char *session) {
241 _cleanup_free_ char *p = NULL, *s = NULL;
243 r = file_of_session(session, &p);
247 r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
255 r = parse_boolean(s);
260 _public_ int sd_session_get_state(const char *session, char **state) {
261 _cleanup_free_ char *p = NULL, *s = NULL;
267 r = file_of_session(session, &p);
271 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
284 _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
286 _cleanup_free_ char *p = NULL, *s = NULL;
291 r = file_of_session(session, &p);
295 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
303 r = parse_uid(s, uid);
308 static int session_get_string(const char *session, const char *field, char **value) {
309 _cleanup_free_ char *p = NULL, *s = NULL;
315 r = file_of_session(session, &p);
319 r = parse_env_file(p, NEWLINE, field, &s, NULL);
332 _public_ int sd_session_get_seat(const char *session, char **seat) {
333 return session_get_string(session, "SEAT", seat);
336 _public_ int sd_session_get_tty(const char *session, char **tty) {
337 return session_get_string(session, "TTY", tty);
340 _public_ int sd_session_get_service(const char *session, char **service) {
341 return session_get_string(session, "SERVICE", service);
344 _public_ int sd_session_get_type(const char *session, char **type) {
345 return session_get_string(session, "TYPE", type);
348 _public_ int sd_session_get_class(const char *session, char **class) {
349 return session_get_string(session, "CLASS", class);
352 _public_ int sd_session_get_display(const char *session, char **display) {
353 return session_get_string(session, "DISPLAY", display);
356 static int file_of_seat(const char *seat, char **_p) {
363 p = strappend("/run/systemd/seats/", seat);
365 _cleanup_free_ char *buf = NULL;
367 r = sd_session_get_seat(NULL, &buf);
371 p = strappend("/run/systemd/seats/", buf);
382 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
383 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
386 if (!session && !uid)
389 r = file_of_seat(seat, &p);
393 r = parse_env_file(p, NEWLINE,
407 r = parse_uid(t, uid);
420 _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
421 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
422 _cleanup_strv_free_ char **a = NULL;
423 _cleanup_free_ uid_t *b = NULL;
427 r = file_of_seat(seat, &p);
431 r = parse_env_file(p, NEWLINE,
433 "ACTIVE_SESSIONS", &t,
440 a = strv_split(s, " ");
449 FOREACH_WORD(w, l, t, state)
459 FOREACH_WORD(w, l, t, state) {
460 _cleanup_free_ char *k = NULL;
466 r = parse_uid(k, b + i);
494 static int seat_get_can(const char *seat, const char *variable) {
495 _cleanup_free_ char *p = NULL, *s = NULL;
498 r = file_of_seat(seat, &p);
502 r = parse_env_file(p, NEWLINE,
509 r = parse_boolean(s);
516 _public_ int sd_seat_can_multi_session(const char *seat) {
517 return seat_get_can(seat, "CAN_MULTI_SESSION");
520 _public_ int sd_seat_can_tty(const char *seat) {
521 return seat_get_can(seat, "CAN_TTY");
524 _public_ int sd_seat_can_graphical(const char *seat) {
525 return seat_get_can(seat, "CAN_GRAPHICAL");
528 _public_ int sd_get_seats(char ***seats) {
529 return get_files_in_directory("/run/systemd/seats/", seats);
532 _public_ int sd_get_sessions(char ***sessions) {
533 return get_files_in_directory("/run/systemd/sessions/", sessions);
536 _public_ int sd_get_uids(uid_t **users) {
537 _cleanup_closedir_ DIR *d;
540 _cleanup_free_ uid_t *l = NULL;
542 d = opendir("/run/systemd/users/");
548 union dirent_storage buf;
552 k = readdir_r(d, &buf.de, &de);
559 dirent_ensure_type(d, de);
561 if (!dirent_is_file(de))
564 k = parse_uid(de->d_name, &uid);
569 if ((unsigned) r >= n) {
573 t = realloc(l, sizeof(uid_t) * n);
580 assert((unsigned) r < n);
594 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
595 return (int) (unsigned long) m - 1;
598 static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
599 return (sd_login_monitor*) (unsigned long) (fd + 1);
602 _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
609 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
613 if (!category || streq(category, "seat")) {
614 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
616 close_nointr_nofail(fd);
623 if (!category || streq(category, "session")) {
624 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
626 close_nointr_nofail(fd);
633 if (!category || streq(category, "uid")) {
634 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
636 close_nointr_nofail(fd);
648 *m = FD_TO_MONITOR(fd);
652 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
658 fd = MONITOR_TO_FD(m);
664 _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
669 return flush_fd(MONITOR_TO_FD(m));
672 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
677 return MONITOR_TO_FD(m);
680 _public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
685 /* For now we will only return POLLIN here, since we don't
686 * need anything else ever for inotify. However, let's have
687 * this API to keep our options open should we later on need
692 _public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
699 /* For now we will only return (uint64_t) -1, since we don't
700 * need any timeout. However, let's have this API to keep our
701 * options open should we later on need it. */
702 *timeout_usec = (uint64_t) -1;