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_slice(pid_t pid, char **slice) {
82 return cg_pid_get_slice(pid, slice);
85 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
93 return cg_pid_get_owner_uid(pid, uid);
96 _public_ int sd_uid_get_state(uid_t uid, char**state) {
103 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
106 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
111 s = strdup("offline");
127 _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) {
129 _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL;
132 const char *variable;
137 variable = require_active ? "ACTIVE_UID" : "UIDS";
139 p = strappend("/run/systemd/seats/", seat);
143 r = parse_env_file(p, NEWLINE, variable, &s, NULL);
151 if (asprintf(&t, "%lu", (unsigned long) uid) < 0)
154 FOREACH_WORD(w, l, s, state) {
162 static int uid_get_array(uid_t uid, const char *variable, char ***array) {
163 _cleanup_free_ char *p = NULL, *s = NULL;
167 if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
170 r = parse_env_file(p, NEWLINE,
189 a = strv_split(s, " ");
205 _public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) {
206 return uid_get_array(
208 require_active == 0 ? "ONLINE_SESSIONS" :
209 require_active > 0 ? "ACTIVE_SESSIONS" :
214 _public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) {
215 return uid_get_array(
217 require_active == 0 ? "ONLINE_SEATS" :
218 require_active > 0 ? "ACTIVE_SEATS" :
223 static int file_of_session(const char *session, char **_p) {
230 p = strappend("/run/systemd/sessions/", session);
234 r = sd_pid_get_session(0, &buf);
238 p = strappend("/run/systemd/sessions/", buf);
249 _public_ int sd_session_is_active(const char *session) {
251 _cleanup_free_ char *p = NULL, *s = NULL;
253 r = file_of_session(session, &p);
257 r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL);
265 r = parse_boolean(s);
270 _public_ int sd_session_get_state(const char *session, char **state) {
271 _cleanup_free_ char *p = NULL, *s = NULL;
277 r = file_of_session(session, &p);
281 r = parse_env_file(p, NEWLINE, "STATE", &s, NULL);
294 _public_ int sd_session_get_uid(const char *session, uid_t *uid) {
296 _cleanup_free_ char *p = NULL, *s = NULL;
301 r = file_of_session(session, &p);
305 r = parse_env_file(p, NEWLINE, "UID", &s, NULL);
313 r = parse_uid(s, uid);
318 static int session_get_string(const char *session, const char *field, char **value) {
319 _cleanup_free_ char *p = NULL, *s = NULL;
325 r = file_of_session(session, &p);
329 r = parse_env_file(p, NEWLINE, field, &s, NULL);
342 _public_ int sd_session_get_seat(const char *session, char **seat) {
343 return session_get_string(session, "SEAT", seat);
346 _public_ int sd_session_get_tty(const char *session, char **tty) {
347 return session_get_string(session, "TTY", tty);
350 _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) {
351 _cleanup_free_ char *vtnr_string;
355 r = session_get_string(session, "VTNr", &vtnr_string);
359 r = safe_atou(vtnr_string, &u);
367 _public_ int sd_session_get_service(const char *session, char **service) {
368 return session_get_string(session, "SERVICE", service);
371 _public_ int sd_session_get_type(const char *session, char **type) {
372 return session_get_string(session, "TYPE", type);
375 _public_ int sd_session_get_class(const char *session, char **class) {
376 return session_get_string(session, "CLASS", class);
379 _public_ int sd_session_get_display(const char *session, char **display) {
380 return session_get_string(session, "DISPLAY", display);
383 static int file_of_seat(const char *seat, char **_p) {
390 p = strappend("/run/systemd/seats/", seat);
392 _cleanup_free_ char *buf = NULL;
394 r = sd_session_get_seat(NULL, &buf);
398 p = strappend("/run/systemd/seats/", buf);
409 _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) {
410 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
413 if (!session && !uid)
416 r = file_of_seat(seat, &p);
420 r = parse_env_file(p, NEWLINE,
434 r = parse_uid(t, uid);
447 _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) {
448 _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL;
449 _cleanup_strv_free_ char **a = NULL;
450 _cleanup_free_ uid_t *b = NULL;
454 r = file_of_seat(seat, &p);
458 r = parse_env_file(p, NEWLINE,
460 "ACTIVE_SESSIONS", &t,
467 a = strv_split(s, " ");
476 FOREACH_WORD(w, l, t, state)
486 FOREACH_WORD(w, l, t, state) {
487 _cleanup_free_ char *k = NULL;
493 r = parse_uid(k, b + i);
521 static int seat_get_can(const char *seat, const char *variable) {
522 _cleanup_free_ char *p = NULL, *s = NULL;
525 r = file_of_seat(seat, &p);
529 r = parse_env_file(p, NEWLINE,
536 r = parse_boolean(s);
543 _public_ int sd_seat_can_multi_session(const char *seat) {
544 return seat_get_can(seat, "CAN_MULTI_SESSION");
547 _public_ int sd_seat_can_tty(const char *seat) {
548 return seat_get_can(seat, "CAN_TTY");
551 _public_ int sd_seat_can_graphical(const char *seat) {
552 return seat_get_can(seat, "CAN_GRAPHICAL");
555 _public_ int sd_get_seats(char ***seats) {
556 return get_files_in_directory("/run/systemd/seats/", seats);
559 _public_ int sd_get_sessions(char ***sessions) {
560 return get_files_in_directory("/run/systemd/sessions/", sessions);
563 _public_ int sd_get_uids(uid_t **users) {
564 _cleanup_closedir_ DIR *d;
567 _cleanup_free_ uid_t *l = NULL;
569 d = opendir("/run/systemd/users/");
575 union dirent_storage buf;
579 k = readdir_r(d, &buf.de, &de);
586 dirent_ensure_type(d, de);
588 if (!dirent_is_file(de))
591 k = parse_uid(de->d_name, &uid);
596 if ((unsigned) r >= n) {
600 t = realloc(l, sizeof(uid_t) * n);
607 assert((unsigned) r < n);
621 _public_ int sd_get_machine_names(char ***machines) {
622 return get_files_in_directory("/run/systemd/machines/", machines);
625 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
626 return (int) (unsigned long) m - 1;
629 static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
630 return (sd_login_monitor*) (unsigned long) (fd + 1);
633 _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
640 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
644 if (!category || streq(category, "seat")) {
645 k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
647 close_nointr_nofail(fd);
654 if (!category || streq(category, "session")) {
655 k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
657 close_nointr_nofail(fd);
664 if (!category || streq(category, "uid")) {
665 k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
667 close_nointr_nofail(fd);
674 if (!category || streq(category, "machine")) {
675 k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE);
677 close_nointr_nofail(fd);
689 *m = FD_TO_MONITOR(fd);
693 _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
699 fd = MONITOR_TO_FD(m);
705 _public_ int sd_login_monitor_flush(sd_login_monitor *m) {
710 return flush_fd(MONITOR_TO_FD(m));
713 _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
718 return MONITOR_TO_FD(m);
721 _public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
726 /* For now we will only return POLLIN here, since we don't
727 * need anything else ever for inotify. However, let's have
728 * this API to keep our options open should we later on need
733 _public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
740 /* For now we will only return (uint64_t) -1, since we don't
741 * need any timeout. However, let's have this API to keep our
742 * options open should we later on need it. */
743 *timeout_usec = (uint64_t) -1;