Compare commits
5 Commits
0fc659eea9
...
50f5e2e281
Author | SHA1 | Date |
---|---|---|
Evgeny Vereshchagin | 50f5e2e281 | |
Lennart Poettering | 82aa14e2a3 | |
Lennart Poettering | 29965a2a6e | |
Lennart Poettering | 5fed82c642 | |
Lennart Poettering | 77b19caf6b |
4
TODO
4
TODO
|
@ -117,7 +117,8 @@ Features:
|
||||||
|
|
||||||
* systemd-repart: allow config of partition uuid
|
* systemd-repart: allow config of partition uuid
|
||||||
|
|
||||||
* userdb: allow username prefix searches in varlink API
|
* userdb: allow username prefix searches in varlink API, allow realname and
|
||||||
|
realname substr searches in varlink API
|
||||||
|
|
||||||
* userdb: allow existence checks
|
* userdb: allow existence checks
|
||||||
|
|
||||||
|
@ -864,6 +865,7 @@ Features:
|
||||||
make assumptions about their slice anymore.
|
make assumptions about their slice anymore.
|
||||||
- follow PropertiesChanged state more closely, to deal with quick logouts and
|
- follow PropertiesChanged state more closely, to deal with quick logouts and
|
||||||
relogins
|
relogins
|
||||||
|
- (optionally?) spawn seat-manager@$SEAT.service whenever a seat shows up that as CanGraphical set
|
||||||
|
|
||||||
* journal:
|
* journal:
|
||||||
- consider introducing implicit _TTY= + _PPID= + _EUID= + _EGID= + _FSUID= + _FSGID= fields
|
- consider introducing implicit _TTY= + _PPID= + _EUID= + _EGID= + _FSUID= + _FSGID= fields
|
||||||
|
|
|
@ -113,7 +113,7 @@ static size_t strcspn_escaped(const char *s, const char *reject) {
|
||||||
bool escaped = false;
|
bool escaped = false;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
for (n=0; s[n]; n++) {
|
for (n = 0; s[n] != '\0'; n++) {
|
||||||
if (escaped)
|
if (escaped)
|
||||||
escaped = false;
|
escaped = false;
|
||||||
else if (s[n] == '\\')
|
else if (s[n] == '\\')
|
||||||
|
@ -122,35 +122,44 @@ static size_t strcspn_escaped(const char *s, const char *reject) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if s ends in \, return index of previous char */
|
return n;
|
||||||
return n - escaped;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Split a string into words. */
|
/* Split a string into words. */
|
||||||
const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags) {
|
const char* split(
|
||||||
|
const char **state,
|
||||||
|
size_t *l,
|
||||||
|
const char *separator,
|
||||||
|
SplitFlags flags) {
|
||||||
|
|
||||||
const char *current;
|
const char *current;
|
||||||
|
|
||||||
|
assert(state);
|
||||||
|
assert(l);
|
||||||
|
|
||||||
|
if (!separator)
|
||||||
|
separator = WHITESPACE;
|
||||||
|
|
||||||
current = *state;
|
current = *state;
|
||||||
|
|
||||||
if (!*current) {
|
if (*current == '\0') /* already at the end? */
|
||||||
assert(**state == '\0');
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
current += strspn(current, separator);
|
current += strspn(current, separator); /* skip leading separators */
|
||||||
if (!*current) {
|
if (*current == '\0') { /* at the end now? */
|
||||||
*state = current;
|
*state = current;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & SPLIT_QUOTES && strchr("\'\"", *current)) {
|
if (FLAGS_SET(flags, SPLIT_QUOTES)) {
|
||||||
char quotechars[2] = {*current, '\0'};
|
|
||||||
|
|
||||||
*l = strcspn_escaped(current + 1, quotechars);
|
if (strchr(QUOTES, *current)) {
|
||||||
if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
|
/* We are looking at a quote */
|
||||||
(current[*l + 2] && !strchr(separator, current[*l + 2]))) {
|
*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 */
|
/* right quote missing or garbage at the end */
|
||||||
if (flags & SPLIT_RELAX) {
|
if (FLAGS_SET(flags, SPLIT_RELAX)) {
|
||||||
*state = current + *l + 1 + (current[*l + 1] != '\0');
|
*state = current + *l + 1 + (current[*l + 1] != '\0');
|
||||||
return current + 1;
|
return current + 1;
|
||||||
}
|
}
|
||||||
|
@ -158,14 +167,17 @@ const char* split(const char **state, size_t *l, const char *separator, SplitFla
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*state = current++ + *l + 2;
|
*state = current++ + *l + 2;
|
||||||
} else if (flags & SPLIT_QUOTES) {
|
|
||||||
|
} else {
|
||||||
|
/* We are looking at a something that is not a quote */
|
||||||
*l = strcspn_escaped(current, separator);
|
*l = strcspn_escaped(current, separator);
|
||||||
if (current[*l] && !strchr(separator, current[*l]) && !(flags & SPLIT_RELAX)) {
|
if (current[*l] && !strchr(separator, current[*l]) && !FLAGS_SET(flags, SPLIT_RELAX)) {
|
||||||
/* unfinished escape */
|
/* unfinished escape */
|
||||||
*state = current;
|
*state = current;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*state = current + *l;
|
*state = current + *l;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*l = strcspn(current, separator);
|
*l = strcspn(current, separator);
|
||||||
*state = current + *l;
|
*state = current + *l;
|
||||||
|
|
|
@ -112,8 +112,10 @@ typedef enum SplitFlags {
|
||||||
SPLIT_RELAX = 0x01 << 1,
|
SPLIT_RELAX = 0x01 << 1,
|
||||||
} SplitFlags;
|
} 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);
|
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) \
|
#define FOREACH_WORD(word, length, s, state) \
|
||||||
_FOREACH_WORD(word, length, s, WHITESPACE, 0, state)
|
_FOREACH_WORD(word, length, s, WHITESPACE, 0, state)
|
||||||
|
|
||||||
|
|
|
@ -307,6 +307,12 @@ static void test_strv_split(void) {
|
||||||
l = strv_split_full(" 'one' \" two\t three \"' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
|
l = strv_split_full(" 'one' \" two\t three \"' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
|
||||||
assert_se(l);
|
assert_se(l);
|
||||||
assert_se(strv_equal(l, (char**) input_table_quoted));
|
assert_se(strv_equal(l, (char**) input_table_quoted));
|
||||||
|
|
||||||
|
strv_free_erase(l);
|
||||||
|
|
||||||
|
l = strv_split_full("\\", NULL, SPLIT_QUOTES | SPLIT_RELAX);
|
||||||
|
assert_se(l);
|
||||||
|
assert_se(strv_equal(l, STRV_MAKE("\\")));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_strv_split_empty(void) {
|
static void test_strv_split_empty(void) {
|
||||||
|
|
Loading…
Reference in New Issue