Merge pull request #16635 from keszybz/do-not-for-each-word

Drop FOREACH_WORD
This commit is contained in:
Lennart Poettering
2020-09-09 17:43:38 +02:00
committed by GitHub
36 changed files with 686 additions and 641 deletions

View File

@@ -74,9 +74,6 @@ ForEachMacros:
- FOREACH_INOTIFY_EVENT
- FOREACH_STRING
- FOREACH_SUBSYSTEM
- _FOREACH_WORD
- FOREACH_WORD
- FOREACH_WORD_SEPARATOR
- HASHMAP_FOREACH
- HASHMAP_FOREACH_IDX
- HASHMAP_FOREACH_KEY

View File

@@ -35,7 +35,7 @@
<funcprototype>
<funcdef>int <function>sd_machine_get_ifindices</function></funcdef>
<paramdef>const char* <parameter>machine</parameter></paramdef>
<paramdef>int **<parameter>ifindices</parameter></paramdef>
<paramdef>int **<parameter>ret_ifindices</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
@@ -53,21 +53,22 @@
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
<para><function>sd_machine_get_ifindices()</function> may be used
to determine the numeric indices of the network interfaces on the
host that are pointing towards the specified locally running
virtual machine or container that is registered with
<para><function>sd_machine_get_ifindices()</function> may be used to determine the numeric indices of the
network interfaces on the host that are pointing towards the specified locally running virtual machine or
container. The vm or container must be registered with
<citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
The returned array needs to be freed with the libc <citerefentry
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
The output parameter <parameter>ret_ifindices</parameter> may be passed as <constant>NULL</constant> when
the output value is not needed. The returned array needs to be freed with the libc <citerefentry
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry> call after
use.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success, these calls return 0 or a positive integer. On failure, these calls return a negative
errno-style error code.</para>
<para>On success, these functions return a non-negative integer.
<function>sd_machine_get_ifindices()</function> returns the number of the relevant network interfaces.
On failure, these calls return a negative errno-style error code.</para>
<refsect2>
<title>Errors</title>

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

