master xplshn/aruu / cmd / posix / time.c
 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}