return (char*) s + sl - pl;
}
-bool first_word(const char *s, const char *word) {
+char* first_word(const char *s, const char *word) {
size_t sl, wl;
+ const char *p;
assert(s);
assert(word);
+ /* Checks if the string starts with the specified word, either
+ * followed by NUL or by whitespace. Returns a pointer to the
+ * NUL or the first character after the whitespace. */
+
sl = strlen(s);
wl = strlen(word);
if (sl < wl)
- return false;
+ return NULL;
if (wl == 0)
- return true;
+ return (char*) s;
if (memcmp(s, word, wl) != 0)
- return false;
+ return NULL;
+
+ p = s + wl;
+ if (*p == 0)
+ return (char*) p;
+
+ if (!strchr(WHITESPACE, *p))
+ return NULL;
- return s[wl] == 0 ||
- strchr(WHITESPACE, s[wl]);
+ p += strspn(p, WHITESPACE);
+ return (char*) p;
}
int close_nointr(int fd) {
int parse_boolean(const char *v) {
assert(v);
- if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || strcaseeq(v, "on"))
+ if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
return 1;
- else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || strcaseeq(v, "off"))
+ else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
return 0;
return -EINVAL;
return 0;
}
+int safe_atou8(const char *s, uint8_t *ret) {
+ char *x = NULL;
+ unsigned long l;
+
+ assert(s);
+ assert(ret);
+
+ errno = 0;
+ l = strtoul(s, &x, 0);
+
+ if (!x || x == s || *x || errno)
+ return errno > 0 ? -errno : -EINVAL;
+
+ if ((unsigned long) (uint8_t) l != l)
+ return -ERANGE;
+
+ *ret = (uint8_t) l;
+ return 0;
+}
+
int safe_atollu(const char *s, long long unsigned *ret_llu) {
char *x = NULL;
unsigned long long l;
else if (s[n] == '\\')
escaped = true;
else if (strchr(reject, s[n]))
- return n;
+ break;
}
- return n;
+ /* if s ends in \, return index of previous char */
+ return n - escaped;
}
/* Split a string into words. */
-char *split(const char *c, size_t *l, const char *separator, bool quoted, char **state) {
- char *current;
+const char* split(const char **state, size_t *l, const char *separator, bool quoted) {
+ const char *current;
- current = *state ? *state : (char*) c;
+ current = *state;
- if (!*current || *c == 0)
+ if (!*current) {
+ assert(**state == '\0');
return NULL;
+ }
current += strspn(current, separator);
- if (!*current)
+ if (!*current) {
+ *state = current;
return NULL;
+ }
if (quoted && strchr("\'\"", *current)) {
- char quotechar = *(current++);
- *l = strcspn_escaped(current, (char[]){quotechar, '\0'});
- *state = current+*l+1;
+ char quotechars[2] = {*current, '\0'};
+
+ *l = strcspn_escaped(current + 1, quotechars);
+ if (current[*l + 1] == '\0' ||
+ (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
+ /* right quote missing or garbage at the end*/
+ *state = current;
+ return NULL;
+ }
+ assert(current[*l + 1] == quotechars[0]);
+ *state = current++ + *l + 2;
} else if (quoted) {
*l = strcspn_escaped(current, separator);
- *state = current+*l;
+ *state = current + *l;
} else {
*l = strcspn(current, separator);
- *state = current+*l;
+ *state = current + *l;
}
- return (char*) current;
+ return current;
}
int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
r = new(char, pl+length+1);
if (!r)
- return r;
+ return NULL;
if (prefix)
memcpy(r, prefix, pl);
if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
size_t k;
- if (t != (usec_t) -1) {
+ if (t != USEC_INFINITY) {
if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
tcsetattr(fileno(f), TCSADRAIN, &old_termios);
return -ETIMEDOUT;
}
}
- if (t != (usec_t) -1) {
+ if (t != USEC_INFINITY) {
if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
return -ETIMEDOUT;
}
fflush(stdout);
- r = read_one_char(stdin, &c, (usec_t) -1, &need_nl);
+ r = read_one_char(stdin, &c, USEC_INFINITY, &need_nl);
if (r < 0) {
if (r == -EBADMSG) {
* on the same tty as an untrusted user this should not be a
* problem. (Which he probably should not do anyway.) */
- if (timeout != (usec_t) -1)
+ if (timeout != USEC_INFINITY)
ts = now(CLOCK_MONOTONIC);
if (!fail && !force) {
- notify = inotify_init1(IN_CLOEXEC | (timeout != (usec_t) -1 ? IN_NONBLOCK : 0));
+ notify = inotify_init1(IN_CLOEXEC | (timeout != USEC_INFINITY ? IN_NONBLOCK : 0));
if (notify < 0) {
r = -errno;
goto fail;
ssize_t l;
struct inotify_event *e;
- if (timeout != (usec_t) -1) {
+ if (timeout != USEC_INFINITY) {
usec_t n;
n = now(CLOCK_MONOTONIC);
* and expect that any error/EOF is reported
* via read() */
- fd_wait_for_event(fd, POLLIN, (usec_t) -1);
+ fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
continue;
}
* and expect that any error/EOF is reported
* via write() */
- fd_wait_for_event(fd, POLLOUT, (usec_t) -1);
+ fd_wait_for_event(fd, POLLOUT, USEC_INFINITY);
continue;
}
}
char **replace_env_argv(char **argv, char **env) {
- char **r, **i;
+ char **ret, **i;
unsigned k = 0, l = 0;
l = strv_length(argv);
- if (!(r = new(char*, l+1)))
+ ret = new(char*, l+1);
+ if (!ret)
return NULL;
STRV_FOREACH(i, argv) {
e = strv_env_get(env, *i+1);
if (e) {
+ int r;
- if (!(m = strv_split_quoted(e))) {
- r[k] = NULL;
- strv_free(r);
+ r = strv_split_quoted(&m, e);
+ if (r < 0) {
+ ret[k] = NULL;
+ strv_free(ret);
return NULL;
}
} else
q = strv_length(m);
l = l + q - 1;
- if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
- r[k] = NULL;
- strv_free(r);
+ w = realloc(ret, sizeof(char*) * (l+1));
+ if (!w) {
+ ret[k] = NULL;
+ strv_free(ret);
strv_free(m);
return NULL;
}
- r = w;
+ ret = w;
if (m) {
- memcpy(r + k, m, q * sizeof(char*));
+ memcpy(ret + k, m, q * sizeof(char*));
free(m);
}
}
/* If ${FOO} appears as part of a word, replace it by the variable as-is */
- if (!(r[k++] = replace_env(*i, env))) {
- strv_free(r);
+ ret[k] = replace_env(*i, env);
+ if (!ret[k]) {
+ strv_free(ret);
return NULL;
}
+ k++;
}
- r[k] = NULL;
- return r;
+ ret[k] = NULL;
+ return ret;
}
int fd_columns(int fd) {
return -errno;
}
- if (stamp != (usec_t) -1) {
+ if (stamp != USEC_INFINITY) {
struct timespec ts[2];
timespec_store(&ts[0], stamp);
}
int touch(const char *path) {
- return touch_file(path, false, (usec_t) -1, (uid_t) -1, (gid_t) -1, 0);
+ return touch_file(path, false, USEC_INFINITY, (uid_t) -1, (gid_t) -1, 0);
}
char *unquote(const char *s, const char* quotes) {
* timout. We simply rely on SIGALRM as default action
* terminating the process, and turn on alarm(). */
- if (timeout != (usec_t) -1)
+ if (timeout != USEC_INFINITY)
alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
while (!hashmap_isempty(pids)) {
struct timespec ts;
int r;
- r = ppoll(&pollfd, 1, t == (usec_t) -1 ? NULL : timespec_store(&ts, t), NULL);
+ r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
if (r < 0)
return -errno;
/* Make /dev/console the controlling terminal and stdin/stdout/stderr */
- fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
+ fd = acquire_terminal("/dev/console", false, true, true, USEC_INFINITY);
if (fd < 0) {
log_error("Failed to acquire terminal: %s", strerror(-fd));
return fd;
int shall_restore_state(void) {
_cleanup_free_ char *line = NULL;
- char *w, *state;
+ const char *word, *state;
size_t l;
int r;
r = 1;
- FOREACH_WORD_QUOTED(w, l, line, state) {
+ FOREACH_WORD_QUOTED(word, l, line, state) {
const char *e;
char n[l+1];
int k;
- memcpy(n, w, l);
+ memcpy(n, word, l);
n[l] = 0;
e = startswith(n, "systemd.restore_state=");
int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
_cleanup_free_ char *line = NULL;
- char *w, *state;
+ const char *w, *state;
size_t l;
int r;