Compare commits

..

3 Commits

Author SHA1 Message Date
William Hubbs
12064291e9 version 0.47.1 2023-04-20 11:43:48 -05:00
Sam James
23f6ec028b shared: fix pointer type in UNCONST
Thanks to vapier for noticing.
2023-04-20 11:39:43 -05:00
Sam James
9d7f39603e Rename attribute macros to namespaced RC_*
This conflicts with linux-headers which uses __unused for some padding members
on ppc64le at least.

Closes: https://github.com/OpenRC/openrc/issues/622
2023-04-20 11:38:59 -05:00
37 changed files with 310 additions and 360 deletions

View File

@@ -4,8 +4,8 @@
test_task:
freebsd_instance:
matrix:
image: freebsd-13-2-release-amd64
image: freebsd-13-3-release-amd64
image: freebsd-13-1-release-amd64
image: freebsd-12-4-release-amd64
env:
OS: FreeBSD
procfs_script: >

52
NEWS.md
View File

@@ -4,58 +4,6 @@ OpenRC NEWS
This file will contain a list of notable changes for each release. Note
the information in this file is in reverse order.
## OpenRC 0.54
This release drops the support for the split-usr build option.
Also, it drops the support for ncurses/termcap and uses ansi codes
directly for color support on terminals that support them.
## OpenRC 0.53
The names of cgroups for services started by OpenRC are now prefixed by
"openrc." This is done because some services, like docker, create their
own cgroups.
It is now possible to override the mount options used to mount the
cgroups filesystems.
## OpenRC 0.52
This release drops the "runscript" and "rc" binaries.
These binaries have been deprecated for multiple years, so it should be
fine to remove them at this point.
There was an issue before this release with the default setting for
cgroups being inconsistent. This is fixed.
Start-stop-daemon did not work correctly on Linux 6.6 systems.
This has been fixed in this release as well.
## OpenRC 0.51
The default RC_CGROUP_MODE has been updated to unified.
This benefits users since it will assign each service to its own cgroup,
making resource nanagement better over all.
OUTPUT_LOGGER and ERROR_LOGGER have been implemented for
supervise-daemon. For mor einformation on these settings, please check
the man page.
## OpenRC 0.50
This is a bug fix release which fixes a significant performance issue on
musl libc systems.
## OpenRC 0.49
This release adds support for glibc's builtin
strlcpy, strlcat etc functions, which will be in posix next.
Also, it fixes completions.
## OpenRC 0.48
This release is a maintenance release; it has no user-facing changes.
## OpenRC 0.47
This release is primarily an internal cleanup release.

View File

@@ -92,11 +92,13 @@ _rc_service()
return 0
elif [[ ${COMP_CWORD} -eq 2 ]] && [[ ${prev} != -* ]]; then # if second word typed and we didn't type in a function
rc-service --exists "$prev" || return
shopt -s extglob
while read -r _ line; do
if [[ $line == +([[:alnum:]_]):* ]]; then
opts+="${line%%:*} "
fi
done < <(rc-service "$prev" describe 2>&1)
shopt -u extglob
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi

View File

@@ -1,2 +0,0 @@
# override cgroup mount options
#cgroup_opts=nodev,noexec,nosuid

View File

@@ -199,7 +199,7 @@ rc_tty_number=12
# cgroups version 1 on /sys/fs/cgroup.
# "legacy" mounts cgroups version 1 on /sys/fs/cgroup
# "unified" mounts cgroups version 2 on /sys/fs/cgroup
#rc_cgroup_mode="unified"
#rc_cgroup_mode="hybrid"
# This is a list of controllers which should be enabled for cgroups version 2
# when hybrid mode is being used.

View File

@@ -11,7 +11,7 @@
description="Mount the control groups."
: "${cgroup_opts:="nodev,noexec,nosuid"}"
cgroup_opts=nodev,noexec,nosuid
depend()
{
@@ -87,7 +87,7 @@ cgroup2_controllers()
[ ! -e "${cgroup_path}/cgroup.subtree_control" ]&& return 0
read -r active < "${cgroup_path}/cgroup.controllers"
for x in ${active}; do
case "${rc_cgroup_mode:-unified}" in
case "$rc_cgroup_mode" in
unified)
echo "+${x}" > "${cgroup_path}/cgroup.subtree_control"
;;
@@ -128,7 +128,7 @@ cgroups_unified()
mount_cgroups()
{
case "${rc_cgroup_mode:-unified}" in
case "${rc_cgroup_mode:-hybrid}" in
hybrid) cgroups_hybrid ;;
legacy) cgroups_legacy ;;
unified) cgroups_unified ;;

View File

@@ -158,6 +158,13 @@ is true.
prefixes the string
.Fa prefix
to the above functions.
.Sh IMPLEMENTATION NOTES
einfo can optionally be linked against the
.Lb libtermcap
so that we can correctly query the connected console for our color and
cursor escape codes.
If not, then we have a hard coded list of terminals we know about that support
the commonly used codes for color and cursor position.
.Sh ENVIRONMENT
.Va EINFO_QUIET
when set to true makes the

View File

@@ -84,8 +84,6 @@ Print the action(s) that would be taken, but don't actually do anything.
The return value is set as if the command was taken and worked.
.It Fl v , -verbose
Print the action(s) that are taken just before doing them.
.It Fl q , -quiet
Run quietly (repeat to suppress errors).
.It Fl P , -progress
Echo a . to the console for each second elapsed whilst waiting.
.El
@@ -185,6 +183,10 @@ Wait
after starting and check that daemon is still running.
Useful for daemons that check configuration after forking or stopping race
conditions where the pidfile is written out after forking.
.It Fl 2 , -stderr Ar logfile
The same thing as
.Fl 1 , -stdout
but with the standard error output.
.El
.Pp
These options are only used for stopping daemons:

View File

