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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2020-07-30 12:43:07 +02:00
parent 87a4d416e5
commit aa3b40c3f9
3 changed files with 63 additions and 67 deletions

View File

@ -38,9 +38,9 @@
<funcprototype>
<funcdef>int <function>sd_seat_get_sessions</function></funcdef>
<paramdef>const char *<parameter>seat</parameter></paramdef>
<paramdef>char ***<parameter>sessions</parameter></paramdef>
<paramdef>uid_t **<parameter>uid</parameter></paramdef>
<paramdef>unsigned int *<parameter>n_uids</parameter></paramdef>
<paramdef>char ***<parameter>ret_sessions</parameter></paramdef>
<paramdef>uid_t **<parameter>ret_uids</parameter></paramdef>
<paramdef>unsigned int *<parameter>ret_n_uids</parameter></paramdef>
</funcprototype>
<funcprototype>
@ -68,21 +68,16 @@
<citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
<para><function>sd_seat_get_sessions()</function> may be used to
determine all sessions on the specified seat. Returns two arrays,
one (<constant>NULL</constant> 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
<constant>NULL</constant> in case these values need not to be
determined. The arrays and the strings referenced by them need to
be freed with the libc
<citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use. Note that instead of an empty array
<constant>NULL</constant> may be returned and should be considered
equivalent to an empty array.</para>
<para><function>sd_seat_get_sessions()</function> may be used to determine all sessions on the specified
seat. Returns two arrays, one (<constant>NULL</constant> 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
<constant>NULL</constant> in case these output values are not needed. The arrays and the strings
referenced by them need to be freed with the libc <citerefentry
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry> call after
use. Note that instead of an empty array <constant>NULL</constant> may be returned and should be
considered equivalent to an empty array.</para>
<para><function>sd_seat_can_tty()</function> may be used to
determine whether a specific seat provides TTY functionality, i.e.

View File

@ -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) {

View File

@ -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_;