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

Reply via email to