mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-28 19:38:45 +00:00
- Invent openatemp() API - Invent O_UNLINK open flag - Introduce getenv_secure() API - Remove `git pull` from cosmocc - Fix utimes() when path is NULL - Fix mktemp() to never return NULL - Fix utimensat() UTIME_OMIT on XNU - Improve utimensat() code for RHEL5 - Turn `argv[0]` C:/ to /C/ on Windows - Introduce tmpnam() and tmpnam_r() APIs - Fix more const issues with internal APIs - Permit utimes() on WIN32 in O_RDONLY mode - Fix fdopendir() to check fd is a directory - Fix recent crash regression in landlock make - Fix futimens(AT_FDCWD, NULL) to return EBADF - Use workaround so `make -j` doesn't fork bomb - Rename dontdiscard to __wur (just like glibc) - Fix st_size for WIN32 symlinks containing UTF-8 - Introduce stdio ext APIs needed by GNU coreutils - Fix lstat() on WIN32 for symlinks to directories - Move some constants from normalize.inc to limits.h - Fix segv with memchr() and memcmp() overlapping page - Implement POSIX fflush() behavior for reader streams - Implement AT_SYMLINK_NOFOLLOW for utimensat() on WIN32 - Don't change read-only status of existing files on WIN32 - Correctly handle `0x[^[:xdigit:]]` case in strtol() functions
100 lines
3 KiB
C
100 lines
3 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/time/time.h"
|
|
#include "libc/calls/calls.h"
|
|
#include "libc/calls/struct/timespec.h"
|
|
#include "libc/fmt/itoa.h"
|
|
#include "libc/limits.h"
|
|
#include "libc/log/log.h"
|
|
#include "libc/math.h"
|
|
#include "libc/runtime/runtime.h"
|
|
#include "libc/str/str.h"
|
|
#include "libc/sysv/consts/ex.h"
|
|
#include "libc/x/xspawn.h"
|
|
|
|
/**
|
|
* @fileoverview command for showing how long a command takes
|
|
*
|
|
* This offers the following improvements over the existing `time`
|
|
* command that's incorporated into most shells:
|
|
*
|
|
* - This will show microseconds if seconds < 1
|
|
* - This will launch APE binaries on systems with broken libc execv()
|
|
*/
|
|
|
|
#define WRITE(FD, STR) write(FD, STR, strlen(STR))
|
|
|
|
void OnChild(void *arg) {
|
|
char **argv = arg;
|
|
execv(argv[0], argv);
|
|
_exit(127);
|
|
}
|
|
|
|
long double GetTimeval(struct timeval t) {
|
|
return t.tv_sec + t.tv_usec * 1e-6l;
|
|
}
|
|
|
|
void PrintMetric(const char *name, long double d) {
|
|
char buf[256], *p = buf;
|
|
long mins, secs, mils, mics;
|
|
mins = d / 60;
|
|
secs = fmodl(d, 60);
|
|
mils = fmodl(d * 1000, 1000);
|
|
mics = fmodl(d * 1000000, 1000);
|
|
p = stpcpy(p, name), *p++ = '\t';
|
|
p = FormatInt64(p, mins), *p++ = 'm';
|
|
p = FormatInt64(p, secs), *p++ = '.';
|
|
*p++ = '0' + mils / 100;
|
|
*p++ = '0' + mils / 10 % 10;
|
|
*p++ = '0' + mils % 10;
|
|
if (!secs) {
|
|
*p++ = '0' + mics / 100;
|
|
*p++ = '0' + mics / 10 % 10;
|
|
*p++ = '0' + mics % 10;
|
|
}
|
|
*p++ = 's';
|
|
*p++ = '\n';
|
|
write(2, buf, p - buf);
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int ws;
|
|
char *exepath;
|
|
struct rusage r;
|
|
long double real;
|
|
char exebuf[PATH_MAX];
|
|
if (argc >= 2) {
|
|
if ((exepath = commandv(argv[1], exebuf, sizeof(exebuf)))) {
|
|
real = nowl();
|
|
argv[1] = exepath;
|
|
if ((ws = xvspawn(OnChild, argv + 1, &r)) != -1) {
|
|
PrintMetric("real", nowl() - real);
|
|
PrintMetric("user", GetTimeval(r.ru_utime));
|
|
PrintMetric("sys", GetTimeval(r.ru_stime));
|
|
if (WIFEXITED(ws)) {
|
|
return WEXITSTATUS(ws);
|
|
} else {
|
|
return 128 + WTERMSIG(ws);
|
|
}
|
|
} else {
|
|
perror("xvspawn");
|
|
return 127;
|
|
}
|
|
} else {
|
|
perror(argv[1]);
|
|
return 127;
|
|
}
|
|
} else {
|
|
WRITE(2, "Usage: ");
|
|
WRITE(2, argv[0]);
|
|
WRITE(2, " PROG [ARGS...]\n");
|
|
return EX_USAGE;
|
|
}
|
|
}
|