1/* See LICENSE file for copyright and license details. */
2
3#include <sys/times.h>
4#include <sys/wait.h>
5
6#include <errno.h>
7#include <stdio.h>
8#include <unistd.h>
9
10#include "util.h"
11#include "wexec.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 {
33 // ?man -p: preserve file attributes
34 case 'p':
35 break;
36 default:
37 usage();
38 }
39 ARGEND
40
41 if (!argc)
42 usage();
43
44 if ((ticks = sysconf(_SC_CLK_TCK)) <= 0)
45 eprintf("sysconf _SC_CLK_TCK:");
46
47 if ((r0 = times(&tms)) == (clock_t)-1)
48 eprintf("times:");
49
50 switch ((pid = fork())) {
51 case -1:
52 eprintf("fork:");
53 /* fallthrough */
54 case 0:
55 wexecvp_self(argv[0], argv);
56 savederrno = errno;
57 weprintf("wexecvp %s:", argv[0]);
58 _exit(126 + (savederrno == ENOENT));
59 default:
60 break;
61 }
62 waitpid(pid, &status, 0);
63
64 if ((r1 = times(&tms)) == (clock_t)-1)
65 eprintf("times:");
66
67 if (WIFSIGNALED(status)) {
68 fprintf(stderr, "Command terminated by signal %d\n", WTERMSIG(status));
69 ret = 128 + WTERMSIG(status);
70 }
71
72 fprintf(
73 stderr,
74 "real %f\nuser %f\nsys %f\n",
75 (r1 - r0) / (double)ticks,
76 tms.tms_cutime / (double)ticks,
77 tms.tms_cstime / (double)ticks
78 );
79
80 if (WIFEXITED(status))
81 ret = WEXITSTATUS(status);
82
83 return ret;
84}