aboutsummaryrefslogtreecommitdiffstats
path: root/pseudo_wrappers.c
diff options
context:
space:
mode:
Diffstat (limited to 'pseudo_wrappers.c')
-rw-r--r--pseudo_wrappers.c464
1 files changed, 34 insertions, 430 deletions
diff --git a/pseudo_wrappers.c b/pseudo_wrappers.c
index 470206a..dd4a800 100644
--- a/pseudo_wrappers.c
+++ b/pseudo_wrappers.c
@@ -1,5 +1,21 @@
-/* wrapper code -- this is the shared code used around the pseduo
- * wrapper functions, which are in pseudo_wrapfuncs.c.
+/*
+ * pseudo_wrappers.c, shared code for wrapper functions
+ *
+ * Copyright (c) 2008-2011 Wind River Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the Lesser GNU General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Lesser GNU General Public License for more details.
+ *
+ * You should have received a copy of the Lesser GNU General Public License
+ * version 2.1 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
*/
#include <assert.h>
#include <stdlib.h>
@@ -91,12 +107,22 @@ pseudo_init_wrappers(void) {
char *e;
dlerror();
f = dlsym(RTLD_NEXT, pseudo_functions[i].name);
- if ((e = dlerror()) != NULL) {
- /* leave it NULL, which our implementation checks for */
- pseudo_diag("No wrapper for %s: %s\n", pseudo_functions[i].name, e);
+ if (f) {
+ *pseudo_functions[i].real = f;
} else {
- if (f)
- *pseudo_functions[i].real = f;
+ e = dlerror();
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ char *s = pseudo_functions[i].name;
+ s += strlen(s) - 2;
+ /* *at() don't have to exist */
+ if (!strcmp(s, "at")) {
+ continue;
+ }
+#else
+ if (e != NULL) {
+ pseudo_diag("No real function for %s: %s\n", pseudo_functions[i].name, e);
+ }
+#endif
}
}
}
@@ -210,426 +236,4 @@ pseudo_check_wrappers(void) {
return _libpseudo_initted;
}
-static char **
-execl_to_v(va_list ap, const char *argv0, char *const **envp) {
- size_t i = 0;
- size_t alloc_size = 256;
-
- char **argv = malloc((sizeof *argv) * alloc_size);
-
- if (!argv) {
- pseudo_debug(1, "execl failed: couldn't allocate memory for %lu arguments\n",
- (unsigned long) alloc_size);
- return NULL;
- }
- argv[i++] = (char *) argv0;
-
- while (argv[i-1]) {
- argv[i++] = va_arg(ap, char *const);
- if (i > alloc_size - 1) {
- alloc_size = alloc_size + 256;
- argv = realloc(argv, (sizeof *argv) * alloc_size);
- if (!argv) {
- pseudo_debug(1, "execl failed: couldn't allocate memory for %lu arguments\n",
- (unsigned long) alloc_size);
- return NULL;
- }
- }
- }
- if (envp) {
- *envp = va_arg(ap, char **);
- }
- return argv;
-}
-
-/* The following wrappers require Special Handling */
-
-int
-execl(const char *file, const char *arg, ...) {
- sigset_t saved;
- va_list ap;
- char **argv;
-
- int rc = -1;
-
- if (!pseudo_check_wrappers()) {
- /* rc was initialized to the "failure" value */
- pseudo_enosys("execl");
- return rc;
- }
-
- va_start(ap, arg);
- argv = execl_to_v(ap, arg, 0);
- va_end(ap);
- if (!argv) {
- errno = ENOMEM;
- return -1;
- }
-
- pseudo_debug(4, "called: execl\n");
- pseudo_sigblock(&saved);
- if (pseudo_getlock()) {
- errno = EBUSY;
- sigprocmask(SIG_SETMASK, &saved, NULL);
- return -1;
- }
-
- int save_errno;
-
- /* exec*() use this to restore the sig mask */
- pseudo_saved_sigmask = saved;
- rc = wrap_execv(file, argv);
-
- save_errno = errno;
- pseudo_droplock();
- sigprocmask(SIG_SETMASK, &saved, NULL);
- pseudo_debug(4, "completed: execl\n");
- errno = save_errno;
- free(argv);
- return rc;
-}
-
-int
-execlp(const char *file, const char *arg, ...) {
- sigset_t saved;
- va_list ap;
- char **argv;
-
- int rc = -1;
-
- if (!pseudo_check_wrappers()) {
- /* rc was initialized to the "failure" value */
- pseudo_enosys("execlp");
- return rc;
- }
-
- va_start(ap, arg);
- argv = execl_to_v(ap, arg, 0);
- va_end(ap);
- if (!argv) {
- errno = ENOMEM;
- return -1;
- }
-
- pseudo_debug(4, "called: execlp\n");
- pseudo_sigblock(&saved);
- if (pseudo_getlock()) {
- errno = EBUSY;
- sigprocmask(SIG_SETMASK, &saved, NULL);
- return -1;
- }
-
- int save_errno;
-
- /* exec*() use this to restore the sig mask */
- pseudo_saved_sigmask = saved;
- rc = wrap_execvp(file, argv);
-
- save_errno = errno;
- pseudo_droplock();
- sigprocmask(SIG_SETMASK, &saved, NULL);
- pseudo_debug(4, "completed: execlp\n");
- errno = save_errno;
- free(argv);
- return rc;
-}
-
-int
-execle(const char *file, const char *arg, ...) {
- sigset_t saved;
- va_list ap;
- char **argv;
- char **envp;
-
- int rc = -1;
-
- if (!pseudo_check_wrappers()) {
- /* rc was initialized to the "failure" value */
- pseudo_enosys("execle");
- return rc;
- }
-
- va_start(ap, arg);
- argv = execl_to_v(ap, arg, (char *const **)&envp);
- va_end(ap);
- if (!argv) {
- errno = ENOMEM;
- return -1;
- }
-
- pseudo_debug(4, "called: execle\n");
- pseudo_sigblock(&saved);
- if (pseudo_getlock()) {
- errno = EBUSY;
- sigprocmask(SIG_SETMASK, &saved, NULL);
- return -1;
- }
-
- int save_errno;
-
- /* exec*() use this to restore the sig mask */
- pseudo_saved_sigmask = saved;
- rc = wrap_execve(file, argv, envp);
-
- save_errno = errno;
- pseudo_droplock();
- sigprocmask(SIG_SETMASK, &saved, NULL);
- pseudo_debug(4, "completed: execle\n");
- errno = save_errno;
- free(argv);
- return rc;
-}
-
-int
-execv(const char *file, char *const *argv) {
- sigset_t saved;
-
- int rc = -1;
-
- if (!pseudo_check_wrappers() || !real_execv) {
- /* rc was initialized to the "failure" value */
- pseudo_enosys("execv");
- return rc;
- }
-
- pseudo_debug(4, "called: execv\n");
- pseudo_sigblock(&saved);
- if (pseudo_getlock()) {
- errno = EBUSY;
- sigprocmask(SIG_SETMASK, &saved, NULL);
- return -1;
- }
-
- int save_errno;
-
- /* exec*() use this to restore the sig mask */
- pseudo_saved_sigmask = saved;
- rc = wrap_execv(file, argv);
-
- save_errno = errno;
- pseudo_droplock();
- sigprocmask(SIG_SETMASK, &saved, NULL);
- pseudo_debug(4, "completed: execv\n");
- errno = save_errno;
- return rc;
-}
-
-int
-execve(const char *file, char *const *argv, char *const *envp) {
- sigset_t saved;
-
- int rc = -1;
-
- if (!pseudo_check_wrappers() || !real_execve) {
- /* rc was initialized to the "failure" value */
- pseudo_enosys("execve");
- return rc;
- }
-
- pseudo_debug(4, "called: execve\n");
- pseudo_sigblock(&saved);
- if (pseudo_getlock()) {
- errno = EBUSY;
- sigprocmask(SIG_SETMASK, &saved, NULL);
- return -1;
- }
-
- int save_errno;
-
- /* exec*() use this to restore the sig mask */
- pseudo_saved_sigmask = saved;
- rc = wrap_execve(file, argv, envp);
-
- save_errno = errno;
- pseudo_droplock();
- sigprocmask(SIG_SETMASK, &saved, NULL);
- pseudo_debug(4, "completed: execve\n");
- errno = save_errno;
- return rc;
-}
-
-int
-execvp(const char *file, char *const *argv) {
- sigset_t saved;
-
- int rc = -1;
-
- if (!pseudo_check_wrappers() || !real_execvp) {
- /* rc was initialized to the "failure" value */
- pseudo_enosys("execvp");
- return rc;
- }
-
- pseudo_debug(4, "called: execvp\n");
- pseudo_sigblock(&saved);
- if (pseudo_getlock()) {
- errno = EBUSY;
- sigprocmask(SIG_SETMASK, &saved, NULL);
- return -1;
- }
-
- int save_errno;
-
- /* exec*() use this to restore the sig mask */
- pseudo_saved_sigmask = saved;
- rc = wrap_execvp(file, argv);
-
- save_errno = errno;
- pseudo_droplock();
- sigprocmask(SIG_SETMASK, &saved, NULL);
- pseudo_debug(4, "completed: execvp\n");
- errno = save_errno;
- return rc;
-}
-
-int
-fork(void) {
- sigset_t saved;
-
- int rc = -1;
-
- if (!pseudo_check_wrappers() || !real_fork) {
- /* rc was initialized to the "failure" value */
- pseudo_enosys("fork");
- return rc;
- }
-
- pseudo_debug(4, "called: fork\n");
- pseudo_sigblock(&saved);
- if (pseudo_getlock()) {
- errno = EBUSY;
- sigprocmask(SIG_SETMASK, &saved, NULL);
- return -1;
- }
-
- int save_errno;
-
- rc = wrap_fork();
-
- save_errno = errno;
-
- pseudo_droplock();
- sigprocmask(SIG_SETMASK, &saved, NULL);
- pseudo_debug(4, "completed: fork\n");
- errno = save_errno;
- return rc;
-}
-
-int
-vfork(void) {
- /* we don't provide support for the distinct semantics
- * of vfork()
- */
- return fork();
-}
-
-int
-clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) {
- sigset_t saved;
- va_list ap;
- pid_t *pid;
- struct user_desc *tls;
- pid_t *ctid;
-
- int rc = -1;
-
- if (!pseudo_check_wrappers() || !real_clone) {
- /* rc was initialized to the "failure" value */
- pseudo_enosys("clone");
- return rc;
- }
-
- va_start(ap, arg);
- pid = va_arg(ap, pid_t *);
- tls = va_arg(ap, struct user_desc *);
- ctid = va_arg(ap, pid_t *);
- va_end(ap);
-
- pseudo_debug(4, "called: clone\n");
- pseudo_sigblock(&saved);
- if (pseudo_getlock()) {
- errno = EBUSY;
- sigprocmask(SIG_SETMASK, &saved, NULL);
- return -1;
- }
-
- int save_errno;
- int save_disabled = pseudo_disabled;
- /* because clone() doesn't actually continue in this function, we
- * can't check the return and fix up environment variables in the
- * child. Instead, we have to temporarily do any fixup, then possibly
- * undo it later. UGH!
- */
-
-#include "guts/clone.c"
-
- if (save_disabled != pseudo_disabled) {
- if (pseudo_disabled) {
- pseudo_disabled = 0;
- pseudo_magic();
- } else {
- pseudo_disabled = 1;
- pseudo_antimagic();
- }
- }
-
- save_errno = errno;
- pseudo_droplock();
- sigprocmask(SIG_SETMASK, &saved, NULL);
- pseudo_debug(4, "completed: clone\n");
- errno = save_errno;
- return rc;
-}
-
-#if 0
-static int (*real_execlp)(const char *file, const char *arg, ...) = NULL;
-static int (*real_execl)(const char *file, const char *arg, ...) = NULL;
-static int (*real_execle)(const char *file, const char *arg, ...) = NULL;
-#endif
-static int (*real_execv)(const char *file, char *const *argv) = NULL;
-static int (*real_execve)(const char *file, char *const *argv, char *const *envp) = NULL;
-static int (*real_execvp)(const char *file, char *const *argv) = NULL;
-static int (*real_fork)(void) = NULL;
-static int (*real_clone)(int (*)(void *), void *, int, void *, ...) = NULL;
-
-static int
-wrap_execv(const char *file, char *const *argv) {
- int rc = -1;
-
-#include "guts/execv.c"
-
- return rc;
-}
-
-static int
-wrap_execve(const char *file, char *const *argv, char *const *envp) {
- int rc = -1;
-
-#include "guts/execve.c"
-
- return rc;
-}
-
-static int
-wrap_execvp(const char *file, char *const *argv) {
- int rc = -1;
-
-#include "guts/execvp.c"
-
- return rc;
-}
-
-static int
-wrap_fork(void) {
- int rc = -1;
-
-#include "guts/fork.c"
-
- return rc;
-}
-
-int
-wrap_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) {
- /* unused */
- return 0;
-}
+#include "port_wrappers.c"