Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37818876
en ru br
Репозитории ALT

Группа :: Мониторинг
Пакет: timelimit

 Главная   Изменения   Спек   Патчи   Исходники   Загрузить   Gear   Bugs and FR  Repocop 

timelimit-1.5/000075500000000000000000000000001213266431100133515ustar00rootroot00000000000000timelimit-1.5/ChangeLog000064400000000000000000000044211213266431100151240ustar00rootroot00000000000000Change log for timelimit, the process time limit tool

1.5 2009/10/30
- add the '__dead2' definition for no-return functions
- add the '-p' flag to propagate information about the child
process being terminated by a signal [teddy, roam]

1.4 2008/11/12
- correct options parsing on GNU systems - do not let timelimit
grab the option arguments passed to the executed program
Debian: #505140, reported by John Hasler <jhasler@debian.org>

1.3 2008/09/03
- fix the $Ringlet VCS keyword in the source files [roam]

1.2 2008/08/22
- return the child process exit code instead of always exiting
with 0 [cberg, roam]
- define _GNU_SOURCE to properly use the Linux header files [roam]

1.1 2007/12/07
- move the manual page from section 8 to section 1 [mario]

1.0 2007/11/28
- add an 'install' target to the Makefile [roam]
- build and install the gzipped manual page, too [roam]
- remove the TARGETS file that was never used as intended [roam]
- break the web-visible documentation out of the source tree [roam]
- add a two-clause BSD copyright to all files [roam]
- style fixes to the manual page [roam]
- attempt to create the installation directories [roam]

1.0pre3 2001/06/09
- actually add the -q flag to the getopt() arguments (ARGH!) [roam]
- use envopts[] for time/sig variable setting (both env and cmdline)
[roam]
- warn when no time/sig arguments specified, as suggested by alpha
[roam]
- silence a few gcc warnings [roam]
- removed CC, CFLAGS initial settings from Makefile [alpha]

1.0pre2 2001/05/21
- added the '-q' flag to not output messages about signals sent
to the child process [roam]
- changed the execv() call to execvp(), so PATH is searched for
the specified command, as suggested by alpha [roam]
- changed the default compiler to gcc, as suggested by alpha [roam]
- added timelimit.8 manpage [roam/alpha]
- added killtime/warntime/killsig/warnsig defaults [alpha]

1.0pre1 2001/05/16
- first rolled-together prerelease.

Name tags:
roam Peter Pentchev <roam@ringlet.net>
alpha Karsten W Rohrbach <karsten@rohrbach.de>
mario Mario Iseli <mario@debian.org>
cberg Christoph Berg <myon@debian.org>
teddy Teddy Hogeborn <teddy@fukt.bsnet.se>

Comments: Peter Pentchev <roam@ringlet.net>

$Ringlet: ChangeLog 4182 2009-10-30 15:46:15Z roam $
timelimit-1.5/Makefile000064400000000000000000000053341213266431100150160ustar00rootroot00000000000000# Copyright (c) 2001, 2007 Peter Pentchev
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; 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.
#
# $Ringlet: Makefile 2544 2008-09-03 13:24:36Z roam $

CC?= gcc
CFLAGS?= -O -pipe
LDFLAGS?=
LFLAGS?= ${LDFLAGS}
LIBS?=

RM= rm -f
MKDIR?= mkdir -p

PROG= timelimit
OBJS= timelimit.o
SRCS= timelimit.c

MAN1= timelimit.1
MAN1GZ= ${MAN1}.gz

LOCALBASE?= /usr/local
PREFIX?= ${LOCALBASE}
BINDIR?= ${PREFIX}/bin
MANDIR?= ${PREFIX}/man/man

BINOWN?= root
BINGRP?= wheel
BINMODE?= 555

MANOWN?= root
MANGRP?= wheel
MANMODE?= 644

# comment this if you do not have err(3) and errx(3) (most BSD systems do)
CFLAGS+= -DHAVE_ERR
# comment this if you do not have the sysexits.h header file (most systems do)
CFLAGS+= -DHAVE_SYSEXITS_H
# comment this if you do not have the errno.h header file (most systems do)
CFLAGS+= -DHAVE_ERRNO_H
# comment this if you do not have sigaction(2) (most systems do)
CFLAGS+= -DHAVE_SIGACTION

