about summary refs log tree commit diff
path: root/src/internal/emulate_wait4.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal/emulate_wait4.c')
-rw-r--r--src/internal/emulate_wait4.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/internal/emulate_wait4.c b/src/internal/emulate_wait4.c
new file mode 100644
index 00000000..f6303412
--- /dev/null
+++ b/src/internal/emulate_wait4.c
@@ -0,0 +1,55 @@
+#include <sys/wait.h>
+#include "syscall.h"
+
+#ifndef SYS_wait4
+hidden long __emulate_wait4(int pid, int *status, int options, void *kru, int cp)
+{
+	idtype_t t;
+	int r;
+	siginfo_t info;
+
+	info.si_pid = 0;
+	if (pid < -1) {
+		t = P_PGID;
+		pid = -pid;
+	} else if (pid == -1) {
+		t = P_ALL;
+	} else if (pid == 0) {
+		t = P_PGID;
+	} else {
+		t = P_PID;
+	}
+
+	if (cp) r = __syscall_cp(SYS_waitid, t, pid, &info, options|WEXITED, kru);
+	else r = __syscall(SYS_waitid, t, pid, &info, options|WEXITED, kru);
+
+	if (r<0) return r;
+
+	if (info.si_pid && status) {
+		int sw=0;
+		switch (info.si_code) {
+		case CLD_CONTINUED:
+			sw = 0xffff;
+			break;
+		case CLD_DUMPED:
+			sw = info.si_status&0x7f | 0x80;
+			break;
+		case CLD_EXITED:
+			sw = (info.si_status&0xff) << 8;
+			break;
+		case CLD_KILLED:
+			sw = info.si_status&0x7f;
+			break;
+		case CLD_STOPPED:
+		case CLD_TRAPPED:
+			/* see ptrace(2); the high bits of si_status can contain */
+			/* PTRACE_EVENT_ values which must be preserved */
+			sw = (info.si_status << 8) + 0x7f;
+			break;
+		}
+		*status = sw;
+	}
+
+	return info.si_pid;
+}
+#endif