diff options
Diffstat (limited to 'pseudo_wrappers.c')
-rw-r--r-- | pseudo_wrappers.c | 464 |
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" |