static int parse_filter_args(int filter_num, char *options, void **conf)
{
struct filter *f = &filters[filter_num];
- int ret, i, argc = 2;
+ int ret, argc;
char **argv;
-// PARA_DEBUG_LOG("%s, options: %s, parser: %p\n", f->name,
-// options? options : "(none)", f->parse_config);
if (!f->parse_config)
return strlen(options)? -E_BAD_FILTER_OPTIONS : filter_num;
-// PARA_DEBUG_LOG("options: %s\n", options);
- argc = create_argv(options, " \t", &argv);
+ argc = create_shifted_argv(options, " \t", &argv);
if (argc < 0)
return -E_BAD_FILTER_OPTIONS;
- PARA_DEBUG_LOG("argc = %d, argv[0]: %s\n", argc, argv[0]);
- for (i = argc - 1; i >= 0; i--)
- argv[i + 1] = argv[i];
argv[0] = para_strdup(f->name);
- argc++;
ret = f->parse_config(argc, argv, conf);
- free(argv[argc - 1]);
- argv[argc - 1] = NULL;
free_argv(argv);
return ret < 0? ret : filter_num;
}
{
struct receiver *r = &receivers[receiver_num];
char **argv;
- int argc, i;
+ int argc;
void *conf;
-
- PARA_DEBUG_LOG("%s, options: %s\n", r->name,
- options? options : "(none)");
if (options) {
- PARA_DEBUG_LOG("options: %s\n", options);
- argc = create_argv(options, " \t", &argv);
+ argc = create_shifted_argv(options, " \t", &argv);
if (argc < 0)
return NULL;
- for (i = argc - 1; i >= 0; i--)
- argv[i + 1] = argv[i];
- argc++;
} else {
argc = 1;
argv = para_malloc(2 * sizeof(char*));
}
argv[0] = make_message("%s_recv", r->name);
conf = r->parse_config(argc, argv);
- for (i = 0; i < argc; i++)
- free(argv[i]);
- free(argv);
+ free_argv(argv);
return conf;
}
}
/**
- * Free an array of words created by create_argv().
+ * Free an array of words created by create_argv() or create_shifted_argv().
*
* \param argv A pointer previously obtained by \ref create_argv().
*/
free(argv);
}
+static int create_argv_offset(int offset, const char *buf, const char *delim,
+ char ***result)
+{
+ char *word, **argv = para_malloc((offset + 1) * sizeof(char *));
+ const char *p;
+ int i, ret;
+
+ for (i = 0; i < offset; i++)
+ argv[i] = NULL;
+ for (p = buf; p && *p; p += ret, i++) {
+ ret = get_next_word(p, delim, &word);
+ if (ret < 0)
+ goto err;
+ if (!ret)
+ break;
+ argv = para_realloc(argv, (i + 2) * sizeof(char*));
+ argv[i] = word;
+ }
+ argv[i] = NULL;
+ *result = argv;
+ return i;
+err:
+ while (i > 0)
+ free(argv[--i]);
+ free(argv);
+ *result = NULL;
+ return ret;
+}
+
/**
* Split a buffer into words.
*
*/
int create_argv(const char *buf, const char *delim, char ***result)
{
- char *word, **argv = para_malloc(sizeof(char *));
- const char *p;
- int ret, num_words;
+ return create_argv_offset(0, buf, delim, result);
+}
- for (p = buf, num_words = 0; ; p += ret, num_words++) {
- ret = get_next_word(p, delim, &word);
- if (ret < 0)
- goto err;
- if (!ret)
- break;
- argv = para_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);
- *result = NULL;
- return ret;
+/**
+ * Split a buffer into words, offset one.
+ *
+ * This is similar to \ref create_argv() but the returned array is one element
+ * larger, words start at index one and element zero is initialized to \p NULL.
+ * Callers must set element zero to a non-NULL value before calling free_argv()
+ * on the returned array to avoid a memory leak.
+ *
+ * \param buf See \ref create_argv().
+ * \param delim See \ref create_argv().
+ * \param result See \ref create_argv().
+ *
+ * \return Number of words plus one on success, negative on errors.
+ */
+int create_shifted_argv(const char *buf, const char *delim, char ***result)
+{
+ return create_argv_offset(1, buf, delim, result);
}
/**
int get_loglevel_by_name(const char *txt);
int read_size_header(const char *buf);
int create_argv(const char *buf, const char *delim, char ***result);
+int create_shifted_argv(const char *buf, const char *delim, char ***result);
int find_arg(const char *arg, char **argv);
void free_argv(char **argv);
int para_regcomp(regex_t *preg, const char *regex, int cflags);