1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
/*{\src2tex{textfont=tt}}
****p* ABINIT/Timeout/timeout
* NAME
* timeout
*
* FUNCTION
* Executes a command and imposes an elapsed time limit. The command
* is run in a separate POSIX process group so that the right thing
* happens with commands that spawn child processes.
*
* COPYRIGHT
* This program is part of SATAN.
* Copyright 1995 by Dan Farmer and Wietse Venema. All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this entire copyright notice is duplicated in all
* such copies. No charge, other than an "at-cost" distribution fee,
* may be charged for copies, derivations, or distributions of this
* material without the express written consent of the copyright
* holders.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR ANY PARTICULAR
* PURPOSE.
*
* IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR
* PROFITS OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* NOTES
* Command line: timeout [-<signal>] time command
*
* -<signal>
* Specify an optional signal to send to the controlled process.
* By default, timeout sends SIGKILL, which cannot be caught or
* ignored.
*
* time
* The elapsed time limit after which the command is terminated.
*
* command
* The command to be executed.
*
* The exit status is the one of the command (status 1 in case of a
* usage error).
*
* SOURCE
*/
/* System libraries. */
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
extern int optind;
/* Application-specific. */
#define perrorexit(s) { perror(s); exit(1); }
static int kill_signal = SIGKILL;
static char *progname;
static char *commandname;
static int time_to_run;
static void usage()
{
fprintf(stderr, "usage: %s [-signal] time command...\n", progname);
exit(1);
}
static void terminate(sig)
int sig;
{
signal(kill_signal, SIG_DFL);
fprintf(stderr, "timeout.c: aborting command ``%s'' after %d seconds with signal %d\n",
commandname, time_to_run, kill_signal);
kill(0, kill_signal);
}
int main(argc, argv)
int argc;
char **argv;
{
/*int time_to_run;*/
pid_t pid;
pid_t child_pid;
int status;
progname = argv[0];
/*
* Parse JCL.
*/
while (--argc && *++argv && **argv == '-')
if ((kill_signal = atoi(*argv + 1)) <= 0)
usage();
if (argc < 2 || (time_to_run = atoi(argv[0])) <= 0)
usage();
commandname = argv[1];
/*
* Run the command and its watchdog in a separate process group so that
* both can be killed off with one signal.
*/
setsid();
switch (child_pid = fork()) {
case -1: /* error */
perrorexit("timeout: fork");
case 0: /* run controlled command */
execvp(argv[1], argv + 1);
perrorexit(argv[1]);
default: /* become watchdog */
(void) signal(SIGHUP, terminate);
(void) signal(SIGINT, terminate);
(void) signal(SIGQUIT, terminate);
(void) signal(SIGTERM, terminate);
(void) signal(SIGALRM, terminate);
alarm(time_to_run);
while ((pid = wait(&status)) != -1 && pid != child_pid)
/* void */ ;
return (pid == child_pid ? WEXITSTATUS(status) : -1);
}
}
/*****/
|