1/* timeout -- run a command with bounded time
2   Copyright (C) 2008-2010 Free Software Foundation, Inc.
3
4   This program is free software: you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation, either version 3 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17
18/* timeout - Start a command, and kill it if the specified timeout expires
19
20   We try to behave like a shell starting a single (foreground) job,
21   and will kill the job if we receive the alarm signal we setup.
22   The exit status of the job is returned, or one of these errors:
23     EXIT_TIMEDOUT      124      job timed out
24     EXIT_CANCELED      125      internal error
25     EXIT_CANNOT_INVOKE 126      error executing job
26     EXIT_ENOENT        127      couldn't find job to exec
27
28   Caveats:
29     If user specifies the KILL (9) signal is to be sent on timeout,
30     the monitor is killed and so exits with 128+9 rather than 124.
31
32     If you start a command in the background, which reads from the tty
33     and so is immediately sent SIGTTIN to stop, then the timeout
34     process will ignore this so it can timeout the command as expected.
35     This can be seen with `timeout 10 dd&` for example.
36     However if one brings this group to the foreground with the `fg`
37     command before the timer expires, the command will remain
38     in the sTop state as the shell doesn't send a SIGCONT
39     because the timeout process (group leader) is already running.
40     To get the command running again one can Ctrl-Z, and do fg again.
41     Note one can Ctrl-C the whole job when in this state.
42     I think this could be fixed but I'm not sure the extra
43     complication is justified for this scenario.
44
45   Written by P��draig Brady.  */
46
47#include <config.h>
48#include <getopt.h>
49#include <stdio.h>
50#include <sys/types.h>
51#include <signal.h>
52
53#if HAVE_SYS_WAIT_H
54# include <sys/wait.h>
55#endif
56#ifndef WIFSIGNALED
57# define WIFSIGNALED(s) (((s) & 0xFFFF) - 1 < (unsigned int) 0xFF)
58#endif
59#ifndef WTERMSIG
60# define WTERMSIG(s) ((s) & 0x7F)
61#endif
62
63#include "system.h"
64#include "xstrtol.h"
65#include "sig2str.h"
66#include "operand2sig.h"
67#include "cloexec.h"
68#include "error.h"
69#include "long-options.h"
70#include "quote.h"
71
72#define PROGRAM_NAME "timeout"
73
74#define AUTHORS proper_name_utf8 ("Padraig Brady", "P\303\241draig Brady")
75
76static int timed_out;
77static int term_signal = SIGTERM;  /* same default as kill command.  */
78static int monitored_pid;
79static int sigs_to_ignore[NSIG];   /* so monitor can ignore sigs it resends.  */
80
81static struct option const long_options[] =
82{
83  {"signal", required_argument, NULL, 's'},
84  {NULL, 0, NULL, 0}
85};
86
87/* send sig to group but not ourselves.
88 * FIXME: Is there a better way to achieve this?  */
89static int
90send_sig (int where, int sig)
91{
92  sigs_to_ignore[sig] = 1;
93  return kill (where, sig);
94}
95
96static void
97cleanup (int sig)
98{
99  if (sig == SIGALRM)
100    {
101      timed_out = 1;
102      sig = term_signal;
103    }
104  if (monitored_pid)
105    {
106      if (sigs_to_ignore[sig])
107        {
108          sigs_to_ignore[sig] = 0;
109          return;
110        }
111      send_sig (0, sig);
112      if (sig != SIGKILL && sig != SIGCONT)
113        send_sig (0, SIGCONT);
114    }
115  else /* we're the child or the child is not exec'd yet.  */
116    _exit (128 + sig);
117}
118
119void
120usage (int status)
121{
122  if (status != EXIT_SUCCESS)
123    fprintf (stderr, _("Try `%s --help' for more information.\n"),
124             program_name);
125  else
126    {
127      printf (_("\
128Usage: %s [OPTION] NUMBER[SUFFIX] COMMAND [ARG]...\n\
129  or:  %s [OPTION]\n"), program_name, program_name);
130
131      fputs (_("\
132Start COMMAND, and kill it if still running after NUMBER seconds.\n\
133SUFFIX may be `s' for seconds (the default), `m' for minutes,\n\
134`h' for hours or `d' for days.\n\
135\n\
136"), stdout);
137
138      fputs (_("\
139Mandatory arguments to long options are mandatory for short options too.\n\
140"), stdout);
141      fputs (_("\
142  -s, --signal=SIGNAL\n\
143                   specify the signal to be sent on timeout.\n\
144                   SIGNAL may be a name like `HUP' or a number.\n\
145                   See `kill -l` for a list of signals\n"), stdout);
146
147      fputs (HELP_OPTION_DESCRIPTION, stdout);
148      fputs (VERSION_OPTION_DESCRIPTION, stdout);
149      fputs (_("\n\
150If the command times out, then exit with status 124.  Otherwise, exit\n\
151with the status of COMMAND.  If no signal is specified, send the TERM\n\
152signal upon timeout.  The TERM signal kills any process that does not\n\
153block or catch that signal.  For other processes, it may be necessary to\n\
154use the KILL (9) signal, since this signal cannot be caught.\n"), stdout);
155      emit_ancillary_info ();
156    }
157  exit (status);
158}
159
160/* Given a long integer value *X, and a suffix character, SUFFIX_CHAR,
161   scale *X by the multiplier implied by SUFFIX_CHAR.  SUFFIX_CHAR may
162   be the NUL byte or `s' to denote seconds, `m' for minutes, `h' for
163   hours, or `d' for days.  If SUFFIX_CHAR is invalid, don't modify *X
164   and return false.  If *X would overflow an integer, don't modify *X
165   and return false. Otherwise return true.  */
166
167static bool
168apply_time_suffix (unsigned long *x, char suffix_char)
169{
170  unsigned int multiplier = 1;
171
172  switch (suffix_char)
173    {
174    case 0:
175    case 's':
176      return true;
177    case 'd':
178      multiplier *= 24;
179    case 'h':
180      multiplier *= 60;
181    case 'm':
182      if (multiplier > UINT_MAX / 60) /* 16 bit overflow */
183        return false;
184      multiplier *= 60;
185      break;
186    default:
187      return false;
188    }
189
190  if (*x > UINT_MAX / multiplier)
191    return false;
192
193  *x *= multiplier;
194
195  return true;
196}
197
198static void
199install_signal_handlers (int sigterm)
200{
201  struct sigaction sa;
202  sigemptyset(&sa.sa_mask);  /* Allow concurrent calls to handler */
203  sa.sa_handler = cleanup;
204  sa.sa_flags = SA_RESTART;  /* restart syscalls (like wait() below) */
205
206  sigaction (SIGALRM, &sa, NULL); /* our timeout.  */
207  sigaction (SIGINT, &sa, NULL);  /* Ctrl-C at terminal for example.  */
208  sigaction (SIGQUIT, &sa, NULL); /* Ctrl-\ at terminal for example.  */
209  sigaction (SIGHUP, &sa, NULL);  /* terminal closed for example.  */
210  sigaction (SIGTERM, &sa, NULL); /* if we're killed, stop monitored proc.  */
211  sigaction (sigterm, &sa, NULL); /* user specified termination signal.  */
212}
213
214int
215main (int argc, char **argv)
216{
217  unsigned long timeout;
218  char signame[SIG2STR_MAX];
219  int c;
220  char *ep;
221
222  initialize_main (&argc, &argv);
223  set_program_name (argv[0]);
224  setlocale (LC_ALL, "");
225  bindtextdomain (PACKAGE, LOCALEDIR);
226  textdomain (PACKAGE);
227
228  initialize_exit_failure (EXIT_CANCELED);
229  atexit (close_stdout);
230
231  parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
232                      usage, AUTHORS, (char const *) NULL);
233
234  while ((c = getopt_long (argc, argv, "+s:", long_options, NULL)) != -1)
235    {
236      switch (c)
237        {
238        case 's':
239          term_signal = operand2sig (optarg, signame);
240          if (term_signal == -1)
241            usage (EXIT_CANCELED);
242          break;
243        default:
244          usage (EXIT_CANCELED);
245          break;
246        }
247    }
248
249  if (argc - optind < 2)
250    usage (EXIT_CANCELED);
251
252  if (xstrtoul (argv[optind], &ep, 10, &timeout, NULL)
253      /* Invalid interval. Note 0 disables timeout  */
254      || (timeout > UINT_MAX)
255      /* Extra chars after the number and an optional s,m,h,d char.  */
256      || (*ep && *(ep + 1))
257      /* Check any suffix char and update timeout based on the suffix.  */
258      || !apply_time_suffix (&timeout, *ep))
259    {
260      error (0, 0, _("invalid time interval %s"), quote (argv[optind]));
261      usage (EXIT_CANCELED);
262    }
263  optind++;
264
265  argv += optind;
266
267  /* Ensure we're in our own group so all subprocesses can be killed.
268     Note we don't just put the child in a separate group as
269     then we would need to worry about foreground and background groups
270     and propagating signals between them.  */
271  setpgid (0, 0);
272
273  /* Setup handlers before fork() so that we
274     handle any signals caused by child, without races.  */
275  install_signal_handlers (term_signal);
276  signal (SIGTTIN, SIG_IGN);    /* don't sTop if background child needs tty.  */
277  signal (SIGTTOU, SIG_IGN);    /* don't sTop if background child needs tty.  */
278  signal (SIGCHLD, SIG_DFL);    /* Don't inherit CHLD handling from parent.   */
279
280  monitored_pid = fork ();
281  if (monitored_pid == -1)
282    {
283      error (0, errno, _("fork system call failed"));
284      return EXIT_CANCELED;
285    }
286  else if (monitored_pid == 0)
287    {                           /* child */
288      int exit_status;
289
290      /* exec doesn't reset SIG_IGN -> SIG_DFL.  */
291      signal (SIGTTIN, SIG_DFL);
292      signal (SIGTTOU, SIG_DFL);
293
294      execvp (argv[0], argv);   /* FIXME: should we use "sh -c" ... here?  */
295
296      /* exit like sh, env, nohup, ...  */
297      exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
298      error (0, errno, _("failed to run command %s"), quote (argv[0]));
299      return exit_status;
300    }
301  else
302    {
303      int status;
304
305      alarm (timeout);
306
307      /* We're just waiting for a single process here, so wait() suffices.
308         Note the signal() calls above on GNU/Linux and BSD at least,
309         essentially call the lower level sigaction() with the SA_RESTART flag
310         set, which ensures the following wait call will only return if the
311         child exits, not on this process receiving a signal. Also we're not
312         passing WUNTRACED | WCONTINUED to a waitpid() call and so will not get
313         indication that the child has stopped or continued.  */
314      if (wait (&status) == -1)
315        {
316          /* shouldn't happen.  */
317          error (0, errno, _("error waiting for command"));
318          status = EXIT_CANCELED;
319        }
320      else
321        {
322          if (WIFEXITED (status))
323            status = WEXITSTATUS (status);
324          else if (WIFSIGNALED (status))
325            status = WTERMSIG (status) + 128; /* what sh does at least.  */
326          else
327            {
328              /* shouldn't happen.  */
329              error (0, 0, _("unknown status from command (0x%X)"), status);
330              status = EXIT_FAILURE;
331            }
332        }
333
334      if (timed_out)
335        return EXIT_TIMEDOUT;
336      else
337        return status;
338    }
339}
340