#include <dlfcn.h>
#include <unistd.h>
#include <stdio.h>
+#include <signal.h>
+#include "usterr.h"
+
+extern void ust_fork(void);
+extern void ust_potential_exec(void);
pid_t fork(void)
{
pid_t retval;
+ int result;
+ sigset_t all_sigs;
+ sigset_t orig_sigs;
+
if(plibc_func == NULL) {
plibc_func = dlsym(RTLD_NEXT, "fork");
if(plibc_func == NULL) {
fprintf(stderr, "libcwrap: unable to find fork\n");
- return NULL;
+ return -1;
}
}
+ /* Disable interrupts. This is to avoid that the child
+ * intervenes before it is properly setup for tracing. It is
+ * safer to disable all signals, because then we know we are not
+ * breaking anything by restoring the original mask.
+ */
+
+ /* FIXME:
+ - only do this if tracing is active
+ */
+
+ /* Disable signals */
+ sigfillset(&all_sigs);
+ result = sigprocmask(SIG_BLOCK, &all_sigs, &orig_sigs);
+ if(result == -1) {
+ PERROR("sigprocmask");
+ return -1;
+ }
+
+ /* Do the real fork */
retval = plibc_func();
- if(retval == 0)
+ if(retval == 0) {
+ /* child */
ust_fork();
+ }
+
+ /* Restore signals */
+ result = sigprocmask(SIG_BLOCK, &orig_sigs, NULL);
+ if(result == -1) {
+ PERROR("sigprocmask");
+ return -1;
+ }
+
+ return retval;
+}
+
+int execve(const char *filename, char *const argv[], char *const envp[])
+{
+ static int (*plibc_func)(const char *filename, char *const argv[], char *const envp[]) = NULL;
+
+ pid_t retval;
+
+ if(plibc_func == NULL) {
+ plibc_func = dlsym(RTLD_NEXT, "execve");
+ if(plibc_func == NULL) {
+ fprintf(stderr, "libcwrap: unable to find execve\n");
+ return -1;
+ }
+ }
+
+ ust_potential_exec();
+
+ retval = plibc_func(filename, argv, envp);
return retval;
}