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