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 149 : static void new_process_group(void) 55 : { 56 149 : if (setpgid(0,0) == -1) { 57 0 : perror("setpgid"); 58 0 : exit(1); 59 : } 60 149 : } 61 : 62 : 63 149 : int main(int argc, char *argv[]) 64 : { 65 149 : int maxtime, ret=1; 66 : 67 149 : if (argc < 3) { 68 0 : usage(); 69 0 : exit(1); 70 : } 71 : 72 149 : maxtime = atoi(argv[1]); 73 : 74 149 : child_pid = fork(); 75 298 : if (child_pid == 0) { 76 149 : new_process_group(); 77 149 : execvp(argv[2], argv+2); 78 149 : perror(argv[2]); 79 0 : exit(1); 80 : } 81 : 82 149 : signal(SIGTERM, sig_term); 83 149 : signal(SIGINT, sig_term); 84 149 : signal(SIGQUIT, sig_term); 85 149 : signal(SIGUSR1, sig_usr1); 86 149 : signal(SIGALRM, sig_alrm_term); 87 149 : alarm(maxtime); 88 : 89 149 : do { 90 : int status; 91 298 : pid_t pid = wait(&status); 92 298 : if (pid != -1) { 93 149 : ret = WEXITSTATUS(status); 94 149 : } else if (errno == ECHILD) { 95 149 : break; 96 : } 97 : } while (1); 98 : 99 149 : kill(-child_pid, SIGKILL); 100 : 101 149 : exit(ret); 102 : }