summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@tele2.at>2018-04-11 19:45:26 +0200
committerDavid Oberhollenzer <david.oberhollenzer@tele2.at>2018-04-11 19:45:26 +0200
commit6642b2b2bf3d16e0632989c1e29c672882e0d283 (patch)
treef39581ab909a41fe07c005cbb81f2ec273d057ea
parent71d98c150f6242fcf1b8a5845e46db56caad3885 (diff)
Don't pre-allocate argument vector for command lines
Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
-rw-r--r--initd/runlst.c23
-rw-r--r--lib/include/service.h4
-rw-r--r--lib/include/util.h12
-rw-r--r--lib/src/delsvc.c1
-rw-r--r--lib/src/rdsvc.c29
-rw-r--r--lib/src/split_argv.c22
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 <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
+#include <string.h>
#include <stdio.h>
#include <fcntl.h>
@@ -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
@@ -113,18 +113,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
with the name set to NULL.
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;
-}