# development/debugging flags, you may safely ignore them
#CFLAGS+= ${BDECFLAGS}
#CFLAGS+= -ggdb -g3

all: ${PROG} ${MAN1GZ}

clean:
${RM} ${PROG} ${OBJS} ${MAN1GZ}

${PROG}: ${OBJS}
${CC} ${LFLAGS} -o ${PROG} ${OBJS}

timelimit.o: timelimit.c config.h
${CC} ${CFLAGS} -c timelimit.c

${MAN1GZ}: ${MAN1}
gzip -c9 ${MAN1} > ${MAN1GZ}.tmp
mv ${MAN1GZ}.tmp ${MAN1GZ}

install: all
-${MKDIR} ${DESTDIR}${BINDIR}
-${MKDIR} ${DESTDIR}${MANDIR}1
install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} ${PROG} ${DESTDIR}${BINDIR}/
install -c -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} ${MAN1GZ} ${DESTDIR}${MANDIR}1/
timelimit-1.5/config.h000064400000000000000000000062061213266431100147730ustar00rootroot00000000000000#ifndef _INCLUDED_TIMELIMIT_CONFIG_H
#define _INCLUDED_TIMELIMIT_CONFIG_H

/*-
* Copyright (c) 2001, 2007 - 2009 Peter Pentchev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; 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.
*
* $Ringlet: config.h 4172 2009-10-30 10:24:40Z roam $ */

#define _GNU_SOURCE

/* we hope all OS's have those..*/
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/wait.h>

#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif /* HAVE_ERRNO_H */

#ifdef HAVE_ERR
#include <err.h>
#endif /* HAVE_ERR */

#ifdef HAVE_SYSEXITS_H
#include <sysexits.h>
#else
#define EX_OK 0 /* successful termination */
#define EX__BASE 64 /* base value for error messages */
#define EX_USAGE 64 /* command line usage error */
#define EX_DATAERR 65 /* data format error */
#define EX_NOINPUT 66 /* cannot open input */
#define EX_NOUSER 67 /* addressee unknown */
#define EX_NOHOST 68 /* host name unknown */
#define EX_UNAVAILABLE 69 /* service unavailable */
#define EX_SOFTWARE 70 /* internal software error */
#define EX_OSERR 71 /* system error (e.g., can't fork) */
#define EX_OSFILE 72 /* critical OS file missing */
#define EX_CANTCREAT 73 /* can't create (user) output file */
#define EX_IOERR 74 /* input/output error */
#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
#define EX_PROTOCOL 76 /* remote error in protocol */
#define EX_NOPERM 77 /* permission denied */
#define EX_CONFIG 78 /* configuration error */
#define EX__MAX 78 /* maximum listed value */
#endif /* HAVE_SYSEXITS_H */

#ifndef __unused
#ifdef __GNUC__
#define __unused __attribute__((unused))
#else /* __GNUC__ */
#define __unused
#endif /* __GNUC__ */
#endif /* __unused */

#ifndef __dead2
#ifdef __GNUC__
#define __dead2 __attribute__((noreturn))
#else /* __GNUC__ */
#define __dead2
#endif /* __GNUC__ */
#endif /* __dead2 */

