#define NOPLAN9DEFINES
#include <u.h>
#include <libc.h>

#include <signal.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/time.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",
	SIGEMT,		"sys: emulate instruction executed",
	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",
	SIGINFO,		"sys: status request",
	SIGUSR1,		"sys: usr1",
	SIGUSR2,		"sys: usr2",
};
	
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;
}

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 %lud %lud %lud %d", pid, u, s, u+s, status);
			else
				snprint(buf, sizeof buf, "%d %lud %lud %lud ''", pid, u, s, u+s, status);
			strecpy(str, str+n, buf);
			return strlen(str);
		}
		if(WIFSIGNALED(status)){
			cd = WCOREDUMP(status);
			USED(cd);
			snprint(buf, sizeof buf, "%d %lud %lud %lud '%s'", pid, u, s, u+s, _p9sigstr(WTERMSIG(status), tmp));
			strecpy(str, str+n, buf);
			return strlen(str);
		}
	}
}
