X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibelogind%2Fsd-login%2Fsd-login.c;h=80b8f8fefc7f91f1a817d2936655d51e1dc998ab;hb=1f4ffab4a84a9fb4c7b10c01a2435f79c39ef05e;hp=cc0677bdf21c94a72e9ea36d1ac76aebd699f6f4;hpb=f48dd74a8d39b6074f820f904953f5cece03b9b0;p=elogind.git diff --git a/src/libelogind/sd-login/sd-login.c b/src/libelogind/sd-login/sd-login.c index cc0677bdf..80b8f8fef 100644 --- a/src/libelogind/sd-login/sd-login.c +++ b/src/libelogind/sd-login/sd-login.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -19,153 +17,319 @@ along with systemd; If not, see . ***/ -#include -#include #include -#include #include +#include +#include +#include -#include "util.h" +#include "sd-login.h" + +#include "alloc-util.h" #include "cgroup-util.h" +#include "dirent-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "io-util.h" +#include "login-util.h" #include "macro.h" +#include "parse-util.h" +#include "path-util.h" +#include "socket-util.h" +#include "string-util.h" #include "strv.h" -#include "fileio.h" -#include "login-shared.h" -#include "sd-login.h" +#include "user-util.h" +#include "util.h" + +/* Error codes: + * + * invalid input parameters → -EINVAL + * invalid fd → -EBADF + * process does not exist → -ESRCH + * cgroup does not exist → -ENOENT + * machine, session does not exist → -ENXIO + * requested metadata on object is missing → -ENODATA + */ _public_ int sd_pid_get_session(pid_t pid, char **session) { + int r; assert_return(pid >= 0, -EINVAL); assert_return(session, -EINVAL); - return cg_pid_get_session(pid, session); + r = cg_pid_get_session(pid, session); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; } _public_ int sd_pid_get_unit(pid_t pid, char **unit) { +#if 0 /// UNNEEDED by elogind + int r; +#endif // 0 assert_return(pid >= 0, -EINVAL); assert_return(unit, -EINVAL); - return cg_pid_get_unit(pid, unit); +#if 0 /// elogind does not support systemd units + r = cg_pid_get_unit(pid, unit); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +#else + return -ESRCH; +#endif // 0 } _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) { +#if 0 /// UNNEEDED by elogind + int r; +#endif // 0 assert_return(pid >= 0, -EINVAL); assert_return(unit, -EINVAL); - return cg_pid_get_user_unit(pid, unit); +#if 0 /// elogind does not support systemd units + r = cg_pid_get_user_unit(pid, unit); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +#else + return -ESRCH; +#endif // 0 } _public_ int sd_pid_get_machine_name(pid_t pid, char **name) { +#if 0 /// UNNEEDED by elogind + int r; +#endif // 0 assert_return(pid >= 0, -EINVAL); assert_return(name, -EINVAL); - return cg_pid_get_machine_name(pid, name); +#if 0 /// elogind does not support systemd units + r = cg_pid_get_machine_name(pid, name); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +#else + return -ESRCH; +#endif // 0 } _public_ int sd_pid_get_slice(pid_t pid, char **slice) { +#if 0 /// UNNEEDED by elogind + int r; +#endif // 0 assert_return(pid >= 0, -EINVAL); assert_return(slice, -EINVAL); - return cg_pid_get_slice(pid, slice); +#if 0 /// elogind does not support systemd slices + r = cg_pid_get_slice(pid, slice); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +#else + return -ESRCH; +#endif // 0 +} + +_public_ int sd_pid_get_user_slice(pid_t pid, char **slice) { +#if 0 /// UNNEEDED by elogind + int r; +#endif // 0 + + assert_return(pid >= 0, -EINVAL); + assert_return(slice, -EINVAL); + +#if 0 /// elogind does not support systemd slices + r = cg_pid_get_user_slice(pid, slice); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +#else + return -ESRCH; +#endif // 0 } _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) { +#if 0 /// UNNEEDED by elogind + int r; +#endif // 0 assert_return(pid >= 0, -EINVAL); assert_return(uid, -EINVAL); - return cg_pid_get_owner_uid(pid, uid); +#if 0 /// elogind does not support systemd slices + r = cg_pid_get_owner_uid(pid, uid); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +#else + return -ESRCH; +#endif // 0 +} + +_public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) { + char *c; + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(cgroup, -EINVAL); + + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &c); + if (r < 0) + return r; + + /* The internal APIs return the empty string for the root + * cgroup, let's return the "/" in the public APIs instead, as + * that's easier and less ambiguous for people to grok. */ + if (isempty(c)) { + free(c); + c = strdup("/"); + if (!c) + return -ENOMEM; + + } + + *cgroup = c; + return 0; } _public_ int sd_peer_get_session(int fd, char **session) { struct ucred ucred = {}; int r; - assert_return(fd >= 0, -EINVAL); + assert_return(fd >= 0, -EBADF); assert_return(session, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; +#if 0 /// elogind does not support systemd scopes return cg_pid_get_session(ucred.pid, session); +#else + return -ESRCH; +#endif // 0 } _public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) { struct ucred ucred; int r; - assert_return(fd >= 0, -EINVAL); + assert_return(fd >= 0, -EBADF); assert_return(uid, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; +#if 0 /// elogind does not support systemd units return cg_pid_get_owner_uid(ucred.pid, uid); +#else + return -ESRCH; +#endif // 0 } _public_ int sd_peer_get_unit(int fd, char **unit) { struct ucred ucred; int r; - assert_return(fd >= 0, -EINVAL); + assert_return(fd >= 0, -EBADF); assert_return(unit, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; +#if 0 /// elogind does not support systemd units return cg_pid_get_unit(ucred.pid, unit); +#else + return -ESRCH; +#endif // 0 } _public_ int sd_peer_get_user_unit(int fd, char **unit) { struct ucred ucred; int r; - assert_return(fd >= 0, -EINVAL); + assert_return(fd >= 0, -EBADF); assert_return(unit, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; +#if 0 /// elogind does not support systemd units return cg_pid_get_user_unit(ucred.pid, unit); +#else + return -ESRCH; +#endif // 0 } _public_ int sd_peer_get_machine_name(int fd, char **machine) { struct ucred ucred; int r; - assert_return(fd >= 0, -EINVAL); + assert_return(fd >= 0, -EBADF); assert_return(machine, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; +#if 0 /// elogind does not support systemd units return cg_pid_get_machine_name(ucred.pid, machine); +#else + return -ESRCH; +#endif // 0 } _public_ int sd_peer_get_slice(int fd, char **slice) { struct ucred ucred; int r; - assert_return(fd >= 0, -EINVAL); + assert_return(fd >= 0, -EBADF); assert_return(slice, -EINVAL); r = getpeercred(fd, &ucred); if (r < 0) return r; +#if 0 /// elogind does not support systemd slices return cg_pid_get_slice(ucred.pid, slice); +#else + return -ESRCH; +#endif // 0 +} + +_public_ int sd_peer_get_user_slice(int fd, char **slice) { + struct ucred ucred; + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(slice, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + +#if 0 /// elogind does not support systemd slices + return cg_pid_get_user_slice(ucred.pid, slice); +#else + return -ESRCH; +#endif // 0 +} + +_public_ int sd_peer_get_cgroup(int fd, char **cgroup) { + struct ucred ucred; + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(cgroup, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return sd_pid_get_cgroup(ucred.pid, cgroup); } static int file_of_uid(uid_t uid, char **p) { + + assert_return(uid_is_valid(uid), -EINVAL); assert(p); if (asprintf(p, "/run/systemd/users/" UID_FMT, uid) < 0) @@ -192,11 +356,15 @@ _public_ int sd_uid_get_state(uid_t uid, char**state) { if (!s) return -ENOMEM; - } else if (r < 0) { + } + if (r < 0) { free(s); return r; - } else if (!s) + } + if (isempty(s)) { + free(s); return -EIO; + } *state = s; return 0; @@ -213,11 +381,12 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) { return r; r = parse_env_file(p, NEWLINE, "DISPLAY", &s, NULL); + if (r == -ENOENT) + return -ENODATA; if (r < 0) return r; - if (isempty(s)) - return -ENOENT; + return -ENODATA; *session = s; s = NULL; @@ -225,35 +394,63 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) { return 0; } +static int file_of_seat(const char *seat, char **_p) { + char *p; + int r; + + assert(_p); + + if (seat) { + if (!filename_is_valid(seat)) + return -EINVAL; + + p = strappend("/run/systemd/seats/", seat); + } else { + _cleanup_free_ char *buf = NULL; + + r = sd_session_get_seat(NULL, &buf); + if (r < 0) + return r; + + p = strappend("/run/systemd/seats/", buf); + } + + if (!p) + return -ENOMEM; + + *_p = p; + p = NULL; + return 0; +} + _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) { _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL; size_t l; int r; const char *word, *variable, *state; - assert_return(seat, -EINVAL); + assert_return(uid_is_valid(uid), -EINVAL); - variable = require_active ? "ACTIVE_UID" : "UIDS"; + r = file_of_seat(seat, &p); + if (r < 0) + return r; - p = strappend("/run/systemd/seats/", seat); - if (!p) - return -ENOMEM; + variable = require_active ? "ACTIVE_UID" : "UIDS"; r = parse_env_file(p, NEWLINE, variable, &s, NULL); - + if (r == -ENOENT) + return 0; if (r < 0) return r; - - if (!s) - return -EIO; + if (isempty(s)) + return 0; if (asprintf(&t, UID_FMT, uid) < 0) return -ENOMEM; - FOREACH_WORD(word, l, s, state) { + FOREACH_WORD(word, l, s, state) if (strneq(t, word, l)) return 1; - } return 0; } @@ -263,31 +460,22 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) { char **a; int r; + assert(variable); + r = file_of_uid(uid, &p); if (r < 0) return r; - r = parse_env_file(p, NEWLINE, - variable, &s, - NULL); - if (r < 0) { - if (r == -ENOENT) { - if (array) - *array = NULL; - return 0; - } - - return r; - } - - if (!s) { + r = parse_env_file(p, NEWLINE, variable, &s, NULL); + if (r == -ENOENT || (r >= 0 && isempty(s))) { if (array) *array = NULL; return 0; } + if (r < 0) + return r; a = strv_split(s, " "); - if (!a) return -ENOMEM; @@ -349,37 +537,39 @@ static int file_of_session(const char *session, char **_p) { } _public_ int sd_session_is_active(const char *session) { - int r; _cleanup_free_ char *p = NULL, *s = NULL; + int r; r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL); + if (r == -ENOENT) + return -ENXIO; if (r < 0) return r; - - if (!s) + if (isempty(s)) return -EIO; return parse_boolean(s); } _public_ int sd_session_is_remote(const char *session) { - int r; _cleanup_free_ char *p = NULL, *s = NULL; + int r; r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "REMOTE", &s, NULL); + if (r == -ENOENT) + return -ENXIO; if (r < 0) return r; - - if (!s) - return -EIO; + if (isempty(s)) + return -ENODATA; return parse_boolean(s); } @@ -395,9 +585,11 @@ _public_ int sd_session_get_state(const char *session, char **state) { return r; r = parse_env_file(p, NEWLINE, "STATE", &s, NULL); + if (r == -ENOENT) + return -ENXIO; if (r < 0) return r; - else if (!s) + if (isempty(s)) return -EIO; *state = s; @@ -417,10 +609,11 @@ _public_ int sd_session_get_uid(const char *session, uid_t *uid) { return r; r = parse_env_file(p, NEWLINE, "UID", &s, NULL); + if (r == -ENOENT) + return -ENXIO; if (r < 0) return r; - - if (!s) + if (isempty(s)) return -EIO; return parse_uid(s, uid); @@ -431,17 +624,19 @@ static int session_get_string(const char *session, const char *field, char **val int r; assert_return(value, -EINVAL); + assert(field); r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, field, &s, NULL); + if (r == -ENOENT) + return -ENXIO; if (r < 0) return r; - if (isempty(s)) - return -ENOENT; + return -ENODATA; *value = s; s = NULL; @@ -461,6 +656,8 @@ _public_ int sd_session_get_vt(const char *session, unsigned *vtnr) { unsigned u; int r; + assert_return(vtnr, -EINVAL); + r = session_get_string(session, "VTNR", &vtnr_string); if (r < 0) return r; @@ -496,9 +693,9 @@ _public_ int sd_session_get_desktop(const char *session, char **desktop) { if (r < 0) return r; - t = cunescape(escaped); - if (!t) - return -ENOMEM; + r = cunescape(escaped, 0, &t); + if (r < 0) + return r; *desktop = t; return 0; @@ -516,32 +713,6 @@ _public_ int sd_session_get_remote_host(const char *session, char **remote_host) return session_get_string(session, "REMOTE_HOST", remote_host); } -static int file_of_seat(const char *seat, char **_p) { - char *p; - int r; - - assert(_p); - - if (seat) - p = strappend("/run/systemd/seats/", seat); - else { - _cleanup_free_ char *buf = NULL; - - r = sd_session_get_seat(NULL, &buf); - if (r < 0) - return r; - - p = strappend("/run/systemd/seats/", buf); - } - - if (!p) - return -ENOMEM; - - *_p = p; - p = NULL; - return 0; -} - _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) { _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; int r; @@ -556,14 +727,16 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) { "ACTIVE", &s, "ACTIVE_UID", &t, NULL); + if (r == -ENOENT) + return -ENXIO; if (r < 0) return r; if (session && !s) - return -ENOENT; + return -ENODATA; if (uid && !t) - return -ENOENT; + return -ENODATA; if (uid && t) { r = parse_uid(t, uid); @@ -592,9 +765,10 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui r = parse_env_file(p, NEWLINE, "SESSIONS", &s, - "ACTIVE_SESSIONS", &t, + "UIDS", &t, NULL); - + if (r == -ENOENT) + return -ENXIO; if (r < 0) return r; @@ -626,9 +800,8 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui return -ENOMEM; r = parse_uid(k, b + i); - if (r < 0) - continue; + return r; i++; } @@ -657,7 +830,7 @@ static int seat_get_can(const char *seat, const char *variable) { _cleanup_free_ char *p = NULL, *s = NULL; int r; - assert_return(variable, -EINVAL); + assert(variable); r = file_of_seat(seat, &p); if (r < 0) @@ -666,10 +839,12 @@ static int seat_get_can(const char *seat, const char *variable) { r = parse_env_file(p, NEWLINE, variable, &s, NULL); + if (r == -ENOENT) + return -ENXIO; if (r < 0) return r; - if (!s) - return 0; + if (isempty(s)) + return -ENODATA; return parse_boolean(s); } @@ -687,36 +862,50 @@ _public_ int sd_seat_can_graphical(const char *seat) { } _public_ int sd_get_seats(char ***seats) { - return get_files_in_directory("/run/systemd/seats/", seats); + int r; + + r = get_files_in_directory("/run/systemd/seats/", seats); + if (r == -ENOENT) { + if (seats) + *seats = NULL; + return 0; + } + return r; } _public_ int sd_get_sessions(char ***sessions) { - return get_files_in_directory("/run/systemd/sessions/", sessions); + int r; + + r = get_files_in_directory("/run/systemd/sessions/", sessions); + if (r == -ENOENT) { + if (sessions) + *sessions = NULL; + return 0; + } + return r; } _public_ int sd_get_uids(uid_t **users) { _cleanup_closedir_ DIR *d; + struct dirent *de; int r = 0; unsigned n = 0; _cleanup_free_ uid_t *l = NULL; d = opendir("/run/systemd/users/"); - if (!d) + if (!d) { + if (errno == ENOENT) { + if (users) + *users = NULL; + return 0; + } return -errno; + } - for (;;) { - struct dirent *de; + FOREACH_DIRENT_ALL(de, d, return -errno) { int k; uid_t uid; - errno = 0; - de = readdir(d); - if (!de && errno != 0) - return -errno; - - if (!de) - break; - dirent_ensure_type(d, de); if (!dirent_is_file(de)) @@ -753,12 +942,16 @@ _public_ int sd_get_uids(uid_t **users) { } _public_ int sd_get_machine_names(char ***machines) { - char **l = NULL, **a, **b; + _cleanup_strv_free_ char **l = NULL; + char **a, **b; int r; - assert_return(machines, -EINVAL); - r = get_files_in_directory("/run/systemd/machines/", &l); + if (r == -ENOENT) { + if (machines) + *machines = NULL; + return 0; + } if (r < 0) return r; @@ -766,8 +959,8 @@ _public_ int sd_get_machine_names(char ***machines) { r = 0; /* Filter out the unit: symlinks */ - for (a = l, b = l; *a; a++) { - if (startswith(*a, "unit:")) + for (a = b = l; *a; a++) { + if (startswith(*a, "unit:") || !machine_name_is_valid(*a)) free(*a); else { *b = *a; @@ -779,7 +972,10 @@ _public_ int sd_get_machine_names(char ***machines) { *b = NULL; } - *machines = l; + if (machines) { + *machines = l; + l = NULL; + } return r; } @@ -793,6 +989,8 @@ _public_ int sd_machine_get_class(const char *machine, char **class) { p = strjoina("/run/systemd/machines/", machine); r = parse_env_file(p, NEWLINE, "CLASS", &c, NULL); + if (r == -ENOENT) + return -ENXIO; if (r < 0) return r; if (!c) @@ -816,6 +1014,8 @@ _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) { p = strjoina("/run/systemd/machines/", machine); r = parse_env_file(p, NEWLINE, "NETIF", &netif, NULL); + if (r == -ENOENT) + return -ENXIO; if (r < 0) return r; if (!netif) { @@ -829,9 +1029,7 @@ _public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) { *(char*) (mempcpy(buf, word, l)) = 0; - if (safe_atoi(buf, &ifi) < 0) - continue; - if (ifi <= 0) + if (parse_ifindex(buf, &ifi) < 0) continue; if (!GREEDY_REALLOC(ni, allocated, nr+1)) { @@ -916,7 +1114,8 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) { _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) { int fd; - assert_return(m, NULL); + if (!m) + return NULL; fd = MONITOR_TO_FD(m); close_nointr(fd);