1 #include "config.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <signal.h>
6 #include <sys/wait.h>
7
8 #include <assert.h>
9
10 static int caught = 0;
11
caught_signal(int which)12 static void caught_signal(int which)
13 {
14 caught = which;
15 }
16
wait_for_process(pid_t pid)17 static int wait_for_process(pid_t pid)
18 {
19 int rv = EX_SOFTWARE;
20 int stats = 0;
21 int i = 0;
22 struct sigaction sig_handler;
23
24 sig_handler.sa_handler = caught_signal;
25 sig_handler.sa_flags = 0;
26
27 sigaction(SIGALRM, &sig_handler, NULL);
28 sigaction(SIGHUP, &sig_handler, NULL);
29 sigaction(SIGINT, &sig_handler, NULL);
30 sigaction(SIGTERM, &sig_handler, NULL);
31 sigaction(SIGPIPE, &sig_handler, NULL);
32
33 /* Loop forever waiting for the process to quit */
34 for (i = 0; ;i++) {
35 pid_t p = waitpid(pid, &stats, 0);
36 if (p == pid) {
37 /* child exited. Let's get out of here */
38 rv = WIFEXITED(stats) ?
39 WEXITSTATUS(stats) :
40 (0x80 | WTERMSIG(stats));
41 break;
42 } else {
43 int sig = 0;
44 switch (i) {
45 case 0:
46 /* On the first iteration, pass the signal through */
47 sig = caught > 0 ? caught : SIGTERM;
48 if (caught == SIGALRM) {
49 fprintf(stderr, "Timeout.. killing the process\n");
50 }
51 break;
52 case 1:
53 sig = SIGTERM;
54 break;
55 default:
56 sig = SIGKILL;
57 break;
58 }
59 if (kill(pid, sig) < 0) {
60 /* Kill failed. Must have lost the process. :/ */
61 perror("lost child when trying to kill");
62 }
63 /* Wait up to 5 seconds for the pid */
64 alarm(5);
65 }
66 }
67 return rv;
68 }
69
spawn_and_wait(int argc,char ** argv)70 static int spawn_and_wait(int argc, char **argv)
71 {
72 int rv = EX_SOFTWARE;
73 pid_t pid = fork();
74
75 assert(argc > 1);
76
77 switch (pid) {
78 case -1:
79 perror("fork");
80 rv = EX_OSERR;
81 break; /* NOTREACHED */
82 case 0:
83 execvp(argv[0], argv);
84 perror("exec");
85 rv = EX_SOFTWARE;
86 break; /* NOTREACHED */
87 default:
88 rv = wait_for_process(pid);
89 }
90 return rv;
91 }
92
main(int argc,char ** argv)93 int main(int argc, char **argv)
94 {
95 int naptime = 0;
96 assert(argc > 2);
97
98 naptime = atoi(argv[1]);
99 /* assert(naptime > 0 && naptime < 1800); */
100
101 alarm(naptime);
102
103 return spawn_and_wait(argc+2, argv+2);
104 }
105