@@ -652,14 +652,13 @@ int cg_remove_xattr(const char *controller, const char *path, const char *name)
return 0;
}
int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
_cleanup_fclose_ FILE *f = NULL;
const char *fs, *controller_str;
int unified, r;
size_t cs = 0;
assert(path);
assert(pid >= 0);
assert(ret_path);
if (controller) {
if (!cg_controller_is_valid(controller))
@@ -675,8 +674,6 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
controller_str = SYSTEMD_CGROUP_CONTROLLER_LEGACY;
else
controller_str = controller;
cs = strlen(controller_str);
}
fs = procfs_file_alloca(pid, "cgroup");
@@ -688,13 +685,13 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
for (;;) {
_cleanup_free_ char *line = NULL;
char *e, *p;
char *e;
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
return r;
if (r == 0)
break;
return -ENODATA;
if (unified) {
e = startswith(line, "0:");
@@ -706,9 +703,6 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
continue;
} else {
char *l;
size_t k;
const char *word, *state;
bool found = false;
l = strchr(line, ':');
if (!l)
@@ -718,31 +712,27 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
e = strchr(l, ':');
if (!e)
continue;
*e = 0;
FOREACH_WORD_SEPARATOR(word, k, l, ",", state)
if (k == cs && memcmp(word, controller_str, cs) == 0) {
found = true;
break;
}
if (!found)
r = string_contains_word(l, ",", controller_str);
if (r < 0)
return r;
if (r == 0)
continue;
}
p = strdup(e + 1);
if (!p)
char *path = strdup(e + 1);
if (!path)
return -ENOMEM;
/* Truncate suffix indicating the process is a zombie */
e = endswith(p, " (deleted)");
e = endswith(path, " (deleted)");
if (e)
*e = 0;
*path = p;
*ret_path = path;
return 0;
}
return -ENODATA;
}
int cg_install_release_agent(const char *controller, const char *agent) {

View File

@@ -687,7 +687,7 @@ char **replace_env_argv(char **argv, char **env) {
if (e) {
int r;
r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE);
r = strv_split_full(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE);
if (r < 0) {
ret[k] = NULL;
strv_free(ret);

View File

@@ -14,6 +14,7 @@
#include "log.h"
#include "macro.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {

View File

@@ -538,6 +538,9 @@ static inline int __coverity_check_and_return__(int condition) {
(y) = (_t); \
} while (false)
#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
/* Iterates through a specified list of pointers. Accepts NULL pointers, but uses (void*) -1 as internal marker for EOL. */
#define FOREACH_POINTER(p, x, ...) \
for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, (void*) -1 }; \

View File

@@ -8,12 +8,14 @@
#include "alloc-util.h"
#include "escape.h"
#include "extract-word.h"
#include "fileio.h"
#include "gunicode.h"
#include "locale-util.h"
#include "macro.h"
#include "memory-util.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "utf8.h"
#include "util.h"
@@ -110,83 +112,6 @@ char* first_word(const char *s, const char *word) {
return (char*) p;
}
static size_t strcspn_escaped(const char *s, const char *reject) {
bool escaped = false;
int n;
for (n = 0; s[n] != '\0'; n++) {
if (escaped)
escaped = false;
else if (s[n] == '\\')
escaped = true;
else if (strchr(reject, s[n]))
break;
}
return n;
}
/* Split a string into words. */
const char* split(
const char **state,
size_t *l,
const char *separator,
SplitFlags flags) {
const char *current;
assert(state);
assert(l);
if (!separator)
separator = WHITESPACE;
current = *state;
if (*current == '\0') /* already at the end? */
return NULL;
current += strspn(current, separator); /* skip leading separators */
if (*current == '\0') { /* at the end now? */
*state = current;
return NULL;
}
if (FLAGS_SET(flags, SPLIT_QUOTES)) {
if (strchr(QUOTES, *current)) {
/* We are looking at a quote */
*l = strcspn_escaped(current + 1, CHAR_TO_STR(*current));
if (current[*l + 1] != *current ||
(current[*l + 2] != 0 && !strchr(separator, current[*l + 2]))) {
/* right quote missing or garbage at the end */
if (FLAGS_SET(flags, SPLIT_RELAX)) {
*state = current + *l + 1 + (current[*l + 1] != '\0');
return current + 1;
}
*state = current;
return NULL;
}
*state = current++ + *l + 2;
} else {
/* We are looking at a something that is not a quote */
*l = strcspn_escaped(current, separator);
if (current[*l] && !strchr(separator, current[*l]) && !FLAGS_SET(flags, SPLIT_RELAX)) {
/* unfinished escape */
*state = current;
return NULL;
}
*state = current + *l;
}
} else {
*l = strcspn(current, separator);
*state = current + *l;
}
return current;
}
char *strnappend(const char *s, const char *suffix, size_t b) {
size_t a;
char *r;
@@ -1207,3 +1132,30 @@ int string_extract_line(const char *s, size_t i, char **ret) {
c++;
}
}
int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word) {
/* In the default mode with no separators specified, we split on whitespace and
* don't coalesce separators. */
const ExtractFlags flags = separators ? EXTRACT_DONT_COALESCE_SEPARATORS : 0;
const char *found = NULL;
for (const char *p = string;;) {
_cleanup_free_ char *w = NULL;
int r;
r = extract_first_word(&p, &w, separators, flags);
if (r < 0)
return r;
if (r == 0)
break;
found = strv_find(words, w);
if (found)
break;
}
if (ret_word)
*ret_word = found;
return !!found;
}

View File

@@ -108,24 +108,6 @@ char *endswith_no_case(const char *s, const char *postfix) _pure_;
char *first_word(const char *s, const char *word) _pure_;
typedef enum SplitFlags {
SPLIT_QUOTES = 0x01 << 0,
SPLIT_RELAX = 0x01 << 1,
} SplitFlags;
/* Smelly. Do not use this anymore. Use extract_first_word() instead! */
const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags);
/* Similar, don't use this anymore */
#define FOREACH_WORD(word, length, s, state) \
_FOREACH_WORD(word, length, s, WHITESPACE, 0, state)
#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
_FOREACH_WORD(word, length, s, separator, 0, state)
#define _FOREACH_WORD(word, length, s, separator, flags, state) \
for ((state) = (s), (word) = split(&(state), &(length), (separator), (flags)); (word); (word) = split(&(state), &(length), (separator), (flags)))
char *strnappend(const char *s, const char *suffix, size_t length);
char *strjoin_real(const char *x, ...) _sentinel_;
@@ -280,3 +262,8 @@ char* string_erase(char *x);
int string_truncate_lines(const char *s, size_t n_lines, char **ret);
int string_extract_line(const char *s, size_t i, char **ret);
int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word);
static inline int string_contains_word(const char *string, const char *separators, const char *word) {
return string_contains_word_strv(string, separators, STRV_MAKE(word), NULL);
}

