From 6642b2b2bf3d16e0632989c1e29c672882e0d283 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Wed, 11 Apr 2018 19:45:26 +0200 Subject: Don't pre-allocate argument vector for command lines Signed-off-by: David Oberhollenzer --- initd/runlst.c | 23 +++++++++++++++++------ lib/include/service.h | 4 ++-- lib/include/util.h | 12 ------------ lib/src/delsvc.c | 1 - lib/src/rdsvc.c | 29 +++++------------------------ lib/src/split_argv.c | 22 ---------------------- 6 files changed, 24 insertions(+), 67 deletions(-) diff --git a/initd/runlst.c b/initd/runlst.c index 7840aff..933daeb 100644 --- a/initd/runlst.c +++ b/initd/runlst.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,20 @@ static int child_setup(const char *ctty) return 0; } +static NORETURN void argv_exec(exec_t *e) +{ + char **argv = alloca(e->argc + 1), *ptr; + int i; + + for (ptr = e->args, i = 0; i < e->argc; ++i, ptr += strlen(ptr) + 1) + argv[i] = ptr; + + argv[i] = NULL; + execve(argv[0], argv, environ); + perror(argv[0]); + exit(EXIT_FAILURE); +} + int runlst_wait(exec_t *list, const char *ctty) { pid_t ret, pid; @@ -66,9 +81,7 @@ int runlst_wait(exec_t *list, const char *ctty) if (pid == 0) { if (child_setup(ctty)) exit(EXIT_FAILURE); - execve(list->argv[0], list->argv, environ); - perror(list->argv[0]); - exit(EXIT_FAILURE); + argv_exec(list); } if (pid == -1) { @@ -101,9 +114,7 @@ pid_t runlst(exec_t *list, const char *ctty) if (list->next != NULL) exit(runlst_wait(list, NULL)); - execve(list->argv[0], list->argv, environ); - perror(list->argv[0]); - exit(EXIT_FAILURE); + argv_exec(list); } if (pid == -1) diff --git a/lib/include/service.h b/lib/include/service.h index 471ccbb..595c60e 100644 --- a/lib/include/service.h +++ b/lib/include/service.h @@ -46,8 +46,8 @@ enum { typedef struct exec_t { struct exec_t *next; - char **argv; /* NULL terminated argument vector */ - char buffer[]; /* backing store for argv */ + int argc; /* number of elements in argument vector */ + char args[]; /* argument vectot string blob */ } exec_t; typedef struct service_t { diff --git a/lib/include/util.h b/lib/include/util.h index d824b22..d6b68f1 100644 --- a/lib/include/util.h +++ b/lib/include/util.h @@ -112,18 +112,6 @@ int unescape(char *src); */ int pack_argv(char *str); -/* - Split a space seperated string into a sequence of null-terminated - strings. Return a NULL terminated array of strings pointing to the - start of each sub string. - - It basically runs pack_argv on 'str' and then constructs the argv - vector from that, with each entry pointing into 'str'. - - The returned array must be freed with free(). -*/ -char **split_argv(char *str); - /* Search through an array of enum_map_t entries to resolve a string to a numeric value. The end of the map is indicated by a sentinel entry diff --git a/lib/src/delsvc.c b/lib/src/delsvc.c index f4f9c76..fd10cfe 100644 --- a/lib/src/delsvc.c +++ b/lib/src/delsvc.c @@ -30,7 +30,6 @@ void delsvc(service_t *svc) e = svc->exec; svc->exec = e->next; - free(e->argv); free(e); } diff --git a/lib/src/rdsvc.c b/lib/src/rdsvc.c index c8ba590..1a8cf7e 100644 --- a/lib/src/rdsvc.c +++ b/lib/src/rdsvc.c @@ -38,26 +38,6 @@ static int try_unescape(char *arg, rdline_t *rd) return 0; } -static char **try_split_argv(char *str, rdline_t *rd) -{ - char **argv = split_argv(str); - - if (argv == NULL) { - switch (errno) { - case EINVAL: - fprintf(stderr, "%s: %zu: malformed string constant\n", - rd->filename, rd->lineno); - break; - default: - fprintf(stderr, "%s: %zu: %s\n", - rd->filename, rd->lineno, strerror(errno)); - break; - } - } - - return argv; -} - static char *try_strdup(const char *str, rdline_t *rd) { char *out = strdup(str); @@ -96,11 +76,12 @@ static int svc_exec(service_t *svc, char *arg, rdline_t *rd) return -1; } - strcpy(e->buffer, arg); + strcpy(e->args, arg); - e->argv = try_split_argv(e->buffer, rd); - if (e->argv == NULL) { - free(e); + e->argc = pack_argv(e->args); + if (e->argc < 0) { + fprintf(stderr, "%s: %zu: malformed string constant\n", + rd->filename, rd->lineno); return -1; } diff --git a/lib/src/split_argv.c b/lib/src/split_argv.c index b95720d..5930e2d 100644 --- a/lib/src/split_argv.c +++ b/lib/src/split_argv.c @@ -80,25 +80,3 @@ fail_str: errno = EINVAL; return -1; } - -char **split_argv(char *str) -{ - char **argv = NULL; - int i, count; - - count = pack_argv(str); - if (count <= 0) - return NULL; - - argv = malloc(sizeof(argv[0]) * (count + 1)); - if (argv == NULL) - return NULL; - - for (i = 0; i < count; ++i) { - argv[i] = str; - str += strlen(str) + 1; - } - - argv[i] = NULL; - return argv; -} -- cgit v1.2.3