#endif /* _INCLUDED */
timelimit-1.5/timelimit.1000064400000000000000000000133621213266431100154350ustar00rootroot00000000000000.\" Copyright (c) 2001, 2007 - 2009 Peter Pentchev
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; 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.
.\"
.\" $Ringlet: timelimit.1 4173 2009-10-30 10:27:16Z roam $
.\"
.Dd October 30, 2009
.Dt TIMELIMIT 1
.Os
.Sh NAME
.Nm timelimit
.Nd effectively limit the absolute execution time of a process
.Sh SYNOPSIS
.Nm
.Op Fl pq
.Op Fl S Ar killsig
.Op Fl s Ar warnsig
.Op Fl T Ar killtime
.Op Fl t Ar warntime
.Ar command
.Op Ar arguments ...
.Sh DESCRIPTION
The
.Nm
utility executes a given
.Ar command
with the supplied
.Ar arguments
and terminates the spawned process after a given time with a given signal.
If the process exits before the time limit has elapsed,
.Nm
will silently exit, too.
.Pp
Options:
.Bl -tag -width indent
.It Fl p
If the child process is terminated by a signal,
.Nm
propagates this condition, i.e. sends the same signal to itself.
This allows the program executing
.Nm
to determine whether the child process was terminated by a signal or
actually exited with an exit code larger than 128.
.It Fl q
Quiet operation -
.Nm
does not output diagnostic messages about signals sent to the child process.
.It Fl S Ar killsig
Specify the number of the signal to be sent to the process
.Ar killtime
seconds after
.Ar warntime
has expired.
Defaults to 9 (SIGKILL).
.It Fl s Ar warnsig
Specify the number of the signal to be sent to the process
.Ar warntime
seconds after it has been started.
Defaults to 15 (SIGTERM).
.It Fl T Ar killtime
Specify the maximum execution time of the process before sending
.Ar killsig
after
.Ar warnsig
has been sent.
Defaults to 120 seconds.
.It Fl t Ar warntime
Specify the maximum execution time of the process in seconds before sending
.Ar warnsig .
Defaults to 3600 seconds.
.El
.Sh ENVIRONMENT
.Bl -tag -width indent
.It Ev KILLSIG
The
.Ar killsig
to use if the
.Fl S
option was not specified.
.It Ev KILLTIME
The
.Ar killtime
to use if the
.Fl T
option was not specified.
.It Ev WARNSIG
The
.Ar warnsig
to use if the
.Fl s
option was not specified.
.It Ev WARNTIME
The
.Ar warntime
to use if the
.Fl t
option was not specified.
.El
.Sh EXIT STATUS
If the child process exits normally, the
.Nm
utility will pass its exit code on up.
If the child process is terminated by a signal and the
.Fl p
flag was not specified, the
.Nm
utility's exit status is 128 plus the signal number, similar to
.Xr sh 1 .
If the
.Fl p
flag was specified, the
.Nm
utility will raise the signal itself so that its own parent process
may in turn reliably distinguish between a signal and a larger than 128
exit code.
.Pp
In rare cases, the
.Nm
utility may encounter a system or user error; then, its exit status is one
of the standard
.Xr sysexits 3
values:
.Bl -tag -width indent
.It Dv EX_USAGE
The command-line parameters and options were incorrectly specified.
.It Dv EX_SOFTWARE
The
.Nm
utility itself received an unexpected signal while waiting for the child
process to terminate.
.It Dv EX_OSERR
The
.Nm
utility was unable to execute the child process, wait for it to terminate,
or examine its exit status.
.El
.Sh EXAMPLES
.Pp
The following examples are shown as given to the shell:
.Pp
.Dl timelimit -p /usr/local/bin/rsync rsync://some.host/dir /opt/mirror
.Pp
Run the rsync program to mirror a WWW or FTP site and kill it if it
runs longer than 1 hour (that is 3600 seconds) with SIGTERM.
If the rsync process does not exit after receiving the SIGTERM,
.Nm
issues a SIGKILL 120 seconds after the SIGTERM.
If the rsync process is terminated by a signal,
.Nm
will itself raise this signal.
.Pp
.Dl tcpserver 0 8888 timelimit -t600 -T300 /opt/services/chat/stats
.Pp
Start a
.Xr tcpserver n
process listening on tcp port 8888; each client connection shall invoke
an instance of an IRC statistics tool under
.Pa /opt/services/chat
and kill it after 600 seconds have elapsed.
If the stats process is still running after the SIGTERM, it will be
killed by a SIGKILL sent 300 seconds later.
.Pp
.Dl env WARNTIME=600 WARNSIG=1 KILLTIME=30 timelimit sh stats.sh
.Pp
Start a shell script and kill it with a SIGHUP in 600 seconds.
If the shell gets stuck and does not respond to the SIGHUP, kill it
with the default SIGKILL after 30 more seconds.
.Sh SEE ALSO
.Xr kill 1 ,
.Xr rsync 1 ,
.Xr signal 3 ,
.Xr tcpserver n
.Sh STANDARDS
No standards documentation was harmed in the process of creating
.Nm .
.Sh BUGS
Please report any bugs in
.Nm
to the author.
.Sh AUTHOR
The
.Nm
utility was conceived and written by
.An Peter Pentchev Aq roam@ringlet.net
with contributions by
.An Karsten W Rohrbach Aq karsten@rohrbach.de
and
.An Teddy Hogeborn Aq teddy@fukt.bsnet.se .
timelimit-1.5/timelimit.c000064400000000000000000000166341213266431100155240ustar00rootroot00000000000000/*-
* Copyright (c) 2001, 2007 - 2009 Peter Pentchev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; 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.
*/

