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
_public_ int sd_get_machine_names(char ***machines) {
595
_cleanup_closedir_ DIR *d = NULL;
596
_cleanup_strv_free_ char **l = NULL;
597
_cleanup_free_ char *md = NULL;
601
r = cg_get_machine_path(NULL, &md);
605
r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, md, &d);
609
while ((r = cg_read_subgroup(d, &n)) > 0) {
611
r = strv_push(&l, n);
631
static inline int MONITOR_TO_FD(sd_login_monitor *m) {
632
return (int) (unsigned long) m - 1;
635
static inline sd_login_monitor* FD_TO_MONITOR(int fd) {
636
return (sd_login_monitor*) (unsigned long) (fd + 1);
639
_public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) {
646
fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
650
if (!category || streq(category, "seat")) {
651
k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE);
653
close_nointr_nofail(fd);
660
if (!category || streq(category, "session")) {
661
k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE);
663
close_nointr_nofail(fd);
670
if (!category || streq(category, "uid")) {
671
k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE);
673
close_nointr_nofail(fd);
680
if (!category || streq(category, "machine")) {
681
_cleanup_free_ char *md = NULL, *p = NULL;
684
r = cg_get_machine_path(NULL, &md);
688
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, md, NULL, &p);
692
k = inotify_add_watch(fd, p, IN_MOVED_TO|IN_CREATE|IN_DELETE);
694
close_nointr_nofail(fd);
706
*m = FD_TO_MONITOR(fd);
710
_public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
716
fd = MONITOR_TO_FD(m);
722
_public_ int sd_login_monitor_flush(sd_login_monitor *m) {
727
return flush_fd(MONITOR_TO_FD(m));
730
_public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
735
return MONITOR_TO_FD(m);
738
_public_ int sd_login_monitor_get_events(sd_login_monitor *m) {
743
/* For now we will only return POLLIN here, since we don't
744
* need anything else ever for inotify. However, let's have
745
* this API to keep our options open should we later on need
750
_public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) {
757
/* For now we will only return (uint64_t) -1, since we don't
758
* need any timeout. However, let's have this API to keep our
759
* options open should we later on need it. */
760
*timeout_usec = (uint64_t) -1;