Line data Source code
1 : /* run a command with a limited timeout
2 : tridge@samba.org, June 2005
3 : metze@samba.org, March 2006
4 :
5 : attempt to be as portable as possible (fighting posix all the way)
6 : */
7 : #include <stdio.h>
8 : #include <string.h>
9 : #include <stdlib.h>
10 : #include <unistd.h>
11 : #include <signal.h>
12 : #include <errno.h>
13 : #include <sys/types.h>
14 : #include <sys/wait.h>
15 :
16 : static pid_t child_pid;
17 :
18 0 : static void usage(void)
19 : {
20 0 : printf("usage: timelimit <time> <command>\n");
21 0 : printf(" SIGUSR1 - passes SIGTERM to command's process group\n");
22 0 : printf(" SIGALRM - passes SIGTERM to command's process group\n");
23 0 : printf(" after 5s SIGKILL will be passed and exit(1)\n");
24 0 : printf(" SIGTERM - passes SIGTERM to command's process group\n");
25 0 : printf(" after 1s SIGKILL will be passed and exit(1)\n");
26 0 : }
27 :
28 0 : static void sig_alrm_kill(int sig)
29 : {
30 0 : fprintf(stderr, "\nMaximum time expired in timelimit - killing\n");
31 0 : kill(-child_pid, SIGKILL);
32 0 : exit(1);
33 : }
34 :
35 0 : static void sig_alrm_term(int sig)
36 : {
37 0 : kill(-child_pid, SIGTERM);
38 0 : alarm(5);
39 0 : signal(SIGALRM, sig_alrm_kill);
40 0 : }
41 :
42 0 : static void sig_term(int sig)
43 : {
44 0 : kill(-child_pid, SIGTERM);
45 0 : alarm(1);
46 0 : signal(SIGALRM, sig_alrm_kill);
47 0 : }
48 :
49 0 : static void sig_usr1(int sig)
50 : {
51 0 : kill(-child_pid, SIGTERM);
52 0 : }
53 :
54 84 : static void new_process_group(void)
55 : {
56 84 : if (setpgid(0,0) == -1) {
57 0 : perror("setpgid");
58 0 : exit(1);
59 : }
60 84 : }
61 :
62 :
63 84 : int main(int argc, char *argv[])
64 : {
65 84 : int maxtime, ret=1;
66 :
67 84 : if (argc < 3) {
68 0 : usage();
69 0 : exit(1);
70 : }
71 :
72 84 : maxtime = atoi(argv[1]);
73 :
74 84 : child_pid = fork();
75 168 : if (child_pid == 0) {
76 84 : new_process_group();
77 84 : execvp(argv[2], argv+2);
78 84 : perror(argv[2]);
79 0 : exit(1);
80 : }
81 :
82 84 : signal(SIGTERM, sig_term);
83 84 : signal(SIGINT, sig_term);
84 84 : signal(SIGQUIT, sig_term);
85 84 : signal(SIGUSR1, sig_usr1);
86 84 : signal(SIGALRM, sig_alrm_term);
87 84 : alarm(maxtime);
88 :
89 84 : do {
90 : int status;
91 168 : pid_t pid = wait(&status);
92 168 : if (pid != -1) {
93 84 : ret = WEXITSTATUS(status);
94 84 : } else if (errno == ECHILD) {
95 84 : break;
96 : }
97 : } while (1);
98 :
99 84 : kill(-child_pid, SIGKILL);
100 :
101 84 : exit(ret);
102 : }
|