diff options
-rw-r--r-- | ChangeLog.txt | 4 | ||||
-rw-r--r-- | guts/execl.c | 30 | ||||
-rw-r--r-- | guts/execle.c | 32 | ||||
-rw-r--r-- | guts/execlp.c | 30 | ||||
-rw-r--r-- | guts/execv.c | 15 | ||||
-rw-r--r-- | guts/execvp.c | 15 | ||||
-rwxr-xr-x | makewrappers | 47 | ||||
-rwxr-xr-x | run_tests.sh | 2 | ||||
-rwxr-xr-x | test/test-execl.sh | 21 | ||||
-rw-r--r-- | wrapfuncs.in | 5 |
10 files changed, 194 insertions, 7 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 1acac41..044afcb 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,7 @@ +2010-08-10: + * (mhatle) add execl, execle, execlp, execv, and execvp wrappers + * (seebs) handle ... for execl, etc. + 2010-08-06: * (mhatle) Fix an exec program with an empty environment diff --git a/guts/execl.c b/guts/execl.c new file mode 100644 index 0000000..92a4cdc --- /dev/null +++ b/guts/execl.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execl(const char *path, const char *arg, va_list ap) { + * int rc = -1; + */ + + size_t i = 0; + size_t alloc_size = 256; + const char **argv = malloc(sizeof (const char *) * alloc_size); + + argv[i++] = arg; + + while (argv[i-1]) { + argv[i++] = va_arg (ap, const char *); + if ( i > alloc_size - 1 ) { + alloc_size = alloc_size + 256; + argv = realloc(argv, sizeof (const char *) * alloc_size); + } + } + + rc = wrap_execv (path, (char *const *) argv); + + free (argv); + +/* return rc; + * } + */ diff --git a/guts/execle.c b/guts/execle.c new file mode 100644 index 0000000..f4c2ea7 --- /dev/null +++ b/guts/execle.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execle(const char *path, const char *arg, va_list ap) { + * int rc = -1; + */ + + size_t i = 0; + size_t alloc_size = 256; + const char **argv = malloc(sizeof (const char *) * alloc_size); + char *const *envp; + + argv[i++] = arg; + + while (argv[i-1]) { + argv[i++] = va_arg (ap, const char *); + if ( i > alloc_size - 1 ) { + alloc_size = alloc_size + 256; + argv = realloc(argv, sizeof (const char *) * alloc_size); + } + } + envp = va_arg (ap, char *const *); + + rc = wrap_execve (path, (char *const *) argv, envp); + + free (argv); + +/* return rc; + * } + */ diff --git a/guts/execlp.c b/guts/execlp.c new file mode 100644 index 0000000..8fd2cdf --- /dev/null +++ b/guts/execlp.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execlp(const char *file, const char *arg, va_list ap) { + * int rc = -1; + */ + + size_t i = 0; + size_t alloc_size = 256; + const char **argv = malloc(sizeof (const char *) * alloc_size); + + argv[i++] = arg; + + while (argv[i-1]) { + argv[i++] = va_arg (ap, const char *); + if ( i > alloc_size - 1 ) { + alloc_size = alloc_size + 256; + argv = realloc(argv, sizeof (const char *) * alloc_size); + } + } + + rc = wrap_execvp (file, (char *const *) argv); + + free (argv); + +/* return rc; + * } + */ diff --git a/guts/execv.c b/guts/execv.c new file mode 100644 index 0000000..3fec52a --- /dev/null +++ b/guts/execv.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execv(const char *path, char *const *argv) { + * int rc = -1; + */ + environ = pseudo_setupenv(environ, getenv("PSEUDO_OPTS")); + + rc = real_execv(path, argv); + +/* return rc; + * } + */ diff --git a/guts/execvp.c b/guts/execvp.c new file mode 100644 index 0000000..64e4b4b --- /dev/null +++ b/guts/execvp.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2008-2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execvp(const char *file, char *const *argv) { + * int rc = -1; + */ + environ = pseudo_setupenv(environ, getenv("PSEUDO_OPTS")); + + rc = real_execvp(file, argv); + +/* return rc; + * } + */ diff --git a/makewrappers b/makewrappers index c094a55..60e8938 100755 --- a/makewrappers +++ b/makewrappers @@ -97,7 +97,11 @@ do IFS=$save_IFS args='' dummy_args='' + wrap_args='' + va_list_abort_on_real='' optional_arg=false + make_va_list=false + maybe_va_end='' prepend='' depth=0 for arg @@ -138,9 +142,24 @@ do arg=${arg% } prepend='' case $arg in + ...) + make_va_list=true + maybe_va_end='va_end(ap);' + va_list_abort_on_real='assert(!"cannot chain to real versions of variadic functions");' + args="$args${args+, }..." + dummy_args="$dummy_args${dummy_args:+, }..." + wrap_args="$wrap_args${wrap_args:+, }va_list ap" + arg="..." + argname="ap" + argnames="$argnames${argnames:+, }ap" + wrapargnames="$wrapargnames${wrapargnames:+, }ap" + # used for creating a va_list + optional_prev=$prev_argname + ;; ...*) optional_arg=true args="$args${args:+, }..." + wrap_args="$wrap_args${wrap_args:+, }..." dummy_args="$dummy_args${dummy_args:+, }..." arg=`expr "$arg" : '\.\.\.{\(.*\)}'` argname=`expr "$arg" : '.*[^a-zA-Z0-9_]\([a-zA-Z0-9_]*\)$'` @@ -156,6 +175,7 @@ do *\(*) # function pointer argname=`expr "$arg" : '[^(]*(\*\([a-zA-Z0-9_]*\).*'` args="$args${args:+, }$arg" + wrap_args="$wrap_args${wrap_args:+, }$arg" dummy_args="$dummy_args${dummy_args:+, }$arg __attribute__((unused))" wrapargnames="$wrapargnames${wrapargnames:+, }$argname" argnames="$argnames${argnames:+, }$argname" @@ -164,6 +184,7 @@ do *) argname=`expr "$arg" : '.*[^a-zA-Z0-9_](*\([a-zA-Z0-9_]*\))*(*)*$'` args="$args${args:+, }$arg" + wrap_args="$wrap_args${wrap_args:+, }$arg" dummy_args="$dummy_args${dummy_args:+, }$arg __attribute__((unused))" # special handling for canonicalization # set this before changing path -> rpath, for guts files @@ -268,9 +289,16 @@ $type $name($args) { EOF fi + if $make_va_list; then + cat >&5 <<EOF + va_list ap; + va_start(ap, $optional_prev); +EOF + fi # and now the body of the wrapper: cat >&5 <<EOF sigset_t blocked, saved; + $(write_decl "$type" "rc" "$default_value") pseudo_debug(4, "called: $name\n"); /* these are signals for which the handlers often @@ -292,10 +320,14 @@ EOF } $decl_paths if (pseudo_populate_wrappers()) { - $(write_decl "$type" "rc" "$default_value") int save_errno; if (antimagic > 0) { if (real_$name) { + /* if this function takes ..., there is + * no way to pass the real argument list + * to it... + */ + $va_list_abort_on_real $(write_assign rc) (*real_$name)($argnames); } else { $(write_assign rc) dummy_$name($argnames); @@ -305,6 +337,7 @@ $alloc_paths $(write_assign rc) wrap_$name($argnames); $free_paths } + $maybe_va_end save_errno = errno; pseudo_droplock(); sigprocmask(SIG_SETMASK, &saved, NULL); @@ -315,7 +348,9 @@ $free_paths pseudo_droplock(); sigprocmask(SIG_SETMASK, &saved, NULL); pseudo_debug(4, "completed: $name\n"); - $(write_return "dummy_$name($argnames)"); + $(write_assign rc) dummy_$name($argnames); + $maybe_va_end + $(write_return rc); } } @@ -332,7 +367,7 @@ EOF if $optional_arg; then cat >&5 << EOF static $type -wrap_$name($args) { +wrap_$name($wrap_args) { $(write_decl "$type" "rc" "$default_value") $optional_decl; @@ -349,7 +384,7 @@ EOF else cat >&5 << EOF static $type -wrap_$name($args) { +wrap_$name($wrap_args) { $(write_decl "$type" "rc" "$default_value") #include "$guts" @@ -385,7 +420,7 @@ EOF * guts/COPYRIGHT for information. * * static $type - * wrap_$name($args) { + * wrap_$name($wrap_args) { * $(write_decl "$type" "rc" "$default_value") */ @@ -401,7 +436,7 @@ EOF cat >&6 <<EOF /* $type $name($args); */ static $type dummy_$name($args); -static $type wrap_$name($args); +static $type wrap_$name($wrap_args); static $type (*real_$name)($args); EOF diff --git a/run_tests.sh b/run_tests.sh index 9228668..0eced9f 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -42,7 +42,7 @@ do else echo "${filename/%.sh}: Failed." fi - rm -rf var + rm -rf var/pseudo/* done echo "${num_passed_tests}/${num_tests} test(s) passed." diff --git a/test/test-execl.sh b/test/test-execl.sh new file mode 100755 index 0000000..1a1c580 --- /dev/null +++ b/test/test-execl.sh @@ -0,0 +1,21 @@ +#!/bin/bash +cat > execl_test.c << EOF +#include <unistd.h> +int main() { + return execl("/usr/bin/env", "/usr/bin/env", "A=A", "B=B", "C=C", NULL); +} +EOF + +gcc -o execl_test execl_test.c + +./execl_test | grep -q "C=C" + +if [ "$?" = "0" ] +then + #echo "Passed." + rm -f execl_test execl_test.c + exit 0 +fi +#echo "Failed" +rm -f execl_test execl_test.c +exit 1 diff --git a/wrapfuncs.in b/wrapfuncs.in index 95bb8b9..40c86eb 100644 --- a/wrapfuncs.in +++ b/wrapfuncs.in @@ -88,7 +88,12 @@ char *tmpnam(char *s); int truncate(const char *path, off_t length); int utime(const char *path, const struct utimbuf *buf); int utimes(const char *path, const struct timeval *times); +int execl(const char *path, const char *arg, ...); +int execlp(const char *file, const char *arg, ...); +int execle(const char *path, const char *arg, ...); +int execv(const char *path, char *const *argv); int execve(const char *filename, char *const *argv, char *const *envp); +int execvp(const char *file, char *const *argv); # for emulation of passwd utilities struct passwd *getpwnam(const char *name); struct passwd *getpwuid(uid_t uid); |