chiark / gitweb /
mtimeout.c: Accept time unit specification on timeout options.
authorMark Wooding <mdw@distorted.org.uk>
Thu, 15 Dec 2011 00:55:01 +0000 (00:55 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Thu, 15 Dec 2011 01:12:33 +0000 (01:12 +0000)
mtimeout.1
mtimeout.c

index c696f93c376a25db0ef09bfb5fb7b3a28530e388..9332807cc051daec3cc9d0ee4390dcfb3cabc1db 100644 (file)
@@ -6,15 +6,27 @@ mtimeout \- run a program for at most a given amount of time
 .B mtimeout
 .RB [ \-s
 .IR signal ]
-.I seconds
+.I time
 .I command
 .RI [ arguments ...]
 .
 .SH DESCRIPTION
 The
 .B mtimeout
-command runs a specified program for at most a given number of
-.IR seconds .
+command runs a specified program for at most a given amount of
+.IR time .
+The
+.I time
+may be fractional (with a decimal point), and may be followed by a unit
+suffix:
+.RB ` s '
+for seconds,
+.RB ` m '
+for minutes,
+.RB ` h '
+for hours, and
+.RB ` d '
+for days.
 .PP
 It works by running the given command as a separate process group.  It
 then waits either for the top-level process (only) to exit, or for the
index 1bb484800f99c99597b63e5cf07641b3b6267da1..38723ae14e8d210a4531ce7b06d75d5eb44c32c1 100644 (file)
@@ -50,6 +50,7 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <math.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -250,6 +251,39 @@ static int namesig(const char *p)
   else return (-1);
 }
 
+/* --- @strtotime@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to string
+ *             @struct timeval *tv@ = where to put the result
+ *
+ * Returns:    ---
+ *
+ * Use:                Converts a string representation of a duration into an
+ *             internal version.  Understands various time units.
+ */
+
+static void strtotime(const char *p, struct timeval *tv)
+{
+  char *q = (/*unconst*/ char *)p;
+  double t, i, f;
+
+  while (isspace((unsigned char)*q)) q++;
+  t = strtod(q, &q);
+  while (isspace((unsigned char)*q)) q++;
+  switch (*q) {
+    case 'd': case 'D': t *= 24;
+    case 'h': case 'H': t *= 60;
+    case 'm': case 'M': t *= 60;
+    case 's': case 'S':
+      q++;
+      while (isspace((unsigned char)*q)) q++;
+  }
+  if (*q) die(253, "bad time value `%s'", p);
+  f = modf(t, &i);
+  tv->tv_sec = i;
+  tv->tv_usec = f * 1000000;
+}
+
 /*----- Help functions ----------------------------------------------------*/
 
 static void usage(FILE *fp)
@@ -369,11 +403,9 @@ static void sigpropagate(int sig, void *p)
 
 int main(int argc, char *const argv[])
 {
-  char *p;
-  double t;
   int signo = SIGTERM;
   pid_t kid;
-  struct timeval tv;
+  struct timeval now, tv;
   struct timeout to;
   struct sigchld sc;
   sig sig_CHLD;
@@ -411,12 +443,7 @@ int main(int argc, char *const argv[])
   }
   argc -= optind; argv += optind;
   if ((f & F_BOGUS) || argc < 2) { usage(stderr); exit(253); }
-
-  p = argv[0];
-  while (isspace((unsigned char)*p)) p++;
-  t = strtod(argv[0], &p);
-  while (isspace((unsigned char)*p)) p++;
-  if (*p) die(253, "bad time value `%s'", argv[0]);
+  strtotime(argv[0], &tv);
 
   /* --- Get things set up --- */
 
@@ -452,8 +479,8 @@ int main(int argc, char *const argv[])
   to.kid = kid;
   to.sig = signo;
   to.panic = 0;
-  gettimeofday(&tv, 0);
-  TV_ADDL(&tv, &tv, (time_t)t, ((long)(t * 1000000))%1000000);
+  gettimeofday(&now, 0);
+  TV_ADD(&tv, &now, &tv);
   sel_addtimer(&sel, &to.t, &tv, timeout, &to);
 
   /* --- Main @select@ loop */