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_get_state(const char *session, char **state) {
258 _cleanup_free_ char *p = NULL, *s = NULL;
261 assert_return(state, -EINVAL);
263 r = file_of_session(session, &p);
267 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
280 _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
282 _cleanup_free_ char *p = NULL, *s = NULL;
284 assert_return(uid, -EINVAL);
286 r = file_of_session(session, &p);
290 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
298 r = parse_uid(s, uid);
303 static int session_get_string(const char *session, const char *field, char **value) {
304 _cleanup_free_ char *p = NULL, *s = NULL;
307 assert_return(value, -EINVAL);
309 r = file_of_session(session, &p);
313 r = parse_env_file(p, NEWLINE, field, &s, NULL);
326 _public_ int sd_session_get_seat(const char *session, char **seat) {
327 return session_get_string(session, "SEAT", seat);
330 _public_ int sd_session_get_tty(const char *session, char **tty) {
331 return session_get_string(session, "TTY", tty);
334 _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
335 _cleanup_free_ char *vtnr_string = NULL;
339 r = session_get_string(session, "VTNR", &vtnr_string);
343 r = safe_atou(vtnr_string, &u);
351 _public_ int sd_session_get_service(const char *session, char **service) {
352 return session_get_string(session, "SERVICE", service);
355 _public_ int sd_session_get_type(const char *session, char **type) {
356 return session_get_string(session, "TYPE", type);
359 _public_ int sd_session_get_class(const char *session, char **class) {
360 return session_get_string(session, "CLASS", class);
363 _public_ int sd_session_get_display(const char *session, char **display) {
364 return session_get_string(session, "DISPLAY", display);
367 static int file_of_seat(const char *seat, char **_p) {
374 p = strappend("/run/systemd/seats/", seat);
376 _cleanup_free_ char *buf = NULL;
378 r = sd_session_get_seat(NULL, &buf);
382 p = strappend("/run/systemd/seats/", buf);
393 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
394 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
397 assert_return(session || uid, -EINVAL);
399 r = file_of_seat(seat, &p);
403 r = parse_env_file(p, NEWLINE,
417 r = parse_uid(t, uid);
430 _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
431 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
432 _cleanup_strv_free_ char **a = NULL;
433 _cleanup_free_ uid_t *b = NULL;
437 r = file_of_seat(seat, &p);
441 r = parse_env_file(p, NEWLINE,
443 "ACTIVE_SESSIONS", &t,
450 a = strv_split(s, " ");
459 FOREACH_WORD(w, l, t, state)
469 FOREACH_WORD(w, l, t, state) {
470 _cleanup_free_ char *k = NULL;
476 r = parse_uid(k, b + i);
504 static int seat_get_can(const char *seat, const char *variable) {
505 _cleanup_free_ char *p = NULL, *s = NULL;
508 r = file_of_seat(seat, &p);
512 r = parse_env_file(p, NEWLINE,
519 r = parse_boolean(s);
526 _public_ int sd_seat_can_multi_session(const char *seat) {
527 return seat_get_can(seat, "CAN_MULTI_SESSION");
530 _public_ int sd_seat_can_tty(const char *seat) {
531 return seat_get_can(seat, "CAN_TTY");
534 _public_ int sd_seat_can_graphical(const char *seat) {
535 return seat_get_can(seat, "CAN_GRAPHICAL");
538 _public_ int sd_get_seats(char ***seats) {
539 return get_files_in_directory("/run/systemd/seats/", seats);
542 _public_ int sd_get_sessions(char ***sessions) {
543 return get_files_in_directory("/run/systemd/sessions/", sessions);
546 _public_ int sd_get_uids(uid_t **users) {
547 _cleanup_closedir_ DIR *d;
550 _cleanup_free_ uid_t *l = NULL;
552 d = opendir("/run/systemd/users/");
558 union dirent_storage buf;
562 k = readdir_r(d, &buf.de, &de);
569 dirent_ensure_type(d, de);
571 if (!dirent_is_file(de))
574 k = parse_uid(de->d_name, &uid);
579 if ((unsigned) r >= n) {
583 t = realloc(l, sizeof(uid_t) * n);
590 assert((unsigned) r < n);
604 _public_ int sd_get_machine_names(char ***machines) {
605 return get_files_in_directory("/run/systemd/machines/", machines);
608 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
609 return (int) (unsigned long) m - 1;
612 static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
613 return (sd_login_monitor*) (unsigned long) (fd + 1);
616 _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
620 assert_return(m, -EINVAL);
622 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
626 if (!category || streq(category, "seat")) {
627 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
629 close_nointr_nofail(fd);
636 if (!category || streq(category, "session")) {
637 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
639 close_nointr_nofail(fd);
646 if (!category || streq(category, "uid")) {
647 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
649 close_nointr_nofail(fd);
656 if (!category || streq(category, "machine")) {
657 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
659 close_nointr_nofail(fd);
671 *m = FD_TO_MONITOR(fd);
675 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
678 assert_return(m, NULL);
680 fd = MONITOR_TO_FD(m);
686 _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
688 assert_return(m, -EINVAL);
690 return flush_fd(MONITOR_TO_FD(m));
693 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
695 assert_return(m, -EINVAL);
697 return MONITOR_TO_FD(m);
700 _public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
702 assert_return(m, -EINVAL);
704 /* For now we will only return POLLIN here, since we don't
705 * need anything else ever for inotify. However, let's have
706 * this API to keep our options open should we later on need
711 _public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
713 assert_return(m, -EINVAL);
714 assert_return(timeout_usec, -EINVAL);
716 /* For now we will only return (uint64_t) -1, since we don't
717 * need any timeout. However, let's have this API to keep our
718 * options open should we later on need it. */
719 *timeout_usec = (uint64_t) -1;