Introduce create_shifted_argv().
authorAndre Noll <maan@systemlinux.org>
Sun, 29 Jul 2012 16:39:58 +0000 (18:39 +0200)
committerAndre Noll <maan@systemlinux.org>
Mon, 27 Aug 2012 11:01:07 +0000 (13:01 +0200)
In order to create argument vectors for the gengetopt parsers,
filter_common.c and recv_common.c call create_argv() on the given
--filter or --receiver option, then shift the returned array by one
to the right because gengetopt expects the program name in argv[0].

This commit creates a new helper function for this purpose and changes
the two callers to use the new function.

filter_common.c
recv_common.c
string.c
string.h

index ffb2199..0d3377b 100644 (file)
@@ -41,25 +41,16 @@ void filter_init(void)
 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;
 }
index 4f157ab..7d7d2b0 100644 (file)
@@ -33,20 +33,13 @@ static void *parse_receiver_args(int receiver_num, char *options)
 {
        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*));
@@ -54,9 +47,7 @@ static void *parse_receiver_args(int receiver_num, char *options)
        }
        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;
 }
 
index a727f2a..283c46e 100644 (file)
--- a/string.c
+++ b/string.c
@@ -800,7 +800,7 @@ int compute_word_num(const char *buf, const char *delim, int point)
 }
 
 /**
- * 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().
  */
@@ -815,6 +815,35 @@ void free_argv(char **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.
  *
@@ -831,28 +860,26 @@ void free_argv(char **argv)
  */
 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);
 }
 
 /**
index aebb651..cf02d97 100644 (file)
--- a/string.h
+++ b/string.h
@@ -83,6 +83,7 @@ int para_atoi32(const char *str, int32_t *value);
 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);