wait_for_something.c -> sysdeps/linux-gnu/events.c
diff --git a/sysdeps/linux-gnu/events.c b/sysdeps/linux-gnu/events.c
new file mode 100644
index 0000000..afe6a96
--- /dev/null
+++ b/sysdeps/linux-gnu/events.c
@@ -0,0 +1,152 @@
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define _GNU_SOURCE 1
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+
+#include "ltrace.h"
+#include "options.h"
+#include "debug.h"
+
+static struct event event;
+
+struct event *
+next_event(void) {
+ pid_t pid;
+ int status;
+ int tmp;
+ int stop_signal;
+
+ if (!list_of_processes) {
+ debug(1, "No more children");
+ exit(0);
+ }
+ pid = wait(&status);
+ if (pid == -1) {
+ if (errno == ECHILD) {
+ debug(1, "No more children");
+ exit(0);
+ } else if (errno == EINTR) {
+ debug(1, "wait received EINTR ?");
+ event.thing = EVENT_NONE;
+ return &event;
+ }
+ perror("wait");
+ exit(1);
+ }
+ event.proc = pid2proc(pid);
+ if (!event.proc) {
+ fprintf(stderr, "signal from wrong pid %u ?!?\n", pid);
+ exit(1);
+ }
+ get_arch_dep(event.proc);
+ event.proc->instruction_pointer = NULL;
+ debug(3, "signal from pid %u", pid);
+ if (event.proc->breakpoints_enabled == -1) {
+ enable_all_breakpoints(event.proc);
+ event.thing = EVENT_NONE;
+ trace_set_options(event.proc, event.proc->pid);
+ continue_process(event.proc->pid);
+ return &event;
+ }
+ if (opt_i) {
+ event.proc->instruction_pointer =
+ get_instruction_pointer(event.proc);
+ }
+ switch (syscall_p(event.proc, status, &tmp)) {
+ case 1:
+ event.thing = EVENT_SYSCALL;
+ event.e_un.sysnum = tmp;
+ return &event;
+ case 2:
+ event.thing = EVENT_SYSRET;
+ event.e_un.sysnum = tmp;
+ return &event;
+ case 3:
+ event.thing = EVENT_ARCH_SYSCALL;
+ event.e_un.sysnum = tmp;
+ return &event;
+ case 4:
+ event.thing = EVENT_ARCH_SYSRET;
+ event.e_un.sysnum = tmp;
+ return &event;
+ case -1:
+ event.thing = EVENT_NONE;
+ continue_process(event.proc->pid);
+ return &event;
+ }
+ if (WIFEXITED(status)) {
+ event.thing = EVENT_EXIT;
+ event.e_un.ret_val = WEXITSTATUS(status);
+ return &event;
+ }
+ if (WIFSIGNALED(status)) {
+ event.thing = EVENT_EXIT_SIGNAL;
+ event.e_un.signum = WTERMSIG(status);
+ return &event;
+ }
+ if (!WIFSTOPPED(status)) {
+ event.thing = EVENT_NONE;
+ return &event;
+ }
+
+ stop_signal = WSTOPSIG(status);
+
+ /* On some targets, breakpoints are signalled not using
+ SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. Check
+ for these. */
+ if (stop_signal == SIGSEGV
+ || stop_signal == SIGILL
+#ifdef SIGEMT
+ || stop_signal == SIGEMT
+#endif
+ ) {
+ // If we didn't need to know IP so far, get it now.
+ void * addr = opt_i
+ ? event.proc->instruction_pointer
+ : (event.proc->instruction_pointer = get_instruction_pointer (event.proc));
+
+ if (address2bpstruct(event.proc, addr))
+ stop_signal = SIGTRAP;
+ }
+
+ if (stop_signal != (SIGTRAP | event.proc->tracesysgood)
+ && stop_signal != SIGTRAP) {
+ event.thing = EVENT_SIGNAL;
+ event.e_un.signum = stop_signal;
+ return &event;
+ }
+
+ if (was_exec(event.proc, status)) {
+ pid_t saved_pid;
+
+ event.thing = EVENT_NONE;
+ event.e_un.signum = WSTOPSIG(status);
+ debug(1, "Placing breakpoints for the new program");
+ event.proc->mask_32bit = 0;
+ event.proc->personality = 0;
+ event.proc->arch_ptr = NULL;
+ event.proc->filename = pid2name(event.proc->pid);
+ saved_pid = event.proc->pid;
+ event.proc->pid = 0;
+ breakpoints_init(event.proc);
+ event.proc->pid = saved_pid;
+ continue_process(event.proc->pid);
+ return &event;
+ }
+
+ event.thing = EVENT_BREAKPOINT;
+ if (!event.proc->instruction_pointer) {
+ event.proc->instruction_pointer =
+ get_instruction_pointer(event.proc);
+ }
+ event.e_un.brk_addr =
+ event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
+ return &event;
+}