From aa3b40c3f98f28312967b3f9ba1f353efd9c9873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 30 Jul 2020 12:43:07 +0200 Subject: [PATCH] Fix output value of sd_seat_get_sessions() and drop FOREACH_WORD use sd_seat_get_sessions() would return 0 in the 'n_uids' (now 'ret_n_uids') output parameter when 'uid' (now 'ret_uids') was passed as NULL. While at it, drop FOREACH_WORD() use. Also use any whitespace as separator. In practice this shouldn't matter, since logind always uses spaces, but it seems nicer to not specify this explicitly, and the default is more flexible. --- man/sd_seat_get_active.xml | 31 +++++----- src/libsystemd/sd-login/sd-login.c | 93 +++++++++++++++--------------- src/systemd/sd-login.h | 6 +- 3 files changed, 63 insertions(+), 67 deletions(-) diff --git a/man/sd_seat_get_active.xml b/man/sd_seat_get_active.xml index cf70b35785..94401caa72 100644 --- a/man/sd_seat_get_active.xml +++ b/man/sd_seat_get_active.xml @@ -38,9 +38,9 @@ int sd_seat_get_sessions const char *seat - char ***sessions - uid_t **uid - unsigned int *n_uids + char ***ret_sessions + uid_t **ret_uids + unsigned int *ret_n_uids @@ -68,21 +68,16 @@ free3 call after use. - sd_seat_get_sessions() may be used to - determine all sessions on the specified seat. Returns two arrays, - one (NULL terminated) with the session - identifiers of the sessions and one with the user identifiers of - the Unix users the sessions belong to. An additional parameter may - be used to return the number of entries in the latter array. This - value is the same the return value, if the latter is nonnegative. - The two arrays and the last parameter may be passed as - NULL in case these values need not to be - determined. The arrays and the strings referenced by them need to - be freed with the libc - free3 - call after use. Note that instead of an empty array - NULL may be returned and should be considered - equivalent to an empty array. + sd_seat_get_sessions() may be used to determine all sessions on the specified + seat. Returns two arrays, one (NULL terminated) with the session identifiers of the + sessions and one with the user identifiers of the Unix users the sessions belong to. An additional + parameter may be used to return the number of entries in the latter array. This value is the same as the + return value if the return value is nonnegative. The output parameters may be passed as + NULL in case these output values are not needed. The arrays and the strings + referenced by them need to be freed with the libc free3 call after + use. Note that instead of an empty array NULL may be returned and should be + considered equivalent to an empty array. sd_seat_can_tty() may be used to determine whether a specific seat provides TTY functionality, i.e. diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c index 6412002f49..14e0468720 100644 --- a/src/libsystemd/sd-login/sd-login.c +++ b/src/libsystemd/sd-login/sd-login.c @@ -378,7 +378,7 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) { if (r < 0) return r; - a = strv_split(s, " "); + a = strv_split(s, NULL); if (!a) return -ENOMEM; @@ -650,73 +650,70 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) { return 0; } -_public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) { - _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; - _cleanup_strv_free_ char **a = NULL; - _cleanup_free_ uid_t *b = NULL; - unsigned n = 0; +_public_ int sd_seat_get_sessions( + const char *seat, + char ***ret_sessions, + uid_t **ret_uids, + unsigned *ret_n_uids) { + + _cleanup_free_ char *fname = NULL, *session_line = NULL, *uid_line = NULL; + _cleanup_strv_free_ char **sessions = NULL; + _cleanup_free_ uid_t *uids = NULL; + unsigned n_sessions = 0; int r; - r = file_of_seat(seat, &p); + r = file_of_seat(seat, &fname); if (r < 0) return r; - r = parse_env_file(NULL, p, - "SESSIONS", &s, - "UIDS", &t); + r = parse_env_file(NULL, fname, + "SESSIONS", &session_line, + "UIDS", &uid_line); if (r == -ENOENT) return -ENXIO; if (r < 0) return r; - if (s) { - a = strv_split(s, " "); - if (!a) + if (session_line) { + sessions = strv_split(session_line, NULL); + if (!sessions) return -ENOMEM; - } - if (uids && t) { - const char *word, *state; - size_t l; + n_sessions = strv_length(sessions); + }; - FOREACH_WORD(word, l, t, state) - n++; + if (ret_uids && uid_line) { + uids = new(uid_t, n_sessions); + if (!uids) + return -ENOMEM; - if (n > 0) { - unsigned i = 0; + size_t n = 0; + for (const char *p = uid_line;;) { + _cleanup_free_ char *word = NULL; - b = new(uid_t, n); - if (!b) - return -ENOMEM; + r = extract_first_word(&p, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; - FOREACH_WORD(word, l, t, state) { - _cleanup_free_ char *k = NULL; - - k = strndup(word, l); - if (!k) - return -ENOMEM; - - r = parse_uid(k, b + i); - if (r < 0) - return r; - - i++; - } + r = parse_uid(word, &uids[n++]); + if (r < 0) + return r; } + + if (n != n_sessions) + return -EUCLEAN; } - r = (int) strv_length(a); + if (ret_sessions) + *ret_sessions = TAKE_PTR(sessions); + if (ret_uids) + *ret_uids = TAKE_PTR(uids); + if (ret_n_uids) + *ret_n_uids = n_sessions; - if (sessions) - *sessions = TAKE_PTR(a); - - if (uids) - *uids = TAKE_PTR(b); - - if (n_uids) - *n_uids = n; - - return r; + return n_sessions; } static int seat_get_can(const char *seat, const char *variable) { diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h index e18f01bb67..360f44d341 100644 --- a/src/systemd/sd-login.h +++ b/src/systemd/sd-login.h @@ -180,7 +180,11 @@ int sd_seat_get_active(const char *seat, char **session, uid_t *uid); /* Return sessions and users on seat. Returns number of sessions. * If sessions is NULL, this returns only the number of sessions. */ -int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids); +int sd_seat_get_sessions( + const char *seat, + char ***ret_sessions, + uid_t **ret_uids, + unsigned *ret_n_uids); /* Return whether the seat is multi-session capable */ int sd_seat_can_multi_session(const char *seat) _sd_deprecated_;