(*ur)[n].high = 0;
return n;
}
+
+enum line_state_flags {LSF_HAVE_WORD = 1, LSF_BACKSLASH = 2, LSF_QUOTE = 4};
+
+static int get_next_word(const char *line, char **word)
+{
+ const char *in;
+ char *out;
+ int ret, state = 0;
+
+ out = adu_malloc(strlen(line) + 1);
+ *out = '\0';
+ *word = out;
+ for (in = line; *in; in++) {
+ switch (*in) {
+ case '\\':
+ if (state & LSF_BACKSLASH) /* \\ */
+ break;
+ state |= LSF_BACKSLASH;
+ state |= LSF_HAVE_WORD;
+ continue;
+ case 'n':
+ case 't':
+ if (state & LSF_BACKSLASH) { /* \n or \t */
+ *out++ = (*in == 'n')? '\n' : '\t';
+ state &= ~LSF_BACKSLASH;
+ continue;
+ }
+ break;
+ case '"':
+ if (state & LSF_BACKSLASH) /* \" */
+ break;
+ if (state & LSF_QUOTE) {
+ state &= ~LSF_QUOTE;
+ continue;
+ }
+ state |= LSF_HAVE_WORD;
+ state |= LSF_QUOTE;
+ continue;
+ case ' ':
+ case '\t':
+ case '\n':
+ if (state & LSF_BACKSLASH)
+ break;
+ if (state & LSF_QUOTE)
+ break;
+ if (state & LSF_HAVE_WORD)
+ goto success;
+ /* ignore space at the beginning */
+ continue;
+ }
+ /* copy char */
+ state |= LSF_HAVE_WORD;
+ *out++ = *in;
+ state &= ~LSF_BACKSLASH;
+ }
+ ret = 0;
+ if (!(state & LSF_HAVE_WORD))
+ goto out;
+ ret = -ERRNO_TO_ERROR(EINVAL);
+ if (state & LSF_BACKSLASH) {
+ ERROR_LOG("trailing backslash\n");
+ goto out;
+ }
+ if (state & LSF_QUOTE) {
+ ERROR_LOG("unmatched quote character\n");
+ goto out;
+ }
+success:
+ *out = '\0';
+ return in - line;
+out:
+ free(*word);
+ *word = NULL;
+ return ret;
+}
+
+void free_argv(char **argv)
+{
+ int i;
+
+ for (i = 0; argv[i]; i++)
+ free(argv[i]);
+ free(argv);
+}
+
+/**
+ * \return Number of words in \a line, negative on errors.
+ */
+int create_argv(const char *line, char ***result)
+{
+ char *word, **argv = adu_malloc(2 * sizeof(char *));
+ const char *p;
+ int ret, num_words;
+
+ argv[0] = adu_strdup(line);
+ for (p = line, num_words = 1; ; p += ret, num_words++) {
+ ret = get_next_word(p, &word);
+ if (ret < 0)
+ goto err;
+ if (!ret)
+ break;
+ argv = adu_realloc(argv, (num_words + 2) * sizeof(char*));
+ argv[num_words] = word;
+ }
+ argv[num_words] = NULL;
+ *result = argv;
+ return num_words;
+err:
+ while (num_words > 0)
+ free(argv[--num_words]);
+ free(argv);
+ return ret;
+}
__must_check __malloc __printf_1_2 char *make_message(const char *fmt, ...);
__must_check int atoi64(const char *str, int64_t *result);
int parse_uid_arg(const char *orig_arg, struct uid_range **ur);
+int create_argv(const char *line, char ***result);
+void free_argv(char **argv);