View File

@@ -256,44 +256,6 @@ int strv_extend_strv_concat(char ***a, char * const *b, const char *suffix) {
return 0;
}
char **strv_split_full(const char *s, const char *separator, SplitFlags flags) {
const char *word, *state;
size_t l;
size_t n, i;
char **r;
assert(s);
if (!separator)
separator = WHITESPACE;
s += strspn(s, separator);
if (isempty(s))
return new0(char*, 1);
n = 0;
_FOREACH_WORD(word, l, s, separator, flags, state)
n++;
r = new(char*, n+1);
if (!r)
return NULL;
i = 0;
_FOREACH_WORD(word, l, s, separator, flags, state) {
r[i] = strndup(word, l);
if (!r[i]) {
strv_free(r);
return NULL;
}
i++;
}
r[i] = NULL;
return r;
}
char **strv_split_newlines(const char *s) {
char **l;
size_t n;
@@ -317,7 +279,7 @@ char **strv_split_newlines(const char *s) {
return l;
}
int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags) {
_cleanup_strv_free_ char **l = NULL;
size_t n = 0, allocated = 0;
int r;

View File

@@ -72,13 +72,19 @@ static inline bool strv_isempty(char * const *l) {
return !l || !*l;
}
char **strv_split_full(const char *s, const char *separator, SplitFlags flags);
static inline char **strv_split(const char *s, const char *separator) {
return strv_split_full(s, separator, 0);
}
char **strv_split_newlines(const char *s);
int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags);
static inline char **strv_split(const char *s, const char *separators) {
char **ret;
int r;
r = strv_split_full(&ret, s, separators, 0);
if (r < 0)
return NULL;
return ret;
}
/* Given a string containing white-space separated tuples of words themselves separated by ':',
* returns a vector of strings. If the second element in a tuple is missing, the corresponding
@@ -123,10 +129,6 @@ bool strv_overlap(char * const *a, char * const *b) _pure_;
char **strv_sort(char **l);
void strv_print(char * const *l);
#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
#define strv_from_stdarg_alloca(first) \
({ \
char **_l; \

View File

@@ -4438,15 +4438,13 @@ int config_parse_set_status(
void *data,
void *userdata) {
size_t l;
const char *word, *state;
int r;
ExitStatusSet *status_set = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
assert(status_set);
/* Empty assignment resets the list */
if (isempty(rvalue)) {
@@ -4454,25 +4452,26 @@ int config_parse_set_status(
return 0;
}
FOREACH_WORD(word, l, rvalue, state) {
_cleanup_free_ char *temp;
for (const char *p = rvalue;;) {
_cleanup_free_ char *word = NULL;
Bitmap *bitmap;
temp = strndup(word, l);
if (!temp)
return log_oom();
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to parse %s: %m", lvalue);
if (r == 0)
return 0;
/* We need to call exit_status_from_string() first, because we want
* to parse numbers as exit statuses, not signals. */
r = exit_status_from_string(temp);
r = exit_status_from_string(word);
if (r >= 0) {
assert(r >= 0 && r < 256);
bitmap = &status_set->status;
} else {
r = signal_from_string(temp);
if (r <= 0) {
r = signal_from_string(word);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Failed to parse value, ignoring: %s", word);
continue;
@@ -4484,10 +4483,6 @@ int config_parse_set_status(
if (r < 0)
return log_error_errno(r, "Failed to set signal or status %s: %m", word);
}
if (!isempty(state))
log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
int config_parse_namespace_path_strv(

View File

@@ -288,19 +288,19 @@ static int parse_one_option(const char *option) {
}
static int parse_options(const char *options) {
const char *word, *state;
size_t l;
int r;
assert(options);
FOREACH_WORD_SEPARATOR(word, l, options, ",", state) {
_cleanup_free_ char *o;
for (;;) {
_cleanup_free_ char *word = NULL;
int r;
o = strndup(word, l);
if (!o)
return -ENOMEM;
r = parse_one_option(o);
r = extract_first_word(&options, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return log_debug_errno(r, "Failed to parse options: %m");
if (r == 0)
break;
r = parse_one_option(word);
if (r < 0)
return r;
}

View File

@@ -541,28 +541,33 @@ static int help(void) {
}
static int parse_flags(const char *flag_str, int flags) {
const char *word, *state;
size_t l;
for (;;) {
_cleanup_free_ char *word = NULL;
int r;
FOREACH_WORD_SEPARATOR(word, l, flag_str, ",", state) {
if (strneq("masked", word, l))
r = extract_first_word(&flag_str, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return r;
if (r == 0)
return flags;
if (streq(word, "masked"))
flags |= SHOW_MASKED;
else if (strneq ("equivalent", word, l))
else if (streq(word, "equivalent"))
flags |= SHOW_EQUIVALENT;
else if (strneq("redirected", word, l))
else if (streq(word, "redirected"))
flags |= SHOW_REDIRECTED;
else if (strneq("overridden", word, l))
else if (streq(word, "overridden"))
flags |= SHOW_OVERRIDDEN;
else if (strneq("unchanged", word, l))
else if (streq(word, "unchanged"))
flags |= SHOW_UNCHANGED;
else if (strneq("extended", word, l))
else if (streq(word, "extended"))
flags |= SHOW_EXTENDED;
else if (strneq("default", word, l))
else if (streq(word, "default"))
flags |= SHOW_DEFAULTS;
else
return -EINVAL;
}
return flags;
}
static int parse_argv(int argc, char *argv[]) {

View File

@@ -99,89 +99,85 @@ static int verify_tty(const char *name) {
return 0;
}
static int run_container(void) {
_cleanup_free_ char *container_ttys = NULL;
int r;
log_debug("Automatically adding console shell.");
r = add_symlink("console-getty.service", "console-getty.service");
if (r < 0)
return r;
/* When $container_ttys is set for PID 1, spawn gettys on all ptys named therein.
* Note that despite the variable name we only support ptys here. */
(void) getenv_for_pid(1, "container_ttys", &container_ttys);
for (const char *p = container_ttys;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to parse $container_ttys: %m");
if (r == 0)
return 0;
const char *tty = word;
/* First strip off /dev/ if it is specified */
tty = path_startswith(tty, "/dev/") ?: tty;
/* Then, make sure it's actually a pty */
tty = path_startswith(tty, "pts/");
if (!tty)
continue;
r = add_container_getty(tty);
if (r < 0)
return r;
}
}
static int run(const char *dest, const char *dest_early, const char *dest_late) {
_cleanup_free_ char *active = NULL;
const char *j;
int r;
assert_se(arg_dest = dest);
if (detect_container() > 0) {
_cleanup_free_ char *container_ttys = NULL;
if (detect_container() > 0)
/* Add console shell and look at $container_ttys, but don't do add any
* further magic if we are in a container. */
return run_container();
log_debug("Automatically adding console shell.");
/* Automatically add in a serial getty on all active kernel consoles */
_cleanup_free_ char *active = NULL;
(void) read_one_line_file("/sys/class/tty/console/active", &active);
for (const char *p = active;;) {
_cleanup_free_ char *tty = NULL;
r = add_symlink("console-getty.service", "console-getty.service");
r = extract_first_word(&p, &tty, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to parse /sys/class/tty/console/active: %m");
if (r == 0)
break;
/* We assume that gettys on virtual terminals are started via manual configuration and do
* this magic only for non-VC terminals. */
if (isempty(tty) || tty_is_vc(tty))
continue;
if (verify_tty(tty) < 0)
continue;
r = add_serial_getty(tty);
if (r < 0)
return r;
/* When $container_ttys is set for PID 1, spawn
* gettys on all ptys named therein. Note that despite
* the variable name we only support ptys here. */
r = getenv_for_pid(1, "container_ttys", &container_ttys);
if (r > 0) {
const char *word, *state;
size_t l;
FOREACH_WORD(word, l, container_ttys, state) {
const char *t;
char tty[l + 1];
memcpy(tty, word, l);
tty[l] = 0;
/* First strip off /dev/ if it is specified */
t = path_startswith(tty, "/dev/");
if (!t)
t = tty;
/* Then, make sure it's actually a pty */
t = path_startswith(t, "pts/");
if (!t)
continue;
r = add_container_getty(t);
if (r < 0)
return r;
}
}
/* Don't add any further magic if we are in a container */
return 0;
}
if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
const char *word, *state;
size_t l;
/* Automatically add in a serial getty on all active
* kernel consoles */
FOREACH_WORD(word, l, active, state) {
_cleanup_free_ char *tty = NULL;
tty = strndup(word, l);
if (!tty)
return log_oom();
/* We assume that gettys on virtual terminals are
* started via manual configuration and do this magic
* only for non-VC terminals. */
if (isempty(tty) || tty_is_vc(tty))
continue;
if (verify_tty(tty) < 0)
continue;
r = add_serial_getty(tty);
if (r < 0)
return r;
}
}
/* Automatically add in a serial getty on the first
* virtualizer console */
const char *j;
FOREACH_STRING(j,
"hvc0",
"xvc0",

View File

@@ -124,7 +124,7 @@ static int spawn_getter(const char *getter) {
_cleanup_strv_free_ char **words = NULL;
assert(getter);
r = strv_split_extract(&words, getter, WHITESPACE, EXTRACT_UNQUOTE);
r = strv_split_full(&words, getter, WHITESPACE, EXTRACT_UNQUOTE);
if (r < 0)
return log_error_errno(r, "Failed to split getter option: %m");

View File

@@ -950,74 +950,69 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
}
_public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
const char *word, *state;
size_t l;
unsigned long long seqnum, monotonic, realtime, xor_hash;
bool
seqnum_id_set = false,
seqnum_set = false,
boot_id_set = false,
monotonic_set = false,
realtime_set = false,
xor_hash_set = false;
bool seqnum_id_set = false,
seqnum_set = false,
boot_id_set = false,
monotonic_set = false,
realtime_set = false,
xor_hash_set = false;
sd_id128_t seqnum_id, boot_id;
int r;
assert_return(j, -EINVAL);
assert_return(!journal_pid_changed(j), -ECHILD);
assert_return(!isempty(cursor), -EINVAL);
FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) {
char *item;
int k = 0;
for (const char *p = cursor;;) {
_cleanup_free_ char *word = NULL;
if (l < 2 || word[1] != '=')
r = extract_first_word(&p, &word, ";", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return r;
if (r == 0)
break;
if (word[0] == '\0' || word[1] != '=')
return -EINVAL;
item = strndup(word, l);
if (!item)
return -ENOMEM;
switch (word[0]) {
case 's':
seqnum_id_set = true;
k = sd_id128_from_string(item+2, &seqnum_id);
r = sd_id128_from_string(word + 2, &seqnum_id);
if (r < 0)
return r;
break;
case 'i':
seqnum_set = true;
if (sscanf(item+2, "%llx", &seqnum) != 1)
k = -EINVAL;
if (sscanf(word + 2, "%llx", &seqnum) != 1)
return -EINVAL;
break;
case 'b':
boot_id_set = true;
k = sd_id128_from_string(item+2, &boot_id);
r = sd_id128_from_string(word + 2, &boot_id);
break;
case 'm':
monotonic_set = true;
if (sscanf(item+2, "%llx", &monotonic) != 1)
k = -EINVAL;
if (sscanf(word + 2, "%llx", &monotonic) != 1)
return -EINVAL;
break;
case 't':
realtime_set = true;
if (sscanf(item+2, "%llx", &realtime) != 1)
k = -EINVAL;
if (sscanf(word + 2, "%llx", &realtime) != 1)
return -EINVAL;
break;
case 'x':
xor_hash_set = true;
if (sscanf(item+2, "%llx", &xor_hash) != 1)
k = -EINVAL;
if (sscanf(word + 2, "%llx", &xor_hash) != 1)
return -EINVAL;
break;
}
free(item);
if (k < 0)
return k;
}
if ((!seqnum_set || !seqnum_id_set) &&

View File

@@ -101,7 +101,7 @@ _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) {
e = getenv("LISTEN_FDNAMES");
if (e) {
n_names = strv_split_extract(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
n_names = strv_split_full(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (n_names < 0) {
unsetenv_all(unset_environment);
return n_names;

View File

@@ -316,34 +316,33 @@ static int device_amend(sd_device *device, const char *key, const char *value) {
if (r < 0)
return log_device_debug_errno(device, r, "sd-device: Failed to set SEQNUM to '%s': %m", value);
} else if (streq(key, "DEVLINKS")) {
const char *word, *state;
size_t l;
for (const char *p = value;;) {
_cleanup_free_ char *word = NULL;
FOREACH_WORD(word, l, value, state) {
char devlink[l + 1];
strncpy(devlink, word, l);
devlink[l] = '\0';
r = device_add_devlink(device, devlink);
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", devlink);
return r;
if (r == 0)
break;
r = device_add_devlink(device, word);
if (r < 0)
return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", word);
}
} else if (STR_IN_SET(key, "TAGS", "CURRENT_TAGS")) {
const char *word, *state;
size_t l;
for (const char *p = value;;) {
_cleanup_free_ char *word = NULL;
FOREACH_WORD_SEPARATOR(word, l, value, ":", state) {
char tag[l + 1];
(void) strncpy(tag, word, l);
tag[l] = '\0';
r = device_add_tag(device, tag, streq(key, "CURRENT_TAGS"));
r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", tag);
}
return r;
if (r == 0)
break;
r = device_add_tag(device, word, streq(key, "CURRENT_TAGS"));
if (r < 0)
return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", word);
}
} else {
r = device_add_property_internal(device, key, value);
if (r < 0)

View File

@@ -12,6 +12,7 @@
#include "dirent-util.h"
#include "env-file.h"
#include "escape.h"
#include "extract-word.h"
#include "fd-util.h"
#include "format-util.h"
#include "fs-util.h"
@@ -22,6 +23,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "socket-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
@@ -331,35 +333,29 @@ static int file_of_seat(const char *seat, char **_p) {
}
_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;
_cleanup_free_ char *filename = NULL, *content = NULL;
int r;
const char *word, *variable, *state;
assert_return(uid_is_valid(uid), -EINVAL);
r = file_of_seat(seat, &p);
r = file_of_seat(seat, &filename);
if (r < 0)
return r;
variable = require_active ? "ACTIVE_UID" : "UIDS";
r = parse_env_file(NULL, p, variable, &s);
r = parse_env_file(NULL, filename,
require_active ? "ACTIVE_UID" : "UIDS",
&content);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
if (isempty(s))
if (isempty(content))
return 0;
if (asprintf(&t, UID_FMT, uid) < 0)
return -ENOMEM;
char t[DECIMAL_STR_MAX(uid_t)];
xsprintf(t, UID_FMT, uid);
FOREACH_WORD(word, l, s, state)
if (strneq(t, word, l))
return 1;
return 0;
return string_contains_word(content, ",", t);
}
static int uid_get_array(uid_t uid, const char *variable, char ***array) {
@@ -382,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;
@@ -654,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) {
@@ -901,47 +894,52 @@ _public_ int sd_machine_get_class(const char *machine, char **class) {
return 0;
}
_public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) {
_cleanup_free_ char *netif = NULL;
size_t l, allocated = 0, nr = 0;
int *ni = NULL;
const char *p, *word, *state;
_public_ int sd_machine_get_ifindices(const char *machine, int **ret_ifindices) {
_cleanup_free_ char *netif_line = NULL;
const char *p;
int r;
assert_return(machine_name_is_valid(machine), -EINVAL);
assert_return(ifindices, -EINVAL);
p = strjoina("/run/systemd/machines/", machine);
r = parse_env_file(NULL, p, "NETIF", &netif);
r = parse_env_file(NULL, p, "NETIF", &netif_line);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
return r;
if (!netif) {
*ifindices = NULL;
if (!netif_line) {
*ret_ifindices = NULL;
return 0;
}
FOREACH_WORD(word, l, netif, state) {
char buf[l+1];
int ifi;
_cleanup_strv_free_ char **tt = strv_split(netif_line, NULL);
if (!tt)
return -ENOMEM;
*(char*) (mempcpy(buf, word, l)) = 0;
ifi = parse_ifindex(buf);
if (ifi < 0)
continue;
if (!GREEDY_REALLOC(ni, allocated, nr+1)) {
free(ni);
size_t n = 0;
int *ifindices;
if (ret_ifindices) {
ifindices = new(int, strv_length(tt));
if (!ifindices)
return -ENOMEM;
}
ni[nr++] = ifi;
}
*ifindices = ni;
return nr;
for (size_t i = 0; tt[i]; i++) {
int ind;
ind = parse_ifindex(tt[i]);
if (ind < 0)
/* Return -EUCLEAN to distinguish from -EINVAL for invalid args */
return ind == -EINVAL ? -EUCLEAN : ind;
if (ret_ifindices)
ifindices[n] = ind;
n++;
}
if (ret_ifindices)
*ret_ifindices = ifindices;
return n;
}
static int MONITOR_TO_FD(sd_login_monitor *m) {

Some files were not shown because too many files have changed in this diff Show More