aboutsummaryrefslogtreecommitdiff
path: root/src/lib9/await.c
blob: 9df7faa5c2264e487ec01e0af2fc1b2a07095023 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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);
		}
	}
}