aboutsummaryrefslogtreecommitdiffstats
path: root/pseudo_wrappers.c
diff options
context:
space:
mode:
authorPeter Seebach <peter.seebach@windriver.com>2011-03-25 12:38:43 -0500
committerPeter Seebach <peter.seebach@windriver.com>2011-03-25 12:38:43 -0500
commit29e8b8a4cd8f7383c3d851b6255272f1c2a5d286 (patch)
treec9619032a670d06124ef45c392484f4a04f7d0f0 /pseudo_wrappers.c
parent96d8e7ce8b483e5cafd0449b9735e4714f41f20b (diff)
downloadpseudo-29e8b8a4cd8f7383c3d851b6255272f1c2a5d286.tar.gz
pseudo-29e8b8a4cd8f7383c3d851b6255272f1c2a5d286.tar.bz2
pseudo-29e8b8a4cd8f7383c3d851b6255272f1c2a5d286.zip
Merge in ports work
This is a spiffied-up rebase of a bunch of intermediate changes, presented as a whole because it is, surprisingly, less confusing that way. The basic idea is to separate the guts code into categories ranging from generic stuff that can be the same everywhere and specific variants. The big scary one is the Darwin support, which actually seems to run okay on 64-bit OS X 10.6. (No other variants were tested.) The other example given is support for the old clone() syscall on RHEL 4, which affects some wrlinux use cases. There's a few minor cleanup bits here, such as a function with inconsistent calling conventions, but nothing really exciting.
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"