chiark / gitweb /
mtimeout.c: Accept time unit specification on timeout options.
[misc] / mtimeout.c
index dbdc83ef60584bd0e03f3c2b67a115fb2d631a76..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>
@@ -104,27 +105,31 @@ int cmp_namesig(const void *k, const void *v)
 static int namesig(const char *p)
 {
   const static struct namesig tab[] = {
-/*
-  ;;; The signal name table is very boring to type.  To make life less awful,
-  ;;; put the signal names in this list and evaluate the code to get Emacs to
-  ;;; regenerate it.  We use @bsearch@ on it, so it's important that it be
-  ;;; sorted: Emacs does this for us.
-  (let ((signals '(HUP INT QUIT ILL ABRT FPE KILL SEGV PIPE ALRM TERM
-                  USR1 USR2 CHLD CONT STOP TSTP TTIN TTOU BUS POLL
-                  PROF SYS TRAP URG VTALRM XCPU XFSZ IOT EMT STKFLT
-                  IO CLD PWR INFO LOST WINCH)))
-    (save-excursion
-      (goto-char (point-min))
-      (let ((start (search-forward (concat "/" "* SIGLIST *" "/\n")))
-           (end (search-forward (concat "/" "* END *" "/\n"))))
-       (delete-region start end))
-      (dolist (sig (sort (copy-list signals) #'string<))
-       (insert (format "#ifdef SIG%s\n    { \"%s\", SIG%s },\n#endif\n"
-                       sig sig sig)))
-      (insert (concat "/" "* END *" "/\n"))))
-*/
-
-/* SIGLIST */
+  /*
+     ;;; The signal name table is very boring to type.  To make life less
+     ;;; awful, put the signal names in this list and evaluate the code to
+     ;;; get Emacs to regenerate it.  We use @bsearch@ on it, so it's
+     ;;; important that it be sorted: Emacs does this for us.
+
+     (let ((signals '(HUP INT QUIT ILL ABRT FPE KILL SEGV PIPE ALRM TERM
+                     USR1 USR2 CHLD CONT STOP TSTP TTIN TTOU BUS POLL
+                     PROF SYS TRAP URG VTALRM XCPU XFSZ IOT EMT STKFLT
+                     IO CLD PWR INFO LOST WINCH)))
+       (save-excursion
+        (goto-char (point-min))
+        (search-forward (concat "***" "BEGIN siglist" "***"))
+        (beginning-of-line 2)
+        (delete-region (point)
+                       (progn
+                         (search-forward "***END***")
+                         (beginning-of-line)
+                         (point)))
+        (dolist (sig (sort (copy-list signals) #'string<))
+          (insert (format "#ifdef SIG%s\n    { \"%s\", SIG%s },\n#endif\n"
+                          sig sig sig)))))
+  */
+
+    /***BEGIN siglist***/
 #ifdef SIGABRT
     { "ABRT", SIGABRT },
 #endif
@@ -236,7 +241,7 @@ static int namesig(const char *p)
 #ifdef SIGXFSZ
     { "XFSZ", SIGXFSZ },
 #endif
-/* END */
+    /***END***/
   };
 
   const struct namesig *ns = bsearch(p, tab, N(tab), sizeof(tab[0]),
@@ -246,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)
@@ -365,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;
@@ -407,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 --- */
 
@@ -448,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 */