summaryrefslogtreecommitdiffstats
path: root/otherlibs/unix/wait.c
diff options
context:
space:
mode:
Diffstat (limited to 'otherlibs/unix/wait.c')
-rw-r--r--otherlibs/unix/wait.c76
1 files changed, 57 insertions, 19 deletions
diff --git a/otherlibs/unix/wait.c b/otherlibs/unix/wait.c
index 12579ddac..fa7f77404 100644
--- a/otherlibs/unix/wait.c
+++ b/otherlibs/unix/wait.c
@@ -16,33 +16,71 @@
#include <memory.h>
#include "unix.h"
-value unix_wait() /* ML */
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#ifndef WIFEXITED
+#define WIFEXITED(status) ((status) & 0xFF == 0)
+#define WEXITSTATUS(status) (((status) >> 8) & 0xFF)
+#define WIFSTOPPED(status) ((status) & 0xFF == 0xFF)
+#define WSTOPSIG(status) (((status) >> 8) & 0xFF)
+#define WTERMSIG(status) ((status) & 0x3F)
+#endif
+
+static value alloc_process_status(pid, status)
+ int pid, status;
{
- value res;
- int pid, status;
+ value st, res;
Push_roots(r, 1);
-#define st r[0]
- pid = wait(&status);
- if (pid == -1) uerror("wait", Nothing);
- switch (status & 0xFF) {
- case 0:
+
+ if (WIFEXITED(status)) {
st = alloc(1, 0);
- Field(st, 0) = Val_int((status >> 8) & 0xFF);
- break;
- case 0177:
+ Field(st, 0) = Val_int(WEXITSTATUS(status));
+ }
+ else if (WIFSTOPPED(status)) {
st = alloc(1, 2);
- Field(st, 0) = Val_int((status >> 8) & 0xFF);
- break;
- default:
- st = alloc(2, 1);
- Field(st, 0) = Val_int(status & 0x3F);
- Field(st, 1) = status & 0200 ? Val_true : Val_false;
- break;
+ Field(st, 0) = Val_int(WSTOPSIG(status));
+ }
+ else {
+ st = alloc(1, 1);
+ Field(st, 0) = Val_int(WTERMSIG(status));
}
+ r[0] = st;
res = alloc_tuple(2);
Field(res, 0) = Val_int(pid);
- Field(res, 1) = st;
+ Field(res, 1) = r[0];
Pop_roots();
return res;
}
+value unix_wait() /* ML */
+{
+ int pid, status;
+ Push_roots(r, 1);
+ pid = wait(&status);
+ if (pid == -1) uerror("wait", Nothing);
+ return alloc_process_status(pid, status);
+}
+
+#ifdef HAS_WAITPID
+
+static int wait_flag_table[] = {
+ WNOHANG, WUNTRACED
+};
+
+value unix_waitpid(flags, pid_req)
+ value flags, pid_req;
+{
+ int pid, status;
+
+ pid = waitpid(Int_val(pid_req), &status,
+ convert_flag_list(flags, wait_flag_table));
+ if (pid == -1) uerror("waitpid", Nothing);
+ return alloc_process_status(pid, status);
+}
+
+#else
+
+value unix_waitpid() { invalid_argument("waitpid not implemented"); }
+
+#endif