aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);