00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include <string.h>
00009 #include <stdlib.h>
00010 #include <unistd.h>
00011 #include <signal.h>
00012 #include <errno.h>
00013 #include <sys/types.h>
00014 #include <sys/wait.h>
00015
00016 static pid_t child_pid;
00017
00018 static void usage(void)
00019 {
00020 printf("usage: timelimit <time> <command>\n");
00021 printf(" SIGUSR1 - passes SIGTERM to command's process group\n");
00022 printf(" SIGALRM - passes SIGTERM to command's process group\n");
00023 printf(" after 5s SIGKILL will be passed and exit(1)\n");
00024 printf(" SIGTERM - passes SIGTERM to command's process group\n");
00025 printf(" after 1s SIGKILL will be passed and exit(1)\n");
00026 }
00027
00028 static void sig_alrm_kill(int sig)
00029 {
00030 fprintf(stderr, "\nMaximum time expired in timelimit - killing\n");
00031 kill(-child_pid, SIGKILL);
00032 exit(1);
00033 }
00034
00035 static void sig_alrm_term(int sig)
00036 {
00037 kill(-child_pid, SIGTERM);
00038 alarm(5);
00039 signal(SIGALRM, sig_alrm_kill);
00040 }
00041
00042 static void sig_term(int sig)
00043 {
00044 kill(-child_pid, SIGTERM);
00045 alarm(1);
00046 signal(SIGALRM, sig_alrm_kill);
00047 }
00048
00049 static void sig_usr1(int sig)
00050 {
00051 kill(-child_pid, SIGTERM);
00052 }
00053
00054 static void new_process_group(void)
00055 {
00056 if (setpgid(0,0) == -1) {
00057 perror("setpgid");
00058 exit(1);
00059 }
00060 }
00061
00062
00063 int main(int argc, char *argv[])
00064 {
00065 int maxtime, ret=1;
00066
00067 if (argc < 3) {
00068 usage();
00069 exit(1);
00070 }
00071
00072 maxtime = atoi(argv[1]);
00073
00074 child_pid = fork();
00075 if (child_pid == 0) {
00076 new_process_group();
00077 execvp(argv[2], argv+2);
00078 perror(argv[2]);
00079 exit(1);
00080 }
00081
00082 signal(SIGTERM, sig_term);
00083 signal(SIGUSR1, sig_usr1);
00084 signal(SIGALRM, sig_alrm_term);
00085 alarm(maxtime);
00086
00087 do {
00088 int status;
00089 pid_t pid = wait(&status);
00090 if (pid != -1) {
00091 ret = WEXITSTATUS(status);
00092 } else if (errno == ECHILD) {
00093 break;
00094 }
00095 } while (1);
00096
00097 kill(-child_pid, SIGKILL);
00098
00099 exit(ret);
00100 }