cosmopolitan/examples/rusage.c
2023-09-07 05:41:18 -07:00

90 lines
2.7 KiB
C

#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);
}