X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogin%2Fsd-login.c;h=c9a2e8a07fbb883e007f553d77779f92d726e880;hb=6a70535669f9016056c1ad8bcb21e1fd14c2141a;hp=82fe2ce3e338b744fa043f1e2a2162df60ca5410;hpb=d18dff430bf60291a41b2c7dbe0ae5a5c4edf36c;p=elogind.git diff --git a/src/login/sd-login.c b/src/login/sd-login.c index 82fe2ce3e..c9a2e8a07 100644 --- a/src/login/sd-login.c +++ b/src/login/sd-login.c @@ -23,122 +23,69 @@ #include #include #include +#include #include "util.h" #include "cgroup-util.h" #include "macro.h" -#include "sd-login.h" #include "strv.h" +#include "fileio.h" +#include "login-shared.h" +#include "sd-login.h" _public_ int sd_pid_get_session(pid_t pid, char **session) { - int r; - char *cgroup, *p; - - if (pid < 0) - return -EINVAL; - - if (!session) - return -EINVAL; - - r = cg_pid_get_cgroup(pid, NULL, &cgroup); - if (r < 0) - return r; - - if (!startswith(cgroup, "/user/")) { - free(cgroup); - return -ENOENT; - } - - p = strchr(cgroup + 6, '/'); - if (!p) { - free(cgroup); - return -ENOENT; - } - p++; - if (startswith(p, "shared/") || streq(p, "shared")) { - free(cgroup); - return -ENOENT; - } - - p = strndup(p, strcspn(p, "/")); - free(cgroup); - - if (!p) - return -ENOMEM; + assert_return(pid >= 0, -EINVAL); + assert_return(session, -EINVAL); - *session = p; - return 0; + return cg_pid_get_session(pid, session); } _public_ int sd_pid_get_unit(pid_t pid, char **unit) { - if (pid < 0) - return -EINVAL; - - if (!unit) - return -EINVAL; + assert_return(pid >= 0, -EINVAL); + assert_return(unit, -EINVAL); return cg_pid_get_unit(pid, unit); } -_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) { - int r; - char *root, *cgroup, *p, *cc; - struct stat st; +_public_ int sd_pid_get_user_unit(pid_t pid, char **unit) { - if (pid < 0) - return -EINVAL; - - if (!uid) - return -EINVAL; + assert_return(pid >= 0, -EINVAL); + assert_return(unit, -EINVAL); - r = cg_pid_get_cgroup(pid, &root, &cgroup); - if (r < 0) - return r; + return cg_pid_get_user_unit(pid, unit); +} - if (!startswith(cgroup, "/user/")) { - free(cgroup); - free(root); - return -ENOENT; - } +_public_ int sd_pid_get_machine_name(pid_t pid, char **name) { - p = strchr(cgroup + 6, '/'); - if (!p) { - free(cgroup); - return -ENOENT; - } + assert_return(pid >= 0, -EINVAL); + assert_return(name, -EINVAL); - p++; - p += strcspn(p, "/"); - *p = 0; + return cg_pid_get_machine_name(pid, name); +} - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, cgroup, &cc); - free(root); - free(cgroup); +_public_ int sd_pid_get_slice(pid_t pid, char **slice) { - if (r < 0) - return -ENOMEM; + assert_return(pid >= 0, -EINVAL); + assert_return(slice, -EINVAL); - r = lstat(cc, &st); - free(cc); + return cg_pid_get_slice(pid, slice); +} - if (r < 0) - return -errno; +_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) { - if (!S_ISDIR(st.st_mode)) - return -ENOTDIR; + assert_return(pid >= 0, -EINVAL); + assert_return(uid, -EINVAL); - *uid = st.st_uid; - return 0; + return cg_pid_get_owner_uid(pid, uid); } _public_ int sd_uid_get_state(uid_t uid, char**state) { char *p, *s = NULL; int r; - if (!state) - return -EINVAL; + assert_return(state, -EINVAL); if (asprintf(&p, "/run/systemd/users/%lu", (unsigned long) uid) < 0) return -ENOMEM; @@ -165,13 +112,13 @@ _public_ int sd_uid_get_state(uid_t uid, char**state) { } _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) { - char *p, *w, *t, *state, *s = NULL; + char *w, *state; + _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL; size_t l; int r; const char *variable; - if (!seat) - return -EINVAL; + assert_return(seat, -EINVAL); variable = require_active ? "ACTIVE_UID" : "UIDS"; @@ -180,38 +127,26 @@ _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) return -ENOMEM; r = parse_env_file(p, NEWLINE, variable, &s, NULL); - free(p); - if (r < 0) { - free(s); + if (r < 0) return r; - } if (!s) return -EIO; - if (asprintf(&t, "%lu", (unsigned long) uid) < 0) { - free(s); + if (asprintf(&t, "%lu", (unsigned long) uid) < 0) return -ENOMEM; - } FOREACH_WORD(w, l, s, state) { - if (strncmp(t, w, l) == 0) { - free(s); - free(t); - + if (strneq(t, w, l)) return 1; - } } - free(s); - free(t); - return 0; } static int uid_get_array(uid_t uid, const char *variable, char ***array) { - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; char **a; int r; @@ -221,11 +156,7 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) { r = parse_env_file(p, NEWLINE, variable, &s, NULL); - free(p); - if (r < 0) { - free(s); - if (r == -ENOENT) { if (array) *array = NULL; @@ -242,7 +173,6 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) { } a = strv_split(s, " "); - free(s); if (!a) return -ENOMEM; @@ -282,17 +212,19 @@ static int file_of_session(const char *session, char **_p) { assert(_p); - if (session) + if (session) { + if (!session_id_valid(session)) + return -EINVAL; + p = strappend("/run/systemd/sessions/", session); - else { - char *buf; + } else { + _cleanup_free_ char *buf = NULL; r = sd_pid_get_session(0, &buf); if (r < 0) return r; p = strappend("/run/systemd/sessions/", buf); - free(buf); } if (!p) @@ -304,104 +236,90 @@ static int file_of_session(const char *session, char **_p) { _public_ int sd_session_is_active(const char *session) { int r; - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL); - free(p); - - if (r < 0) { - free(s); + if (r < 0) return r; - } if (!s) return -EIO; r = parse_boolean(s); - free(s); return r; } _public_ int sd_session_get_state(const char *session, char **state) { - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; int r; - if (!state) - return -EINVAL; + assert_return(state, -EINVAL); r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "STATE", &s, NULL); - free(p); - if (r < 0) { - free(s); + if (r < 0) return r; - } else if (!s) + else if (!s) return -EIO; *state = s; + s = NULL; + return 0; } _public_ int sd_session_get_uid(const char *session, uid_t *uid) { int r; - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; - if (!uid) - return -EINVAL; + assert_return(uid, -EINVAL); r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "UID", &s, NULL); - free(p); - if (r < 0) { - free(s); + if (r < 0) return r; - } if (!s) return -EIO; r = parse_uid(s, uid); - free(s); return r; } static int session_get_string(const char *session, const char *field, char **value) { - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; int r; - if (!value) - return -EINVAL; + assert_return(value, -EINVAL); r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, field, &s, NULL); - free(p); - if (r < 0) { - free(s); + if (r < 0) return r; - } if (isempty(s)) return -ENOENT; *value = s; + s = NULL; return 0; } @@ -409,6 +327,27 @@ _public_ int sd_session_get_seat(const char *session, char **seat) { return session_get_string(session, "SEAT", seat); } +_public_ int sd_session_get_tty(const char *session, char **tty) { + return session_get_string(session, "TTY", tty); +} + +_public_ int sd_session_get_vt(const char *session, unsigned *vtnr) { + _cleanup_free_ char *vtnr_string = NULL; + unsigned u; + int r; + + r = session_get_string(session, "VTNR", &vtnr_string); + if (r < 0) + return r; + + r = safe_atou(vtnr_string, &u); + if (r < 0) + return r; + + *vtnr = u; + return 0; +} + _public_ int sd_session_get_service(const char *session, char **service) { return session_get_string(session, "SERVICE", service); } @@ -434,29 +373,28 @@ static int file_of_seat(const char *seat, char **_p) { if (seat) p = strappend("/run/systemd/seats/", seat); else { - char *buf; + _cleanup_free_ char *buf = NULL; r = sd_session_get_seat(NULL, &buf); if (r < 0) return r; p = strappend("/run/systemd/seats/", buf); - free(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) { - char *p, *s = NULL, *t = NULL; + _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; int r; - if (!session && !uid) - return -EINVAL; + assert_return(session || uid, -EINVAL); r = file_of_seat(seat, &p); if (r < 0) @@ -466,46 +404,33 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) { "ACTIVE", &s, "ACTIVE_UID", &t, NULL); - free(p); - - if (r < 0) { - free(s); - free(t); + if (r < 0) return r; - } - if (session && !s) { - free(t); + if (session && !s) return -ENOENT; - } - if (uid && !t) { - free(s); + if (uid && !t) return -ENOENT; - } if (uid && t) { r = parse_uid(t, uid); - if (r < 0) { - free(t); - free(s); + if (r < 0) return r; - } } - free(t); - - if (session && s) + if (session && s) { *session = s; - else - free(s); + s = NULL; + } return 0; } _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) { - char *p, *s = NULL, *t = NULL, **a = NULL; - uid_t *b = NULL; + _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; + _cleanup_strv_free_ char **a = NULL; + _cleanup_free_ uid_t *b = NULL; unsigned n = 0; int r; @@ -517,25 +442,16 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui "SESSIONS", &s, "ACTIVE_SESSIONS", &t, NULL); - free(p); - if (r < 0) { - free(s); - free(t); + if (r < 0) return r; - } if (s) { a = strv_split(s, " "); - if (!a) { - free(s); - free(t); + if (!a) return -ENOMEM; - } } - free(s); - if (uids && t) { char *w, *state; size_t l; @@ -543,30 +459,22 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui FOREACH_WORD(w, l, t, state) n++; - if (n == 0) - b = NULL; - else { + if (n > 0) { unsigned i = 0; b = new(uid_t, n); - if (!b) { - strv_free(a); + if (!b) return -ENOMEM; - } FOREACH_WORD(w, l, t, state) { - char *k; + _cleanup_free_ char *k = NULL; k = strndup(w, l); - if (!k) { - free(t); - free(b); - strv_free(a); + if (!k) return -ENOMEM; - } r = parse_uid(k, b + i); - free(k); + if (r < 0) continue; @@ -575,17 +483,17 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui } } - free(t); - r = strv_length(a); - if (sessions) + if (sessions) { *sessions = a; - else - strv_free(a); + a = NULL; + } - if (uids) + if (uids) { *uids = b; + b = NULL; + } if (n_uids) *n_uids = n; @@ -594,7 +502,7 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui } static int seat_get_can(const char *seat, const char *variable) { - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; int r; r = file_of_seat(seat, &p); @@ -604,17 +512,12 @@ static int seat_get_can(const char *seat, const char *variable) { r = parse_env_file(p, NEWLINE, variable, &s, NULL); - free(p); - - if (r < 0) { - free(s); + if (r < 0) return r; - } - if (s) { + if (s) r = parse_boolean(s); - free(s); - } else + else r = 0; return r; @@ -641,25 +544,24 @@ _public_ int sd_get_sessions(char ***sessions) { } _public_ int sd_get_uids(uid_t **users) { - DIR *d; + _cleanup_closedir_ DIR *d; int r = 0; unsigned n = 0; - uid_t *l = NULL; + _cleanup_free_ uid_t *l = NULL; d = opendir("/run/systemd/users/"); if (!d) return -errno; for (;;) { - struct dirent buffer, *de; + struct dirent *de; + union dirent_storage buf; int k; uid_t uid; - k = readdir_r(d, &buffer, &de); - if (k != 0) { - r = -k; - goto finish; - } + k = readdir_r(d, &buf.de, &de); + if (k != 0) + return -k; if (!de) break; @@ -679,10 +581,8 @@ _public_ int sd_get_uids(uid_t **users) { n = MAX(16, 2*r); t = realloc(l, sizeof(uid_t) * n); - if (!t) { - r = -ENOMEM; - goto finish; - } + if (!t) + return -ENOMEM; l = t; } @@ -693,19 +593,18 @@ _public_ int sd_get_uids(uid_t **users) { r++; } -finish: - if (d) - closedir(d); - - if (r >= 0) { - if (users) - *users = l; - } else - free(l); + if (users) { + *users = l; + l = NULL; + } return r; } +_public_ int sd_get_machine_names(char ***machines) { + return get_files_in_directory("/run/systemd/machines/", machines); +} + static inline int MONITOR_TO_FD(sd_login_monitor *m) { return (int) (unsigned long) m - 1; } @@ -718,12 +617,11 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) { int fd, k; bool good = false; - if (!m) - return -EINVAL; + assert_return(m, -EINVAL); fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (fd < 0) - return errno; + return -errno; if (!category || streq(category, "seat")) { k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE); @@ -755,6 +653,16 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) { good = true; } + if (!category || streq(category, "machine")) { + k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE); + if (k < 0) { + close_nointr_nofail(fd); + return -errno; + } + + good = true; + } + if (!good) { close_nointr(fd); return -EINVAL; @@ -767,8 +675,7 @@ _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; - if (!m) - return NULL; + assert_return(m, NULL); fd = MONITOR_TO_FD(m); close_nointr(fd); @@ -778,16 +685,37 @@ _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) { _public_ int sd_login_monitor_flush(sd_login_monitor *m) { - if (!m) - return -EINVAL; + assert_return(m, -EINVAL); return flush_fd(MONITOR_TO_FD(m)); } _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) { - if (!m) - return -EINVAL; + assert_return(m, -EINVAL); return MONITOR_TO_FD(m); } + +_public_ int sd_login_monitor_get_events(sd_login_monitor *m) { + + assert_return(m, -EINVAL); + + /* For now we will only return POLLIN here, since we don't + * need anything else ever for inotify. However, let's have + * this API to keep our options open should we later on need + * it. */ + return POLLIN; +} + +_public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) { + + assert_return(m, -EINVAL); + assert_return(timeout_usec, -EINVAL); + + /* For now we will only return (uint64_t) -1, since we don't + * need any timeout. However, let's have this API to keep our + * options open should we later on need it. */ + *timeout_usec = (uint64_t) -1; + return 0; +}