@@ -158,23 +158,6 @@ The logfile can also be a named pipe.
The same thing as
.Fl 1 , -stdout
but with the standard error output.
.It Fl -stdout-logger Ar cmd
Run cmd as a child process redirecting the standard output to the
standard input of cmd when started with
.Fl background .
Cmd must be an absolute pathname, but relative to the path optionally given with
.Fl r , -chroot .
This process must be prepared to accept input on stdin and be able to
log it or send it to another location.
.It Fl -stderr-logger Ar cmd
Run cmd as a child process and
Redirect the standard error of the process to the standard input of cmd
when started with
.Fl background .
Cmd must be an absolute pathname, but relative to the path optionally given with
.Fl r , -chroot .
This process must be prepared to accept input on stdin and be able to
log it or send it to another location.
.It Fl -capabilities Ar cap-list
Start the daemon with the listed inheritable, ambient and bounding capabilities.
The format is the same as in cap_iab(3).

View File

@@ -1,5 +1,5 @@
project('OpenRC', 'c',
version : '0.54',
version : '0.47.1',
license: 'BSD-2',
default_options : [
'c_std=c99',
@@ -83,9 +83,16 @@ else
pkg_prefix = option_pkg_prefix
endif
if get_option('split-usr') == 'auto'
split_usr = run_command('test', '-L', '/bin', check: false).returncode() != 0
else
split_usr = get_option('split-usr') == 'true'
endif
rootprefix = get_option('rootprefix')
rootprefix_default = fs.is_symlink('/bin') ? '/usr' : '/'
if rootprefix == ''
rootprefix = '/'
rootprefix = rootprefix_default
endif
bindir = rootprefix / get_option('bindir')
@@ -126,6 +133,15 @@ else
cc_selinux_flags = []
endif
termcap = get_option('termcap')
if termcap != ''
termcap_dep = dependency(termcap)
termcap_flags = '-DHAVE_TERMCAP'
else
termcap_dep = []
termcap_flags = []
endif
if get_option('buildtype').startswith('debug')
cc_debug_flags = ['-DRC_DEBUG']
else
@@ -160,10 +176,7 @@ cc_warning_flags_test = [
'-Wsequence-point',
'-Wshadow',
'-Wwrite-strings',
'-Werror=implicit-int',
'-Werror=implicit-function-declaration',
'-Werror=int-conversion',
'-Werror=incompatible-function-pointer-types',
]
cc_warning_flags = cc.get_supported_arguments(cc_warning_flags_test)
cc_flags = [cc_debug_flags, cc_os_flags, cc_warning_flags]
@@ -179,14 +192,12 @@ if cc.compiles(malloc_attribute_test, name : 'malloc attribute with arguments')
add_project_arguments('-DHAVE_MALLOC_EXTENDED_ATTRIBUTE', language: 'c')
endif
if cc.has_function('close_range', prefix: '#define _GNU_SOURCE\n#include <unistd.h>')
add_project_arguments('-DHAVE_CLOSE_RANGE', language: 'c')
elif cc.has_header('linux/close_range.h')
add_project_arguments('-DHAVE_LINUX_CLOSE_RANGE_H', language: 'c')
if cc.has_function('closefrom', prefix: '#define _GNU_SOURCE\n#include <unistd.h>')
add_project_arguments('-DHAVE_CLOSEFROM', language: 'c')
endif
if cc.has_function('strlcpy', prefix: '#define _GNU_SOURCE\n#include <string.h>')
add_project_arguments('-DHAVE_STRLCPY', language: 'c')
if cc.has_function('close_range', prefix: '#define _GNU_SOURCE\n#include <unistd.h>') and \
cc.has_header_symbol('unistd.h', 'CLOSE_RANGE_CLOEXEC', prefix: '#define _GNU_SOURCE')
add_project_arguments('-DHAVE_CLOSE_RANGE_CLOEXEC', language: 'c')
endif
incdir = include_directories('src/shared')

View File

@@ -26,7 +26,14 @@ option('selinux', type : 'feature', value : 'auto',
description : 'enable SELinux support')
option('shell', type : 'string', value : '/bin/sh',
description : 'Default posix compatible shell')
option('split-usr', type : 'combo',
choices : ['auto', 'true', 'false'],
description : '''/bin, /sbin aren't symlinks into /usr''')
option('sysvinit', type : 'boolean', value : false,
description : 'enable SysVinit compatibility (linux only)')
option('termcap', type : 'combo',
choices :
[ '', 'ncurses', 'termcap' ],
description : 'the termcap library to use')
option('zsh-completions', type : 'boolean',
description : 'install zsh completions')

View File

@@ -35,7 +35,7 @@ cgroup_get_pids()
cgroup_pids=
cgroup_procs="$(cgroup2_find_path)"
if [ -n "${cgroup_procs}" ]; then
cgroup_procs="${cgroup_procs}/openrc.${RC_SVCNAME}/cgroup.procs"
cgroup_procs="${cgroup_procs}/${RC_SVCNAME}/cgroup.procs"
else
cgroup_procs="/sys/fs/cgroup/openrc/${RC_SVCNAME}/tasks"
fi
@@ -154,7 +154,7 @@ cgroup_set_limits()
cgroup2_find_path()
{
if grep -qw cgroup2 /proc/filesystems; then
case "${rc_cgroup_mode:-unified}" in
case "${rc_cgroup_mode:-hybrid}" in
hybrid) printf "/sys/fs/cgroup/unified" ;;
unified) printf "/sys/fs/cgroup" ;;
esac
@@ -167,7 +167,7 @@ cgroup2_remove()
local cgroup_path rc_cgroup_path
cgroup_path="$(cgroup2_find_path)"
[ -z "${cgroup_path}" ] && return 0
rc_cgroup_path="${cgroup_path}/openrc.${RC_SVCNAME}"
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
[ ! -d "${rc_cgroup_path}" ] ||
[ ! -e "${rc_cgroup_path}"/cgroup.events ] &&
return 0
@@ -191,7 +191,7 @@ cgroup2_set_limits()
cgroup_path="$(cgroup2_find_path)"
[ -z "${cgroup_path}" ] && return 0
mountinfo -q "${cgroup_path}"|| return 0
rc_cgroup_path="${cgroup_path}/openrc.${RC_SVCNAME}"
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
[ -f "${rc_cgroup_path}"/cgroup.procs ] &&
printf 0 > "${rc_cgroup_path}"/cgroup.procs
@@ -210,7 +210,7 @@ cgroup2_kill_cgroup() {
local cgroup_path
cgroup_path="$(cgroup2_find_path)"
[ -z "${cgroup_path}" ] && return 1
rc_cgroup_path="${cgroup_path}/openrc.${RC_SVCNAME}"
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
if [ -f "${rc_cgroup_path}"/cgroup.kill ]; then
printf "%d" 1 > "${rc_cgroup_path}"/cgroup.kill
fi

View File

@@ -30,8 +30,6 @@ supervise_start()
${chroot:+--chroot} $chroot \
${output_log+--stdout} ${output_log} \
${error_log+--stderr} $error_log \
${output_logger:+--stdout-logger \"$output_logger\"} \
${error_logger:+--stderr-logger \"$error_logger\"} \
${pidfile:+--pidfile} $pidfile \
${respawn_delay:+--respawn-delay} $respawn_delay \
${respawn_max:+--respawn-max} $respawn_max \
@@ -40,7 +38,7 @@ supervise_start()
${healthcheck_timer:+--healthcheck-timer} $healthcheck_timer \
${capabilities+--capabilities} "$capabilities" \
${secbits:+--secbits} "$secbits" \
${no_new_privs:+--no-new-privs} \
${no_new_privs:+--no_new_privs} \
${command_user+--user} $command_user \
${umask+--umask} $umask \
${supervise_daemon_args-${start_stop_daemon_args}} \

View File

@@ -78,7 +78,7 @@ int main(int argc, char **argv)
if (strcmp(applet, "eend") == 0 ||
strcmp(applet, "ewend") == 0 ||
strcmp(applet, "veend") == 0 ||
strcmp(applet, "vewend") == 0 ||
strcmp(applet, "vweend") == 0 ||
strcmp(applet, "ewaitfile") == 0)
{
errno = 0;

View File

@@ -23,7 +23,6 @@
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <spawn.h>
/* Yay for linux and its non liking of POSIX functions.
Okay, we could use getfsent but the man page says use getmntent instead
@@ -64,8 +63,6 @@
#include "_usage.h"
#include "helpers.h"
extern char **environ;
const char *applet = NULL;
const char *extraopts = NULL;
const char getoptstring[] = "MRbmop:t:" getoptstring_COMMON;
@@ -115,7 +112,7 @@ do_mount(struct ENT *ent, bool remount)
{
char *argv[10];
pid_t pid;
int status, err;
int status;
argv[0] = UNCONST("mount");
argv[1] = UNCONST("-o");
@@ -140,14 +137,23 @@ do_mount(struct ENT *ent, bool remount)
argv[8] = NULL;
#endif
}
err = posix_spawnp(&pid, argv[0], NULL, NULL, argv, environ);
if (err)
eerrorx("%s: posix_spawnp: %s", applet, strerror(err));
while (waitpid(pid, &status, 0) < 0 && errno == EINTR);
if (WIFEXITED(status))
return WEXITSTATUS(status);
else
return -1;
switch (pid = vfork()) {
case -1:
eerrorx("%s: vfork: %s", applet, strerror(errno));
/* NOTREACHED */
case 0:
execvp(argv[0], argv);
eerror("%s: execvp: %s", applet, strerror(errno));
_exit(EXIT_FAILURE);
/* NOTREACHED */
default:
waitpid(pid, &status, 0);
if (WIFEXITED(status))
return WEXITSTATUS(status);
else
return -1;
/* NOTREACHED */
}
}
#define OUTPUT_FILE (1 << 1)

View File

@@ -69,22 +69,22 @@ void elog(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3);
* The x suffix means function will exit() returning failure.
*/
/*@{*/
int einfon(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int ewarnn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int eerrorn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int einfo(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int ewarn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
void ewarnx(const char * EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2);
int eerror(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
void eerrorx(const char * EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2);
int einfon(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int ewarnn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int eerrorn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int einfo(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int ewarn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
void ewarnx(const char * __EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2);
int eerror(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
void eerrorx(const char * __EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2);
int einfovn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int ewarnvn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int ebeginvn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int eendvn(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3);
int ewendvn(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3);
int einfov(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int ewarnv(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int einfovn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int ewarnvn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int ebeginvn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int eendvn(int, const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3);
int ewendvn(int, const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3);
int einfov(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
int ewarnv(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
/*@}*/
/*! @ingroup ebegin

View File

@@ -4,7 +4,7 @@
*/
/*
* Copyright (c) 2007-2024 The OpenRC Authors.
* Copyright (c) 2007-2015 The OpenRC Authors.
* See the Authors file at the top-level directory of this distribution and
* https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS
*
@@ -26,6 +26,9 @@
#include <string.h>
#include <strings.h>
#include <syslog.h>
#ifdef HAVE_TERMCAP
# include <termcap.h>
#endif
#include <unistd.h>
#include "einfo.h"
@@ -50,7 +53,8 @@
#define HILITE 6
#define BRACKET 4
/* ANSI escape codes which mimic termcap */
/* We fallback to these escape codes if termcap isn't available
* like say /usr isn't mounted */
#define AF "\033[3%dm"
#define CE "\033[K"
#define CH "\033[%dC"
@@ -93,7 +97,13 @@ static char *goto_column = NULL;
static const char *term = NULL;
static bool term_is_cons25 = false;
/* Hardcoded list of colour capable terms
/* Termcap buffers and pointers
* Static buffers suck hard, but some termcap implementations require them */
#ifdef HAVE_TERMCAP
static char termcapbuf[2048];
static char tcapbuf[512];
#else
/* No curses support, so we hardcode a list of colour capable terms
* Only terminals without "color" in the name need to be explicitly listed */
static const char *const color_terms[] = {
"Eterm",
@@ -132,11 +142,13 @@ static const char *const color_terms[] = {
"wsvt25",
"xterm",
"xterm-debian",
"xterm-kitty",
NULL
};
#endif
#ifndef HAVE_STRLCPY
/* strlcat and strlcpy are nice, shame glibc does not define them */
#ifdef __GLIBC__
# if !defined (__UCLIBC__) && !defined (__dietlibc__)
static size_t
strlcat(char *dst, const char *src, size_t size)
{
@@ -164,6 +176,7 @@ strlcat(char *dst, const char *src, size_t size)
return dst_n + (s - src);
}
# endif
#endif
static bool
@@ -226,6 +239,7 @@ is_verbose(void)
}
/* Fake tgoto call - very crapy, but works for our needs */
#ifndef HAVE_TERMCAP
static char *
tgoto(const char *cap, int col, int line)
{
@@ -288,6 +302,7 @@ tgoto(const char *cap, int col, int line)
*p = '\0';
return buf;
}
#endif
static bool
colour_terminal(FILE * EINFO_RESTRICT f)
@@ -300,6 +315,9 @@ colour_terminal(FILE * EINFO_RESTRICT f)
const char *bold;
char tmp[100];
unsigned int i = 0;
#ifdef HAVE_TERMCAP
char *bp;
#endif
if (f && !isatty(fileno(f)))
return false;
@@ -321,33 +339,65 @@ colour_terminal(FILE * EINFO_RESTRICT f)
if (strcmp(term, "cons25") == 0)
term_is_cons25 = true;
if (strstr(term, "color"))
in_colour = 1;
while (color_terms[i] && in_colour != 1) {
if (strcmp(color_terms[i], term) == 0) {
in_colour = 1;
}
i++;
#ifdef HAVE_TERMCAP
/* Check termcap to see if we can do colour or not */
if (tgetent(termcapbuf, term) == 1) {
bp = tcapbuf;
_af = tgetstr("AF", &bp);
_ce = tgetstr("ce", &bp);
_ch = tgetstr("ch", &bp);
/* Our ch use also works with RI .... for now */
if (!_ch)
_ch = tgetstr("RI", &bp);
_md = tgetstr("md", &bp);
_me = tgetstr("me", &bp);
_up = tgetstr("up", &bp);
}
if (in_colour != 1) {
/* Cheat here as vanilla BSD has the whole termcap info in /usr
* which is not available to us when we boot */
if (term_is_cons25 || strcmp(term, "wsvt25") == 0) {
#else
if (strstr(term, "color"))
in_colour = 1;
while (color_terms[i] && in_colour != 1) {
if (strcmp(color_terms[i], term) == 0) {
in_colour = 1;
}
i++;
}
if (in_colour != 1) {
in_colour = 0;
return false;
}
#endif
if (!_af)
_af = AF;
if (!_ce)
_ce = CE;
if (!_ch)
_ch = CH;
if (!_md)
_md = MD;
if (!_me)
_me = ME;
if (!_up)
_up = UP;
#ifdef HAVE_TERMCAP
}
if (!_af || !_ce || !_me || !_md || !_up) {
in_colour = 0;
return false;
}
if (!_af)
_af = AF;
if (!_ce)
_ce = CE;
/* Many termcap databases don't have ch or RI even though they
* do work */
if (!_ch)
_ch = CH;
if (!_md)
_md = MD;
if (!_me)
_me = ME;
if (!_up)
_up = UP;
#endif
/* Now setup our colours */
p = ebuffer;

View File

@@ -1,7 +1,9 @@
libeinfo_version = '1'
libeinfo = library('einfo', ['libeinfo.c'],
c_args : termcap_flags,
include_directories : incdir,
dependencies : termcap_dep,
link_depends : 'einfo.map',
version : libeinfo_version,
install : true,

View File

@@ -402,7 +402,7 @@ rc_service_daemon_set(const char *service, const char *exec,
bool retval = false;
DIR *dp;
struct dirent *d;
RC_STRINGLIST *match, *renamelist;
RC_STRINGLIST *match;
int i = 0;
FILE *fp;
@@ -416,17 +416,11 @@ rc_service_daemon_set(const char *service, const char *exec,
/* Regardless, erase any existing daemon info */
if ((dp = opendir(dirpath))) {
match = _match_list(exec, argv, pidfile);
renamelist = rc_stringlist_new();
while ((d = readdir(dp))) {
if (d->d_name[0] == '.')
continue;
xasprintf(&file, "%s/%s", dirpath, d->d_name);
if (rc_stringlist_find(renamelist, file)) {
free(file);
continue;
}
nfiles++;
if (!*oldfile) {
@@ -438,15 +432,11 @@ rc_service_daemon_set(const char *service, const char *exec,
} else {
rename(file, oldfile);
strlcpy(oldfile, file, sizeof(oldfile));
/* Add renamed file to renamelist, as this new file name could
* be read again from readdir() */
rc_stringlist_add(renamelist, oldfile);
}
free(file);
}
closedir(dp);
rc_stringlist_free(match);
rc_stringlist_free(renamelist);
}
/* Now store our daemon info */

View File

@@ -287,7 +287,6 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
overrides = rc_stringlist_new();
/* A list of variables which may be overridden on the kernel command line */
rc_stringlist_add(overrides, "rc_interactive");
rc_stringlist_add(overrides, "rc_parallel");
TAILQ_FOREACH(override, overrides, entries) {

View File

@@ -6,3 +6,12 @@ executable('openrc-run',
include_directories: [incdir, einfo_incdir, rc_incdir],
install: true,
install_dir: sbindir)
executable('runscript',
['openrc-run.c', misc_c, plugin_c, selinux_c, usage_c, version_h],
c_args : [cc_audit_flags, cc_branding_flags, cc_pam_flags, cc_selinux_flags],
link_with: [libeinfo, librc],
dependencies: [audit_dep, dl_dep, pam_dep, pam_misc_dep, selinux_dep, util_dep, crypt_dep],
include_directories: [incdir, einfo_incdir, rc_incdir],
install: true,
install_dir: sbindir)

View File

@@ -107,8 +107,7 @@ static RC_STRINGLIST *deptypes_mwua; /* need+want+use+after deps for stopping */
static void
handle_signal(int sig)
{
int serrno = errno, status;
pid_t pid;
int serrno = errno;
const char *signame = NULL;
struct winsize ws;
@@ -118,13 +117,12 @@ handle_signal(int sig)
break;
case SIGCHLD:
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
if (signal_pipe[1] > -1 && pid == service_pid) {
if (write(signal_pipe[1], &status, sizeof(status)) == -1)
eerror("%s: send: %s",
service, strerror(errno));
}
}
if (signal_pipe[1] > -1) {
if (write(signal_pipe[1], &sig, sizeof(sig)) == -1)
eerror("%s: send: %s",
service, strerror(errno));
} else
rc_waitpid(-1);
break;
case SIGWINCH:
@@ -440,7 +438,6 @@ svc_exec(const char *arg1, const char *arg2)
if (errno != EINTR) {
eerror("%s: poll: %s",
service, strerror(errno));
ret = -1;
break;
}
}
@@ -451,20 +448,9 @@ svc_exec(const char *arg1, const char *arg2)
write_prefix(buffer, bytes, &prefixed);
}
/* signal_pipe receives service_pid's exit status */
if (fd[0].revents & (POLLIN | POLLHUP)) {
if ((s = read(signal_pipe[0], &ret, sizeof(ret))) != sizeof(ret)) {
eerror("%s: receive failed: %s", service,
s < 0 ? strerror(errno) : "short read");
ret = -1;
break;
}
ret = WEXITSTATUS(ret);
if (ret != 0 && errno == ECHILD)
/* killall5 -9 could cause this */
ret = 0;
/* Only SIGCHLD signals come down this pipe */
if (fd[0].revents & (POLLIN | POLLHUP))
break;
}
}
}
@@ -487,6 +473,11 @@ svc_exec(const char *arg1, const char *arg2)
master_tty = -1;
}
ret = rc_waitpid(service_pid);
ret = WEXITSTATUS(ret);
if (ret != 0 && errno == ECHILD)
/* killall5 -9 could cause this */
ret = 0;
service_pid = 0;
return ret;
@@ -621,7 +612,7 @@ svc_start_check(void)
}
if (exclusive_fd == -1)
exclusive_fd = svc_lock(applet, !deps);
exclusive_fd = svc_lock(applet);
if (exclusive_fd == -1) {
if (errno == EACCES)
eerrorx("%s: superuser access required", applet);
@@ -873,7 +864,7 @@ svc_stop_check(RC_SERVICE *state)
exit(EXIT_FAILURE);
if (exclusive_fd == -1)
exclusive_fd = svc_lock(applet, !deps);
exclusive_fd = svc_lock(applet);
if (exclusive_fd == -1) {
if (errno == EACCES)
eerrorx("%s: superuser access required", applet);
@@ -1050,6 +1041,26 @@ svc_stop(void)
static void
svc_restart(void)
{
/* This is hairy and a better way needs to be found I think!
* The issue is this - openvpn need net and dns. net can restart
* dns via resolvconf, so you could have openvpn trying to restart
* dnsmasq which in turn is waiting on net which in turn is waiting
* on dnsmasq.
* The work around is for resolvconf to restart its services with
* --nodeps which means just that.
* The downside is that there is a small window when our status is
* invalid.
* One workaround would be to introduce a new status,
* or status locking. */
if (!deps) {
RC_SERVICE state = rc_service_state(service);
if (state & RC_SERVICE_STARTED || state & RC_SERVICE_INACTIVE)
svc_exec("stop", "start");
else
svc_exec("start", NULL);
return;
}
if (!(rc_service_state(service) & RC_SERVICE_STOPPED)) {
get_started_services();
svc_stop();
@@ -1097,6 +1108,7 @@ service_plugable(void)
int main(int argc, char **argv)
{
bool doneone = false;
bool runscript = false;
int retval, opt, depoptions = RC_DEP_TRACE;
RC_STRING *svc;
char *path = NULL;
@@ -1114,6 +1126,8 @@ int main(int argc, char **argv)
}
applet = basename_c(argv[0]);
if (strcmp(applet, "runscript") == 0)
runscript = true;
if (stat(argv[1], &stbuf) != 0) {
fprintf(stderr, "openrc-run `%s': %s\n",
@@ -1286,6 +1300,9 @@ int main(int argc, char **argv)
applet_list = rc_stringlist_new();
rc_stringlist_add(applet_list, applet);
if (runscript)
ewarn("%s uses runscript, please convert to openrc-run.", service);
/* Now run each option */
retval = EXIT_SUCCESS;
while (optind < argc) {

View File

@@ -6,3 +6,12 @@ executable('openrc',
include_directories: [incdir, einfo_incdir, rc_incdir],
install: true,
install_dir: sbindir)
executable('rc',
['rc.c', 'rc-logger.c', misc_c, plugin_c, usage_c, version_h],
c_args : cc_branding_flags,
link_with: [libeinfo, librc],
dependencies: [dl_dep, util_dep],
include_directories: [incdir, einfo_incdir, rc_incdir],
install: true,
install_dir: sbindir)

View File

@@ -87,7 +87,6 @@ static RC_HOOK hook_out;
struct termios *termios_orig = NULL;
RC_PIDLIST service_pids;
RC_PIDLIST free_these_pids;
static void
clean_failed(void)
@@ -117,7 +116,8 @@ clean_failed(void)
static void
cleanup(void)
{
RC_PID *p, *tmp;
RC_PID *p1 = LIST_FIRST(&service_pids);
RC_PID *p2;
if (!rc_in_logger && !rc_in_plugin &&
applet && (strcmp(applet, "rc") == 0 || strcmp(applet, "openrc") == 0))
@@ -139,13 +139,10 @@ cleanup(void)
rc_logger_close();
}
LIST_FOREACH_SAFE(p, &service_pids, entries, tmp) {
LIST_REMOVE(p, entries);
free(p);
}
LIST_FOREACH_SAFE(p, &free_these_pids, entries, tmp) {
LIST_REMOVE(p, entries);
free(p);
while (p1) {
p2 = LIST_NEXT(p1, entries);
free(p1);
p1 = p2;
}
rc_stringlist_free(main_hotplugged_services);
@@ -347,46 +344,22 @@ static char *get_krunlevel(void)
static void
add_pid(pid_t pid)
{
sigset_t sset, old;
RC_PID *p = xmalloc(sizeof(*p));
p->pid = pid;
/* this list will be accessed inside the SIGCHLD signal handler.
* so we need to ensure that the SIGCHLD handler doesn't get invoked
* while the list is at an inconsistent state.
*/
sigemptyset(&sset);
sigaddset(&sset, SIGCHLD);
sigprocmask(SIG_SETMASK, &sset, &old);
LIST_INSERT_HEAD(&service_pids, p, entries);
sigprocmask(SIG_SETMASK, &old, NULL);
}
static void
remove_pid(pid_t pid, bool inside_signal)
remove_pid(pid_t pid)
{
sigset_t sset, old;
RC_PID *p, *tmp;
RC_PID *p;
/* same rationale for blocking SIGCHLD as add_pid() */
sigemptyset(&sset);
sigaddset(&sset, SIGCHLD);
sigprocmask(SIG_SETMASK, &sset, &old);
LIST_FOREACH(p, &service_pids, entries) {
if (p->pid == pid) {
LIST_REMOVE(p, entries);
LIST_INSERT_HEAD(&free_these_pids, p, entries);
break;
}
}
/* only call free if we're not inside a signal handler */
if (!inside_signal) {
LIST_FOREACH_SAFE(p, &free_these_pids, entries, tmp) {
LIST_REMOVE(p, entries);
free(p);
}
}
sigprocmask(SIG_SETMASK, &old, NULL);
LIST_FOREACH(p, &service_pids, entries)
if (p->pid == pid) {
LIST_REMOVE(p, entries);
free(p);
return;
}
}
static void
@@ -424,7 +397,7 @@ handle_signal(int sig)
/* Remove that pid from our list */
if (pid > 0)
remove_pid(pid, true);
remove_pid(pid);
break;
case SIGWINCH:
@@ -527,7 +500,7 @@ runlevel_config(const char *service, const char *level)
char *conf, *dir;
bool retval;
dir = dirname(dirname(init));
dir = dirname(init);
xasprintf(&conf, "%s/conf.d/%s.%s", dir, service, level);
retval = exists(conf);
free(conf);
@@ -633,7 +606,7 @@ stop:
add_pid(pid);
if (!parallel) {
rc_waitpid(pid);
remove_pid(pid, false);
remove_pid(pid);
}
}
}
@@ -699,7 +672,7 @@ do_start_services(const RC_STRINGLIST *start_services, bool parallel)
add_pid(pid);
if (!parallel) {
rc_waitpid(pid);
remove_pid(pid, false);
remove_pid(pid);
}
}
}
@@ -772,7 +745,6 @@ int main(int argc, char **argv)
applet = basename_c(argv[0]);
LIST_INIT(&service_pids);
LIST_INIT(&free_these_pids);
atexit(cleanup);
if (!applet)
eerrorx("arguments required");
@@ -837,6 +809,8 @@ int main(int argc, char **argv)
}
}
if (strcmp(applet, "rc") == 0)
ewarn("rc is deprecated, please use openrc instead.");
newlevel = argv[optind++];
/* To make life easier, we only have the shutdown runlevel as
* nothing really needs to know that we're rebooting.

View File

@@ -88,7 +88,7 @@ delete(const char *runlevel, const char *service)
errno = 0;
if (rc_service_delete(runlevel, service)) {
einfo("service %s deleted from runlevel %s",
einfo("service %s removed from runlevel %s",
service, runlevel);
return 1;
}
@@ -97,7 +97,7 @@ delete(const char *runlevel, const char *service)
eerror("%s: service `%s' is not in the runlevel `%s'",
applet, service, runlevel);
else
eerror("%s: failed to delete service `%s' from runlevel `%s': %s",
eerror("%s: failed to remove service `%s' from runlevel `%s': %s",
applet, service, runlevel, strerror (errno));
return retval;
@@ -144,7 +144,7 @@ static int
delstack(const char *runlevel, const char *stack)
{
if (rc_runlevel_unstack(runlevel, stack)) {
einfo("runlevel %s deleted from runlevel %s", stack, runlevel);
einfo("runlevel %s removed from runlevel %s", stack, runlevel);
return 1;
}
@@ -152,7 +152,7 @@ delstack(const char *runlevel, const char *stack)
eerror("%s: runlevel `%s' is not in the runlevel `%s'",
applet, stack, runlevel);
else
eerror("%s: failed to delete runlevel `%s' from runlevel `%s': %s",
eerror("%s: failed to remove runlevel `%s' from runlevel `%s': %s",
applet, stack, runlevel, strerror (errno));
return -1;

View File

@@ -37,8 +37,10 @@
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#ifndef HAVE_STRLCPY
#ifdef __GLIBC__
# if !defined (__UCLIBC__) && !defined (__dietlibc__)
# define strlcpy(dst, src, size) snprintf(dst, size, "%s", src)
# endif
#endif
#ifndef timespecsub

View File

@@ -10,10 +10,6 @@ schedules_c = files([
'schedules.c',
])
pipes_c = files([
'pipes.c',
])
if selinux_dep.found()
selinux_c = files([
'selinux.c',

View File

@@ -15,18 +15,10 @@
* except according to the terms contained in the LICENSE file.
*/
#ifdef HAVE_CLOSE_RANGE
/* For close_range() */
# define _GNU_SOURCE
#endif
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#ifdef HAVE_LINUX_CLOSE_RANGE_H
# include <linux/close_range.h>
#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -34,7 +26,6 @@
#include <sys/file.h>
#include <sys/time.h>
#ifdef __linux__
# include <sys/syscall.h> /* for close_range */
# include <sys/sysinfo.h>
#endif
#include <sys/types.h>
@@ -243,7 +234,7 @@ signal_setup_restart(int sig, void (*handler)(int))
}
int
svc_lock(const char *applet, bool ignore_lock_failure)
svc_lock(const char *applet)
{
char *file = NULL;
int fd;
@@ -254,14 +245,6 @@ svc_lock(const char *applet, bool ignore_lock_failure)
if (fd == -1)
return -1;
if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
if (ignore_lock_failure) {
/* Two services with a need b, and b's start()
* calling restart --no-deps on a would cause
* harmless errors: just ignore them.
* See https://github.com/OpenRC/openrc/issues/224
*/
exit(EXIT_SUCCESS);
}
eerror("Call to flock failed: %s", strerror(errno));
close(fd);
return -1;
@@ -291,7 +274,7 @@ exec_service(const char *service, const char *arg)
sigset_t old;
struct sigaction sa;
fd = svc_lock(basename_c(service), false);
fd = svc_lock(basename_c(service));
if (fd == -1)
return -1;
@@ -509,30 +492,3 @@ pid_t get_pid(const char *applet,const char *pidfile)
return pid;
}
#ifndef HAVE_CLOSE_RANGE
static inline int close_range(int first RC_UNUSED,
int last RC_UNUSED,
unsigned int flags RC_UNUSED)
{
#ifdef SYS_close_range
return syscall(SYS_close_range, first, last, flags);
#else
errno = ENOSYS;
return -1;
#endif
}
#endif
#ifndef CLOSE_RANGE_CLOEXEC
# define CLOSE_RANGE_CLOEXEC (1U << 2)
#endif
void
cloexec_fds_from(int first)
{
int i;
if (close_range(first, UINT_MAX, CLOSE_RANGE_CLOEXEC) < 0) {
for (i = getdtablesize() - 1; i >= first; --i)
fcntl(i, F_SETFD, FD_CLOEXEC);
}
}

View File

@@ -50,7 +50,7 @@ void env_filter(void);
void env_config(void);
int signal_setup(int sig, void (*handler)(int));
int signal_setup_restart(int sig, void (*handler)(int));
int svc_lock(const char *, bool);
int svc_lock(const char *);
int svc_unlock(const char *, int);
pid_t exec_service(const char *, const char *);
@@ -73,6 +73,4 @@ void from_time_t(char *time_string, time_t tv);
time_t to_time_t(char *timestring);
pid_t get_pid(const char *applet, const char *pidfile);
void cloexec_fds_from(int);
#endif

View File

@@ -1,5 +1,5 @@
executable('start-stop-daemon',
['start-stop-daemon.c', pipes_c, misc_c, schedules_c,
['start-stop-daemon.c', 'pipes.c', misc_c, schedules_c,
selinux_c, usage_c, version_h],
c_args : [cc_audit_flags, cc_branding_flags, cc_pam_flags, cc_cap_flags, cc_selinux_flags],
link_with: [libeinfo, librc],

View File

@@ -1098,7 +1098,12 @@ int main(int argc, char **argv)
|| rc_yesno(getenv("EINFO_QUIET")))
dup2(stderr_fd, STDERR_FILENO);
cloexec_fds_from(3);
#ifdef HAVE_CLOSEFROM
closefrom(3);
#else
for (i = getdtablesize() - 1; i >= 3; --i)
close(i);
#endif
if (scheduler != NULL) {
int scheduler_index;

View File

@@ -1,5 +1,5 @@
executable('supervise-daemon',
['supervise-daemon.c', pipes_c, misc_c, plugin_c, schedules_c, usage_c, version_h],
['supervise-daemon.c', misc_c, plugin_c, schedules_c, usage_c, version_h],
c_args : [cc_branding_flags, cc_pam_flags, cc_cap_flags, cc_selinux_flags],
link_with: [libeinfo, librc],
dependencies: [dl_dep, pam_dep, cap_dep, util_dep, selinux_dep],

View File

@@ -22,6 +22,11 @@
#define ONE_SECOND 1000000000
#define ONE_MS 1000000
#ifdef HAVE_CLOSE_RANGE_CLOEXEC
/* For close_range() */
# define _GNU_SOURCE
#endif
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
@@ -62,7 +67,6 @@ static struct pam_conv conv = { NULL, NULL};
#include "queue.h"
#include "rc.h"
#include "misc.h"
#include "pipes.h"
#include "plugin.h"
#include "schedules.h"
#include "_usage.h"
@@ -80,8 +84,6 @@ enum {
LONGOPT_OOM_SCORE_ADJ,
LONGOPT_NO_NEW_PRIVS,
LONGOPT_SECBITS,
LONGOPT_STDERR_LOGGER,
LONGOPT_STDOUT_LOGGER,
};
const char *applet = NULL;
@@ -113,8 +115,6 @@ const struct option longopts[] = {
{ "user", 1, NULL, 'u'},
{ "stdout", 1, NULL, '1'},
{ "stderr", 1, NULL, '2'},
{ "stdout-logger",1, NULL, LONGOPT_STDOUT_LOGGER},
{ "stderr-logger",1, NULL, LONGOPT_STDERR_LOGGER},
{ "reexec", 0, NULL, '3'},
longopts_COMMON
};
@@ -143,8 +143,6 @@ const char * const longopts_help[] = {
"Change the process user",
"Redirect stdout to file",
"Redirect stderr to file",
"Redirect stdout to process",
"Redirect stderr to process",
"reexec (used internally)",
longopts_help_COMMON
};
@@ -167,8 +165,6 @@ static int stdout_fd;
static int stderr_fd;
static char *redirect_stderr = NULL;
static char *redirect_stdout = NULL;
static char *stderr_process = NULL;
static char *stdout_process = NULL;
#ifdef TIOCNOTTY
static int tty_fd = -1;
#endif
@@ -558,12 +554,6 @@ RC_NORETURN static void child_process(char *exec, char **argv)
eerrorx("%s: unable to open the logfile"
" for stdout `%s': %s",
applet, redirect_stdout, strerror(errno));
} else if (stdout_process) {
stdout_fd = rc_pipe_command(stdout_process);
if (stdout_fd == -1)
eerrorx("%s: unable to open the logging process"
" for stdout `%s': %s",
applet, stdout_process, strerror(errno));
}
if (redirect_stderr) {
if ((stderr_fd = open(redirect_stderr,
@@ -572,22 +562,19 @@ RC_NORETURN static void child_process(char *exec, char **argv)
eerrorx("%s: unable to open the logfile"
" for stderr `%s': %s",
applet, redirect_stderr, strerror(errno));
} else if (stderr_process) {
stderr_fd = rc_pipe_command(stderr_process);
if (stderr_fd == -1)
eerrorx("%s: unable to open the logging process"
" for stderr `%s': %s",
applet, stderr_process, strerror(errno));
}
dup2(stdin_fd, STDIN_FILENO);
if (redirect_stdout || stdout_process || rc_yesno(getenv("EINFO_QUIET")))
if (redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
dup2(stdout_fd, STDOUT_FILENO);
if (redirect_stderr || stderr_process || rc_yesno(getenv("EINFO_QUIET")))
if (redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
dup2(stderr_fd, STDERR_FILENO);
cloexec_fds_from(3);
#ifdef HAVE_CLOSE_RANGE_CLOEXEC
if (close_range(3, UINT_MAX, CLOSE_RANGE_CLOEXEC) < 0)
#endif
for (i = getdtablesize() - 1; i >= 3; --i)
fcntl(i, F_SETFD, FD_CLOEXEC);
cmdline = make_cmdline(argv);
syslog(LOG_INFO, "Child command line: %s", cmdline);
free(cmdline);
@@ -1060,14 +1047,6 @@ int main(int argc, char **argv)
reexec = true;
break;
case LONGOPT_STDOUT_LOGGER: /* --stdout-logger "command to run for stdout logging" */
stdout_process = optarg;
break;
case LONGOPT_STDERR_LOGGER: /* --stderr-logger "command to run for stderr logging" */
stderr_process = optarg;
break;
case_RC_COMMON_GETOPT
}

View File

@@ -1,54 +1,55 @@
# Using supervise-daemon
Using supervise-daemon
======================
Beginning with OpenRC-0.21 we have our own daemon supervisor,
`supervise-daemon`, which can start a daemon and restart it if it
supervise-daemon., which can start a daemon and restart it if it
terminates unexpectedly.
The following is a brief guide on using this capability.
* **Use Default start, stop and status functions**.
* Use Default start, stop and status functions
If you write your own start, stop and status functions in your service
script, none of this will work. You must allow OpenRC to use the default
functions.
* **Daemons must not fork**.
Any daemon that you would like to have monitored by `supervise-daemon`
* Daemons must not fork
Any daemon that you would like to have monitored by supervise-daemon
must not fork. Instead, it must stay in the foreground. If the daemon
forks, the supervisor will be unable to monitor it.
If the daemon can be configured to not fork, this should be done in the
daemon's configuration file, or by adding a command line option that
instructs it not to fork to the `command_args_foreground` variable shown
instructs it not to fork to the command_args_foreground variable shown
below.
## Health checks
# Health Checks
Health checks are a way to make sure a service monitored by
`supervise-daemon` stays healthy. To configure a health check for a
service, you need to write a `healthcheck()` function, and optionally an
`unhealthy()` function in the service script. Also, you will need to set
the `healthcheck_timer` and optionally `healthcheck_delay` variables.
supervise-daemon stays healthy. To configure a health check for a
service, you need to write a healthcheck() function, and optionally an
unhealthy() function in the service script. Also, you will need to set
the healthcheck_timer and optionally healthcheck_delay variables.
### healthcheck() function
## healthcheck() function
The `healthcheck()` function is run repeatedly based on the settings of
the `healthcheck_*` variables. This function should return zero if the
The healthcheck() function is run repeatedly based on the settings of
the healthcheck_* variables. This function should return zero if the
service is currently healthy or non-zero otherwise.
### unhealthy() function
## unhealthy() function
If the `healthcheck()` function returns non-zero, the `unhealthy()` function
If the healthcheck() function returns non-zero, the unhealthy() function
is run, then the service is restarted. Since the service will be
restarted by the supervisor, the unhealthy function should not try to
restart it; the purpose of the function is to allow any cleanup tasks
other than restarting the service to be run.
## Variable settings
# Variable Settings
The most important setting is the supervisor variable. At the top of
your service script, you should set this variable as follows:
```sh
``` sh
supervisor=supervise-daemon
```
@@ -56,29 +57,29 @@ Several other variables affect the way services behave under
supervise-daemon. They are documented on the openrc-run man page, but I
will list them here for convenience:
```sh
``` sh
command_args_foreground="arguments"
```
This should be used if the daemon you want to monitor
This should be used if the daemon you want to monitor
forks and goes to the background by default. This should be set to the
command line option that instructs the daemon to stay in the foreground.
```sh
``` sh
healthcheck_delay=seconds
```
This is the delay, in seconds, before the first health check is run.
If it is not set, we use the value of `healthcheck_timer`.
If it is not set, we use the value of healthcheck_timer.
```sh
``` sh
healthcheck_timer=seconds
```
This is the number of seconds between health checks. If it is not set,
no health checks will be run.
```sh
``` sh
respawn_delay
```
@@ -86,7 +87,7 @@ This is the number of seconds to delay before attempting to respawn a
supervised process after it dies unexpectedly.
The default is to respawn immediately.
```sh
``` sh
respawn_max=x
```
@@ -94,17 +95,17 @@ This is the maximum number of times to respawn a supervised process
during the given respawn period.
The default is 10. 0 means unlimited.
```sh
``` sh
respawn_period=seconds
```
This works in conjunction with `respawn_max` and `respawn_delay` above to
This works in conjunction with respawn_max and respawn_delay above to
decide if a process should not be respawned for some reason.
For example, if respawn period is 10 and `respawn_max` is 2, the process
For example, if respawn period is 10 and respawn_max is 2, the process
would need to die 3 times within 10 seconds to no longer be respawned.
Note that `respawn_delay` will delay all of this, so in the above scenario
a `respawn_delay` of greater than 5 will cause infinite respawns.
Note that respawn_delay will delay all of this, so in the above scenario
a respawn_delay of greater than 5 will cause infinite respawns.
By default, this is unset and `respawn_max` applies to the entire lifetime
By default, this is unset and respawn_max applies to the entire lifetime
of the service.

View File

@@ -11,7 +11,8 @@ sysvinit="$4"
if [ "${os}" != Linux ]; then
install -d "${DESTDIR}/${rc_libexecdir}"/init.d
fi
install -d "${DESTDIR}/${rc_libexecdir}"/tmp
install -m 644 "${MESON_BUILD_ROOT}/src/shared/version" "${DESTDIR}/${rc_libexecdir}"
if [ "${os}" = Linux ] && [ "${sysvinit}" = yes ]; then
ln -sf openrc-init "${DESTDIR}/${sbindir}"/init
ln -s openrc-init "${DESTDIR}/${sbindir}"/init
fi