1 /* execute a program with a timeout by alarm(2) */
12 static const char *argv0;
13 static char **prgargv;
16 static unsigned int timeout;
18 static void timedout(int sig)
20 fprintf(stderr, "%s[%d]: %s[%d] timed out after %u sec\n",
21 argv0, getpid(), *prgargv, pid, timeout);
26 static void interrupted(int sig)
35 fprintf(stderr, "%s <timeout-seconds> [-<signal>] program ...\n"
36 "Where <signal> is a signal number (see kill -l).\n"
37 "Some symbolic names recognized. KILL used by default\n",
61 {"STKFLT", SIGSTKFLT},
71 {"VTALRM", SIGVTALRM},
79 static int signo_arg(const char *arg)
83 int s = strtol(++arg, &p, 10);
84 if (!*p && p > arg && s > 0 && s < _NSIG) {
88 if (!strncasecmp(arg, "SIG", 3))
90 for (s = 0; s < sizeof(known)/sizeof(*known); ++s)
91 if (!strcasecmp(arg, known[s].name)) {
92 signo = known[s].signo;
99 int main(int argc, char** argv)
101 argv0 = strrchr(*argv, '/');
107 signal(SIGALRM, timedout);
108 signal(SIGINT, interrupted);
109 signal(SIGHUP, interrupted);
116 if (signo_arg(*argv))
118 if (sscanf(*argv, "%u", &timeout) == 1)
122 if (!signo && signo_arg(*argv))
135 signal(SIGALRM, SIG_DFL);
136 signal(SIGCHLD, SIG_DFL);
137 signal(SIGINT, SIG_DFL);
138 signal(SIGHUP, SIG_DFL);
140 execvp(*prgargv, prgargv);
141 fprintf(stderr, "%s: %s: %s\n",
142 argv0, *prgargv, strerror(errno));
144 } else if (pid < 0) {
145 fprintf(stderr, "%s: %s\n", argv0, strerror(errno));
148 while (waitpid(pid, &status, 0) < 0 && EINTR == errno)
151 if (WIFEXITED(status))
152 return WEXITSTATUS(status);
153 if (WIFSIGNALED(status)) {
155 * Some signals are special, lets die with
156 * the same signal as child process
158 if (WTERMSIG(status) == SIGHUP ||
159 WTERMSIG(status) == SIGINT ||
160 WTERMSIG(status) == SIGTERM ||
161 WTERMSIG(status) == SIGQUIT ||
162 WTERMSIG(status) == SIGKILL) {
163 signal(WTERMSIG(status), SIG_DFL);
164 raise(WTERMSIG(status));
166 fprintf(stderr, "%s: %s: %s\n",
167 argv0, *prgargv, strsignal(WTERMSIG(status)));
170 fprintf(stderr, "%s died\n", *prgargv);