2020-06-15 14:18:57 +00:00
|
|
|
#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
|
2023-09-07 12:39:58 +00:00
|
|
|
#include "libc/calls/struct/rusage.h"
|
2020-06-15 14:18:57 +00:00
|
|
|
#include "libc/calls/calls.h"
|
|
|
|
#include "libc/calls/struct/rusage.h"
|
2021-10-14 00:27:13 +00:00
|
|
|
#include "libc/calls/struct/sigaction.h"
|
2023-09-07 12:39:58 +00:00
|
|
|
#include "libc/calls/struct/sigset.h"
|
|
|
|
#include "libc/calls/struct/timespec.h"
|
|
|
|
#include "libc/fmt/itoa.h"
|
|
|
|
#include "libc/log/appendresourcereport.internal.h"
|
2020-06-15 14:18:57 +00:00
|
|
|
#include "libc/runtime/runtime.h"
|
2023-09-07 12:39:58 +00:00
|
|
|
#include "libc/stdio/append.h"
|
2020-06-15 14:18:57 +00:00
|
|
|
#include "libc/stdio/stdio.h"
|
2021-06-24 19:31:26 +00:00
|
|
|
#include "libc/sysv/consts/sig.h"
|
2020-06-15 14:18:57 +00:00
|
|
|
|
2023-09-07 12:39:58 +00:00
|
|
|
int main(int argc, char *argv[]) {
|
2020-06-15 14:18:57 +00:00
|
|
|
|
2023-09-07 12:39:58 +00:00
|
|
|
const char *prog = argv[0];
|
|
|
|
if (!prog)
|
|
|
|
prog = "rusage";
|
|
|
|
|
|
|
|
if (argc < 2) {
|
|
|
|
tinyprint(2, prog, ": missing command\n", NULL);
|
|
|
|
exit(1);
|
2021-06-24 19:31:26 +00:00
|
|
|
}
|
2020-06-15 14:18:57 +00:00
|
|
|
|
2023-09-07 12:39:58 +00:00
|
|
|
// block process management signals
|
|
|
|
sigset_t mask, orig;
|
|
|
|
sigemptyset(&mask);
|
|
|
|
sigaddset(&mask, SIGINT);
|
|
|
|
sigaddset(&mask, SIGQUIT);
|
|
|
|
sigaddset(&mask, SIGCHLD);
|
|
|
|
sigprocmask(SIG_BLOCK, &mask, &orig);
|
2021-06-24 19:31:26 +00:00
|
|
|
|
2023-09-07 12:39:58 +00:00
|
|
|
struct timespec started = timespec_real();
|
|
|
|
|
|
|
|
// launch subprocess
|
|
|
|
int child = fork();
|
|
|
|
if (child == -1) {
|
|
|
|
perror(prog);
|
|
|
|
exit(1);
|
2021-01-25 21:08:05 +00:00
|
|
|
}
|
2023-09-07 12:39:58 +00:00
|
|
|
if (!child) {
|
|
|
|
sigprocmask(SIG_SETMASK, &orig, 0);
|
2021-01-25 21:08:05 +00:00
|
|
|
execvp(argv[1], argv + 1);
|
2021-06-24 19:31:26 +00:00
|
|
|
_Exit(127);
|
|
|
|
}
|
2023-09-07 12:39:58 +00:00
|
|
|
|
|
|
|
// 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);
|
2021-01-25 21:08:05 +00:00
|
|
|
}
|
2023-09-07 12:39:58 +00:00
|
|
|
|
|
|
|
// 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));
|
2021-01-25 21:08:05 +00:00
|
|
|
}
|
2023-09-07 12:39:58 +00:00
|
|
|
return WEXITSTATUS(ws);
|
2020-06-15 14:18:57 +00:00
|
|
|
}
|