From: Zbigniew Jędrzejewski-Szmek Date: Thu, 30 Jul 2020 10:43:07 +0000 (+0200) Subject: Fix output value of sd_seat_get_sessions() and drop FOREACH_WORD use X-Git-Tag: v247-rc1~275^2~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=aa3b40c3f98f28312967b3f9ba1f353efd9c9873;p=thirdparty%2Fsystemd.git 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. --- diff --git a/man/sd_seat_get_active.xml b/man/sd_seat_get_active.xml index cf70b35785a..94401caa728 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 6412002f490..14e04687206 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; - - FOREACH_WORD(word, l, t, state) - n++; - - if (n > 0) { - unsigned i = 0; - b = new(uid_t, n); - if (!b) - return -ENOMEM; + n_sessions = strv_length(sessions); + }; - FOREACH_WORD(word, l, t, state) { - _cleanup_free_ char *k = NULL; + if (ret_uids && uid_line) { + uids = new(uid_t, n_sessions); + if (!uids) + return -ENOMEM; - k = strndup(word, l); - if (!k) - return -ENOMEM; + size_t n = 0; + for (const char *p = uid_line;;) { + _cleanup_free_ char *word = NULL; - r = parse_uid(k, b + i); - if (r < 0) - return r; + r = extract_first_word(&p, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; - i++; - } + r = parse_uid(word, &uids[n++]); + if (r < 0) + return r; } - } - r = (int) strv_length(a); - - if (sessions) - *sessions = TAKE_PTR(a); - - if (uids) - *uids = TAKE_PTR(b); + if (n != n_sessions) + return -EUCLEAN; + } - if (n_uids) - *n_uids = n; + 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; - 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 e18f01bb671..360f44d341e 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_;