aboutsummaryrefslogtreecommitdiff
path: root/src/lib9/await.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib9/await.c')
-rw-r--r--src/lib9/await.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/lib9/await.c b/src/lib9/await.c
new file mode 100644
index 00000000..9df7faa5
--- /dev/null
+++ b/src/lib9/await.c
@@ -0,0 +1,105 @@
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <string.h>
+#include <errno.h>
+#include <lib9.h>
+
+static struct {
+ int sig;
+ char *str;
+} tab[] = {
+ SIGHUP, "hangup",
+ SIGINT, "interrupt",
+ SIGQUIT, "quit",
+ SIGILL, "sys: trap: illegal instruction",
+ SIGTRAP, "sys: trace trap",
+ SIGABRT, "sys: abort",
+#ifdef SIGEMT
+ SIGEMT, "sys: emulate instruction executed",
+#endif
+ SIGFPE, "sys: fp: trap",
+ SIGKILL, "sys: kill",
+ SIGBUS, "sys: bus error",
+ SIGSEGV, "sys: segmentation violation",
+ SIGALRM, "alarm",
+ SIGTERM, "kill",
+ SIGURG, "sys: urgent condition on socket",
+ SIGSTOP, "sys: stop",
+ SIGTSTP, "sys: tstp",
+ SIGCONT, "sys: cont",
+ SIGCHLD, "sys: child",
+ SIGTTIN, "sys: ttin",
+ SIGTTOU, "sys: ttou",
+ SIGIO, "sys: i/o possible on fd",
+ SIGXCPU, "sys: cpu time limit exceeded",
+ SIGXFSZ, "sys: file size limit exceeded",
+ SIGVTALRM, "sys: virtual time alarm",
+ SIGPROF, "sys: profiling timer alarm",
+ SIGWINCH, "sys: window size change",
+#ifdef SIGINFO
+ SIGINFO, "sys: status request",
+#endif
+ SIGUSR1, "sys: usr1",
+ SIGUSR2, "sys: usr2",
+};
+
+static char*
+_p9sigstr(int sig, char *tmp)
+{
+ int i;
+
+ for(i=0; i<nelem(tab); i++)
+ if(tab[i].sig == sig)
+ return tab[i].str;
+ sprint(tmp, "sys: signal %d", sig);
+ return tmp;
+}
+
+/*
+static int
+_p9strsig(char *s)
+{
+ int i;
+
+ for(i=0; i<nelem(tab); i++)
+ if(strcmp(s, tab[i].str) == 0)
+ return tab[i].sig;
+ return 0;
+}
+*/
+
+int
+await(char *str, int n)
+{
+ int pid, status, cd;
+ struct rusage ru;
+ char buf[128], tmp[64];
+ ulong u, s;
+
+ for(;;){
+ pid = wait3(&status, 0, &ru);
+ if(pid < 0)
+ return -1;
+ u = ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000);
+ s = ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000);
+ if(WIFEXITED(status)){
+ status = WEXITSTATUS(status);
+ if(status)
+ snprint(buf, sizeof buf, "%d %lu %lu %lu %d", pid, u, s, u+s, status);
+ else
+ snprint(buf, sizeof buf, "%d %lu %lu %lu ''", pid, u, s, u+s);
+ strecpy(str, str+n, buf);
+ return strlen(str);
+ }
+ if(WIFSIGNALED(status)){
+ cd = WCOREDUMP(status);
+ USED(cd);
+ snprint(buf, sizeof buf, "%d %lu %lu %lu '%s'", pid, u, s, u+s, _p9sigstr(WTERMSIG(status), tmp));
+ strecpy(str, str+n, buf);
+ return strlen(str);
+ }
+ }
+}