aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Hatle <mark.hatle@windriver.com>2010-08-09 15:19:41 -0500
committerPeter Seebach <seebs@laptop-seebs-net.local>2010-08-11 14:37:59 -0500
commita3075407e06a000a931874af57c33341b6a13da9 (patch)
tree14c7e28fde0dafa022396b90645f44a1f37bb306
parent34dce532d23326be07dd9824159f341223814ba2 (diff)
downloadpseudo-a3075407e06a000a931874af57c33341b6a13da9.tar.gz
pseudo-a3075407e06a000a931874af57c33341b6a13da9.tar.bz2
pseudo-a3075407e06a000a931874af57c33341b6a13da9.zip
Enable execl, execle, execlp, execv, and execvp wrappers
We wrap all of the execs so that we can ensure the environment is properly configured prior to the exec running. handle ... for the new execl* wrappers Add a test for the new execl* ... handling.
-rw-r--r--ChangeLog.txt4
-rw-r--r--guts/execl.c30
-rw-r--r--guts/execle.c32
-rw-r--r--guts/execlp.c30
-rw-r--r--guts/execv.c15
-rw-r--r--guts/execvp.c15
-rwxr-xr-xmakewrappers47
-rwxr-xr-xrun_tests.sh2
-rwxr-xr-xtest/test-execl.sh21
-rw-r--r--wrapfuncs.in5
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);