#include "config.h"

#define PARSE_CMDLINE

unsigned long warntime, killtime;
unsigned long warnsig, killsig;
volatile int fdone, falarm, fsig, sigcaught;
int propagate, quiet;

static const char cvs_id[] =
"$Ringlet: timelimit.c 4174 2009-10-30 10:34:13Z roam $";

static struct {
const char *name, opt;
unsigned long *var;
} envopts[] = {
{"KILLSIG", 'S', &killsig},
{"KILLTIME", 'T', &killtime},
{"WARNSIG", 's', &warnsig},
{"WARNTIME", 't', &warntime},
{NULL, 0, NULL}
};

#ifndef HAVE_ERR
static void err(int, const char *, ...);
static void errx(int, const char *, ...);
#endif /* !HAVE_ERR */

static void usage(void);

static void init(int, char *[]);
static pid_t doit(char *[]);
static void child(char *[]);
static void raisesignal(int) __dead2;
static void setsig_fatal(int, void (*)(int));
static void setsig_fatal_gen(int, void (*)(int), int, const char *);
static void terminated(const char *);

#ifndef HAVE_ERR
static void
err(int code, const char *fmt, ...) {
va_list v;

va_start(v, fmt);
vfprintf(stderr, fmt, v);
va_end(v);

fprintf(stderr, ": %s\n", strerror(errno));
exit(code);
}

static void
errx(int code, const char *fmt, ...) {
va_list v;

va_start(v, fmt);
vfprintf(stderr, fmt, v);
va_end(v);

fprintf(stderr, "\n");
exit(code);
}

static void
warn(const char *fmt, ...) {
va_list v;

va_start(v, fmt);
vfprintf(stderr, fmt, v);
va_end(v);

fprintf(stderr, ": %s\n", strerror(errno));
}

static void
warnx(const char *fmt, ...) {
va_list v;

va_start(v, fmt);
vfprintf(stderr, fmt, v);
va_end(v);

fprintf(stderr, "\n");
}
#endif /* !HAVE_ERR */

static void
usage(void) {
errx(EX_USAGE, "usage: timelimit [-pq] [-S ksig] [-s wsig] "
"[-T ktime] [-t wtime] command");
}

static unsigned long
atou_fatal(const char *s) {
unsigned long v;
const char *p;

v = 0;
for (p = s; (*p >= '0') && (*p <= '9'); p++)
v = v * 10 + *p - '0';
if (*p != '\0')
usage();
return (v);
}

static void
init(int argc, char *argv[]) {
#ifdef PARSE_CMDLINE
int ch;
#endif
int optset;
unsigned i;
char *s;

/* defaults */
quiet = 0;
warnsig = SIGTERM;
killsig = SIGKILL;
warntime = 3600;
killtime = 120;

optset = 0;

/* process environment variables first */
for (i = 0; envopts[i].name != NULL; i++)
if ((s = getenv(envopts[i].name)) != NULL) {
*envopts[i].var = atou_fatal(s);
optset = 1;
}

#ifdef PARSE_CMDLINE
while ((ch = getopt(argc, argv, "+qpS:s:T:t:")) != EOF) {
switch (ch) {
case 'p':
propagate = 1;
break;
case 'q':
quiet = 1;
break;
default:
/* check if it's a recognized option */
for (i = 0; envopts[i].name != NULL; i++)
if (ch == envopts[i].opt) {
*envopts[i].var =
atou_fatal(optarg);
optset = 1;
break;
}
if (envopts[i].name == NULL)
usage();
}
}
#else
optind = 1;
#endif

if (!optset) /* && !quiet? */
warnx("using defaults: warntime=%lu, warnsig=%lu, "
"killtime=%lu, killsig=%lu",
warntime, warnsig, killtime, killsig);

argc -= optind;
argv += optind;
if (argc == 0)
usage();

/* sanity checks */
if ((warntime == 0) || (killtime == 0))
usage();
}

