172756670274dac9562b869761c50c59ed57b7295Rob Landley/* timeout.c - Run command line with a timeout 272756670274dac9562b869761c50c59ed57b7295Rob Landley * 372756670274dac9562b869761c50c59ed57b7295Rob Landley * Copyright 2013 Rob Landley <rob@landley.net> 472756670274dac9562b869761c50c59ed57b7295Rob Landley * 572756670274dac9562b869761c50c59ed57b7295Rob Landley * No standard 672756670274dac9562b869761c50c59ed57b7295Rob Landley 78a3c0edadbf915b9d2f318412587f6107a8e6d42Rob LandleyUSE_TIMEOUT(NEWTOY(timeout, "<2^vk:s: ", TOYFLAG_BIN)) 872756670274dac9562b869761c50c59ed57b7295Rob Landley 972756670274dac9562b869761c50c59ed57b7295Rob Landleyconfig TIMEOUT 1072756670274dac9562b869761c50c59ed57b7295Rob Landley bool "timeout" 1172756670274dac9562b869761c50c59ed57b7295Rob Landley default y 1272756670274dac9562b869761c50c59ed57b7295Rob Landley depends on TOYBOX_FLOAT 1372756670274dac9562b869761c50c59ed57b7295Rob Landley help 1472756670274dac9562b869761c50c59ed57b7295Rob Landley usage: timeout [-k LENGTH] [-s SIGNAL] LENGTH COMMAND... 1572756670274dac9562b869761c50c59ed57b7295Rob Landley 1672756670274dac9562b869761c50c59ed57b7295Rob Landley Run command line as a child process, sending child a signal if the 1772756670274dac9562b869761c50c59ed57b7295Rob Landley command doesn't exit soon enough. 1872756670274dac9562b869761c50c59ed57b7295Rob Landley 1972756670274dac9562b869761c50c59ed57b7295Rob Landley Length can be a decimal fraction. An optional suffix can be "m" 2072756670274dac9562b869761c50c59ed57b7295Rob Landley (minutes), "h" (hours), "d" (days), or "s" (seconds, the default). 2172756670274dac9562b869761c50c59ed57b7295Rob Landley 2272756670274dac9562b869761c50c59ed57b7295Rob Landley -s Send specified signal (default TERM) 2372756670274dac9562b869761c50c59ed57b7295Rob Landley -k Send KILL signal if child still running this long after first signal. 248a3c0edadbf915b9d2f318412587f6107a8e6d42Rob Landley -v Verbose 2572756670274dac9562b869761c50c59ed57b7295Rob Landley*/ 2672756670274dac9562b869761c50c59ed57b7295Rob Landley 2772756670274dac9562b869761c50c59ed57b7295Rob Landley#define FOR_timeout 2872756670274dac9562b869761c50c59ed57b7295Rob Landley#include "toys.h" 2972756670274dac9562b869761c50c59ed57b7295Rob Landley 3072756670274dac9562b869761c50c59ed57b7295Rob LandleyGLOBALS( 3172756670274dac9562b869761c50c59ed57b7295Rob Landley char *s_signal; 3272756670274dac9562b869761c50c59ed57b7295Rob Landley char *k_timeout; 3372756670274dac9562b869761c50c59ed57b7295Rob Landley 3472756670274dac9562b869761c50c59ed57b7295Rob Landley int nextsig; 3572756670274dac9562b869761c50c59ed57b7295Rob Landley pid_t pid; 3672756670274dac9562b869761c50c59ed57b7295Rob Landley struct timeval ktv; 3772756670274dac9562b869761c50c59ed57b7295Rob Landley struct itimerval itv; 3872756670274dac9562b869761c50c59ed57b7295Rob Landley) 3972756670274dac9562b869761c50c59ed57b7295Rob Landley 4072756670274dac9562b869761c50c59ed57b7295Rob Landleystatic void handler(int i) 4172756670274dac9562b869761c50c59ed57b7295Rob Landley{ 428a3c0edadbf915b9d2f318412587f6107a8e6d42Rob Landley fprintf(stderr, "timeout pid %d signal %d\n", TT.pid, TT.nextsig); 4372756670274dac9562b869761c50c59ed57b7295Rob Landley kill(TT.pid, TT.nextsig); 4472756670274dac9562b869761c50c59ed57b7295Rob Landley 4572756670274dac9562b869761c50c59ed57b7295Rob Landley if (TT.k_timeout) { 4672756670274dac9562b869761c50c59ed57b7295Rob Landley TT.k_timeout = 0; 4772756670274dac9562b869761c50c59ed57b7295Rob Landley TT.nextsig = SIGKILL; 48c776bde13bb2767db2943bc3b02df737a465c035Rob Landley xsignal(SIGALRM, handler); 4972756670274dac9562b869761c50c59ed57b7295Rob Landley TT.itv.it_value = TT.ktv; 508a3c0edadbf915b9d2f318412587f6107a8e6d42Rob Landley setitimer(ITIMER_REAL, &TT.itv, (void *)toybuf); 5172756670274dac9562b869761c50c59ed57b7295Rob Landley } 5272756670274dac9562b869761c50c59ed57b7295Rob Landley} 5372756670274dac9562b869761c50c59ed57b7295Rob Landley 5472756670274dac9562b869761c50c59ed57b7295Rob Landleyvoid timeout_main(void) 5572756670274dac9562b869761c50c59ed57b7295Rob Landley{ 5672756670274dac9562b869761c50c59ed57b7295Rob Landley // Parse early to get any errors out of the way. 5772756670274dac9562b869761c50c59ed57b7295Rob Landley TT.itv.it_value.tv_sec = xparsetime(*toys.optargs, 1000000, &TT.itv.it_value.tv_usec); 5872756670274dac9562b869761c50c59ed57b7295Rob Landley 5972756670274dac9562b869761c50c59ed57b7295Rob Landley if (TT.k_timeout) 6072756670274dac9562b869761c50c59ed57b7295Rob Landley TT.ktv.tv_sec = xparsetime(TT.k_timeout, 1000000, &TT.ktv.tv_usec); 6172756670274dac9562b869761c50c59ed57b7295Rob Landley TT.nextsig = SIGTERM; 6272756670274dac9562b869761c50c59ed57b7295Rob Landley if (TT.s_signal && -1 == (TT.nextsig = sig_to_num(TT.s_signal))) 6372756670274dac9562b869761c50c59ed57b7295Rob Landley error_exit("bad -s: '%s'", TT.s_signal); 6472756670274dac9562b869761c50c59ed57b7295Rob Landley 657d6af77804adc069a83e8566250f868a6cb9786eRob Landley if (!(TT.pid = XVFORK())) xexec(toys.optargs+1); 6672756670274dac9562b869761c50c59ed57b7295Rob Landley else { 67c776bde13bb2767db2943bc3b02df737a465c035Rob Landley xsignal(SIGALRM, handler); 688a3c0edadbf915b9d2f318412587f6107a8e6d42Rob Landley setitimer(ITIMER_REAL, &TT.itv, (void *)toybuf); 697d6af77804adc069a83e8566250f868a6cb9786eRob Landley toys.exitval = xwaitpid(TT.pid); 7072756670274dac9562b869761c50c59ed57b7295Rob Landley } 7172756670274dac9562b869761c50c59ed57b7295Rob Landley} 72