in reply to mocking or trapping system calls

I don't think there's a pure Perl solution... However, you could try to intercept the underlying execvp library function call (at least on unix-ish systems — I think Windows uses spawn). Then, in your wrapper function you could decide what to do, e.g. return fake results, or just pass through to the real function...  I know this is highly platform dependent, ugly and probably otherwise tricky in a number of ways... but anyhow, these would be the basic steps — just to illustrate the idea... (quite a number of issues remain to be solved!)

Demo perl program

#!/usr/bin/perl system "/bin/echo", "hello"; # or # system "/bin/echo hello"; # or # my $out = `/bin/echo hello`;

This is the sample wrapper library, which does nothing except printing a message to stderr, and then forwarding the call to the original library function:

/* fakesys.c */ #include <unistd.h> /* for execvp */ #include <dlfcn.h> /* for dlsym */ #include <stdio.h> static int (*real_execvp)(const char *file, char *const argv[]); int execvp(const char *file, char *const argv[]) { char *msg; /* lookup original shared lib function */ real_execvp = dlsym(RTLD_NEXT, "execvp"); /* see dlsym(3) */ if ( (msg = dlerror() ) != NULL ) { fprintf(stderr, "dlopen of execvp() failed : %s\n", msg); } fprintf(stderr, "calling execvp(\"%s\", ...)\n", file); /* execute original lib function */ return real_execvp(file, argv); }

Compile a shared lib (on Linux):

$ gcc -D_GNU_SOURCE -fPIC -shared fakesys.c -o libfakesys.so

and call the program with the intercepted execvp call, using the LD_PRELOAD mechanism (—> "man ld-linux.so"):

$ LD_PRELOAD=./libfakesys.so perl ./685699.pl

Output:

calling execvp("/bin/echo", ...) hello

You get the idea... :)

Replies are listed 'Best First'.
Re^2: mocking or trapping system calls
by Anonymous Monk on May 10, 2008 at 19:44 UTC

    spawn() is just a wrapper for DOS compatibility. There are WinExec, ShellExecute, ShellExecuteEx, CreateProcess, CreateProcessEx, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW, and perhaps another dozen of functions and wrappers for creating a process in different ways, and with ridiculusly complicated data structures for input and output parameters. It's just pain once you understand how simple and elegant fork() and exec() are. Hooking those Windows functions may be possible, some have documented hook functions, others don't.

    On Unix (Linux), the fakeroot package (a Debian project) may help, perhaps combined with chroot. chroot the entire script collection in a root jail, then run perl as unprivileged user via fakeroot. While everything seems to be a "real" root environment, it isn't. All files belong the unprivileged user, and if they don't, the faked root simply can't open/read/modify/delete them -- unless you give explicit permissions to the unprivileged user. And thanks to chroot, a rm -rf / "just" damages the root jail, which can be restored with a simple tar xf.

    Alexander