mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #16635 from keszybz/do-not-for-each-word
Drop FOREACH_WORD
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 }; \
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; \
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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[]) {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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) &&
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user