File: timeout.c

package info (click to toggle)
abinit 9.10.4-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 518,712 kB
  • sloc: xml: 877,568; f90: 577,240; python: 80,760; perl: 7,019; ansic: 4,585; sh: 1,925; javascript: 601; fortran: 557; cpp: 454; objc: 323; makefile: 77; csh: 42; pascal: 31
file content (137 lines) | stat: -rw-r--r-- 3,798 bytes parent folder | download | duplicates (6)
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);
    }
}
/*****/