Initial revision
diff --git a/src/lib9/await.c b/src/lib9/await.c
new file mode 100644
index 0000000..9df7faa
--- /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);
+		}
+	}
+}