#include #include #include #include #include #include #include #include int volatile got_sigchld, got_sigalrm; void sighan (int sig) { switch (sig) { case SIGCHLD: got_sigchld = 1; break; case SIGALRM: got_sigalrm = 1; break; } } int main (int argc, char **argv) { char *progname = argv[0]; unsigned long n; char *p; pid_t pid, ret; int status; if (argc < 3) { fprintf (stderr, "usage: %s TIMEOUT COMMAND ...\n", progname); exit (1); } errno = 0; n = strtoul (argv[1], &p, 10); if (errno || *p || n == 0) { fprintf (stderr, "%s: %s is not a valid timeout\n", progname, argv[1]); exit (1); } argc -= 2; argv += 2; signal (SIGALRM, sighan); signal (SIGCHLD, sighan); pid = fork (); if (pid == -1) { perror ("fork"); exit (127); } if (pid == 0) { execvp (argv[0], argv); perror (argv[0]); exit (127); } alarm (n); while (1) { pause (); if (got_sigchld) { alarm (0); break; } if (got_sigalrm) { fprintf (stderr, "%s: timed out\n", progname); kill (pid, SIGKILL); exit (127); } } ret = wait (&status); if (ret != pid) { perror ("wait"); exit (127); } if (WIFEXITED (status)) return WEXITSTATUS (status); if (WIFSIGNALED (status)) fprintf (stderr, "%s: %s terminated on signal %d\n", progname, argv[0], WTERMSIG (status)); else if (WIFSTOPPED (status)) fprintf (stderr, "%s: %s stopped\n", progname, argv[0]); else fprintf (stderr, "%s: %s exited with unrecognized status %d\n", progname, argv[0], status); return 127; }