mirror of
https://github.com/pygos/init.git
synced 2024-11-14 15:57:10 +01:00
Don't pre-allocate argument vector for command lines
Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
This commit is contained in:
parent
71d98c150f
commit
6642b2b2bf
6 changed files with 24 additions and 67 deletions
|
@ -18,6 +18,7 @@
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
@ -55,6 +56,20 @@ static int child_setup(const char *ctty)
|
||||||
return 0;
|
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)
|
int runlst_wait(exec_t *list, const char *ctty)
|
||||||
{
|
{
|
||||||
pid_t ret, pid;
|
pid_t ret, pid;
|
||||||
|
@ -66,9 +81,7 @@ int runlst_wait(exec_t *list, const char *ctty)
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
if (child_setup(ctty))
|
if (child_setup(ctty))
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
execve(list->argv[0], list->argv, environ);
|
argv_exec(list);
|
||||||
perror(list->argv[0]);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
|
@ -101,9 +114,7 @@ pid_t runlst(exec_t *list, const char *ctty)
|
||||||
if (list->next != NULL)
|
if (list->next != NULL)
|
||||||
exit(runlst_wait(list, NULL));
|
exit(runlst_wait(list, NULL));
|
||||||
|
|
||||||
execve(list->argv[0], list->argv, environ);
|
argv_exec(list);
|
||||||
perror(list->argv[0]);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
|
|
|
@ -46,8 +46,8 @@ enum {
|
||||||
|
|
||||||
typedef struct exec_t {
|
typedef struct exec_t {
|
||||||
struct exec_t *next;
|
struct exec_t *next;
|
||||||
char **argv; /* NULL terminated argument vector */
|
int argc; /* number of elements in argument vector */
|
||||||
char buffer[]; /* backing store for argv */
|
char args[]; /* argument vectot string blob */
|
||||||
} exec_t;
|
} exec_t;
|
||||||
|
|
||||||
typedef struct service_t {
|
typedef struct service_t {
|
||||||
|
|
|
@ -112,18 +112,6 @@ int unescape(char *src);
|
||||||
*/
|
*/
|
||||||
int pack_argv(char *str);
|
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
|
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
|
a numeric value. The end of the map is indicated by a sentinel entry
|
||||||
|
|
|
@ -30,7 +30,6 @@ void delsvc(service_t *svc)
|
||||||
e = svc->exec;
|
e = svc->exec;
|
||||||
svc->exec = e->next;
|
svc->exec = e->next;
|
||||||
|
|
||||||
free(e->argv);
|
|
||||||
free(e);
|
free(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,26 +38,6 @@ static int try_unescape(char *arg, rdline_t *rd)
|
||||||
return 0;
|
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)
|
static char *try_strdup(const char *str, rdline_t *rd)
|
||||||
{
|
{
|
||||||
char *out = strdup(str);
|
char *out = strdup(str);
|
||||||
|
@ -96,11 +76,12 @@ static int svc_exec(service_t *svc, char *arg, rdline_t *rd)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(e->buffer, arg);
|
strcpy(e->args, arg);
|
||||||
|
|
||||||
e->argv = try_split_argv(e->buffer, rd);
|
e->argc = pack_argv(e->args);
|
||||||
if (e->argv == NULL) {
|
if (e->argc < 0) {
|
||||||
free(e);
|
fprintf(stderr, "%s: %zu: malformed string constant\n",
|
||||||
|
rd->filename, rd->lineno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,25 +80,3 @@ fail_str:
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
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;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue