1/* See LICENSE file for copyright and license details. */
2
3
4#include <sys/times.h>
5#include <sys/wait.h>
6
7#include <errno.h>
8#include <stdio.h>
9#include <unistd.h>
10
11#include "util.h"
12
13static void
14usage(void)
15{
16 eprintf("usage: %s [-p] cmd [arg ...]\n", argv0);
17}
18
19// ?man time: time command execution
20// ?man arguments: cmd [arg ...
21// ?man run a command and report its execution duration
22int
23main(int argc, char *argv[])
24{
25 pid_t pid;
26 struct tms tms; /* user and sys times */
27 clock_t r0, r1; /* real time */
28 long ticks; /* per second */
29 int status, savederrno, ret = 0;
30
31 ARGBEGIN {
32 // ?man -p: preserve file attributes
33 case 'p':
34 break;
35 default:
36 usage();
37 } ARGEND
38
39 if (!argc)
40 usage();
41
42 if ((ticks = sysconf(_SC_CLK_TCK)) <= 0)
43 eprintf("sysconf _SC_CLK_TCK:");
44
45 if ((r0 = times(&tms)) == (clock_t)-1)
46 eprintf("times:");
47
48 switch ((pid = fork())) {
49 case -1:
50 eprintf("fork:");
51 /* fallthrough */
52 case 0:
53 execvp(argv[0], argv);
54 savederrno = errno;
55 weprintf("execvp %s:", argv[0]);
56 _exit(126 + (savederrno == ENOENT));
57 default:
58 break;
59 }
60 waitpid(pid, &status, 0);
61
62 if ((r1 = times(&tms)) == (clock_t)-1)
63 eprintf("times:");
64
65 if (WIFSIGNALED(status)) {
66 fprintf(stderr, "Command terminated by signal %d\n",
67 WTERMSIG(status));
68 ret = 128 + WTERMSIG(status);
69 }
70
71 fprintf(stderr, "real %f\nuser %f\nsys %f\n",
72 (r1 - r0) / (double)ticks,
73 tms.tms_cutime / (double)ticks,
74 tms.tms_cstime / (double)ticks);
75
76 if (WIFEXITED(status))
77 ret = WEXITSTATUS(status);
78
79 return ret;
80}