diff options
Diffstat (limited to 'ports/linux/newclone')
-rw-r--r-- | ports/linux/newclone/guts/clone.c | 27 | ||||
-rw-r--r-- | ports/linux/newclone/pseudo_wrappers.c | 69 | ||||
-rw-r--r-- | ports/linux/newclone/wrapfuncs.in | 1 |
3 files changed, 97 insertions, 0 deletions
diff --git a/ports/linux/newclone/guts/clone.c b/ports/linux/newclone/guts/clone.c new file mode 100644 index 0000000..b3400c7 --- /dev/null +++ b/ports/linux/newclone/guts/clone.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2008-2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * clone(...) { + * .... + */ + /* 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! + */ + pseudo_debug(1, "client resetting for clone(2) call\n"); + if (!pseudo_get_value("PSEUDO_RELOADED")) { + pseudo_setupenv(); + pseudo_reinit_libpseudo(); + } else { + pseudo_setupenv(); + pseudo_dropenv(); + } + /* call the real syscall */ + rc = (*real_clone)(fn, child_stack, flags, arg, pid, tls, ctid); +/* ... + * return rc; + * } + */ diff --git a/ports/linux/newclone/pseudo_wrappers.c b/ports/linux/newclone/pseudo_wrappers.c new file mode 100644 index 0000000..dd44408 --- /dev/null +++ b/ports/linux/newclone/pseudo_wrappers.c @@ -0,0 +1,69 @@ +static int +wrap_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, va_list +ap) { + /* unused */ + (void) fn; + (void) child_stack; + (void) flags; + (void) arg; + (void) ap; + return 0; +} + +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; +} diff --git a/ports/linux/newclone/wrapfuncs.in b/ports/linux/newclone/wrapfuncs.in new file mode 100644 index 0000000..8849310 --- /dev/null +++ b/ports/linux/newclone/wrapfuncs.in @@ -0,0 +1 @@ +int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...); /* hand_wrapped=1 */ |