-
-
Notifications
You must be signed in to change notification settings - Fork 638
/
rusage.c
90 lines (80 loc) · 2.66 KB
/
rusage.c
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
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/struct/rusage.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/timespec.h"
#include "libc/fmt/itoa.h"
#include "libc/log/appendresourcereport.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/append.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/sig.h"
int main(int argc, char *argv[]) {
const char *prog = argv[0];
if (!prog)
prog = "rusage";
if (argc < 2) {
tinyprint(2, prog, ": missing command\n", NULL);
exit(1);
}
// block process management signals
sigset_t mask, orig;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
sigaddset(&mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &mask, &orig);
struct timespec started = timespec_real();
// launch subprocess
int child = fork();
if (child == -1) {
perror(prog);
exit(1);
}
if (!child) {
sigprocmask(SIG_SETMASK, &orig, 0);
execvp(argv[1], argv + 1);
_Exit(127);
}
// wait for subprocess
int ws;
struct rusage ru;
struct sigaction ignore;
ignore.sa_flags = 0;
ignore.sa_handler = SIG_IGN;
sigemptyset(&ignore.sa_mask);
sigaction(SIGINT, &ignore, 0);
sigaction(SIGQUIT, &ignore, 0);
if (wait4(child, &ws, 0, &ru) == -1) {
perror(prog);
exit(1);
}
// compute wall time
char strmicros[27];
struct timespec ended = timespec_real();
struct timespec elapsed = timespec_sub(ended, started);
FormatInt64Thousands(strmicros, timespec_tomicros(elapsed));
// show report
char *b = 0;
appends(&b, "took ");
appends(&b, strmicros);
appends(&b, "µs wall time\n");
AppendResourceReport(&b, &ru, "\n");
write(2, b, appendz(b).i);
// propagate status
if (WIFSIGNALED(ws)) {
signal(WTERMSIG(ws), SIG_DFL);
raise(WTERMSIG(ws));
}
return WEXITSTATUS(ws);
}