aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--NEWS76
-rw-r--r--README14
-rw-r--r--am/proctitle.m479
-rw-r--r--configure.ac5
m---------grecs0
-rw-r--r--src/Makefile.am1
-rw-r--r--src/com_start.c4
-rw-r--r--src/com_stop.c67
-rw-r--r--src/genrc.8140
-rw-r--r--src/genrc.c234
-rw-r--r--src/genrc.h14
-rw-r--r--src/pid_ps.c4
-rw-r--r--src/pidlist.c2
-rw-r--r--src/proctitle.c160
-rw-r--r--src/sentinel.c184
-rw-r--r--src/transform.c10
17 files changed, 859 insertions, 137 deletions
diff --git a/Makefile.am b/Makefile.am
index bb011c5..bf3a9d1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-ACLOCAL_AMFLAGS = -I runcap
+ACLOCAL_AMFLAGS = -I am -I runcap
SUBDIRS = grecs runcap src
dist: ChangeLog
.PHONY: ChangeLog
diff --git a/NEWS b/NEWS
index 57d7295..70bacd4 100644
--- a/NEWS
+++ b/NEWS
@@ -1,9 +1,79 @@
-genrc NEWS -- history of user-visible changes. 2018-05-20
-Copyright (C) 2018 Sergey Poznyakoff
+genrc NEWS -- history of user-visible changes. 2022-05-13
See the end of file for copying conditions.
Please send genrc bug reports to <gray@gnu.org> or <gray@gnu.org.ua>
+Version 1.3.91 (git)
+
+* New option -k (--kill-mode)
+
+The option determines how the termination sequence for the program.
+Its argument can be:
+
+ group
+ Send both the SIGTERM and subsequent SIGKILL (if necessary) to the
+ process control group of the command.
+ process
+ Send both the SIGTERM and subsequent SIGKILL (if necessary) to the
+ main process of the command.
+ mixed
+ Send SIGTERM to the process and subsequent SIGKILL to the process
+ control group.
+
+
+Version 1.3, 2021-07-08
+
+* Fix the --timeout option
+
+
+Version 1.2, 2020-09-09
+
+* Verbose diagnostics
+
+Verbose diagnostics is enabled by the -v,--verbose option.
+
+* Shell selection
+
+By default, the program is started using "/bin/sh -c". Two options
+are provided to alter this behavior:
+
+ -s, --shell=SHELL
+ Use SHELL to start the program. Default is /bin/sh.
+
+ -e, --exec
+ In sentinel mode, run the command directly via exec(3), instead
+ of via the shell.
+
+* Syslog
+
+In sentinel mode, the syslog facility and tag can be changed:
+
+ --log-facility=F
+ Use syslog facility F instead of the default "daemon".
+ (equivalent environment variable - GENRC_LOG_FACILITY)
+
+ --log-tag=S
+ Use syslog tag S instead of the program name.
+ (equivalent environment variable - GENRC_LOG_TAG)
+
+* Runtime resource limits
+
+The --limit (-l) option is provided to control the resource usage.
+Its argument is a resource designator followed by the limit value
+for that resource. Resource designators are:
+
+ c Core file size (KB).
+ d Data size (KB).
+ f File size (KB).
+ l Locked-in-memory address space (KB).
+ m Resident set size (KB).
+ n Number of open files.
+ p Process priority (nice value), -20..20.
+ s Stack size (KB).
+ t CPU time (seconds).
+ u Number of subprocesses.
+ v Virtual memory size (KB).
+
Version 1.1, 2018-05-20
Implements restart mode.
@@ -34,7 +104,7 @@ Initial release
=========================================================================
Copyright information:
-Copyright (C) 2018 Sergey Poznyakoff
+Copyright (C) 2018-2022 Sergey Poznyakoff
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
diff --git a/README b/README
index e9a0c5b..e882a91 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
* Overview
-This is a generic helper program for writing system initialization
+genrc is a generic helper program for writing system initialization
scripts. Depending on the operation mode, it starts, stops,
reconfigures or displays the status of a specific program.
@@ -10,7 +10,7 @@ distribution.
In the contrast to another similar programs like start-stop-daemon,
it is designed so that the entire rc file can consist of only one
-line, invoking (or exec'ing) genrc with the right set of arguments.
+line, invoking (or exec'ing) genrc with a proper set of arguments.
* Example
@@ -28,11 +28,11 @@ exec /sbin/genrc \
This and newer versions of genrc can be downloaded from
- http://download.gnu.org.ua/release/genrc
+ https://download.gnu.org.ua/release/genrc
For the recent development sources, see
- http://git.gnu.org.ua/cgit/genrc.git
+ https://git.gnu.org.ua/genrc.git
* Building
@@ -45,7 +45,7 @@ When building from source package, usual incantations apply:
If you are building from a clone of the Git repository, you will need
GNU autotools to bootstrap the package first. Run
- autoreconf -f -i -s
+ ./bootstrap
in the top level source directory. This will create the configure
script and populate the directory with the missing files. Then proceed
@@ -53,7 +53,7 @@ as described above.
* Documentation
-Manpage genrc.8 included. After installing the package, run
+A manpage (genrc.8) is included. After installing the package, run
man genrc.
* Bug reporting.
@@ -63,7 +63,7 @@ Send bug reports to <gray@gnu.org>.
* Copyright information:
-Copyright (C) 2018 Sergey Poznyakoff
+Copyright (C) 2018-2022 Sergey Poznyakoff
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
diff --git a/am/proctitle.m4 b/am/proctitle.m4
new file mode 100644
index 0000000..d01cebe
--- /dev/null
+++ b/am/proctitle.m4
@@ -0,0 +1,79 @@
+dnl This file is part of Mailfromd.
+dnl Copyright (C) 2008-2022 Sergey Poznyakoff
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+AC_DEFUN([MF_PROCTITLE],[
+ AH_TEMPLATE([MF_PROCTITLE_TYPE], [Type of setproctitle implementation])
+ AH_BOTTOM([
+#define MF_PROCTITLE_SETPROCTITLE 0
+#define MF_PROCTITLE_REPLACE_ARGV 1
+#define MF_PROCTITLE_REWRITE_ARGV 2
+#define MF_PROCTITLE_PSTAT 3
+#define MF_PROCTITLE_PSSTRINGS 4
+])
+ AC_SUBST(MF_PROCTITLE_LIBS)
+
+ AC_TRY_LINK([extern char *__progname, *__progname_full;],
+ [__progname = "foo"; __progname_full = "foo bar";],
+ [AC_DEFINE(HAVE___PROGNAME, 1,
+ [Define to 1 if libc has __progname])])
+
+ mf_proctitle_type=no
+ AC_CHECK_FUNC(setproctitle,
+ [mf_proctitle_type=MF_PROCTITLE_SETPROCTITLE],
+ [AC_CHECK_HEADERS(libutil.h)
+ AC_CHECK_LIB(util, setproctitle,
+ [mf_proctitle_type=MF_PROCTITLE_SETPROCTITLE
+ MF_PROCTITLE_LIBS="-lutil"])])
+
+ if test "$mf_proctitle_type" = no; then
+ AC_CHECK_HEADER([sys/pstat.h],
+ [AC_CHECK_FUNC([pstat],
+ [mf_proctitle_type=MF_PROCTITLE_PSTAT],
+ [mf_proctitle_type=MF_PROCTITLE_REWRITE_ARGV])])
+ if test "$mf_proctitle_type" = no; then
+ AC_TRY_COMPILE([#include <machine/vmparam.h>
+ #include <sys/exec.h>],
+ [
+#include <sys/types.h>
+#include <sys/proc.h>
+#include <vm/pmap.h>
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+#include <sys/exec.h>
+
+main()
+{
+ int i = PS_STRINGS;
+}
+],
+ [mf_proctitle_type=MF_PROCTITLE_PSSTRINGS])
+
+ if test "$mf_proctitle_type" = no; then
+ AC_EGREP_CPP(yes,[
+#if defined(__GNU_HURD__)
+ yes
+#endif
+],
+ [mf_proctitle_type=MF_PROCTITLE_REPLACE_ARGV],
+ [mf_proctitle_type=MF_PROCTITLE_REWRITE_ARGV])
+ fi
+ fi
+ fi
+
+ AC_DEFINE_UNQUOTED([MF_PROCTITLE_TYPE],$mf_proctitle_type)
+
+])
+ \ No newline at end of file
diff --git a/configure.ac b/configure.ac
index 2610762..41ff5ef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
# This file is part of genrc. -*- Autoconf -*-
-# Copyright (C) 2018 Sergey Poznyakoff.
+# Copyright (C) 2018-2022 Sergey Poznyakoff.
#
# Genrc is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
# along with genrc. If not, see <http://www.gnu.org/licenses/>.
AC_PREREQ([2.69])
-AC_INIT([genrc], [1.1], [gray@gnu.org])
+AC_INIT([genrc], [1.3.91], [gray@gnu.org])
AC_CONFIG_SRCDIR([src/genrc.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([1.11 foreign silent-rules])
@@ -37,6 +37,7 @@ AC_CHECK_HEADERS([getopt.h pcre.h])
# Checks for library functions.
AC_CHECK_FUNCS([getdtablesize])
+MF_PROCTITLE
GRECS_SETUP(grecs, [all-parsers git2chg])
RUNCAP_SETUP
diff --git a/grecs b/grecs
-Subproject b06fb7d30415eec1d2efb39286ab96070c724fd
+Subproject 893d875a4065acb757fef55876c391b1dd07004
diff --git a/src/Makefile.am b/src/Makefile.am
index 168ab11..d0cf883 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,6 +27,7 @@ genrc_SOURCES = \
pid_ps.c\
pidlist.c\
procscan.c\
+ proctitle.c\
com_status.c\
com_start.c\
com_stop.c\
diff --git a/src/com_start.c b/src/com_start.c
index 17581cb..5ad1786 100644
--- a/src/com_start.c
+++ b/src/com_start.c
@@ -1,5 +1,5 @@
/* This file is part of genrc
-Copyryght (C) 2018, 2019 Sergey Poznyakoff
+Copyryght (C) 2018-2020 Sergey Poznyakoff
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
@@ -127,7 +127,7 @@ spawn(int *p)
execvp(argv[0], argv);
if (p) {
- openlog(genrc_program, LOG_PID, LOG_DAEMON);
+ genrc_openlog();
syslog(LOG_CRIT, "failed to exec: %m");
} else
system_error(errno, "failed to exec %s", genrc_program);
diff --git a/src/com_stop.c b/src/com_stop.c
index d57fa5e..ffa2ff9 100644
--- a/src/com_stop.c
+++ b/src/com_stop.c
@@ -1,5 +1,5 @@
/* This file is part of genrc
-Copyryght (C) 2018 Sergey Poznyakoff
+Copyryght (C) 2018-2022 Sergey Poznyakoff
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
@@ -17,38 +17,24 @@ timermul(struct timeval *a, int b)
#define MIN_POLL_TTW 20000
-int
-com_stop(void)
+static int
+pidlist_wait(PIDLIST *pids)
{
- PIDLIST pids;
struct timeval stoptime, before, after, ttw, maxttw;
int ratio;
-
- pidlist_init(&pids);
- if (get_pid_list(genrc_pid_closure, &pids)) {
- genrc_error("program status unknown");
- return 1;
- }
-
- if (pids.pidc == 0) {
- genrc_error("%s not running", genrc_program);
- return 1;
- }
-
- if (genrc_verbose)
- printf("Stopping %s\n", genrc_program);
gettimeofday(&stoptime, NULL);
stoptime.tv_sec += genrc_timeout;
ratio = 1;
- while (pids.pidc) {
+
+ /* Wait for the process to terminate */
+ while (pids->pidc) {
gettimeofday(&before, NULL);
if (timercmp(&before, &stoptime, >))
break;
- pidlist_kill(&pids, genrc_signal_stop);
- if (get_pid_list(genrc_pid_closure, &pids))
+ if (get_pid_list(genrc_pid_closure, pids))
break;
- if (pids.pidc == 0)
+ if (pids->pidc == 0)
return 0;
gettimeofday(&after, NULL);
if (timercmp(&after, &stoptime, >=))
@@ -69,7 +55,42 @@ com_stop(void)
break;
}
}
- return 1;
+ return pids->pidc > 0;
+}
+
+int
+com_stop(void)
+{
+ PIDLIST pids;
+
+ pidlist_init(&pids);
+ if (get_pid_list(genrc_pid_closure, &pids)) {
+ genrc_error("program status unknown");
+ return 1;
+ }
+
+ if (pids.pidc == 0) {
+ genrc_error("%s not running", genrc_program);
+ return 1;
+ }
+
+ if (genrc_verbose)
+ printf("Stopping %s\n", genrc_program);
+
+ /* Send the stop signal */
+ if (genrc_kill_mode == genrc_kill_group && pids.pidc == 1)
+ pids.pidv[0] = - pids.pidv[0];
+ pidlist_kill(&pids, genrc_signal_stop);
+
+ /* Wait for the process to terminate */
+ if (pidlist_wait(&pids)) {
+ /* Forcefully terminate the remaining processes */
+ if (genrc_kill_mode == genrc_kill_mixed && pids.pidc == 1)
+ pids.pidv[0] = - pids.pidv[0];
+ pidlist_kill(&pids, SIGKILL);
+ return pidlist_wait(&pids);
+ }
+ return 0;
}
diff --git a/src/genrc.8 b/src/genrc.8
index ed077bf..beb599c 100644
--- a/src/genrc.8
+++ b/src/genrc.8
@@ -1,5 +1,5 @@
.\" This file is part of genrc.
-.\" Copyright (C) 2018, 2019 Sergey Poznyakoff.
+.\" Copyright (C) 2018-2022 Sergey Poznyakoff.
.\"
.\" Genrc is free software; you can redistribute it and/or modify
.\" it under the terms of the GNU General Public License as published by
@@ -13,7 +13,7 @@
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with genrc. If not, see <http://www.gnu.org/licenses/>.
-.TH GENRC 8 "July 11, 2019" "GENRC" "Genrc User Manual"
+.TH GENRC 8 "March 26, 2022" "GENRC" "Genrc User Manual"
.SH NAME
genrc \- generic system initialization script helper
.SH SYNOPSIS
@@ -25,6 +25,8 @@ genrc \- generic system initialization script helper
[\fB\-P\fR \fISOURCE\fR]\
[\fB\-c\fR \fICOMMAND\fR]\
[\fB\-g\fR \fIGROUP\fR[,\fIGROUP\fR...]]\
+ [\fB\-l\fR \fILIMIT\fR]\
+ [\fB\-k\fR \fIMODE\fR]\
[\fB\-p\fR \fIPROGRAM\fR]\
[\fB\-s\fR \fISHELL\fR]\
[\fB\-t\fR \fISECONDS\fR]\
@@ -34,6 +36,10 @@ genrc \- generic system initialization script helper
[\fB\-\-exec\fR]\
[\fB\-\-group=\fIGROUP\fR[,\fIGROUP\fR...]]\
[\fB\-\-help\fR]\
+ [\fB\-\-kill\-mode=\fIMODE\fR]\
+ [\fB\-\-log\-facility=\fIFACILITY\fR]\
+ [\fB\-\-log\-tag=\fITAG\fR]\
+ [\fB\-\-limit=\fILIMIT\fR]\
[\fB\-\-no\-reload\fR]\
[\fB\-\-pid\-from=\fISOURCE\fR]\
[\fB\-\-pidfile=\fIPIDFILE\fR]\
@@ -65,7 +71,7 @@ genrc \- generic system initialization script helper
.B genrc
is a generic helper program for writing system initialization
scripts. Depending on the operation mode, it starts, stops,
-reconfigures or displays the status of a specific program.
+reconfigures or displays current status of a specific program.
.PP
The operation mode of the program is set by its only mandatory
argument. Other program settings are specified via the command
@@ -86,7 +92,7 @@ will be used as the command to run.
.PP
The program operation modes are:
.SS start
-If given \fBstart\fR argument, \fBgenrc\fR runs the supplier
+If given this argument, \fBgenrc\fR runs the supplied
command. Before, it checks if the program is not already running and
refuses to start its second copy if so.
.PP
@@ -94,7 +100,7 @@ It is supposed that the program to be run will detach from the
controlling terminal and continue running in the background (i.e. it
is a \fIdaemon\fR, in UNIX sense). If it is not the case, use the
\fB\-\-sentinel\fR option. With this option, \fBgenrc\fR will start
-the command and will become daemon itself, controlling the execution
+the command and become a daemon, controlling the execution
of the program. It will exit when the command terminates. So long as
the command runs, \fBgenrc\fR will pipe its standard output and error
to syslog facility \fBdaemon\fR. The standard output will be logged
@@ -102,9 +108,9 @@ with the priority \fBinfo\fR and the error with the priority
\fBerr\fR.
.PP
If the \fB\-\-create\-pidfile=\fIFILENAME\fR option is given together with
-\fB\-\-sentinel\fR, the PID of the subsidiary command will be stored
+\fB\-\-sentinel\fR, the PID of the started command will be stored
in \fIFILE\fR. The file will be unlinked after the subsidiary command
-terminates. Unless the \fB\-\-pid\-from\fR option is given,
+terminates. Unless the \fB\-\-pid\-from\fR option is also given,
\fB\-\-pid\-from=FILE:\fIFILENAME\fR will be assumed.
.PP
In sentinel mode, it is possible to restart the program if it
@@ -113,8 +119,8 @@ controlled by the \fB\-\-restart\-on\-exit\fR and
\fB\-\-restart\-on\-signal\fR options. Use this feature to ensure the
service provided by the program won't get terminated because of
hitting a bug or encountering an unforeseen external condition. For
-example, the following two options will ensure that the program will
-be terminated only if it exits with status 0 or it is terminated by
+example, the following two options make sure that the program will
+be terminated only if it exits with status 0 or is delivered the
SIGTERM or SIGQUIT signal:
.EX
--restart-on-exit='!0' --restart-on-signal='!TERM,QUIT'
@@ -134,36 +140,47 @@ the program restarted again.
In \fBstatus\fR mode \fBgenrc\fR verifies if the \fICOMMAND\fR is
already running and outputs its status on the standard output. To this
effect, it uses an abstraction called \fIPID source\fR, which allows
-it to determine the PID of the program by its name of command line.
+it to determine the PID of the program.
.PP
The default PID source is the Linux \fB/proc\fR filesystem (or, if it
-is not available, the output of \fBps -ef\fR), which is scanned for
-the name of the program (given by \fB\-\-program\fR or
+is not available, the output of \fBps -efw\fR), which is scanned for
+the name of the program (as given by \fB\-\-program\fR or
\fB\-\-command\fR options).
.PP
The source to use can be supplied with the \fB\-\-pid\-from\fR option
-(or the \fB\-\-pidfile option, which is equivalent to
+(or the \fB\-\-pidfile\R option, which is equivalent to
\fB\-\-pid\-from=FILE:\fR). See the section \fBPID SOURCES\fR for a
detailed discussion of available sources.
.SS stop
In the \fBstop\fR mode \fBgenrc\fR stops the command by sending it
-\fBSIGTERM\fR (or another signal as supplied with the
+\fBSIGTERM\fR (or another signal, as supplied with the
\fB\-\-signal\-stop\fR option). If the PID source returns multiple
PIDs, by default only parent PID is selected. However, \fBgenrc\fR can
be instructed to signal all PIDs instead (see the \fBa\fR flag in the
description of \fBPROC\fR or \fBPS\fR PID source).
.PP
After sending the signal, the program will wait for all processes to
-terminate. It will report error if they don't terminate within 5
-seconds. This timeout can be changed using the \fB\-\-timeout\fR
+terminate. If they don't terminate within 5 seconds, \fBgenrc\fR will
+send the \fBSIGKILL\fR signal and wait another 5 seconds for them to
+terminate. The timeout can be changed using the \fB\-\-timeout\fR
option.
+.PP
+The way to send the signals to the program is determined by the
+\fB\-k\fR (\fB\-\-kill\-mode\fR) option. If its value is \fBgroup\fR,
+both \fBSIGTERM\fR and, if necessary subsequent \fBSIGKILL\fR will be
+sent to all processes in the process control group. This is the
+default mode if the command is a daemon (i.e., if \fB\-\-sentinel\fR)
+is not given). If the value is \fBprocess\fR, the signal will be sent
+to the process individually. Finally, if the value is \fBmixed\fR, the
+\fBSIGTERM\fR is sent to the main process, while the subsequent
+\fBSIGKILL\fR is sent to the control group of the process.
.SS restart
Restarts the program. It is equivalent to running
.B genrc stop
immediately followed by
.BR "genrc start" .
.SS reload
-Attempt to reload (or reconfigure) the program by sending it the
+Attempts to reload (or reconfigure) the program by sending it the
\fBSIGHUP\fR signal (or another signal, as given with the
\fB\-\-signal\-reload\fR option). The \fB\-\-no\-reload\fR or
\fB\-\-signal\-reload=0\fR option disables this behavior, making
@@ -208,10 +225,79 @@ Run program with this \fIGROUP\fR privileges. If the argument is a
list of groups, the first group becomes the principal, and the
rest of them supplementary groups. Each \fIGROUP\fR is either a group
name or a numeric group number prefixed with a plus sign. Whatever
-notation is used, it must exist in the system group database.
+notation is used, the groups must exist in the system group database.
See also the \fB\-\-user\fR option.
.TP
+\fB\-k\fR, \fB\-\-kill\-mode=\fIMODE\fR
+Specifies how to send termination signal to the main
+process. \fIMODE\fR is one of \fBgroup\fR (send termination signal to
+the process control group), \fBprocess\fR (send it to the process
+itself), or \fBmixed\fR (send termination signal to the process, and
+send subsequent \fBSIGKILL\fR to the program control group). Refer to
+the description of the \fBstop\fR command above for a detailed
+discussion of these three modes.
+.TP
+\fB\-l\fR, \fB\-\-limit=\fILIM\fR
+Set resource limit. \fILIM\fR is a resource letter followed by
+a value. Resource letters are:
+.RS
+.TP
+.B c
+Core file size (KB).
+.TP
+.B d
+Data size (KB).
+.TP
+.B f
+File size (KB).
+.TP
+.B l
+Locked-in-memory address space (KB).
+.TP
+.B m
+Resident set size (KB).
+.TP
+.B n
+Number of open files.
+.TP
+.B p
+Process priority (nice value), -20..20.
+.TP
+.B s
+Stack size (KB).
+.TP
+.B t
+CPU time (seconds).
+.TP
+.B u
+Number of subprocesses.
+.TP
+.B v
+Virtual memory size (KB).
+.RE
+.TP
+.TP
+\fB\-\-log\-facility=\fIFACILITY\fR
+Selects \fBsyslog\fR facility for use in sentinel mode. Valid arguments are
+.BR auth ,
+.BR authpriv ,
+.BR cron ,
+.BR daemon ,
+.BR ftp ,
+.BR lpr ,
+.BR mail ,
+.BR user ,
+and
+.BR local0
+through
+.BR local7 .
+The default is
+.BR daemon .
+.TP
+\fB\-\-log\-tag=\fITAG\fR
+Sets \fBsyslog\fR tag for use in sentinel mode.
+.TP
\fB\-\-no\-reload\fR
Makes \fBreload\fR equivalent to \fBrestart\fR.
.TP
@@ -250,6 +336,9 @@ terminal, start it and run in background until it terminates. The
program's stdout and stderr are sent to the syslog facility
\fBdaemon\fR, priorities \fBinfo\fR and \fBerr\fR, correspondingly.
+The default facility and syslog tag can be changed using the
+\fB\-\-log\-facility\fR and \fB\-\-log-tag\fR options.
+
See the options \fB\-\-restart\-on\-exit\fR and
\fB\-\-restart\-on\-signal\fR for details on how to restart the
program.
@@ -322,14 +411,14 @@ Configuration specified as fully-qualified keyword-value pairs
.RE
.TP
\fBGREP:\fIFILE\fB:s/\fIRX\fB/\fIREPL\fB/[\fIFLAGS\fR][\fB;\fR...]
-Grep for the first line in \fIFILE\fR that matches \fIRX\fR. If found, process
-replace the matched portion according to \fIREPL\fR and \fIFLAGS\fR. Use
+Grep for the first line in \fIFILE\fR that matches \fIRX\fR. If found,
+modify the matched portion according to \fIREPL\fR and \fIFLAGS\fR. Use
the resulting string as PID. More sed expressions can be supplied,
separated with semicolons.
.TP
\fBPROC\fR[\fB:\fR[\fIEXE\fR][\fB:\fIFLAGS\fR]]
Look for matching program in \fB/proc/\fIPID\fB/*\fR. If \fIEXE\fR is
-not supplied or empty, program name from \fB\-\-program\fR will be
+not supplied or empty, the program name from \fB\-\-program\fR will be
used. \fIFLAGS\fR are:
.RS
.TP
@@ -358,7 +447,7 @@ match real executable name (instead of argv0)
signal all matching PIDs
.RE
.TP
-\fBPS:\fR[\fB:\fR[\fIEXE\fR][:\fIFLAGS\fR]]
+\fBPS\fR[\fB:\fR[\fIEXE\fR][:\fIFLAGS\fR]]
Look for matching program in the output of \fBps \-ef\fR. \fIEXE\fR
and \fIFLAGS\fR are as described above.
.SH ENVIRONMENT
@@ -375,14 +464,17 @@ Influential environment variables and corresponding options:
\fBGENRC_SENTINEL=1\fR \fB\-\-sentinel\fR
\fBGENRC_CREATE_PIDFILE=\fINAME\fR \fB\-\-create\-pidfile=\fINAME\fR
\fBGENRC_USER=\fINAME\fR \fB\-\-user=\fINAME\fR
- \fBGENRC_GROUP=\fIGROUPS\fR \fB\-\-group=\fIGROUPS\fR
+ \fBGENRC_GROUP=\fIGROUPS\fR \fB\-\-group=\fIGROUPS\fR
+ \fBGENRC_KILL_MODE=\fIMODE\fR \fB\-\-kill\-mode=\fIMODE\fR
+ \fBGENRC_LOG_FACILITY=\fIF\fR \fB\-\-log\-facility=\fIF\fR
+ \fBGENRC_LOG_TAG=\fISTR\fR \fB\-\-log\-tag=\fISTR\fR
.fi
.SH AUTHORS
Sergey Poznyakoff
.SH "BUG REPORTS"
Report bugs to <gray@gnu.org>.
.SH COPYRIGHT
-Copyright \(co 2018 Sergey Poznyakoff
+Copyright \(co 2018 -- 2022 Sergey Poznyakoff
.br
.na
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
diff --git a/src/genrc.c b/src/genrc.c
index 3dccbda..c6ebcaf 100644
--- a/src/genrc.c
+++ b/src/genrc.c
@@ -1,11 +1,13 @@
/* This file is part of genrc
-Copyryght (C) 2018, 2019 Sergey Poznyakoff
+Copyryght (C) 2018-2022 Sergey Poznyakoff
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
*/
#include "genrc.h"
+#include <syslog.h>
#include <sys/ioctl.h>
+#include <sys/resource.h>
char *genrc_command;
char *genrc_program;
@@ -14,11 +16,13 @@ unsigned genrc_timeout = 5;
int genrc_no_reload;
int genrc_signal_stop = SIGTERM;
int genrc_signal_reload = SIGHUP;
+enum genrc_kill_mode genrc_kill_mode;
GENRC_PID_CLOSURE *genrc_pid_closure;
char *genrc_create_pidfile;
int genrc_verbose;
char *genrc_shell = SHELL;
-
+int genrc_log_facility = LOG_DAEMON;
+char *genrc_log_tag = NULL;
enum {
OPT_USAGE = 256,
@@ -29,6 +33,8 @@ enum {
OPT_CREATE_PIDFILE,
OPT_RESTART_ON_EXIT,
OPT_RESTART_ON_SIGNAL,
+ OPT_LOG_FACILITY,
+ OPT_LOG_TAG
};
struct option longopts[] = {
@@ -52,6 +58,10 @@ struct option longopts[] = {
{ "group", required_argument, 0, 'g' },
{ "restart-on-exit", required_argument, 0, OPT_RESTART_ON_EXIT },
{ "restart-on-signal", required_argument, 0, OPT_RESTART_ON_SIGNAL },
+ { "log-facility", required_argument, 0, OPT_LOG_FACILITY },
+ { "log-tag", required_argument, 0, OPT_LOG_TAG },
+ { "limit", required_argument, 0, 'l' },
+ { "kill-mode", required_argument, 0, 'k' },
{ NULL }
};
char shortopts[2*sizeof(longopts)/sizeof(longopts[0])];
@@ -206,14 +216,29 @@ char const *help_msg[] = {
" Otherwise, if COMMAND is set, but PROGRAM is not, PROGRAM is set to the",
" first word (in the shell sense) in COMMAND.",
"",
- "Runtime privileges:",
+ "Runtime privileges and limits:",
"",
" -u, --user=NAME run with this user privileges",
" -g, --group=GROUP[,GROUP...]]",
" run with this group(s) privileges",
+ " -l, --limit=LIM set resource limit; LIM is a resource letter",
+ " followed by the resource value; resource letters are:",
+ " c core file size (KB)",
+ " d data size (KB)",
+ " f file size (KB)",
+ " l locked-in-memory address space (KB)",
+ " m resident set size (KB)",
+ " n number of open files",
+ " p process priority -20..20",
+ " s stack size (KB)",
+ " t CPU time (seconds)",
+ " u number of subprocesses",
+ " v virtual memory (KB)",
"",
"Additional configuration:",
"",
+ " -k, --kill-mode=MODE set program termination mode: group, program,",
+ " or mixed",
" -t, --timeout=SECONDS time to wait for the program to start up or",
" terminate",
" -P, --pid-from=SOURCE where to look for PIDs of the running programs",
@@ -224,11 +249,16 @@ char const *help_msg[] = {
" --no-reload makes reload equivalent to restart",
" --signal-stop=SIG signal to send in order to terminate the program",
" (default: SIGTERM)",
+ " -v. --verbose enable verbose diagnostics",
"",
"Sentinel mode:",
"",
- " --sentinel PROGRAM runs in foreground; disconnect from the",
+ " -S, --sentinel PROGRAM runs in foreground; disconnect from the",
" controlling terminal, run it and act as a sentinel",
+ " --create-pidfile=FILE",
+ " store PID of the PROGRAM in FILE; implies",
+ " --pid-from=FILE:FILENAME, unless --pid-from is also",
+ " given",
" -s, --shell=SHELL use SHELL instead of /bin/sh;",
" --shell=none to exec PROGRAM directly",
" -e, --exec same as --shell=none",
@@ -238,6 +268,9 @@ char const *help_msg[] = {
" --restart-on-signal=[!]SIG[,...]",
" restart the program if it terminates on one of the",
" listed signals",
+ " --log-facility=FACILITY",
+ " log diagnostic messages to this syslog facility",
+ " --log-tag=TAG use this syslog tag instead of the program name",
"",
"Informational options:",
"",
@@ -254,6 +287,9 @@ char const *help_msg[] = {
" GENRC_SENTINEL=1 --sentinel",
" GENRC_USER=NAME --user=NAME",
" GENRC_GROUP=GROUPS --group=GROUPS",
+ " GENRC_LOG_FACILITY=F --log-facility=F",
+ " GENRC_LOG_TAG=STR --log-tag=STR",
+ " GENRC_KILL_MODE=MODE --kill-mode=MODE",
"",
"",
"PID sources:",
@@ -274,18 +310,18 @@ char const *help_msg[] = {
" PROC[:[<EXE>][:<FLAGS>]]",
" Look for matching program in /proc/<PID>/*. If <EXE> is not supplied",
" or empty, program name from --program will be used. <FLAGS> are:",
- " e exact match",
- " g glob pattern match",
- " x extended POSIX regexp match (default)",
- " p PCRE match",
- " i case-insensitive match",
+ " e exact match",
+ " g glob pattern match",
+ " x extended POSIX regexp match (default)",
+ " p PCRE match",
+ " i case-insensitive match",
"",
- " c match entire command line",
- " r match real executable name (instead of argv0)",
- " a signal all matching PIDs",
+ " c match entire command line",
+ " r match real executable name (instead of argv0)",
+ " a signal all matching PIDs",
"",
- " PS:[:[<EXE>][:<FLAGS>]]",
- " Look for matching program in the output of 'ps -ef'. <EXE> and <FLAGS>",
+ " PS[:[<EXE>][:<FLAGS>]]",
+ " Look for matching program in the output of 'ps -efw'. <EXE> and <FLAGS>",
" as described above",
"",
NULL
@@ -307,6 +343,8 @@ char const *usage_msg[] = {
"[-P SOURCE]",
"[-c COMMAND]",
"[-g GROUP[,GROUP...]]",
+ "[-k MODE]",
+ "[-l LIM]",
"[-p PROGRAM]",
"[-s SHELL]",
"[-t SECONDS]",
@@ -314,6 +352,10 @@ char const *usage_msg[] = {
"[--command=COMMAND]",
"[--group GROUP[,GROUP...]]",
"[--help]",
+ "[--kill-mode=MODE]",
+ "[--limit=LIM]",
+ "[--log-facility=FACILITY]",
+ "[--log-tag=TAG]",
"[--no-reload]",
"[--pid-from=SOURCE]",
"[--pidfile=PIDFILE]",
@@ -356,7 +398,85 @@ screen_width(void)
}
return ws.ws_col;
}
+
+static struct {
+ int letter;
+ int resource;
+ int is_set;
+ long val;
+} resource_tab[] = {
+ { 'c', RLIMIT_CORE },
+ { 'd', RLIMIT_DATA },
+ { 'f', RLIMIT_FSIZE },
+ { 'l', RLIMIT_MEMLOCK },
+ { 'm', RLIMIT_RSS },
+ { 'n', RLIMIT_NOFILE },
+ { 's', RLIMIT_STACK },
+ { 't', RLIMIT_CPU },
+ { 'u', RLIMIT_NPROC },
+ { 'v', RLIMIT_AS },
+ { 'p', 0 }
+};
+
+static int
+find_resource(int letter)
+{
+ int i;
+ for (i = 0; i < sizeof(resource_tab)/sizeof(resource_tab[0]); i++)
+ if (letter == resource_tab[i].letter)
+ return resource_tab[i].resource;
+ return -1;
+}
+
+void
+set_limit(char *arg)
+{
+ int r;
+ unsigned long v;
+ char *p;
+ struct rlimit rlim;
+ if ((r = find_resource(arg[0])) == -1) {
+ usage_error("%s: unrecognized resource code", arg);
+ }
+ if ((v = strtoul(arg + 1, &p, 10)) == ULONG_MAX && errno == ERANGE) {
+ usage_error("%s: resource value out of range", arg);
+ }
+ if (*p) {
+ usage_error("%s: value is not a number (stopped at %s)",
+ arg, p);
+ }
+
+ v *= 1024;
+ rlim.rlim_cur = v;
+ rlim.rlim_max = v;
+ if (setrlimit(r, &rlim))
+ genrc_error("%s: failed to set limit: %s", arg,
+ strerror(errno));
+}
+
+void
+set_nice(char *arg)
+{
+ long v;
+ char *p;
+
+ if ((((v = strtol(arg + 1, &p, 10)) == LONG_MAX || v == LONG_MIN)
+ && errno == ERANGE) ||
+ v < -20 ||
+ v > 20) {
+ usage_error("%s: resource value out of range", arg);
+ }
+ if (*p) {
+ usage_error("%s: value is not a number (stopped at %s)",
+ arg, p);
+ }
+ if (setpriority (PRIO_PROCESS, 0, v)) {
+ usage_error("failed to set process priority: %s",
+ strerror(errno));
+ }
+}
+
void
usage(void)
{
@@ -392,10 +512,48 @@ void
version(void)
{
printf("%s\n", PACKAGE_STRING);
- printf("Copyryght (C) 2018 Sergey Poznyakoff\n");
+ printf("Copyryght (C) 2018-2021 Sergey Poz