static void
sigchld(int sig __unused) {

fdone = 1;
}

static void
sigalrm(int sig __unused) {

falarm = 1;
}

static void
sighandler(int sig) {

sigcaught = sig;
fsig = 1;
}

static void
setsig_fatal(int sig, void (*handler)(int)) {

setsig_fatal_gen(sig, handler, 1, "setting");
}

static void
setsig_fatal_gen(int sig, void (*handler)(int), int nocld, const char *what) {
#ifdef HAVE_SIGACTION
struct sigaction act;

memset(&act, 0, sizeof(act));
act.sa_handler = handler;
act.sa_flags = 0;
#ifdef SA_NOCLDSTOP
if (nocld)
act.sa_flags |= SA_NOCLDSTOP;
#endif /* SA_NOCLDSTOP */
if (sigaction(sig, &act, NULL) < 0)
err(EX_OSERR, "%s signal handler for %d", what, sig);
#else /* HAVE_SIGACTION */
if (signal(sig, handler) == SIG_ERR)
err(EX_OSERR, "%s signal handler for %d", what, sig);
#endif /* HAVE_SIGACTION */
}

static pid_t
doit(char *argv[]) {
pid_t pid;

/* install signal handlers */
fdone = falarm = fsig = sigcaught = 0;
setsig_fatal(SIGALRM, sigalrm);
setsig_fatal(SIGCHLD, sigchld);
setsig_fatal(SIGTERM, sighandler);
setsig_fatal(SIGHUP, sighandler);
setsig_fatal(SIGINT, sighandler);
setsig_fatal(SIGQUIT, sighandler);

/* fork off the child process */
if ((pid = fork()) < 0)
err(EX_OSERR, "fork");
if (pid == 0)
child(argv);

/* sleep for the allowed time */
alarm(warntime);
while (!(fdone || falarm || fsig))
pause();
alarm(0);

/* send the warning signal */
if (fdone)
return (pid);
if (fsig)
terminated("run");
falarm = 0;
if (!quiet)
warnx("sending warning signal %lu", warnsig);
kill(pid, (int) warnsig);

#ifndef HAVE_SIGACTION
/* reset our signal handlers, just in case */
setsig_fatal(SIGALRM, sigalrm);
setsig_fatal(SIGCHLD, sigchld);
setsig_fatal(SIGTERM, sighandler);
setsig_fatal(SIGHUP, sighandler);
setsig_fatal(SIGINT, sighandler);
setsig_fatal(SIGQUIT, sighandler);
#endif /* HAVE_SIGACTION */

/* sleep for the grace time */
alarm(killtime);
while (!(fdone || falarm || fsig))
pause();
alarm(0);

/* send the kill signal */
if (fdone)
return (pid);
if (fsig)
terminated("grace");
if (!quiet)
warnx("sending kill signal %lu", killsig);
kill(pid, (int) killsig);
return (pid);
}

static void
terminated(const char *period) {

errx(EX_SOFTWARE, "terminated by signal %d during the %s period",
sigcaught, period);
}

static void
child(char *argv[]) {

execvp(argv[0], argv);
err(EX_OSERR, "executing %s", argv[0]);
}

static __dead2 void
raisesignal (int sig) {

setsig_fatal_gen(sig, SIG_DFL, 0, "restoring");
raise(sig);
while (1)
pause();
/* NOTREACHED */
}

int
main(int argc, char *argv[]) {
pid_t pid;
int status;

init(argc, argv);
argc -= optind;
argv += optind;
pid = doit(argv);

if (waitpid(pid, &status, 0) == -1)
errx(EX_OSERR, "could not get the exit status for process %ld",
(long)pid);
if (WIFEXITED(status))
return (WEXITSTATUS(status));
else if (!WIFSIGNALED(status))
return (EX_OSERR);
if (propagate)
raisesignal(WTERMSIG(status));
else
return (WTERMSIG(status) + 128);
}
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin