I didn't see time(1p) in the TODO, but it is POSIX and fairly low hanging fruit. Not quite done as the exit status on failure should be
126 if the utility was found but could not be invoked 127 if the utility could not be found Differentiating between these two with execvp() is difficult (and in some cases impossible). For now leave it with execvp() and the possibility of doing a manual path search at a later time if we decide that it's not correct enough. -emg
From 438b8adebc2d37935148c9376f841d340b1ed84a Mon Sep 17 00:00:00 2001 From: Evan Gates <evan.ga...@gmail.com> Date: Fri, 27 Feb 2015 13:31:04 -0800 Subject: [PATCH] add time. do not mark complete/POSIX compliant as exit status is wrong. --- Makefile | 1 + README | 1 + time.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 time.c diff --git a/Makefile b/Makefile index 527de2a..ef57715 100644 --- a/Makefile +++ b/Makefile @@ -137,6 +137,7 @@ BIN =\ tar\ tee\ test\ + time\ touch\ tr\ true\ diff --git a/README b/README index d98ecf5..17a5f87 100644 --- a/README +++ b/README @@ -74,6 +74,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support, =* tar non-posix none =* tee yes none =* test yes none += time no none (incorrect exit status) =* touch yes none #* tr yes none =* true yes none diff --git a/time.c b/time.c new file mode 100644 index 0000000..71bf04d --- /dev/null +++ b/time.c @@ -0,0 +1,63 @@ +#include <stdio.h> +#include <unistd.h> +#include <sys/times.h> +#include <sys/wait.h> + +#include "util.h" + +void +usage(void) +{ + eprintf("usage: %s [-p] utility [argument ...]\n", argv0); +} + +int +main(int argc, char *argv[]) +{ + pid_t pid; + struct tms tms; /* hold user and sys times */ + clock_t rbeg, rend; /* real time */ + long ticks; /* per second */ + int status; + + ARGBEGIN { + case 'p': + /* used to specify POSIX output format, but that's the only format we + * have for now */ + break; + default: + usage(); + } ARGEND; + + if (!*argv) + usage(); + + if ((ticks = sysconf(_SC_CLK_TCK)) < 0) + eprintf("sysconf() failed to retrieve clock ticks per second:"); + + if ((rbeg = times(&tms)) < 0) /* POSIX doesn't say NULL is ok... */ + eprintf("times() failed to retrieve start times:"); + + if (!(pid = fork())) { /* child */ + execvp(*argv, argv); + /* FIXME: check errno for POSIX exit status + * 126: found could not be invoked + * 127: could not be found + * problem is some like EACCESS can mean either... + * worth doing manual path search for correct value? also gives more + * accurate time as the patch search wouldn't be included in child's + * user/sys times... */ + enprintf(127, "failed to exec %s:", *argv); + } + waitpid(pid, &status, 0); + + if ((rend = times(&tms)) < 0) + eprintf("times() failed to retrieve end times:"); + + fprintf(stderr, "real %f\nuser %f\nsys %f\n", + (rend - rbeg) / (double)ticks, + tms.tms_cutime / (double)ticks, + tms.tms_cstime / (double)ticks); + + return WIFEXITED(status) ? WEXITSTATUS(status) : 0; +} -- 2.3.1