• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* timeout.c - Run command line with a timeout
2  *
3  * Copyright 2013 Rob Landley <rob@landley.net>
4  *
5  * No standard
6 
7 USE_TIMEOUT(NEWTOY(timeout, "<2^vk:s: ", TOYFLAG_BIN))
8 
9 config TIMEOUT
10   bool "timeout"
11   default y
12   depends on TOYBOX_FLOAT
13   help
14     usage: timeout [-k LENGTH] [-s SIGNAL] LENGTH COMMAND...
15 
16     Run command line as a child process, sending child a signal if the
17     command doesn't exit soon enough.
18 
19     Length can be a decimal fraction. An optional suffix can be "m"
20     (minutes), "h" (hours), "d" (days), or "s" (seconds, the default).
21 
22     -s	Send specified signal (default TERM)
23     -k	Send KILL signal if child still running this long after first signal
24     -v	Verbose
25 */
26 
27 #define FOR_timeout
28 #include "toys.h"
29 
GLOBALS(char * s_signal;char * k_timeout;int nextsig;pid_t pid;struct timeval ktv;struct itimerval itv;)30 GLOBALS(
31   char *s_signal;
32   char *k_timeout;
33 
34   int nextsig;
35   pid_t pid;
36   struct timeval ktv;
37   struct itimerval itv;
38 )
39 
40 static void handler(int i)
41 {
42   if (toys.optflags & FLAG_v)
43     fprintf(stderr, "timeout pid %d signal %d\n", TT.pid, TT.nextsig);
44   kill(TT.pid, TT.nextsig);
45 
46   if (TT.k_timeout) {
47     TT.k_timeout = 0;
48     TT.nextsig = SIGKILL;
49     xsignal(SIGALRM, handler);
50     TT.itv.it_value = TT.ktv;
51     setitimer(ITIMER_REAL, &TT.itv, (void *)toybuf);
52   }
53 }
54 
timeout_main(void)55 void timeout_main(void)
56 {
57   // Parse early to get any errors out of the way.
58   TT.itv.it_value.tv_sec = xparsetime(*toys.optargs, 1000000, &TT.itv.it_value.tv_usec);
59 
60   if (TT.k_timeout)
61     TT.ktv.tv_sec = xparsetime(TT.k_timeout, 1000000, &TT.ktv.tv_usec);
62   TT.nextsig = SIGTERM;
63   if (TT.s_signal && -1 == (TT.nextsig = sig_to_num(TT.s_signal)))
64     error_exit("bad -s: '%s'", TT.s_signal);
65 
66   if (!(TT.pid = XVFORK())) xexec(toys.optargs+1);
67   else {
68     xsignal(SIGALRM, handler);
69     setitimer(ITIMER_REAL, &TT.itv, (void *)toybuf);
70     toys.exitval = xwaitpid(TT.pid);
71   }
72 }
73