Compare commits

..

28 Commits
0.37 ... 0.34.6

Author SHA1 Message Date
William Hubbs
b98e83ee91 Update ChangeLog 2017-11-07 16:01:08 -06:00
William Hubbs
d59197fafe start-stop-daemon: do not use do_stop to verify whether a daemon is running
X-Gentoo-Bug: 636574
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=636574
2017-11-07 15:38:11 -06:00
William Hubbs
b66c86c9ee version 0.34.6 2017-11-07 15:37:43 -06:00
William Hubbs
f7eb236f6f Update ChangeLog 2017-10-30 18:23:40 -05:00
William Hubbs
1936d73eb1 fix issue with --reexec call 2017-10-30 18:23:11 -05:00
William Hubbs
58872fc090 version 0.34.5 2017-10-30 18:23:00 -05:00
William Hubbs
fc35eb90ca Update ChangeLog 2017-10-27 19:28:31 -05:00
William Hubbs
b18be3f970 supervise-daemon: use RC_SVCNAME as the first argument to the daemon
This makes ps show which service the supervisor is monitoring.
2017-10-27 19:25:40 -05:00
William Hubbs
027438f775 supervise-daemon: fix logging for reexec and the child command line 2017-10-27 17:36:56 -05:00
William Hubbs
93e159ae85 log as supervise-daemon not the service 2017-10-27 15:32:26 -05:00
William Hubbs
bcfcf50562 version 0.34.4 2017-10-27 10:46:46 -05:00
William Hubbs
d0097cc10f Update ChangeLog 2017-10-26 14:16:36 -05:00
William Hubbs
eecf868e3c supervise-daemon: clarify a log message 2017-10-26 14:15:40 -05:00
William Hubbs
a5cd486a7f Update ChangeLog 2017-10-26 14:03:55 -05:00
William Hubbs
6e6b4ac5fa supervise-daemon: log the command line we run to spawn the child process 2017-10-26 14:01:07 -05:00
William Hubbs
558ff4d5fb supervise-daemon: log with the service name instead of "supervise-daemon" 2017-10-26 14:01:07 -05:00
William Hubbs
490f855aef implement "unsupervised" status
The unsupervised status is to be used when a supervisor of a supervised
service dies but leaves the service daemon itself running.
2017-10-26 13:18:16 -05:00
William Hubbs
d1491e201d supervise-daemon: remove child_pid from saved options during shutdown
This allows us to detect when the supervisor dies unexpectedly because
in that case child_pid will still exist.
2017-10-26 13:18:16 -05:00
William Hubbs
3231af9375 rc_service_value_set: remove the option if NULL is the value
This allows the equivalent of "unsetting" a value for a service.
2017-10-26 13:18:16 -05:00
William Hubbs
a5758e7aef supervise-daemon.sh: fix status function with no namespaces 2017-10-26 13:18:16 -05:00
Patrick McLean
61a9393ce1 cgroups_cleanup: clean up shutdown signaling
- do not sleep for the full 90 seconds if processes are dead
- re-arrange the order of signals we attempt to send to the processes
2017-10-26 13:18:16 -05:00
William Hubbs
161d22cb07 version 0.34.3 2017-10-26 13:17:54 -05:00
William Hubbs
3a96ca1c96 Update ChangeLog 2017-10-25 15:15:53 -05:00
William Hubbs
934530914b add "unsupervised" status and return code 64 to supervise-daemon status function
This is to be used if the service is being supervised and the
supervisor is somehow killed.

Currently, this is very linux specific, but I will expand to other
platforms, patches are welcome.
2017-10-25 15:14:33 -05:00
William Hubbs
b717625cd2 version 0.34.2 2017-10-25 15:13:09 -05:00
William Hubbs
b475396134 Update ChangeLog 2017-10-24 17:02:45 -05:00
William Hubbs
e7b1d898ca supervise-daemon: fix build issue for >=glibc-2.26
X-Gentoo-Bug: 635334
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=635334
2017-10-24 17:02:14 -05:00
William Hubbs
5cd09a6f44 version 0.34.1 2017-10-24 17:00:57 -05:00
109 changed files with 1728 additions and 3101 deletions

View File

@@ -1,5 +1,4 @@
Using Busybox as your Default Shell with OpenRC
===============================================
# Using Busybox as your Default Shell with OpenRC
If you have/bin/sh linked to busybox, you need to be aware of several
incompatibilities between busybox's applets and the standalone

2042
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,11 @@
Features Scheduled for Removal
==============================
# Features Scheduled for Removal
The following is a list of files and features that are going to be removed in
the source tree. Every entry should contain what exactly is going away, why it
is happening, and who is going to be doing the work. When the feature is
removed, it should also be removed from this file.
# Service pause action
## Service pause action
When: 1.0
@@ -14,7 +13,7 @@ Why: The same affect can be obtained with the --nodeps option to stop.
Who:
# start-stop-daemon options --startas, --chuid , --oknodo
## start-stop-daemon options --startas, --chuid , --oknodo
When: 1.0
@@ -26,7 +25,7 @@ Why: Obsolete or replaced by other options.
Who:
# runscript and rc symbolic links
## runscript and rc symbolic links
When: 1.0
@@ -35,7 +34,7 @@ Why: Deprecated in favor of openrc-run and openrc due to naming
Who:
# support for the opts variable in service scripts
## support for the opts variable in service scripts
When: 1.0
@@ -44,7 +43,7 @@ Why: Deprecated in favor of extra_commands, extra_started_commands
Who:
# support for local_start and local_stop
## support for local_start and local_stop
When: 1.0
@@ -52,7 +51,7 @@ Why: Deprecated in favor of executable scripts in @SYSCONFDIR@/local.d
Who:
# the mtab service script
## the mtab service script
When: force /etc/mtab to link to /proc/self/mounts in 1.0, remove
service in 2.0
@@ -62,13 +61,13 @@ Why: /etc/mtab should be a symbolic link to /proc/self/mounts on modern
Who:
# C API Functions in rc.h
## C API Functions in rc.h
If you have a c program that links to librc and uses functions from
there, this section will list API functions which are deprecated and
will be removed along with the reason they are being removed.
## rc_getline()
### rc_getline()
When: 1.0

View File

@@ -1,5 +1,4 @@
OpenRC History
==============
# OpenRC History
This history of OpenRC was written by Daniel Robbins, Roy Marples, William
Hubbs and others.

View File

@@ -15,24 +15,12 @@ include ${TOP}/Makefile.inc
SUBDIR= conf.d etc init.d local.d man scripts sh src support sysctl.d
# Build bash completion or not
MKBASHCOMP?= no
ifeq (${MKBASHCOMP},yes)
SUBDIR+= bash-completion
endif
# Build pkgconfig or not
MKPKGCONFIG?= yes
ifeq (${MKPKGCONFIG},yes)
SUBDIR+= pkgconfig
endif
# Build zsh completion or not
MKZSHCOMP?= no
ifeq (${MKZSHCOMP},yes)
SUBDIR+= zsh-completion
endif
# We need to ensure that runlevels is done last
SUBDIR+= runlevels

View File

@@ -1,3 +1,3 @@
NAME= openrc
VERSION= 0.37
VERSION= 0.34.6
PKG= ${NAME}-${VERSION}

58
NEWS.md
View File

@@ -1,64 +1,8 @@
OpenRC NEWS
===========
# 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.37
start-stop-daemon now supports logging stdout and stderr of daemons to
processes instead of files. These processes are defined by the
output_logger and error_logger variables in standard service scripts, or
by the -3/--output-logger or -4/--error-logger switches if you use
start-stop-daemon directly. For more information on this, see the
start-stop-daemon man page.
## OpenRC 0.36
In this release, the modules-load service has been combined into the
modules service since there is no reason I know of to keep them
separate. However, modules also provides modules-load in case you were
using modules-load in your dependencies.
The consolefont, keymaps, numlock and procfs service scripts no longer
have a dependency on localmount.
If you are a linux user and are still separaating / from /usr,
you will need to add the following line to the appropriate conf.d files:
rc_need="localmount"
## OpenRC 0.35
In this version, the cgroups mounting logic has been moved from the
sysfs service to the cgroups service. This was done so cgroups can be
mounted inside an lxc/lxd container without using the other parts of the
sysfs service.
?As a result of this change, if you are upgrading, you need to add
cgroups to your sysinit runlevel by running the following command as
root:
```
# rc-update add cgroups sysinit
```
For more information, see the following issue:
https://github.com/openrc/openrc/issues/187
Consider this your second notification with regard to /etc/mtab being a
file instead of a symbolic link.
In this version, the mtab service will complain loudly if you have
mtab_is_file set to yes and recommend that you change this to no and
restart the mtab service to migrate /etc/mtab to a symbolic link.
If there is a valid technical reason to keep /etc/mtab as a flat file
instead of a symbolic link to /proc/self/mounts, we are interested and
we will keep the support in that case. Please open an issue and let us
know however. Otherwise, consider this your final notice that the mtab
service will be removed in the future.
## OpenRC 0.33
This version removes the "service" binary which was just a copy of

View File

@@ -1,5 +1,4 @@
OpenRC README
=============
# OpenRC README
OpenRC is a dependency-based init system that works with the
system-provided init program, normally `/sbin/init`. Currently, it does
@@ -23,7 +22,6 @@ below arguments to the make command
PROGLDFLAGS=-static
LIBNAME=lib64
DESTDIR=/tmp/openrc-image
MKBASHCOMP=no
MKNET=no
MKPAM=pam
MKPREFIX=yes
@@ -33,7 +31,6 @@ MKSTATICLIBS=no
MKSYSVINIT=yes
MKTERMCAP=ncurses
MKTERMCAP=termcap
MKZSHCOMP=no
PKG_PREFIX=/usr/pkg
LOCAL_PREFIX=/usr/local
PREFIX=/usr/local

View File

@@ -1,5 +1,4 @@
OpenRC Coding Style Guide
=========================
# OpenRC Style Guide
This is the openrc style manual. It governs the coding style of all code
in this repository. Follow it. Contact openrc@gentoo.org for any questions

View File

@@ -1,5 +1,4 @@
Setting up the agetty service in OpenRC
=================================xxxxxx
# Setting up the agetty service in OpenRC
The agetty service is an OpenRC specific way to monitor and respawn a
getty, using agetty, on Linux. To use this method, make sure you aren't

View File

@@ -1,11 +0,0 @@
DIR= ${BASHCOMPDIR}
CONF= openrc \
openrc-service-script \
rc-service \
rc-status \
rc-update \
MK= ../mk
include ${MK}/os.mk
include ${MK}/scripts.mk

View File

@@ -1,24 +0,0 @@
# Copyright (c) 2017 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
#
# This file is part of OpenRC. It is subject to the license terms in
# the LICENSE file found in the top-level directory of this
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
#
# openrc completion command
#
_openrc()
{
local cur
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ ${#COMP_WORDS[*]} -le 2 ]]; then
COMPREPLY=($(compgen -W "$(rc-status --list)" -- $cur))
fi
return 0
} &&
complete -F _openrc openrc

View File

@@ -1,29 +0,0 @@
# Copyright (c) 2017 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
#
# This file is part of OpenRC. It is subject to the license terms in
# the LICENSE file found in the top-level directory of this
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
_openrc_service_script()
{
local script="${COMP_WORDS[0]}"
local cur="${COMP_WORDS[$COMP_CWORD]}"
if [[ ( -f "${script}" || -h "${script}" ) && -r "${script}" ]] \
&& [[ "$(head -n 1 "${script}")" =~ \#\!.*/openrc-run ]]
then
[[ $COMP_CWORD -gt 1 ]] && return 1
COMPREPLY=($(opts="start stop status restart pause zap ineed needsme iuse usesme broken"; \
eval "$(grep '^opts=' "${script}")"; echo "${opts}"))
[[ -n "$COMPREPLY" ]] || COMPREPLY=(start stop restart zap)
COMPREPLY=($(compgen -W "${COMPREPLY[*]}" -- "${cur}"))
else
COMPREPLY=($(compgen -o default -- "${cur}"))
fi
return 0
}
complete -F _openrc_service_script */etc/init.d/*

View File

@@ -1,113 +0,0 @@
# Copyright (c) 2017 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
#
# This file is part of OpenRC. It is subject to the license terms in
# the LICENSE file found in the top-level directory of this
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
#
# rc-service completion command
#
_rc_service()
{
local cur prev numwords opts
local words i x filename
local action actionpos
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
numwords=${#COMP_WORDS[*]}
if [[ ${prev} == '>' || ${prev} == '<' ]] ; then
COMPREPLY=($(compgen -f -- ${cur}))
return 0
fi
# find action
for x in ${COMP_LINE} ; do
if [[ ${x} =~ --(list|exists|resolve) ]] || [[ ${x} =~ -(l|e|r) ]]
then
action=${x}
break
fi
done
if [[ -n ${action} ]]; then
for ((i = 0; i < ${numwords}; i++ )); do
if [[ ${COMP_WORDS[${i}]} == "${action}" ]]; then
actionpos=${i}
break
fi
done
for ((i = 1; i < ${numwords}; i++ )); do
if [[ ! ${COMP_WORDS[$i]} == -* ]]; then
break
fi
done
fi
if [[ ${COMP_CWORD} -eq 3 ]]; then
return 1
fi
# check if an option was typed
if [[ ${cur} == -* ]]; then
if [[ ${cur} == --* ]]; then
opts="--list --exists --resolve"
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
elif [[ ${cur} == -* ]]; then
opts="-l -e -r"
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# NOTE: This slows things down!
# (Adapted from bash_completion by Ian Macdonald <ian@caliban.org>)
# This removes any options from the list of completions that have
# already been specified on the command line.
COMPREPLY=($(echo "${COMP_WORDS[@]}" | \
(while read -d ' ' i; do
[[ -z ${i} ]] && continue
# flatten array with spaces on either side,
# otherwise we cannot grep on word boundaries of
# first and last word
COMPREPLY=" ${COMPREPLY[@]} "
# remove word from list of completions
COMPREPLY=(${COMPREPLY/ ${i%% *} / })
done
echo ${COMPREPLY[@]})))
return 0
else
# no option was typed
if [[ ${COMP_CWORD} -eq 1 ]]; then # if first word typed
words="$(rc-service --list | grep ^${cur})" # complete for init scripts
COMPREPLY=($(for i in ${words} ; do \
[[ ${i} == ${cur}* ]] && echo ${i} ; \
done))
return 0
elif [[ ${COMP_CWORD} -eq 2 ]] && [[ ${prev} != -* ]]; then # if second word typed and we didn't type in a function
filename=$(rc-service --resolve ${prev})
opts=$(cat ${filename} | grep "^\w*()" | sed "s/().*$//") # Greps the functions included in the init script
if [[ "x${opts}" == "x" ]] ; then # if no options found loosen the grep algorhythm
opts=$(cat ${filename} | grep "\w*()" | sed "s/().*$//")
fi
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
fi
if [[ ${action} == '--exists' ]] || [[ ${action} == '-e' ]] || \
[[ ${action} == '--resolve' ]] || [[ ${action} == '-r' ]]; then
words="$(rc-service --list | grep ^${cur})"
COMPREPLY=($(for i in ${words} ; do \
[[ ${i} == ${cur}* ]] && echo ${i} ; \
done))
return 0
fi
return 0
} &&
complete -F _rc_service rc-service

View File

@@ -1,31 +0,0 @@
# Copyright (c) 2017 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
#
# This file is part of OpenRC. It is subject to the license terms in
# the LICENSE file found in the top-level directory of this
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
#
# rc-status completion command
#
_rcstatus()
{
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ $COMP_CWORD -eq 1 ]]; then
if [[ "${cur}" == --* ]]; then
COMPREPLY=($(compgen -W '--all --list --unused' -- ${cur}))
elif [[ "${cur}" == -* ]]; then
COMPREPLY=($(compgen -W '-a -l -u' -- ${cur}))
else
COMPREPLY=($(compgen -W "$(rc-status --list)" -- ${cur}))
fi
else
unset COMPREPLY
fi
return 0
} &&
complete -F _rcstatus rc-status

View File

@@ -1,42 +0,0 @@
# Copyright (c) 2017 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
#
# This file is part of OpenRC. It is subject to the license terms in
# the LICENSE file found in the top-level directory of this
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
#
# rc-update completion command
#
_rc_update()
{
local cur show
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ $COMP_CWORD -eq 1 ]]; then
if [[ "${cur}" == -* ]]; then
COMPREPLY=($(compgen -W '-a -d -s' -- ${cur}))
else
COMPREPLY=($(compgen -W 'add del show' ${cur}))
fi
else
if [[ "${COMP_WORDS[1]}" == "show" ]] || [[ "${COMP_WORDS[1]}" == "-s" ]]; then
show="TRUE"
fi
if ([[ $COMP_CWORD -eq 3 ]] && [[ -z "$show" ]]) || \
([[ $COMP_CWORD -eq 2 ]] && [[ -n "$show" ]]); then
COMPREPLY=($(compgen -W "$(rc-status --list)" -- $cur))
elif [[ $COMP_CWORD -eq 2 ]]; then
COMPREPLY=($(compgen -W "$(rc-service --list)" $cur))
elif [[ ${#COMP_WORDS[*]} -gt 2 ]] ; then
COMPREPLY=($(compgen -W "$(rc-status --list)" -- $cur))
else
unset COMPREPLY
fi
fi
return 0
} &&
complete -F _rc_update rc-update

View File

@@ -1,13 +1,5 @@
# As far as we are aware, there are no modern linux tools or use cases
# which require /etc/mtab to be a separate file from /proc/self/mounts,
# so this setting should be commented out.
# If it is set to yes, please comment it out and run this command:
# # rc-service mtab restart
# In the future, the mtab service will be removed since we are not aware
# of any need to manipulate /etc/mtab as a separate file from
# /proc/self/mounts.
# If you have a technical reason we should keep this support, please
# open an issue at https://github.com/openrc/openrc/issues and let us
# know about your situation.
# This setting controls whether /etc/mtab is a file or symbolic link.
# Most of the time, you shouldn't touch this. However, if the default
# breaks your system in some way, please see the NEWS.md file that comes
# with OpenRC for the actions to take.
# mtab_is_file=no

View File

@@ -227,11 +227,6 @@ rc_tty_number=12
# /sys/fs/cgroup in hybrid or legacy mode.
#rc_controller_cgroups="YES"
# The following setting turns on the memory.use_hierarchy setting in the
# root memory cgroup for cgroups v1.
# It must be set to yes in this file if you want this functionality.
#rc_cggroup_memory_use_hierarchy="NO"
# The following settings allow you to set up values for the cgroups version 1
# controllers for your services.
# They can be set in this file;, however, if you do this, the settings

View File

@@ -1,6 +1,3 @@
OpenRC Users Guide
==================
# Purpose and description
OpenRC is an init system for Unixoid operating systems. It takes care of
@@ -30,8 +27,8 @@ openrc scans the runlevels (default: `/etc/runlevels`) and builds a dependency
graph, then starts the needed service scripts, either serialized (default) or in
parallel.
When all the service scripts are started openrc terminates. There is no
persistent daemon. (Integration with tools like monit, runit or s6 can be done)
When all the init scripts are started openrc terminates. There is no persistent
daemon. (Integration with tools like monit, runit or s6 can be done)
# Shutdown
@@ -66,7 +63,7 @@ own if needed. This allows, for example, to have a default runlevel with
disabled.
The `rc-status` helper will print all currently active runlevels and the state
of services in them:
of init scripts in them:
```
# rc-status
@@ -77,7 +74,7 @@ Runlevel: default
```
All runlevels are represented as folders in `/etc/runlevels/` with symlinks to
the actual service scripts.
the actual init scripts.
Calling openrc with an argument (`openrc default`) will switch to that
runlevel; this will start and stop services as needed.
@@ -86,12 +83,121 @@ Managing runlevels is usually done through the `rc-update` helper, but could of
course be done by hand if desired.
e.g. `rc-update add nginx default` - add nginx to the default runlevel
Note: This will not auto-start nginx! You'd still have to trigger `rc` or run
the service script by hand.
the initscript by hand.
FIXME: Document stacked runlevels
The default startup uses the runlevels `sysinit`, `boot`, and `default`,
in that order. Shutdown uses the `shutdown` runlevel.
The default startup uses the runlevels `boot`, `sysinit` and `default`, in that
order. Shutdown uses the `shutdown` runlevel.
# Syntax of Service Scripts
Service scripts are shell scripts. OpenRC aims at using only the standardized
POSIX sh subset for portability reasons. The default interpreter (build-time
toggle) is `/bin/sh`, so using for example mksh is not a problem.
OpenRC has been tested with busybox sh, ash, dash, bash, mksh, zsh and possibly
others. Using busybox sh has been difficult as it replaces commands with
builtins that don't offer the expected features.
The interpreter for initscripts is `#!/sbin/openrc-run`.
Not using this interpreter will break the use of dependencies and is not
supported. (iow: if you insist on using `#!/bin/sh` you're on your own)
A `depend` function declares the dependencies of this service script.
All scripts must have start/stop/status functions, but defaults are provided.
Extra functions can be added easily:
```
extra_commands="checkconfig"
checkconfig() {
doSomething
}
```
This exports the checkconfig function so that `/etc/init.d/someservice
checkconfig` will be available, and it "just" runs this function.
While commands defined in `extra_commands` are always available, commands
defined in `extra_started_commands` will only work when the service is started
and those defined in `extra_stopped_commands` will only work when the service is
stopped. This can be used for implementing graceful reload and similar
behaviour.
Adding a restart function will not work, this is a design decision within
OpenRC. Since there may be dependencies involved (e.g. network -> apache) a
restart function is in general not going to work.
restart is internally mapped to `stop()` + `start()` (plus handling dependencies).
If a service needs to behave differently when it is being restarted vs
started or stopped, it should test the `$RC_CMD` variable, for example:
```
[ "$RC_CMD" = restart ] && do_something
```
# The Depend Function
This function declares the dependencies for a service script. This
determines the order the service scripts start.
```
depend() {
need net
use dns logger netmount
want coolservice
}
```
`need` declares a hard dependency - net always needs to be started before this
service does
`use` is a soft dependency - if dns, logger or netmount is in this runlevel
start it before, but we don't care if it's not in this runlevel.
`want` is between need and use - try to start coolservice if it is
installed on the system, regardless of whether it is in the
runlevel, but we don't care if it starts.
`before` declares that we need to be started before another service
`after` declares that we need to be started after another service, without
creating a dependency (so on calling stop the two are independent)
`provide` allows multiple implementations to provide one service type, e.g.:
`provide cron` is set in all cron-daemons, so any one of them started
satisfies a cron dependency
`keyword` allows platform-specific overrides, e.g. `keyword -lxc` makes this
service script a noop in lxc containers. Useful for things like keymaps,
module loading etc. that are either platform-specific or not available
in containers/virtualization/...
FIXME: Anything missing in this list?
# The Default Functions
All service scripts are assumed to have the following functions:
```
start()
stop()
status()
```
There are default implementations in `lib/rc/sh/openrc-run.sh` - this allows very
compact service scripts. These functions can be overridden per service script as
needed.
The default functions assume the following variables to be set in the service
script:
```
command=
command_args=
pidfile=
```
Thus the 'smallest' service scripts can be half a dozen lines long
# The Magic of `conf.d`
@@ -111,7 +217,7 @@ start() {
}
```
The big advantage of this split is that most of the time editing of the service
The big advantage of this split is that most of the time editing of the init
script can be avoided.
# Start-Stop-Daemon
@@ -162,9 +268,10 @@ stopped, by using:
The `rc_cgroup_cleanup` setting can be changed to yes to make this
happen automatically when the service is stopped.
# Caching
For performance reasons OpenRC keeps a cache of pre-parsed service metadata
For performance reasons OpenRC keeps a cache of pre-parsed initscript metadata
(e.g. `depend`). The default location for this is `/${RC_SVCDIR}/cache`.
The cache uses `mtime` to check for file staleness. Should any service script
@@ -174,5 +281,5 @@ change it'll re-source the relevant files and update the cache
OpenRC has wrappers for many common output tasks in libeinfo.
This allows to print colour-coded status notices and other things.
To make the output consistent the bundled service scripts all use ebegin/eend to
To make the output consistent the bundled initscripts all use ebegin/eend to
print nice messages.

1
init.d/.gitignore vendored
View File

@@ -1,6 +1,5 @@
agetty
binfmt
cgroups
modules-load
bootmisc
fsck

View File

@@ -19,12 +19,11 @@ SRCS-FreeBSD= hostid.in modules.in moused.in newsyslog.in pf.in rarpd.in \
rc-enabled.in rpcbind.in savecore.in syslogd.in
# These are FreeBSD specific
SRCS-FreeBSD+= adjkerntz.in devd.in dumpon.in encswap.in ipfw.in \
mixer.in nscd.in powerd.in syscons.in
modules-load.in mixer.in nscd.in powerd.in syscons.in
SRCS-Linux= agetty.in binfmt.in devfs.in cgroups.in dmesg.in hwclock.in \
consolefont.in keymaps.in killprocs.in modules.in \
mount-ro.in mtab.in numlock.in procfs.in net-online.in sysfs.in \
termencoding.in
SRCS-Linux= agetty.in binfmt.in devfs.in dmesg.in hwclock.in consolefont.in \
keymaps.in killprocs.in modules.in modules-load.in mount-ro.in mtab.in \
numlock.in procfs.in net-online.in sysfs.in termencoding.in
# Generic BSD scripts
SRCS-NetBSD= hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \

View File

@@ -16,6 +16,7 @@ term_type="${term_type:-linux}"
command=/sbin/agetty
command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}"
pidfile="/run/${RC_SVCNAME}.pid"
export EINFO_QUIET="${quiet:-yes}"
depend() {
after local
@@ -28,12 +29,5 @@ start_pre() {
eerror "symbolic links to it for the ports you want to start"
eerror "agetty on and add those to the appropriate runlevels."
return 1
else
export EINFO_QUIET="${quiet:-yes}"
fi
}
stop_pre()
{
export EINFO_QUIET="${quiet:-yes}"
}

View File

@@ -1,149 +0,0 @@
#!@SBINDIR@/openrc-run
# Copyright (c) 2017 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
#
# This file is part of OpenRC. It is subject to the license terms in
# the LICENSE file found in the top-level directory of this
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
description="Mount the control groups."
cgroup_opts=nodev,noexec,nosuid
depend()
{
keyword -docker -prefix -systemd-nspawn -vserver
after sysfs
}
cgroup1_base()
{
grep -qw cgroup /proc/filesystems || return 0
if ! mountinfo -q /sys/fs/cgroup; then
ebegin "Mounting cgroup filesystem"
local opts="${cgroup_opts},mode=755,size=${rc_cgroupsize:-10m}"
mount -n -t tmpfs -o "${opts}" cgroup_root /sys/fs/cgroup
eend $?
fi
if ! mountinfo -q /sys/fs/cgroup/openrc; then
local agent="${RC_LIBEXECDIR}/sh/cgroup-release-agent.sh"
mkdir /sys/fs/cgroup/openrc
mount -n -t cgroup \
-o none,${cgroup_opts},name=openrc,release_agent="$agent" \
openrc /sys/fs/cgroup/openrc
printf 1 > /sys/fs/cgroup/openrc/notify_on_release
fi
return 0
}
cgroup1_controllers()
{
yesno "${rc_controller_cgroups:-YES}" && [ -e /proc/cgroups ] &&
grep -qw cgroup /proc/filesystems || return 0
while read -r name _ _ enabled _; do
case "${enabled}" in
1) mountinfo -q "/sys/fs/cgroup/${name}" && continue
local x
for x in $rc_cgroup_controllers; do
[ "${name}" = "blkio" ] && [ "${x}" = "io" ] &&
continue 2
[ "${name}" = "${x}" ] &&
continue 2
done
mkdir "/sys/fs/cgroup/${name}"
mount -n -t cgroup -o "${cgroup_opts},${name}" \
"${name}" "/sys/fs/cgroup/${name}"
yesno "${rc_cgroup_memory_use_hierarchy:-no}" &&
[ "${name}" = memory ] &&
echo 1 > /sys/fs/cgroup/memory/memory.use_hierarchy
;;
esac
done < /proc/cgroups
return 0
}
cgroup2_base()
{
grep -qw cgroup2 /proc/filesystems || return 0
local base
base="$(cgroup2_find_path)"
mkdir -p "${base}"
mount -t cgroup2 none -o "${cgroup_opts},nsdelegate" "${base}" 2> /dev/null ||
mount -t cgroup2 none -o "${cgroup_opts}" "${base}"
return 0
}
cgroup2_controllers()
{
grep -qw cgroup2 /proc/filesystems || return 0
local active cgroup_path x y
cgroup_path="$(cgroup2_find_path)"
[ -z "${cgroup_path}" ] && return 0
[ -e "${cgroup_path}/cgroup.controllers" ] &&
read -r active < "${cgroup_path}/cgroup.controllers"
for x in ${rc_cgroup_controllers}; do
for y in ${active}; do
[ "$x" = "$y" ] &&
[ -e "${cgroup_path}/cgroup.subtree_control" ]&&
echo "+${x}" > "${cgroup_path}/cgroup.subtree_control"
done
done
return 0
}
cgroups_hybrid()
{
cgroup1_base
cgroup2_base
cgroup2_controllers
cgroup1_controllers
return 0
}
cgroups_legacy()
{
cgroup1_base
cgroup1_controllers
return 0
}
cgroups_unified()
{
cgroup2_base
cgroup2_controllers
return 0
}
mount_cgroups()
{
case "${rc_cgroup_mode:-hybrid}" in
hybrid) cgroups_hybrid ;;
legacy) cgroups_legacy ;;
unified) cgroups_unified ;;
esac
return 0
}
restorecon_cgroups()
{
if [ -x /sbin/restorecon ]; then
ebegin "Restoring SELinux contexts in /sys/fs/cgroup"
restorecon -rF /sys/fs/cgroup >/dev/null 2>&1
eend $?
fi
return 0
}
start()
{
# set up kernel support for cgroups
if [ -d /sys/fs/cgroup ]; then
mount_cgroups
restorecon_cgroups
fi
return 0
}

View File

@@ -13,7 +13,7 @@ description="Sets a font for the consoles."
depend()
{
need termencoding
need localmount termencoding
after hotplug bootmisc modules
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
}

View File

@@ -20,12 +20,9 @@ depend()
mount_dev()
{
local action conf_d_dir devfstype msg mountopts
action=--mount
conf_d_dir="${RC_SERVICE%/*/*}/conf.d"
msg=Mounting
local action=--mount devfstype msg=Mounting
# Some devices require exec, Bug #92921
mountopts="exec,nosuid,mode=0755"
local mountopts="exec,nosuid,mode=0755"
if yesno ${skip_mount_dev:-no} ; then
einfo "/dev will not be mounted due to user request"
return 0
@@ -36,7 +33,7 @@ mount_dev()
msg=Remounting
fi
if fstabinfo -q /dev; then
ebegin "$msg /dev according to fstab"
ebegin "$msg /dev according to @SYSCONFDIR@/fstab"
fstabinfo -q $action /dev
eend $?
return 0
@@ -57,7 +54,7 @@ mount_dev()
ewarn "is no entry for /dev in fstab."
ewarn "This means /dev will not be mounted."
ewarn "To avoid this message, set CONFIG_DEVTMPFS or CONFIG_TMPFS to y"
ewarn "in your kernel configuration or see ${conf_d_dir}/${RC_SVCNAME}"
ewarn "in your kernel configuration or see @SYSCONFDIR@/conf.d/devfs"
fi
return 0
}

View File

@@ -20,9 +20,9 @@ depend()
start()
{
local h source x
if [ -s /etc/hostname ] && [ -r /etc/hostname ]; then
read h x </etc/hostname
source="from /etc/hostname"
if [ -s @SYSCONFDIR@/hostname ] && [ -r @SYSCONFDIR@/hostname ]; then
read h x <@SYSCONFDIR@/hostname
source="from @SYSCONFDIR@/hostname"
else
# HOSTNAME variable used to be defined in caps in conf.d/hostname.
# It is also a magic variable in bash.

View File

@@ -105,7 +105,7 @@ start()
done
[ -n "$modname" ] &&
ewarn "The $modname module needs to be configured in" \
"${RC_SERVICE%/*/*}/conf.d/modules or built in."
"@SYSCONFDIR@/conf.d/modules or built in."
fi
fi

View File

@@ -13,7 +13,7 @@ description="Applies a keymap for the consoles."
depend()
{
need termencoding
need localmount termencoding
after bootmisc clock
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
}

View File

@@ -9,10 +9,7 @@
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
conf_d_dir="${RC_SERVICE%/*/*}/conf.d"
local_d_dir="${RC_SERVICE%/*/*}/local.d"
description="Executes user programs in ${local_d_dir}"
description="Executes user programs in @SYSCONFDIR@/local.d"
depend()
{
@@ -22,12 +19,12 @@ depend()
start()
{
local file has_errors redirect retval
has_errors=0
yesno $rc_verbose || redirect='> /dev/null 2>&1'
ebegin "Starting local"
local file has_errors=0 redirect retval
yesno $rc_verbose || redirect='> /dev/null 2>&1'
eindent
for file in "${local_d_dir}"/*.start; do
for file in @SYSCONFDIR@/local.d/*.start; do
if [ -x "${file}" ]; then
vebegin "Executing \"${file}\""
eval "${file}" $redirect
@@ -41,32 +38,32 @@ start()
eoutdent
if command -v local_start >/dev/null 2>&1; then
ewarn "\"${conf_d_dir}/local\" should be removed."
ewarn "\"@SYSCONFDIR@/conf.d/local\" should be removed."
ewarn "Please move the code from the local_start function"
ewarn "to executable scripts with an .start extension"
ewarn "in \"${local_d_dir}\""
ewarn "in \"@SYSCONFDIR@/local.d\""
local_start
fi
eend ${has_errors}
# We have to end with a zero exit code, because a failed execution
# of an executable ${local_d_dir}/*.start file shouldn't result in
# of an executable @SYSCONFDIR@/local.d/*.start file shouldn't result in
# marking the local service as failed. Otherwise we are unable to
# execute any executable ${local_d_dir}/*.stop file, because a failed
# execute any executable @SYSCONFDIR@/local.d/*.stop file, because a failed
# marked service cannot be stopped (and the stop function would
# actually call the executable ${local_d_dir}/*.stop file(s)).
# actually call the executable @SYSCONFDIR@/local.d/*.stop file(s)).
return 0
}
stop()
{
local file has_errors redirect retval
has_errors=0
yesno $rc_verbose || redirect='> /dev/null 2>&1'
ebegin "Stopping local"
local file has_errors=0 redirect retval
yesno $rc_verbose || redirect='> /dev/null 2>&1'
eindent
for file in "${local_d_dir}"/*.stop; do
for file in @SYSCONFDIR@/local.d/*.stop; do
if [ -x "${file}" ]; then
vebegin "Executing \"${file}\""
eval "${file}" $redirect
@@ -80,16 +77,16 @@ stop()
eoutdent
if command -v local_stop >/dev/null 2>&1; then
ewarn "\"${conf_d_dir}/local\" should be removed."
ewarn "\"@SYSCONFDIR@/conf.d/local\" should be removed."
ewarn "Please move the code from the local_stop function"
ewarn "to executable scripts with an .stop extension"
ewarn "in \"${local_d_dir}\""
ewarn "in \"@SYSCONFDIR@/local.d\""
local_stop
fi
eend ${has_errors}
# An executable ${local_d_dir}/*.stop file which failed with a
# An executable @SYSCONFDIR@/local.d/*.stop file which failed with a
# non-zero exit status is not a reason to mark this service
# as failed, therefore we have to end with a zero exit code.
return 0

View File

@@ -14,7 +14,7 @@ description="Mounts disks and swap according to /etc/fstab."
depend()
{
need fsck
use lvm modules root
use lvm modules mtab root
after clock lvm modules root
keyword -docker -jail -lxc -prefix -systemd-nspawn -vserver
}

72
init.d/modules-load.in Normal file
View File

@@ -0,0 +1,72 @@
#!@SBINDIR@/openrc-run
# Copyright (c) 2016 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
#
# This file is part of OpenRC. It is subject to the license terms in
# the LICENSE file found in the top-level directory of this
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
description="Loads a list of modules from systemd-compatible locations."
depend()
{
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
}
find_modfiles()
{
local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
local basenames files fn x y
for x in $dirs; do
[ ! -d $x ] && continue
for y in $x/*.conf; do
[ -f $y ] && basenames="${basenames}\n${y##*/}"
done
done
basenames=$(printf "$basenames" | sort -u)
for x in $basenames; do
for y in $dirs; do
[ -r $y/$x ] &&
fn=$y/$x
done
files="$files $fn"
done
echo $files
}
load_modules()
{
local file m modules rc x
file=$1
[ -z "$file" ] && return 0
while read m x; do
case $m in
\;*) continue ;;
\#*) continue ;;
*) modules="$modules $m"
;;
esac
done < $file
for x in $modules; do
ebegin "Loading module $x"
case "$RC_UNAME" in
FreeBSD) kldload "$x"; rc=$? ;;
Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
*) ;;
esac
eend $rc "Failed to load $x"
done
}
start()
{
local x
files=$(find_modfiles)
for x in $files; do
load_modules $x
done
return 0
}

View File

@@ -14,65 +14,10 @@ description="Loads a user defined list of kernel modules."
depend()
{
use isapnp
provide modules-load
want modules-load
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
}
find_modfiles()
{
local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
local basenames files fn x y
for x in $dirs; do
[ ! -d $x ] && continue
for y in $x/*.conf; do
[ -f $y ] && basenames="${basenames}\n${y##*/}"
done
done
basenames=$(printf "$basenames" | sort -u)
for x in $basenames; do
for y in $dirs; do
[ -r $y/$x ] &&
fn=$y/$x
done
files="$files $fn"
done
echo $files
}
load_modules()
{
local file m modules rc x
file=$1
[ -z "$file" ] && return 0
while read m x; do
case $m in
\;*) continue ;;
\#*) continue ;;
*) modules="$modules $m"
;;
esac
done < $file
for x in $modules; do
ebegin "Loading module $x"
case "$RC_UNAME" in
FreeBSD) kldload "$x"; rc=$? ;;
Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
*) ;;
esac
eend $rc "Failed to load $x"
done
}
modules_load_d()
{
local x
files=$(find_modfiles)
for x in $files; do
load_modules $x
done
return 0
}
FreeBSD_modules()
{
local cnt=0 x
@@ -137,10 +82,7 @@ Linux_modules()
start()
{
case "$RC_UNAME" in
FreeBSD|Linux)
modules_load_d
${RC_UNAME}_modules
;;
FreeBSD|Linux) ${RC_UNAME}_modules ;;
*) ;;
esac
return 0

View File

@@ -14,7 +14,6 @@ description="Update /etc/mtab to match what the kernel knows about"
depend()
{
after clock
before localmount
need root
keyword -prefix -systemd-nspawn
}
@@ -31,10 +30,6 @@ start()
einfo "Creating mtab symbolic link"
ln -snf /proc/self/mounts /etc/mtab
else
ewarn "The ${RC_SVCNAME} service will be removed in the future."
ewarn "Please change the mtab_is_file setting to no and run"
ewarn "# rc-service mtab restart"
ewarn "to create the mtab symbolic link."
[ -L /etc/mtab ] && ewarn "Removing /etc/mtab symbolic link"
rm -f /etc/mtab
einfo "Creating mtab file"

View File

@@ -13,7 +13,7 @@ description="Delays until the network is online or a specific timeout"
depend()
{
after modules net
after modules
need sysfs
provide network-online
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -uml -vserver
@@ -23,7 +23,6 @@ get_interfaces()
{
local ifname iftype
for ifname in /sys/class/net/*; do
[ -h "${ifname}" ] && continue
read iftype < ${ifname}/type
[ "$iftype" = "1" ] && printf "%s " ${ifname##*/}
done
@@ -32,7 +31,7 @@ get_interfaces()
start ()
{
local carriers configured dev gateway ifcount infinite
local carrier operstate rc
local rc state x
ebegin "Checking to see if the network is online"
rc=0
@@ -45,12 +44,10 @@ start ()
ifcount=0
for dev in ${interfaces}; do
: $((ifcount += 1))
read carrier < /sys/class/net/$dev/carrier 2> /dev/null ||
carrier=
[ "$carrier" = 1 ] && : $((carriers += 1))
read operstate < /sys/class/net/$dev/operstate 2> /dev/null ||
operstate=
[ "$operstate" = up ] && : $((configured += 1))
read x < /sys/class/net/$dev/carrier
[ $x -eq 1 ] && : $((carriers += 1))
read x < /sys/class/net/$dev/operstate
[ "$x" = up ] && : $((configured += 1))
done
[ $configured -eq $ifcount ] && [ $carriers -ge 1 ] && break
sleep 1
@@ -64,12 +61,8 @@ start ()
if [ $rc -eq 0 ] && yesno ${include_ping_test:-no}; then
ping_test_host="${ping_test_host:-google.com}"
if [ -n "$ping_test_host" ]; then
while $infinite || [ $timeout -gt 0 ]; do
ping -c 1 $ping_test_host > /dev/null 2>&1
rc=$?
[ $rc -eq 0 ] && break
: $((timeout -= 1))
done
ping -c 1 $ping_test_host > /dev/null 2>&1
rc=$?
fi
fi
eend $rc "The network is offline"

View File

@@ -76,7 +76,7 @@ tentative()
case "$RC_UNAME" in
Linux)
[ -n "$(command -v ip)" ] || return 1
[ -x /sbin/ip ] || [ -x /bin/ip ] || return 1
[ -n "$(ip -f inet6 addr show tentative)" ]
;;
*)
@@ -174,7 +174,7 @@ runip()
routeflush()
{
if [ "$RC_UNAME" = Linux ]; then
if [ -n "$(command -v ip)" ]; then
if [ -x /sbin/ip ] || [ -x /bin/ip ]; then
ip route flush scope global
ip route delete default 2>/dev/null
else
@@ -346,7 +346,7 @@ stop()
then
veinfo "$int"
runargs /etc/ifdown."$int" "$downcmd"
if [ -n "$(command -v ip)" ]; then
if [ -x /sbin/ip ] || [ -x /bin/ip ]; then
# We need to do this, otherwise we may
# fail to add things correctly on restart
ip address flush dev "$int" 2>/dev/null

View File

@@ -15,6 +15,7 @@ ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
depend()
{
need localmount
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
}

View File

@@ -16,6 +16,7 @@ depend()
after clock
use devfs
want modules
need localmount
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
}
@@ -26,8 +27,8 @@ start()
[ ! -e /proc/sys/fs/binfmt_misc/register ]; then
if ! grep -qs binfmt_misc /proc/filesystems &&
modprobe -q binfmt-misc; then
ewarn "The binfmt-misc module needs to be loaded by" \
"the modules service or built in."
ewarn "The binfmt-misc module needs to be configured in" \
"@SYSCONFDIR@/conf.d/modules or built in."
fi
if grep -qs binfmt_misc /proc/filesystems; then
ebegin "Mounting misc binary format filesystem"

View File

@@ -49,7 +49,7 @@ start()
fi
ebegin "Saving dependency cache"
local rc=0 save=
for x in depconfig deptree rc.log shutdowntime softlevel; do
for x in shutdowntime softlevel rc.log; do
[ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x"
done
if [ -n "$save" ]; then

View File

@@ -11,7 +11,7 @@
depend()
{
after clock root
after clock
before localmount
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -vserver
}

View File

@@ -21,7 +21,7 @@ BSD_sysctl()
[ -e /etc/sysctl.conf ] || return 0
local retval=0 var= comments= conf=
eindent
for conf in /etc/sysctl.conf /etc/sysctl.d/*.conf; do
for conf in @SYSCONFDIR@/sysctl.conf @SYSCONFDIR@/sysctl.d/*.conf; do
if [ -r "$conf" ]; then
vebegin "applying $conf"
while read var comments; do

View File

@@ -107,11 +107,122 @@ mount_misc()
fi
}
cgroup1_base()
{
grep -qw cgroup /proc/filesystems || return 0
if ! mountinfo -q /sys/fs/cgroup; then
ebegin "Mounting cgroup filesystem"
local opts="${sysfs_opts},mode=755,size=${rc_cgroupsize:-10m}"
mount -n -t tmpfs -o "${opts}" cgroup_root /sys/fs/cgroup
eend $?
fi
if ! mountinfo -q /sys/fs/cgroup/openrc; then
local agent="${RC_LIBEXECDIR}/sh/cgroup-release-agent.sh"
mkdir /sys/fs/cgroup/openrc
mount -n -t cgroup \
-o none,${sysfs_opts},name=openrc,release_agent="$agent" \
openrc /sys/fs/cgroup/openrc
printf 1 > /sys/fs/cgroup/openrc/notify_on_release
fi
return 0
}
cgroup1_controllers()
{
yesno "${rc_controller_cgroups:-YES}" && [ -e /proc/cgroups ] || return 0
while read -r name _ _ enabled rest; do
case "${enabled}" in
1) mountinfo -q "/sys/fs/cgroup/${name}" && continue
local x
for x in $rc_cgroup_controllers; do
[ "${name}" = "blkio" ] && [ "${x}" = "io" ] &&
continue 2
[ "${name}" = "${x}" ] &&
continue 2
done
mkdir "/sys/fs/cgroup/${name}"
mount -n -t cgroup -o "${sysfs_opts},${name}" \
"${name}" "/sys/fs/cgroup/${name}"
;;
esac
done < /proc/cgroups
return 0
}
cgroup2_base()
{
local base
base="$(cgroup2_find_path)"
mkdir -p "${base}"
mount -t cgroup2 none -o "${sysfs_opts},nsdelegate" "${base}" 2> /dev/null ||
mount -t cgroup2 none -o "${sysfs_opts}" "${base}"
return 0
}
cgroup2_controllers()
{
local active cgroup_path x y
cgroup_path="$(cgroup2_find_path)"
[ -z "${cgroup_path}" ] && return 0
[ -e "${cgroup_path}/cgroup.controllers" ] &&
read -r active < "${cgroup_path}/cgroup.controllers"
for x in ${rc_cgroup_controllers}; do
for y in ${active}; do
[ "$x" = "$y" ] &&
[ -e "${cgroup_path}/cgroup.subtree_control" ]&&
echo "+${x}" > "${cgroup_path}/cgroup.subtree_control"
done
done
return 0
}
cgroups_hybrid()
{
grep -qw cgroup /proc/filesystems || return 0
cgroup1_base
if grep -qw cgroup2 /proc/filesystems; then
cgroup2_base
cgroup2_controllers
fi
cgroup1_controllers
return 0
}
cgroups_legacy()
{
grep -qw cgroup /proc/filesystems || return 0
cgroup1_base
cgroup1_controllers
return 0
}
cgroups_unified()
{
cgroup2_base
cgroup2_controllers
return 0
}
mount_cgroups()
{
# set up kernel support for cgroups
if [ -d /sys/fs/cgroup ]; then
case "${rc_cgroup_mode:-hybrid}" in
hybrid) cgroups_hybrid ;;
legacy) cgroups_legacy ;;
unified) cgroups_unified ;;
esac
fi
return 0
}
restorecon_sys()
{
if [ -x /sbin/restorecon ]; then
ebegin "Restoring SELinux contexts in /sys"
restorecon -F /sys/devices/system/cpu/online >/dev/null 2>&1
restorecon -rF /sys/fs/cgroup >/dev/null 2>&1
eend $?
fi
}
@@ -120,6 +231,7 @@ start()
{
mount_sys
mount_misc
mount_cgroups
restorecon_sys
return 0
}

View File

@@ -8,7 +8,7 @@
.\" This file may not be copied, modified, propagated, or distributed
.\" except according to the terms contained in the LICENSE file.
.\"
.Dd November 30, 2017
.Dd December 31, 2011
.Dt openrc-run 8 SMM
.Os OpenRC
.Sh NAME
@@ -111,17 +111,11 @@ The path to the s6 service directory if you are monitoring this service
with S6. The default is /var/svc.d/${RC_SVCNAME}.
.It Ar s6_svwait_options_start
The options to pass to s6-svwait when starting the service via s6.
.It Ar s6_force_kill
Should we force-kill this service if s6_service_timeout_stop expires
but the service doesn't go down during shutdown? The default is yes.
.It Ar s6_service_timeout_stop
The amount of time, in milliseconds, s6-svc should wait for the service
to go down when stopping the service. The default is 60000.
to go down when stopping the service. The default is 10000.
.It Ar start_stop_daemon_args
List of arguments passed to start-stop-daemon when starting the daemon.
.It Ar supervise_daemon_args
List of arguments passed to supervise-daemon when starting the daemon.
If undefined, start_stop_daemon_args is used as a fallback.
.It Ar command
Daemon to start or stop via
.Nm start-stop-daemon
@@ -145,56 +139,21 @@ List of arguments to pass to the daemon when starting via
.Nm supervise-daemon .
to force the daemon to stay in the foreground
.It Ar command_background
Set this to "true", "yes" or "1" (case-insensitive) if you want
Set this to "true", "yes" or "1" (case-insensitive) if you want
.Xr start-stop-daemon 8
to force the daemon into the background. This forces the
"--make-pidfile" and "--pidfile" options, so the pidfile variable must be set.
.It Ar command_progress
Set this to "true", "yes" or "1" (case-insensitive) if you want
Set this to "true", "yes" or "1" (case-insensitive) if you want
.Xr start-stop-daemon 8
to display a progress meter when waiting for a daemon to stop.
.It Ar command_user
If the daemon does not support changing to a different user id, you can
use this to change the user id, and optionally group id, before
use this to change the user id before
.Xr start-stop-daemon 8
or
.Xr supervise-daemon 8
launches the daemon.
.It Ar output_log
This is the path to a file or named pipe where the standard output from
the service will be redirected. If you are starting this service with
.Xr start-stop-daemon 8 ,
, you must set
.Pa command_background
to true. Keep in mind that this path will be inside the chroot if the
.Pa chroot
variable is set.
.It Ar error_log
The same thing as
.Pa output_log
but for the standard error output.
.It Ar output_logger
This is a process which will be used to log the standard output from the
service. If you are starting this service with
.Xr start-stop-daemon 8 ,
, you must set
.Pa command_background
to true. Keep in mind that this command must be executable as a shell
command inside the chroot if the
.Pa chroot
variable is set. Keep in mind also that this command works by accepting
the stdout of the service on stdin.
An example of a command that can be run this way is logger if you want
your service output to go to syslog.
.It Ar error_logger
The same thing as
.Pa output_logger
but for the standard error output.
.It Ar directory
.Xr start-stop-daemon 8
and
.Xr supervise-daemon 8
will chdir to this directory before starting the daemon.
launches the daemon
.It Ar chroot
.Xr start-stop-daemon 8
and
@@ -239,8 +198,6 @@ used along with in_background_fake to support re-entrant services.
.It Ar in_background_fake
Space separated list of commands which should always succeed when
in_background is yes.
.It Ar umask
Set the umask of the daemon.
.Pp
Keep in mind that eval is used to process chroot, command, command_args_*,
command_user, pidfile and procname. This may affect how they are
@@ -490,7 +447,6 @@ Also, the -d, -f or -p options should not be specified along with this option.
.Pp
The -q option suppresses all informational output. If it is specified
twice, all error messages are suppressed as well.
.It Xo
.Ic fstabinfo
.Op Fl M , -mount
.Op Fl R , -remount
@@ -507,7 +463,6 @@ remounted.
.Pp
The -q option suppresses all informational output. If it is specified
twice, all error messages are suppressed as well.
.It Xo
.Ic mountinfo
.Op Fl f, -fstype-regex Ar regex
.Op Fl F, -skip-fstype-regex Ar regex
@@ -522,7 +477,7 @@ twice, all error messages are suppressed as well.
.Op Fl i, -options
.Op Fl s, -fstype
.Op Fl t, -node
.Ar mount1 mount2 ...
.Ar mount1 mount2 ...
.Xc
The f, F, n, N, o, O, p, P, e and E options specify what you want to
search for or skip in the mounted file systems. The i, s and t options
@@ -614,7 +569,7 @@ rc_net_tap1_provide="!net"
# It's also possible to negate keywords. This is mainly useful for prefix
# users testing OpenRC.
rc_keyword="!-prefix"
# This can also be used to block a script from running in all
# This can also be used to block a script from runining in all
# containers except one or two
rc_keyword="!-containers !-docker"
.Ed
@@ -753,8 +708,6 @@ Users are encouraged to use the is_newer_than function which returns correctly.
.Xr rc_plugin_hook 3 ,
.Xr sh 1p ,
.Xr start-stop-daemon 8 ,
.Xr supervise-daemon 8 ,
.Xr uname 1
.Sh AUTHORS
.An Roy Marples <roy@marples.name>
.An William Hubbs <w.d.hubbs@gmail.com>

View File

@@ -16,18 +16,6 @@
.Nd locate and run an OpenRC service with the given arguments
.Sh SYNOPSIS
.Nm
.Op Fl c , -ifcrashed
.Ar service cmd
.Op Ar ...
.Nm
.Fl d , -debug
.Ar service cmd
.Op Ar ...
.Nm
.Fl D , -nodeps
.Ar service cmd
.Op Ar ...
.Nm
.Op Fl i , -ifexists
.Ar service cmd
.Op Ar ...
@@ -40,21 +28,9 @@
.Ar service cmd
.Op Ar ...
.Nm
.Op Fl s , -ifstarted
.Ar service cmd
.Op Ar ...
.Nm
.Op Fl S , -ifstopped
.Ar service cmd
.Op Ar ...
.Nm
.Fl e , -exists
.Ar service
.Nm
.Fl Z , -dry-run
.Ar service cmd
.Op Ar ...
.Nm
.Fl l , -list
.Nm
.Fl r , -resolve
@@ -88,15 +64,6 @@ return 0 if it can find
otherwise -1.
.Fl r , -resolve
does the same and also prints the full path of the service to stdout.
.Pp
.Fl d , -debug
sets -x when running the service script(s).
.Pp
.Fl D , -nodeps
ignores dependencies when running the service.
.Pp
.Fl Z , -dry-run
displays commands rather than executing them.
.Sh SEE ALSO
.Xr openrc 8 ,
.Xr stdout 3

View File

@@ -131,34 +131,9 @@ Modifies the scheduling priority of the daemon.
.It Fl 1 , -stdout Ar logfile
Redirect the standard output of the process to logfile when started with
.Fl background .
The logfile Must be an absolute pathname, but relative to the path
optionally given with
Must be an absolute pathname, but relative to the path optionally given with
.Fl r , -chroot .
The logfile can also be a named pipe.
.It Fl 2 , -stderr Ar logfile
Redirect the standard error of the process to logfile when started with
.Fl background .
The logfile must be an absolute pathname, but relative to the path
optionally given with
.Fl r , -chroot .
The logfile can also be a named pipe.
.It Fl 3 , -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 4 , -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 w , -wait Ar milliseconds
Wait
.Ar milliseconds
@@ -176,7 +151,6 @@ These options are only used for stopping daemons:
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
The retry specification can be either a timeout in seconds or multiple
signal/timeout pairs (like SIGTERM/5).
If this option is not given, the default is SIGTERM/5.
.El
.Sh ENVIRONMENT
.Va SSD_IONICELEVEL

View File

@@ -120,7 +120,6 @@ description of --respawn-max for more information.
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
The retry specification can be either a timeout in seconds or multiple
signal/timeout pairs (like SIGTERM/5).
If this option is not given, the default is SIGTERM/5.
.It Fl r , -chroot Ar path
chroot to this directory before starting the daemon. All other paths, such
as the path to the daemon, chdir and pidfile, should be relative to the chroot.

View File

@@ -11,5 +11,3 @@
# Generic definitions
include ${MK}/os-BSD.mk
CPPFLAGS+= -D_BSD_SOURCE

View File

@@ -13,6 +13,6 @@
SFX= .GNU-kFreeBSD.in
PKG_PREFIX?= /usr
CPPFLAGS+= -D_BSD_SOURCE
CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=700
LIBDL= -Wl,-Bdynamic -ldl
LIBKVM?=

View File

@@ -11,5 +11,5 @@
SFX= .GNU.in
PKG_PREFIX?= /usr
CPPFLAGS+= -D_DEFAULT_SOURCE -DMAXPATHLEN=4096 -DPATH_MAX=4096
CPPFLAGS+= -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -DMAXPATHLEN=4096 -DPATH_MAX=4096
LIBDL= -Wl,-Bdynamic -ldl

View File

@@ -11,7 +11,7 @@
SFX= .Linux.in
PKG_PREFIX?= /usr
CPPFLAGS+= -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L
CPPFLAGS+= -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700
LIBDL= -Wl,-Bdynamic -ldl
ifeq (${MKSELINUX},yes)

View File

@@ -34,7 +34,6 @@ PICFLAG?= -fPIC
SYSCONFDIR?= ${PREFIX}/etc
INITDIR?= ${SYSCONFDIR}/init.d
CONFDIR?= ${SYSCONFDIR}/conf.d
CONFMODE?= 0644
LOCALDIR?= ${SYSCONFDIR}/local.d
SYSCTLDIR?= ${SYSCONFDIR}/sysctl.d
@@ -45,22 +44,20 @@ SBINDIR?= ${PREFIX}/sbin
SBINMODE?= 0755
INCDIR?= ${UPREFIX}/include
INCMODE?= 0644
INCMODE?= 0444
_LIBNAME_SH= case `readlink /lib` in /lib64|lib64) echo "lib64";; *) echo "lib";; esac
_LIBNAME:= $(shell ${_LIBNAME_SH})
LIBNAME?= ${_LIBNAME}
LIBDIR?= ${UPREFIX}/${LIBNAME}
LIBMODE?= 0644
LIBMODE?= 0444
SHLIBDIR?= ${PREFIX}/${LIBNAME}
LIBEXECDIR?= ${PREFIX}/libexec/rc
MANPREFIX?= ${UPREFIX}/share
MANDIR?= ${MANPREFIX}/man
MANMODE?= 0644
BASHCOMPDIR?= ${UPREFIX}/share/bash-completion/completions
MANMODE?= 0444
DATADIR?= ${UPREFIX}/share/openrc
DATAMODE?= 0644
@@ -68,4 +65,4 @@ DATAMODE?= 0644
DOCDIR?= ${UPREFIX}/share/doc
DOCMODE?= 0644
ZSHCOMPDIR?= ${UPREFIX}/share/zsh/site-functions
CONFMODE?= 0644

View File

@@ -1,5 +1,4 @@
Using runit with OpenRC
=======================
# Using runit with OpenRC
Beginning with OpenRC-0.21, we support using runit [1] in place of
start-stop-daemon for monitoring and restarting daemons.

View File

@@ -38,7 +38,7 @@ BOOT-FreeBSD+= adjkerntz dumpon syscons
BOOT-Linux+= binfmt hwclock keymaps modules mtab procfs termencoding
SHUTDOWN-Linux= killprocs mount-ro
SYSINIT-Linux= devfs cgroups dmesg sysfs
SYSINIT-Linux= devfs dmesg sysfs
# Generic BSD stuff
BOOT-NetBSD+= hostid newsyslog savecore syslogd

View File

@@ -1,5 +1,4 @@
Using S6 with OpenRC
====================
# Using S6 with OpenRC
Beginning with OpenRC-0.16, we support using the s6 supervision suite
from Skarnet Software in place of start-stop-daemon for monitoring
@@ -40,10 +39,6 @@ s6_service_path - the path to the s6 service directory. The default is
s6_svwait_options_start - the options to pass to s6-svwait when starting
the service. If this is not set, s6-svwait will not be called.
s6_force_kill - Should we try to force kill this service if the
s6_service_timeout_stop timeout expires when shutting down this service?
The default is yes.
s6_service_timeout_stop - the amount of time, in milliseconds, s6-svc
should wait for a service to go down when stopping.

View File

@@ -1,495 +0,0 @@
OpenRC Service Script Writing Guide
===================================
This document is aimed at developers or packagers who
write OpenRC service scripts, either for their own projects, or for
the packages they maintain. It contains advice, suggestions, tips,
tricks, hints, and counsel; cautions, warnings, heads-ups,
admonitions, proscriptions, enjoinders, and reprimands.
It is intended to prevent common mistakes that are found "in the wild"
by pointing out those mistakes and suggesting alternatives. Each
good/bad thing that you should/not do has a section devoted to it. We
don't consider anything exotic, and assume that you will use
start-stop-daemon to manage a fairly typical long-running UNIX
process.
# Syntax of Service Scripts
Service scripts are shell scripts. OpenRC aims at using only the standardized
POSIX sh subset for portability reasons. The default interpreter (build-time
toggle) is `/bin/sh`, so using for example mksh is not a problem.
OpenRC has been tested with busybox sh, ash, dash, bash, mksh, zsh and possibly
others. Using busybox sh has been difficult as it replaces commands with
builtins that don't offer the expected features.
The interpreter for service scripts is `#!/sbin/openrc-run`.
Not using this interpreter will break the use of dependencies and is not
supported. (iow: if you insist on using `#!/bin/sh` you're on your own)
A `depend` function declares the dependencies of this service script.
All scripts must have start/stop/status functions, but defaults are
provided and should be used unless you have a very strong reason not to
use them.
Extra functions can be added easily:
```
extra_commands="checkconfig"
checkconfig() {
doSomething
}
```
This exports the checkconfig function so that `/etc/init.d/someservice
checkconfig` will be available, and it "just" runs this function.
While commands defined in `extra_commands` are always available, commands
defined in `extra_started_commands` will only work when the service is started
and those defined in `extra_stopped_commands` will only work when the service is
stopped. This can be used for implementing graceful reload and similar
behaviour.
Adding a restart function will not work, this is a design decision within
OpenRC. Since there may be dependencies involved (e.g. network -> apache) a
restart function is in general not going to work.
restart is internally mapped to `stop()` + `start()` (plus handling dependencies).
If a service needs to behave differently when it is being restarted vs
started or stopped, it should test the `$RC_CMD` variable, for example:
```
[ "$RC_CMD" = restart ] && do_something
```
# The Depend Function
This function declares the dependencies for a service script. This
determines the order the service scripts start.
```
depend() {
need net
use dns logger netmount
want coolservice
}
```
`need` declares a hard dependency - net always needs to be started before this
service does
`use` is a soft dependency - if dns, logger or netmount is in this runlevel
start it before, but we don't care if it's not in this runlevel.
`want` is between need and use - try to start coolservice if it is
installed on the system, regardless of whether it is in the
runlevel, but we don't care if it starts.
`before` declares that we need to be started before another service
`after` declares that we need to be started after another service, without
creating a dependency (so on calling stop the two are independent)
`provide` allows multiple implementations to provide one service type, e.g.:
`provide cron` is set in all cron-daemons, so any one of them started
satisfies a cron dependency
`keyword` allows platform-specific overrides, e.g. `keyword -lxc` makes this
service script a noop in lxc containers. Useful for things like keymaps,
module loading etc. that are either platform-specific or not available
in containers/virtualization/...
FIXME: Anything missing in this list?
# The Default Functions
All service scripts are assumed to have the following functions:
```
start()
stop()
status()
```
There are default implementations in `lib/rc/sh/openrc-run.sh` - this allows very
compact service scripts. These functions can be overridden per service script as
needed.
The default functions assume the following variables to be set in the service
script:
```
command=
command_args=
pidfile=
```
Thus the 'smallest' service scripts can be half a dozen lines long
## Don't write your own start/stop functions
OpenRC is capable of stopping and starting most daemons based on the
information that you give it. For a well-behaved daemon that
backgrounds itself and writes its own PID file by default, the
following OpenRC variables are likely all that you'll need:
* command
* command_args
* pidfile
Given those three pieces of information, OpenRC will be able to start
and stop the daemon on its own. The following is taken from an
[OpenNTPD](http://www.openntpd.org/) service script:
```sh
command="/usr/sbin/ntpd"
# The special RC_SVCNAME variable contains the name of this service.
pidfile="/run/${RC_SVCNAME}.pid"
command_args="-p ${pidfile}"
```
If the daemon runs in the foreground by default but has options to
background itself and to create a pidfile, then you'll also need
* command_args_background
That variable should contain the flags needed to background your
daemon, and to make it write a PID file. Take for example the
following snippet of an
[NRPE](https://github.com/NagiosEnterprises/nrpe) service script:
```sh
command="/usr/bin/nrpe"
command_args="--config=/etc/nagios/nrpe.cfg"
command_args_background="--daemon"
pidfile="/run/${RC_SVCNAME}.pid"
```
Since NRPE runs as *root* by default, it needs no special permissions
to write to `/run/nrpe.pid`. OpenRC takes care of starting and
stopping the daemon with the appropriate arguments, even passing the
`--daemon` flag during startup to force NRPE into the background (NRPE
knows how to write its own PID file).
But what if the daemon isn't so well behaved? What if it doesn't know
how to background itself or create a pidfile? If it can do neither,
then use,
* command_background=true
which will additionally pass `--make-pidfile` to start-stop-daemon,
causing it to create the `$pidfile` for you (rather than the daemon
itself being responsible for creating the PID file).
If your daemon doesn't know how to change its own user or group, then
you can tell start-stop-daemon to launch it as an unprivileged user
with
* command_user="user:group"
Finally, if your daemon always forks into the background but fails to
create a PID file, then your only option is to use
* procname
With `procname`, OpenRC will try to find the running daemon by
matching the name of its process. That's not so reliable, but daemons
shouldn't background themselves without creating a PID file in the
first place. The next example is part of the [CA NetConsole
Daemon](https://oss.oracle.com/projects/cancd/) service script:
```sh
command="/usr/sbin/cancd"
command_args="-p ${CANCD_PORT}
-l ${CANCD_LOG_DIR}
-o ${CANCD_LOG_FORMAT}"
command_user="cancd"
# cancd daemonizes itself, but doesn't write a PID file and doesn't
# have an option to run in the foreground. So, the best we can do
# is try to match the process name when stopping it.
procname="cancd"
```
To recap, in order of preference:
1. If the daemon backgrounds itself and creates its own PID file, use
`pidfile`.
2. If the daemon does not background itself (or has an option to run
in the foreground) and does not create a PID file, then use
`command_background=true` and `pidfile`.
3. If the daemon backgrounds itself and does not create a PID file,
use `procname` instead of `pidfile`. But, if your daemon has the
option to run in the foreground, then you should do that instead
(that would be the case in the previous item).
4. The last case, where the daemon does not background itself but
does create a PID file, doesn't make much sense. If there's a way
to disable the daemon's PID file (or, to write it straight into the
garbage), then do that, and use `command_background=true`.
## Reloading your daemon's configuration
Many daemons will reload their configuration files in response to a
signal. Suppose your daemon will reload its configuration in response
to a `SIGHUP`. It's possible to add a new "reload" command to your
service script that performs this action. First, tell the service
script about the new command.
```sh
extra_started_commands="reload"
```
We use `extra_started_commands` as opposed to `extra_commands` because
the "reload" action is only valid while the daemon is running (that
is, started). Now, start-stop-daemon can be used to send the signal to
the appropriate process (assuming you've defined the `pidfile`
variable elsewhere):
```sh
reload() {
ebegin "Reloading ${RC_SVCNAME}"
start-stop-daemon --signal HUP --pidfile "${pidfile}"
eend $?
}
```
## Don't restart/reload with a broken config
Often, users will start a daemon, make some configuration change, and
then attempt to restart the daemon. If the recent configuration change
contains a mistake, the result will be that the daemon is stopped but
then cannot be started again (due to the configuration error). It's
possible to prevent that situation with a function that checks for
configuration errors, and a combination of the `start_pre` and
`stop_pre` hooks.
```sh
checkconfig() {
# However you want to check this...
}
start_pre() {
# If this isn't a restart, make sure that the user's config isn't
# busted before we try to start the daemon (this will produce
# better error messages than if we just try to start it blindly).
#
# If, on the other hand, this *is* a restart, then the stop_pre
# action will have ensured that the config is usable and we don't
# need to do that again.
if [ "${RC_CMD}" != "restart" ] ; then
checkconfig || return $?
fi
}
stop_pre() {
# If this is a restart, check to make sure the user's config
# isn't busted before we stop the running daemon.
if [ "${RC_CMD}" = "restart" ] ; then
checkconfig || return $?
fi
}
```
To prevent a *reload* with a broken config, keep it simple:
```sh
reload() {
checkconfig || return $?
ebegin "Reloading ${RC_SVCNAME}"
start-stop-daemon --signal HUP --pidfile "${pidfile}"
eend $?
}
```
## PID files should be writable only by root
PID files must be writable only by *root*, which means additionally
that they must live in a *root*-owned directory. This directory is
normally /run under Linux and /var/run under other operating systems.
Some daemons run as an unprivileged user account, and create their PID
files (as the unprivileged user) in a path like
`/var/run/foo/foo.pid`. That can usually be exploited by the unprivileged
user to kill *root* processes, since when a service is stopped, *root*
usually sends a SIGTERM to the contents of the PID file (which are
controlled by the unprivileged user). The main warning sign for that
problem is using `checkpath` to set ownership on the directory
containing the PID file. For example,
```sh
# BAD BAD BAD BAD BAD BAD BAD BAD
start_pre() {
# Ensure that the pidfile directory is writable by the foo user/group.
checkpath --directory --mode 0700 --owner foo:foo "/var/run/foo"
}
# BAD BAD BAD BAD BAD BAD BAD BAD
```
If the *foo* user owns `/var/run/foo`, then he can put whatever he wants
in the `/var/run/foo/foo.pid` file. Even if *root* owns the PID file, the
*foo* user can delete it and replace it with his own. To avoid
security concerns, the PID file must be created as *root* and live in
a *root*-owned directory. If your daemon is responsible for forking
and writing its own PID file but the PID file is still owned by the
unprivileged runtime user, then you may have an upstream issue.
Once the PID file is being created as *root* (before dropping
privileges), it can be written directly to a *root*-owned
directory. For example, the *foo* daemon might write
`/var/run/foo.pid`. No calls to checkpath are needed. Note: there is
nothing technically wrong with using a directory structure like
`/var/run/foo/foo.pid`, so long as *root* owns the PID file and the
directory containing it.
Ideally (see "Upstream your service scripts"), your service script
will be integrated upstream and the build system will determine the
appropriate directory for the pid file. For example,
```sh
pidfile="@piddir@/${RC_SVCNAME}.pid"
```
A decent example of this is the [Nagios core service
script](https://github.com/NagiosEnterprises/nagioscore/blob/master/openrc-init.in),
where the full path to the PID file is specified at build-time.
## Don't let the user control the PID file location
It's usually a mistake to let the end user control the PID file
location through a conf.d variable, for a few reasons:
1. When the PID file path is controlled by the user, you need to
ensure that its parent directory exists and is writable. This
adds unnecessary code to the service script.
2. If the PID file path changes while the service is running, then
you'll find yourself unable to stop the service.
3. The directory that should contain the PID file is best determined
by the upstream build system (see "Upstream your service scripts").
On Linux, the preferred location these days is `/run`. Other systems
still use `/var/run`, though, and a `./configure` script is the
best place to decide which one you want.
4. Nobody cares where the PID file is located, anyway.
Since OpenRC service names must be unique, a value of
```sh
pidfile="/var/run/${RC_SVCNAME}.pid"
```
guarantees that your PID file has a unique name.
## Upstream your service scripts (for packagers)
The ideal place for an OpenRC service script is **upstream**. Much like
systemd services, a well-crafted OpenRC service script should be
distribution-agnostic, and the best place for it is upstream. Why? For
two reasons. First, having it upstream means that there's a single
authoritative source for improvements. Second, a few paths in every
service script are dependent upon flags passed to the build system. For
example,
```sh
command=/usr/bin/foo
```
in an autotools-based build system should really be
```sh
command=@bindir@/foo
```
so that the user's value of `--bindir` is respected. If you keep the
service script in your own distribution's repository, then you have to
keep the command path and package synchronized yourself, and that's no
fun.
## Be wary of "need net" dependencies
There are two things you need to know about "need net" dependencies:
1. They are not satisfied by the loopback interface, so "need net"
requires some *other* interface to be up.
2. Depending on the value of `rc_depend_strict` in `rc.conf`, the
"need net" will be satisfied when either *any* non-loopback
interface is up, or when *all* non-loopback interfaces are up.
The first item means that "need net" is wrong for daemons that are
happy with `0.0.0.0`, and the second point means that "need net" is
wrong for daemons that need a particular (for example, the WAN)
interface. We'll consider the two most common users of "need net";
network clients who access some network resource, and network servers
who provide them.
### Network clients
Network clients typically want the WAN interface to be up. That may
tempt you to depend on the WAN interface; but first, you should ask
yourself a question: does anything bad happen if the WAN interface is
not available? In other words, if the administrator wants to disable
the WAN, should the service be stopped? Usually the answer to that
question is "no," and in that case, you should forego the "net"
dependency entirely.
Suppose, for example, that your service retrieves virus signature
updates from the internet. In order to do its job correctly, it needs
a (working) internet connection. However, the service itself does not
require the WAN interface to be up: if it is, great; otherwise, the
worst that will happen is that a "server unavailable" warning will be
logged. The signature update service will not crash, and—perhaps more
importantly—you don't want it to terminate if the administrator turns
off the WAN interface for a second.
### Network servers
Network servers are generally easier to handle than their client
counterparts. Most server daemons listen on `0.0.0.0` (all addresses)
by default, and are therefore satisfied to have the loopback interface
present and operational. OpenRC ships with the loopback service in the
*boot* runlevel, and therefore most server daemons require no further
network dependencies.
The exceptions to this rule are those daemons who produce negative
side-effects when the WAN is unavailable. For example, the Nagios
server daemon will generate "the sky is falling" alerts for as long as
your monitored hosts are unreachable. So in that case, you should
require some other interface (often the WAN) to be up. A "need"
dependency would be appropriate, because you want Nagios to be
stopped before the network is taken down.
If your daemon can optionally be configured to listen on a particular
interface, then please see the "Depending on a particular interface"
section.
### Depending on a particular interface
If you need to depend on one particular interface, usually it's not
easy to determine programmatically what that interface is. For
example, if your *sshd* daemon listens on `192.168.1.100` (rather than
`0.0.0.0`), then you have two problems:
1. Parsing `sshd_config` to figure that out; and
2. Determining which network service name corresponds to the
interface for `192.168.1.100`.
It's generally a bad idea to parse config files in your service
scripts, but the second problem is the harder one. Instead, the most
robust (i.e. the laziest) approach is to make the user specify the
dependency when he makes a change to sshd_config. Include something
like the following in the service configuration file,
```sh
# Specify the network service that corresponds to the "bind" setting
# in your configuration file. For example, if you bind to 127.0.0.1,
# this should be set to "loopback" which provides the loopback interface.
rc_need="loopback"
```
This is a sensible default for daemons that are happy with `0.0.0.0`,
but lets the user specify something else, like `rc_need="net.wan"` if
he needs it. The burden is on the user to determine the appropriate
service whenever he changes the daemon's configuration file.

View File

@@ -33,9 +33,6 @@ else
kmode="-a"
fi
# Set the SELinux label on console before everything so we dont lose output
[ -x /sbin/restorecon ] && /sbin/restorecon -F /dev/console
# Try and set a font and as early as we can
if service_present "$RC_DEFAULTLEVEL" consolefont ||
service_present "$RC_BOOTLEVEL" consolefont; then

View File

@@ -83,7 +83,6 @@ elif ! mountinfo -q /run; then
fi
fi
[ -x /sbin/restorecon ] && /sbin/restorecon -rF /run
checkpath -d $RC_SVCDIR
checkpath -d -m 0775 -o root:uucp /run/lock

View File

@@ -133,10 +133,11 @@ _status()
elif service_inactive; then
ewarn "status: inactive"
return 16
elif service_crashed; then
eerror "status: crashed"
return 32
elif service_started; then
if service_crashed; then
eerror "status: crashed"
return 32
fi
einfo "status: started"
return 0
else
@@ -259,14 +260,12 @@ for _cmd; do
# Apply cgroups settings if defined
if [ "$(command -v cgroup_add_service)" = "cgroup_add_service" ]
then
if grep -qs /sys/fs/cgroup /proc/1/mountinfo
then
if [ -d /sys/fs/cgroup -a ! -w /sys/fs/cgroup ]; then
eerror "No permission to apply cgroup settings"
break
fi
if [ -d /sys/fs/cgroup -a ! -w /sys/fs/cgroup ]; then
eerror "No permission to apply cgroup settings"
break
fi
cgroup_add_service
cgroup_add_service /sys/fs/cgroup/openrc
cgroup_add_service /sys/fs/cgroup/systemd/system
fi
[ "$(command -v cgroup_set_limits)" = "cgroup_set_limits" ] &&
cgroup_set_limits

View File

@@ -184,17 +184,18 @@ cgroup2_set_limits()
cgroup_path="$(cgroup2_find_path)"
[ -d "${cgroup_path}" ] || return 0
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
local OIFS="$IFS"
IFS="
"
[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
[ -f "${rc_cgroup_path}"/cgroup.procs ] &&
printf 0 > "${rc_cgroup_path}"/cgroup.procs
[ -z "${rc_cgroup_settings}" ] && return 0
echo "${rc_cgroup_settings}" | while read -r key value; do
[ -z "${key}" ] && continue
[ -z "${value}" ] && continue
[ ! -f "${rc_cgroup_path}/${key}" ] && continue
veinfo "${RC_SVCNAME}: cgroups: setting ${key} to ${value}"
printf "%s\n" "${value}" > "${rc_cgroup_path}/${key}"
printf "%d" 0 > "${rc_cgroup_path}/cgroup.procs"
echo "${rc_cgroup_settings}" | while IFS="$OIFS" read -r key value; do
[ -z "${key}" ] || [ -z "${value}" ] && continue
[ ! -e "${rc_cgroup_path}/${key}" ] && continue
veinfo "${RC_SVCNAME}: cgroups: ${key} ${value}"
printf "%s" "${value}" > "${rc_cgroup_path}/${key}"
done
IFS="$OIFS"
return 0
}

View File

@@ -12,20 +12,6 @@
[ -z "${s6_service_path}" ] && s6_service_path="/var/svc.d/${RC_SVCNAME}"
_s6_force_kill() {
local pid
s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}"
pid="${3%)}"
[ -z "${pid}" ] && return 0
if kill -0 "${pid}" 2> /dev/null; then
ewarn "Sending DOWN & KILL for ${RC_SVCNAME}"
s6-svc -dk "${s6_service_link}"
sleep 1
kill -0 "${pid}" 2>/dev/null && return 1
fi
return 0
}
s6_start()
{
if [ ! -d "${s6_service_path}" ]; then
@@ -55,11 +41,7 @@ s6_stop()
fi
s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}"
ebegin "Stopping ${name:-$RC_SVCNAME}"
s6-svc -d -wD -T ${s6_service_timeout_stop:-60000} "${s6_service_link}"
set -- $(s6-svstat "${s6_service_link}")
[ "$1" = "up" ] &&
yesno "${s6_force_kill:-yes}" &&
_s6_force_kill "$@"
s6-svc -wD -d -T ${s6_service_timeout_stop:-10000} "${s6_service_link}"
set -- $(s6-svstat "${s6_service_link}")
[ "$1" = "down" ]
eend $? "Failed to stop ${name:-$RC_SVCNAME}"

View File

@@ -38,25 +38,15 @@ ssd_start()
service_inactive && _inactive=true
mark_service_inactive
fi
[ -n "$output_logger" ] &&
output_logger_arg="--stdout-logger \"$output_logger\""
[ -n "$error_logger" ] &&
error_logger_arg="--stderr-logger \"$error_logger\""
#the eval call is necessary for cases like:
# command_args="this \"is a\" test"
# to work properly.
eval start-stop-daemon --start \
--exec $command \
${chroot:+--chroot} $chroot \
${directory:+--chdir} $directory \
${output_log+--stdout} $output_log \
${error_log+--stderr} $error_log \
${output_logger_arg} \
${error_logger_arg} \
${procname:+--name} $procname \
${pidfile:+--pidfile} $pidfile \
${command_user+--user} $command_user \
${umask+--umask} $umask \
$_background $start_stop_daemon_args \
-- $command_args $command_args_background
if eend $? "Failed to start ${name:-$RC_SVCNAME}"; then

View File

@@ -24,17 +24,13 @@ supervise_start()
# to work properly.
eval supervise-daemon "${RC_SVCNAME}" --start \
${retry:+--retry} $retry \
${directory:+--chdir} $directory \
${chroot:+--chroot} $chroot \
${output_log+--stdout} ${output_log} \
${error_log+--stderr} $error_log \
${pidfile:+--pidfile} $pidfile \
${respawn_delay:+--respawn-delay} $respawn_delay \
${respawn_max:+--respawn-max} $respawn_max \
${respawn_period:+--respawn-period} $respawn_period \
${command_user+--user} $command_user \
${umask+--umask} $umask \
${supervise_daemon_args:-${start_stop_daemon_args}} \
$supervise_daemon_args \
$command \
-- $command_args $command_args_foreground
rc=$?

View File

@@ -28,11 +28,9 @@
#if __GNUC__ > 2 || defined(__INTEL_COMPILER)
# define _dead __attribute__((__noreturn__))
# define _unused __attribute__((__unused__))
# define _xasprintf(a, b) __attribute__((__format__(__printf__, a, b)))
#else
# define _dead
# define _unused
# define _xasprintf(a, b)
#endif
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
@@ -55,7 +53,6 @@
} while (/* CONSTCOND */ 0)
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <sys/stat.h>
@@ -99,10 +96,8 @@ _unused static char *xstrdup(const char *str)
#undef ERRX
/*
* basename_c never modifies the argument. As such, if there is a trailing
* slash then an empty string is returned.
*/
/* basename_c never modifies the argument. As such, if there is a trailing
* slash then an empty string is returned. */
_unused static const char *basename_c(const char *path)
{
const char *slash = strrchr(path, '/');
@@ -126,49 +121,4 @@ _unused static bool existss(const char *pathname)
return (stat(pathname, &buf) == 0 && buf.st_size != 0);
}
/*
* This is an OpenRC specific version of the asprintf() function.
* We do this to avoid defining the _GNU_SOURCE feature test macro on
* glibc systems and to insure that we have a consistent function across
* platforms. This also allows us to call our xmalloc and xrealloc
* functions to handle memory allocation.
* this function was originally written by Mike Frysinger.
*/
_unused _xasprintf(2,3) static int xasprintf(char **strp, const char *fmt, ...)
{
va_list ap;
int len;
int memlen;
char *ret;
/*
* Start with a buffer size that should cover the vast majority of uses
* (path construction).
*/
memlen = 4096;
ret = xmalloc(memlen);
va_start(ap, fmt);
len = vsnprintf(ret, memlen, fmt, ap);
va_end(ap);
if (len >= memlen) {
/*
* Output was truncated, so increase buffer to exactly what we need.
*/
memlen = len + 1;
ret = xrealloc(ret, memlen);
va_start(ap, fmt);
len = vsnprintf(ret, len + 1, fmt, ap);
va_end(ap);
}
if (len < 0 || len >= memlen) {
/* Give up! */
fprintf(stderr, "xasprintf: unable to format a buffer\n");
free(ret);
exit(1);
}
*strp = ret;
return len;
}
#endif

View File

@@ -66,6 +66,9 @@ int parse_mode(mode_t *, char *);
/* Handy function so we can wrap einfo around our deptree */
RC_DEPTREE *_rc_deptree_load (int, int *);
/* Test to see if we can see pid 1 or not */
bool _rc_can_find_pids(void);
RC_SERVICE lookup_service_state(const char *service);
void from_time_t(char *time_string, time_t tv);
time_t to_time_t(char *timestring);

View File

@@ -155,7 +155,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
if (rc <= 0)
proc_ns[0] = '\0';
}
if (strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns))
if (strcmp(my_ns, proc_ns))
continue;
if (uid) {
snprintf(buffer, sizeof(buffer), "/proc/%d", p);

View File

@@ -542,41 +542,52 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
}
librc_hidden_def(rc_deptree_order)
/* Given a time, recurse the target path to find out if there are
any older (or newer) files. If false, sets the time to the
oldest (or newest) found.
*/
static bool
deep_mtime_check(const char *target, bool newer,
mtime_check(const char *source, const char *target, bool newer,
time_t *rel, char *file)
{
struct stat buf;
time_t mtime;
bool retval = true;
DIR *dp;
struct dirent *d;
char path[PATH_MAX];
int serrno = errno;
/* We have to exist */
if (stat(source, &buf) != 0)
return false;
mtime = buf.st_mtime;
/* If target does not exist, return true to mimic shell test */
if (stat(target, &buf) != 0)
return true;
if (newer) {
if (*rel < buf.st_mtime) {
if (mtime < buf.st_mtime) {
if (rel == NULL)
return false;
retval = false;
if (file)
strlcpy(file, target, PATH_MAX);
*rel = buf.st_mtime;
}
if (rel != NULL) {
if (*rel < buf.st_mtime) {
if (file)
strlcpy(file, target, PATH_MAX);
*rel = buf.st_mtime;
}
}
} else {
if (*rel > buf.st_mtime) {
if (mtime > buf.st_mtime) {
if (rel == NULL)
return false;
retval = false;
if (file)
strlcpy(file, target, PATH_MAX);
*rel = buf.st_mtime;
}
if (rel != NULL) {
if (*rel > buf.st_mtime) {
if (file)
strlcpy(file, target, PATH_MAX);
*rel = buf.st_mtime;
}
}
}
@@ -591,38 +602,16 @@ deep_mtime_check(const char *target, bool newer,
if (d->d_name[0] == '.')
continue;
snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
if (!deep_mtime_check(path, newer, rel, file)) {
if (!mtime_check(source, path, newer, rel, file)) {
retval = false;
if (rel == NULL)
break;
}
}
closedir(dp);
return retval;
}
/* Recursively check if target is older/newer than source.
* If false, return the filename and most different time (if
* the return value arguments are non-null).
*/
static bool
mtime_check(const char *source, const char *target, bool newer,
time_t *rel, char *file)
{
struct stat buf;
time_t mtime;
bool retval = true;
/* We have to exist */
if (stat(source, &buf) != 0)
return false;
mtime = buf.st_mtime;
retval = deep_mtime_check(target,newer,&mtime,file);
if (rel) {
*rel = mtime;
}
return retval;
}
bool
rc_newer_than(const char *source, const char *target,
time_t *newest, char *file)
@@ -681,8 +670,6 @@ rc_deptree_update_needed(time_t *newest, char *file)
RC_STRINGLIST *config;
RC_STRING *s;
int i;
struct stat buf;
time_t mtime;
/* Create base directories if needed */
for (i = 0; depdirs[i]; i++)
@@ -690,48 +677,42 @@ rc_deptree_update_needed(time_t *newest, char *file)
fprintf(stderr, "mkdir `%s': %s\n", depdirs[i], strerror(errno));
/* Quick test to see if anything we use has changed and we have
* data in our deptree. */
if (stat(RC_DEPTREE_CACHE, &buf) == 0) {
mtime = buf.st_mtime;
} else {
/* No previous cache found.
* We still run the scan, in case of clock skew; we still need to return
* the newest time.
*/
newer = true;
mtime = time(NULL);
}
newer |= !deep_mtime_check(RC_INITDIR,true,&mtime,file);
newer |= !deep_mtime_check(RC_CONFDIR,true,&mtime,file);
* data in our deptree */
if (!existss(RC_DEPTREE_CACHE))
return true;
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR, newest, file))
return true;
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR, newest, file))
return true;
#ifdef RC_PKG_INITDIR
newer |= !deep_mtime_check(RC_PKG_INITDIR,true,&mtime,file);
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR, newest, file))
return true;
#endif
#ifdef RC_PKG_CONFDIR
newer |= !deep_mtime_check(RC_PKG_CONFDIR,true,&mtime,file);
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR, newest, file))
return true;
#endif
#ifdef RC_LOCAL_INITDIRs
newer |= !deep_mtime_check(RC_LOCAL_INITDIR,true,&mtime,file);
#ifdef RC_LOCAL_INITDIR
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR, newest, file))
return true;
#endif
#ifdef RC_LOCAL_CONFDIR
newer |= !deep_mtime_check(RC_LOCAL_CONFDIR,true,&mtime,file);
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR, newest, file))
return true;
#endif
newer |= !deep_mtime_check(RC_CONF,true,&mtime,file);
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONF, newest, file))
return true;
/* Some init scripts dependencies change depending on config files
* outside of baselayout, like syslog-ng, so we check those too. */
config = rc_config_list(RC_DEPCONFIG);
TAILQ_FOREACH(s, config, entries) {
newer |= !deep_mtime_check(s->value, true, &mtime, file);
if (!rc_newer_than(RC_DEPTREE_CACHE, s->value, newest, file)) {
newer = true;
break;
}
}
rc_stringlist_free(config);
/* Return newest file time, if requested */
if ((newer) && (newest != NULL)) {
*newest = mtime;
}
return newer;
}
librc_hidden_def(rc_deptree_update_needed)

View File

@@ -50,7 +50,6 @@ static const rc_service_state_name_t rc_service_state_names[] = {
{ RC_SERVICE_HOTPLUGGED, "hotplugged" },
{ RC_SERVICE_FAILED, "failed" },
{ RC_SERVICE_SCHEDULED, "scheduled"},
{ RC_SERVICE_CRASHED, "crashed"},
{ 0, NULL}
};
@@ -849,10 +848,6 @@ rc_service_state(const char *service)
}
}
if (state & RC_SERVICE_STARTED) {
if (rc_service_daemons_crashed(service))
state |= RC_SERVICE_CRASHED;
}
if (state & RC_SERVICE_STOPPED) {
dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
TAILQ_FOREACH(dir, dirs, entries) {

View File

@@ -188,8 +188,7 @@ typedef enum
/* Optional states service could also be in */
RC_SERVICE_FAILED = 0x0200,
RC_SERVICE_SCHEDULED = 0x0400,
RC_SERVICE_WASINACTIVE = 0x0800,
RC_SERVICE_CRASHED = 0x1000,
RC_SERVICE_WASINACTIVE = 0x0800
} RC_SERVICE;
/*! Add the service to the runlevel

1
src/rc/.gitignore vendored
View File

@@ -56,7 +56,6 @@ mark_service_inactive
mark_service_wasinactive
mark_service_hotplugged
mark_service_failed
mark_service_crashed
rc-abort
rc
openrc

View File

@@ -5,8 +5,8 @@ include ${MK}/os.mk
SRCS= checkpath.c do_e.c do_mark_service.c do_service.c \
do_value.c fstabinfo.c is_newer_than.c is_older_than.c \
mountinfo.c openrc-run.c rc-abort.c rc.c \
rc-depend.c rc-logger.c rc-misc.c rc-pipes.c \
rc-plugin.c rc-service.c rc-status.c rc-update.c \
rc-depend.c rc-logger.c rc-misc.c rc-plugin.c \
rc-service.c rc-status.c rc-update.c \
shell_var.c start-stop-daemon.c supervise-daemon.c swclock.c _usage.c
ifeq (${MKSELINUX},yes)
@@ -41,7 +41,6 @@ RC_SBINPROGS= mark_service_starting mark_service_started \
mark_service_stopping mark_service_stopped \
mark_service_inactive mark_service_wasinactive \
mark_service_hotplugged mark_service_failed \
mark_service_crashed \
rc-abort swclock
ifeq (${OS},Linux)
@@ -124,8 +123,7 @@ is_older_than: is_older_than.o rc-misc.o
mark_service_starting mark_service_started \
mark_service_stopping mark_service_stopped \
mark_service_inactive mark_service_wasinactive \
mark_service_hotplugged mark_service_failed \
mark_service_crashed: do_mark_service.o rc-misc.o
mark_service_hotplugged mark_service_failed: do_mark_service.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
mountinfo: mountinfo.o _usage.o rc-misc.o
@@ -158,7 +156,7 @@ rc-service: rc-service.o _usage.o rc-misc.o
rc-update: rc-update.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-pipes.o rc-schedules.o
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-schedules.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o

View File

@@ -73,32 +73,25 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
inode_t type, bool trunc, bool chowner, bool selinux_on)
{
struct stat st;
int fd;
int flags;
int fd, flags;
int r;
int readfd;
int readflags;
int u;
memset(&st, 0, sizeof(st));
flags = O_CREAT|O_NDELAY|O_WRONLY|O_NOCTTY;
readflags = O_NDELAY|O_NOCTTY|O_RDONLY;
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
readflags |= O_CLOEXEC;
#endif
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
readflags |= O_NOFOLLOW;
#endif
if (trunc)
flags |= O_TRUNC;
readfd = open(path, readflags);
if (readfd == -1 || (type == inode_file && trunc)) {
if (lstat(path, &st) || trunc) {
if (type == inode_file) {
einfo("%s: creating file", path);
if (!mode) /* 664 */
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
flags = O_CREAT|O_NDELAY|O_WRONLY|O_NOCTTY;
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
if (trunc)
flags |= O_TRUNC;
u = umask(0);
fd = open(path, flags, mode);
umask(u);
@@ -106,9 +99,7 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
eerror("%s: open: %s", applet, strerror(errno));
return -1;
}
if (readfd != -1 && trunc)
close(readfd);
readfd = fd;
close (fd);
} else if (type == inode_dir) {
einfo("%s: creating directory", path);
if (!mode) /* 775 */
@@ -122,12 +113,7 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
strerror (errno));
return -1;
}
readfd = open(path, readflags);
if (readfd == -1) {
eerror("%s: unable to open directory: %s", applet,
strerror(errno));
return -1;
}
mode = 0;
} else if (type == inode_fifo) {
einfo("%s: creating fifo", path);
if (!mode) /* 600 */
@@ -140,76 +126,56 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
strerror (errno));
return -1;
}
readfd = open(path, readflags);
if (readfd == -1) {
eerror("%s: unable to open fifo: %s", applet,
strerror(errno));
return -1;
}
}
}
if (fstat(readfd, &st) != -1) {
} else {
if (type != inode_dir && S_ISDIR(st.st_mode)) {
eerror("%s: is a directory", path);
close(readfd);
return 1;
}
if (type != inode_file && S_ISREG(st.st_mode)) {
eerror("%s: is a file", path);
close(readfd);
return 1;
}
if (type != inode_fifo && S_ISFIFO(st.st_mode)) {
eerror("%s: is a fifo", path);
close(readfd);
return -1;
}
if (mode && (st.st_mode & 0777) != mode) {
if ((type != inode_dir) && (st.st_nlink > 1)) {
eerror("%s: chmod: %s %s", applet, "Too many hard links to", path);
close(readfd);
return -1;
}
if (S_ISLNK(st.st_mode)) {
eerror("%s: chmod: %s %s", applet, path, " is a symbolic link");
close(readfd);
return -1;
}
einfo("%s: correcting mode", path);
if (fchmod(readfd, mode)) {
eerror("%s: chmod: %s", applet, strerror(errno));
close(readfd);
return -1;
}
}
if (chowner && (st.st_uid != uid || st.st_gid != gid)) {
if ((type != inode_dir) && (st.st_nlink > 1)) {
eerror("%s: chown: %s %s", applet, "Too many hard links to", path);
close(readfd);
return -1;
}
if (S_ISLNK(st.st_mode)) {
eerror("%s: chown: %s %s", applet, path, " is a symbolic link");
close(readfd);
return -1;
}
einfo("%s: correcting owner", path);
if (fchown(readfd, uid, gid)) {
eerror("%s: chown: %s", applet, strerror(errno));
close(readfd);
return -1;
}
}
if (selinux_on)
selinux_util_label(path);
} else {
eerror("fstat: %s: %s", path, strerror(errno));
close(readfd);
return -1;
}
close(readfd);
if (mode && (st.st_mode & 0777) != mode) {
if ((type != inode_dir) && (st.st_nlink > 1)) {
eerror("%s: chmod: %s %s", applet, "Too many hard links to", path);
return -1;
}
if (S_ISLNK(st.st_mode)) {
eerror("%s: chmod: %s %s", applet, path, " is a symbolic link");
return -1;
}
einfo("%s: correcting mode", path);
if (chmod(path, mode)) {
eerror("%s: chmod: %s", applet, strerror(errno));
return -1;
}
}
if (chowner && (st.st_uid != uid || st.st_gid != gid)) {
if ((type != inode_dir) && (st.st_nlink > 1)) {
eerror("%s: chown: %s %s", applet, "Too many hard links to", path);
return -1;
}
if (S_ISLNK(st.st_mode)) {
eerror("%s: chown: %s %s", applet, path, " is a symbolic link");
return -1;
}
einfo("%s: correcting owner", path);
if (chown(path, uid, gid)) {
eerror("%s: chown: %s", applet, strerror(errno));
return -1;
}
}
if (selinux_on)
selinux_util_label(path);
return 0;
}

View File

@@ -68,7 +68,9 @@ int main(int argc, char **argv)
ok = rc_service_started_daemon(service, exec, NULL, idx);
} else if (strcmp(applet, "service_crashed") == 0) {
ok = ( rc_service_daemons_crashed(service) && errno != EACCES);
ok = (_rc_can_find_pids() &&
rc_service_daemons_crashed(service) &&
errno != EACCES);
} else
eerrorx("%s: unknown applet", applet);

View File

@@ -141,7 +141,7 @@ do_mount(struct ENT *ent, bool remount)
/* NOTREACHED */
case 0:
execvp(argv[0], argv);
eerror("%s: execvp: %s", applet, strerror(errno));
eerror("%s: execv: %s", applet, strerror(errno));
_exit(EXIT_FAILURE);
/* NOTREACHED */
default:

View File

@@ -65,7 +65,7 @@ static int mount_proc(void)
break;
case 0:
/* attempt to mount /proc */
execlp("mount", "mount", "-t", "proc", "proc", "/proc", NULL);
execl("mount", "mount", "-t", "proc", "proc", "/proc", NULL);
syslog(LOG_ERR, "Unable to execute mount");
exit(1);
break;
@@ -87,11 +87,10 @@ static int mount_proc(void)
static bool is_user_process(pid_t pid)
{
char *buf = NULL;
char buf[PATH_MAX+1];
FILE *fp;
char *path = NULL;
char path[PATH_MAX+1];
pid_t temp_pid;
size_t size;
bool user_process = true;
while (pid >0 && user_process) {
@@ -99,9 +98,8 @@ static bool is_user_process(pid_t pid)
user_process = false;
continue;
}
xasprintf(&path, "/proc/%d/status", pid);
snprintf(path, sizeof(path), "/proc/%d/status", pid);
fp = fopen(path, "r");
free(path);
/*
* if we could not open the file, the process disappeared, which
* leaves us no way to determine for sure whether it was a user
@@ -114,14 +112,11 @@ static bool is_user_process(pid_t pid)
}
temp_pid = -1;
while (! feof(fp)) {
buf = NULL;
if (getline(&buf, &size, fp) != -1) {
buf[0] = 0;
if (fgets(buf, sizeof(buf), fp))
sscanf(buf, "PPid: %d", &temp_pid);
free(buf);
} else {
free(buf);
else
break;
}
}
fclose(fp);
if (temp_pid == -1) {
@@ -140,7 +135,7 @@ static int signal_processes(int sig, RC_STRINGLIST *omits, bool dryrun)
sigset_t oldsigs;
DIR *dir;
struct dirent *d;
char *buf = NULL;
char buf[PATH_MAX+1];
pid_t pid;
int sendcount = 0;
@@ -175,11 +170,7 @@ static int signal_processes(int sig, RC_STRINGLIST *omits, bool dryrun)
continue;
/* Is this a process we have been requested to omit? */
if (buf) {
free(buf);
buf = NULL;
}
xasprintf(&buf, "%d", pid);
sprintf(buf, "%d", pid);
if (rc_stringlist_find(omits, buf))
continue;

View File

@@ -248,6 +248,7 @@ find_mounts(struct args *args)
struct opt *o;
int netdev;
char *tmp;
size_t l;
if ((nmnts = getmntinfo(&mnts, MNT_NOWAIT)) == 0)
eerrorx("getmntinfo: %s", strerror (errno));
@@ -263,7 +264,11 @@ find_mounts(struct args *args)
if (! options)
options = xstrdup(o->o_name);
else {
xasprintf(&tmp, "%s,%s", options, o->o_name);
l = strlen(options) +
strlen(o->o_name) + 2;
tmp = xmalloc(sizeof (char) * l);
snprintf(tmp, l, "%s,%s", options,
o->o_name);
free(options);
options = tmp;
}
@@ -310,7 +315,6 @@ find_mounts(struct args *args)
{
FILE *fp;
char *buffer;
size_t size;
char *p;
char *from;
char *to;
@@ -325,8 +329,8 @@ find_mounts(struct args *args)
list = rc_stringlist_new();
buffer = NULL;
while (getline(&buffer, &size, fp) != -1) {
buffer = xmalloc(sizeof(char) * PATH_MAX * 3);
while (fgets(buffer, PATH_MAX * 3, fp)) {
netdev = -1;
p = buffer;
from = strsep(&p, " ");
@@ -342,8 +346,6 @@ find_mounts(struct args *args)
}
process_mount(list, args, from, to, fst, opts, netdev);
free(buffer);
buffer = NULL;
}
free(buffer);
fclose(fp);
@@ -378,7 +380,7 @@ int main(int argc, char **argv)
regex_t *skip_point_regex = NULL;
RC_STRINGLIST *nodes;
RC_STRING *s;
char *real_path = NULL;
char real_path[PATH_MAX + 1];
int opt;
int result;
char *this_path;
@@ -448,12 +450,9 @@ int main(int argc, char **argv)
eerrorx("%s: `%s' is not a mount point",
argv[0], argv[optind]);
this_path = argv[optind++];
real_path = realpath(this_path, NULL);
if (real_path)
if (realpath(this_path, real_path))
this_path = real_path;
rc_stringlist_add(args.mounts, this_path);
free(real_path);
real_path = NULL;
}
nodes = find_mounts(&args);
rc_stringlist_free(args.mounts);

View File

@@ -35,7 +35,6 @@
#include "rc-wtmp.h"
#include "version.h"
static const char *path_default = "/sbin:/usr/sbin:/bin:/usr/bin";
static const char *rc_default_runlevel = "default";
static pid_t do_openrc(const char *runlevel)
@@ -54,7 +53,7 @@ static pid_t do_openrc(const char *runlevel)
sigemptyset(&signals);
sigprocmask(SIG_SETMASK, &signals, NULL);
printf("Starting %s runlevel\n", runlevel);
execlp("openrc", "openrc", runlevel, NULL);
execl("/sbin/openrc", "/sbin/openrc", runlevel, NULL);
perror("exec");
break;
default:
@@ -89,7 +88,7 @@ static void init(const char *default_runlevel)
static void handle_reexec(char *my_name)
{
execlp(my_name, my_name, "reexec", NULL);
execl(my_name, my_name, "reexec", NULL);
return;
}
@@ -184,9 +183,6 @@ int main(int argc, char **argv)
sigaction(SIGINT, &sa, NULL);
reboot(RB_DISABLE_CAD);
/* set default path */
setenv("PATH", path_default, 1);
if (! reexec)
init(default_runlevel);

View File

@@ -109,7 +109,7 @@ static void
handle_signal(int sig)
{
int serrno = errno;
char *signame = NULL;
char signame[10] = { '\0' };
struct winsize ws;
switch (sig) {
@@ -134,22 +134,20 @@ handle_signal(int sig)
break;
case SIGINT:
if (!signame)
xasprintf(&signame, "SIGINT");
if (!signame[0])
snprintf(signame, sizeof(signame), "SIGINT");
/* FALLTHROUGH */
case SIGTERM:
if (!signame)
xasprintf(&signame, "SIGTERM");
if (!signame[0])
snprintf(signame, sizeof(signame), "SIGTERM");
/* FALLTHROUGH */
case SIGQUIT:
if (!signame)
xasprintf(&signame, "SIGQUIT");
if (!signame[0])
snprintf(signame, sizeof(signame), "SIGQUIT");
/* Send the signal to our children too */
if (service_pid > 0)
kill(service_pid, sig);
eerror("%s: caught %s, aborting", applet, signame);
free(signame);
exit(EXIT_FAILURE);
eerrorx("%s: caught %s, aborting", applet, signame);
/* NOTREACHED */
default:
@@ -163,12 +161,11 @@ handle_signal(int sig)
static void
unhotplug()
{
char *file = NULL;
char file[PATH_MAX];
xasprintf(&file, RC_SVCDIR "/hotplugged/%s", applet);
snprintf(file, sizeof(file), RC_SVCDIR "/hotplugged/%s", applet);
if (exists(file) && unlink(file) != 0)
eerror("%s: unlink `%s': %s", applet, file, strerror(errno));
free(file);
}
static void
@@ -488,7 +485,7 @@ svc_exec(const char *arg1, const char *arg2)
static bool
svc_wait(const char *svc)
{
char *file = NULL;
char file[PATH_MAX];
int fd;
bool forever = false;
RC_STRINGLIST *keywords;
@@ -501,7 +498,8 @@ svc_wait(const char *svc)
forever = true;
rc_stringlist_free(keywords);
xasprintf(&file, RC_SVCDIR "/exclusive/%s", basename_c(svc));
snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s",
basename_c(svc));
interval.tv_sec = 0;
interval.tv_nsec = WAIT_INTERVAL;
@@ -514,29 +512,23 @@ svc_wait(const char *svc)
if (fd != -1) {
if (flock(fd, LOCK_SH | LOCK_NB) == 0) {
close(fd);
free(file);
return true;
}
close(fd);
}
if (errno == ENOENT) {
free(file);
if (errno == ENOENT)
return true;
}
if (errno != EWOULDBLOCK) {
eerror("%s: open `%s': %s", applet, file,
if (errno != EWOULDBLOCK)
eerrorx("%s: open `%s': %s", applet, file,
strerror(errno));
free(file);
exit(EXIT_FAILURE);
}
if (nanosleep(&interval, NULL) == -1) {
if (errno != EINTR)
goto finish;
return false;
}
if (!forever) {
timespecsub(&timeout, &interval, &timeout);
if (timeout.tv_sec <= 0)
goto finish;
return false;
timespecsub(&warn, &interval, &warn);
if (warn.tv_sec <= 0) {
ewarn("%s: waiting for %s (%d seconds)",
@@ -546,8 +538,6 @@ svc_wait(const char *svc)
}
}
}
finish:
free(file);
return false;
}
@@ -1115,10 +1105,9 @@ int main(int argc, char **argv)
bool runscript = false;
int retval, opt, depoptions = RC_DEP_TRACE;
RC_STRING *svc;
char *path = NULL;
char *lnk = NULL;
char path[PATH_MAX], lnk[PATH_MAX];
char *dir, *save = NULL, *saveLnk = NULL;
char *pidstr = NULL;
char pidstr[10];
size_t l = 0, ll;
const char *file;
struct stat stbuf;
@@ -1145,14 +1134,12 @@ int main(int argc, char **argv)
* This works fine, provided that we ONLY allow multiplexed services
* to exist in the same directory as the master link.
* Also, the master link as to be a real file in the init dir. */
path = realpath(argv[1], NULL);
if (!path) {
if (!realpath(argv[1], path)) {
fprintf(stderr, "realpath: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
lnk = xmalloc(4096);
memset(lnk, 0, 4096);
if (readlink(argv[1], lnk, 4096)) {
memset(lnk, 0, sizeof(lnk));
if (readlink(argv[1], lnk, sizeof(lnk)-1)) {
dir = dirname(path);
if (strchr(lnk, '/')) {
save = xstrdup(dir);
@@ -1166,7 +1153,8 @@ int main(int argc, char **argv)
} else
file = basename_c(argv[1]);
ll = strlen(dir) + strlen(file) + 2;
xasprintf(&service, "%s/%s", dir, file);
service = xmalloc(ll);
snprintf(service, ll, "%s/%s", dir, file);
if (stat(service, &stbuf) != 0) {
free(service);
service = xstrdup(lnk);
@@ -1174,7 +1162,6 @@ int main(int argc, char **argv)
free(save);
free(saveLnk);
}
free(lnk);
if (!service)
service = xstrdup(path);
applet = basename_c(service);
@@ -1198,7 +1185,7 @@ int main(int argc, char **argv)
/* Set an env var so that we always know our pid regardless of any
subshells the init script may create so that our mark_service_*
functions can always instruct us of this change */
xasprintf(&pidstr, "%d", (int) getpid());
snprintf(pidstr, sizeof(pidstr), "%d", (int) getpid());
setenv("RC_OPENRC_PID", pidstr, 1);
/*
* RC_RUNSCRIPT_PID is deprecated, but we will keep it for a while
@@ -1268,9 +1255,6 @@ int main(int argc, char **argv)
case_RC_COMMON_GETOPT
}
if (rc_yesno(getenv("RC_NODEPS")))
deps = false;
/* If we're changing runlevels and not called by rc then we cannot
work with any dependencies */
if (deps && getenv("RC_PID") == NULL &&
@@ -1285,8 +1269,6 @@ int main(int argc, char **argv)
unsetenv("IN_BACKGROUND");
}
if (rc_yesno(getenv("IN_DRYRUN")))
dry_run = true;
if (rc_yesno(getenv("IN_HOTPLUG"))) {
if (!service_plugable())
eerrorx("%s: not allowed to be hotplugged", applet);

View File

@@ -87,8 +87,6 @@ write_log(int logfd, const char *buffer, size_t bytes)
}
if (!in_escape) {
if (!isprint((int) *p) && *p != '\n')
goto cont;
if (write(logfd, p++, 1) == -1)
eerror("write: %s", strerror(errno));
continue;

View File

@@ -51,8 +51,7 @@ rc_conf_yesno(const char *setting)
static const char *const env_whitelist[] = {
"EERROR_QUIET", "EINFO_QUIET",
"IN_BACKGROUND", "IN_DRYRUN", "IN_HOTPLUG",
"RC_DEBUG", "RC_NODEPS",
"IN_BACKGROUND", "IN_HOTPLUG",
"LANG", "LC_MESSAGES", "TERM",
"EINFO_COLOR", "EINFO_VERBOSE",
NULL
@@ -132,8 +131,7 @@ env_config(void)
char *npp;
char *tok;
const char *sys = rc_sys();
char *buffer = NULL;
size_t size = 0;
char buffer[PATH_MAX];
/* Ensure our PATH is prefixed with the system locations first
for a little extra security */
@@ -172,7 +170,8 @@ env_config(void)
free(e);
if ((fp = fopen(RC_KRUNLEVEL, "r"))) {
if (getline(&buffer, &size, fp) != -1) {
memset(buffer, 0, sizeof (buffer));
if (fgets(buffer, sizeof (buffer), fp)) {
l = strlen (buffer) - 1;
if (buffer[l] == '\n')
buffer[l] = 0;
@@ -182,7 +181,6 @@ env_config(void)
} else
setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1);
free(buffer);
if (sys)
setenv("RC_SYS", sys, 1);
@@ -234,12 +232,11 @@ signal_setup_restart(int sig, void (*handler)(int))
int
svc_lock(const char *applet)
{
char *file = NULL;
char file[PATH_MAX];
int fd;
xasprintf(&file, RC_SVCDIR "/exclusive/%s", applet);
snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s", applet);
fd = open(file, O_WRONLY | O_CREAT | O_NONBLOCK, 0664);
free(file);
if (fd == -1)
return -1;
if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
@@ -253,12 +250,11 @@ svc_lock(const char *applet)
int
svc_unlock(const char *applet, int fd)
{
char *file = NULL;
char file[PATH_MAX];
xasprintf(&file, RC_SVCDIR "/exclusive/%s", applet);
snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s", applet);
close(fd);
unlink(file);
free(file);
return -1;
}
@@ -362,7 +358,7 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
int serrno = errno;
int merrno;
time_t t;
char *file = NULL;
char file[PATH_MAX];
struct stat st;
struct utimbuf ut;
FILE *fp;
@@ -384,10 +380,7 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
eend (retval, "Failed to update the dependency tree");
if (retval == 0) {
if (stat(RC_DEPTREE_CACHE, &st) != 0) {
eerror("stat(%s): %s", RC_DEPTREE_CACHE, strerror(errno));
return NULL;
}
stat(RC_DEPTREE_CACHE, &st);
if (st.st_mtime < t) {
eerror("Clock skew detected with `%s'", file);
eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
@@ -411,6 +404,34 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
return rc_deptree_load();
}
bool _rc_can_find_pids(void)
{
RC_PIDLIST *pids;
RC_PID *pid;
RC_PID *pid2;
bool retval = false;
if (geteuid() == 0)
return true;
/* If we cannot see process 1, then we don't test to see if
* services crashed or not */
pids = rc_find_pids(NULL, NULL, 0, 1);
if (pids) {
pid = LIST_FIRST(pids);
if (pid) {
retval = true;
while (pid) {
pid2 = LIST_NEXT(pid, entries);
free(pid);
pid = pid2;
}
}
free(pids);
}
return retval;
}
static const struct {
const char * const name;
RC_SERVICE bit;
@@ -423,7 +444,6 @@ static const struct {
{ "service_hotplugged", RC_SERVICE_HOTPLUGGED, },
{ "service_wasinactive", RC_SERVICE_WASINACTIVE, },
{ "service_failed", RC_SERVICE_FAILED, },
{ "service_crashed", RC_SERVICE_CRASHED, },
};
RC_SERVICE lookup_service_state(const char *service)

View File

@@ -1,57 +0,0 @@
/*
* rc-pipes.c
* Helper to handle spawning processes and connecting them to pipes.
*/
/*
* Copyright (c) 2018 The OpenRC Authors.
* See the Authors file at the top-level directory of this distribution and
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
*
* This file is part of OpenRC. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file.
*/
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include "rc-pipes.h"
static const int pipe_read_end = 0;
static const int pipe_write_end = 1;
/*
* Starts a command with stdin redirected from a pipe
* Returns the write end of the pipe or -1
*/
int rc_pipe_command(char *cmd)
{
int pfd[2];
pid_t pid;
if (pipe(pfd) < 0)
return -1;
pid = fork();
if (pid < 0)
return -1;
else if (pid > 0) {
/* parent */
close(pfd[0]);
return pfd[pipe_write_end];
} else if (pid == 0) {
/* child */
close(pfd[pipe_write_end]);
if (pfd[0] != STDIN_FILENO) {
if (dup2(pfd[0], STDIN_FILENO) < 0)
exit(1);
close(pfd[0]);
}
execl("/bin/sh", "sh", "-c", cmd, NULL);
exit(1);
}
}

View File

@@ -1,18 +0,0 @@
/*
* Copyright (c) 2018 The OpenRC Authors.
* See the Authors file at the top-level directory of this distribution and
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
*
* This file is part of OpenRC. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file.
*/
#ifndef RC_PIPES_H
#define RC_PIPES_H
int rc_pipe_command(char *cmd);
#endif

View File

@@ -68,7 +68,7 @@ rc_plugin_load(void)
DIR *dp;
struct dirent *d;
PLUGIN *plugin;
char *file = NULL;
char file[PATH_MAX];
void *h;
int (*fptr)(RC_HOOK, const char *);
@@ -85,9 +85,8 @@ rc_plugin_load(void)
if (d->d_name[0] == '.')
continue;
xasprintf(&file, RC_PLUGINDIR "/%s", d->d_name);
snprintf(file, sizeof(file), RC_PLUGINDIR "/%s", d->d_name);
h = dlopen(file, RTLD_LAZY);
free(file);
if (h == NULL) {
eerror("dlopen: %s", dlerror());
continue;

View File

@@ -307,9 +307,6 @@ int run_stop_schedule(const char *applet,
const char *const *p;
bool progressed = false;
if (!(pid > 0 || exec || uid || (argv && *argv)))
return 0;
if (exec)
einfov("Will stop %s", exec);
if (pid > 0)

View File

@@ -256,19 +256,19 @@ static int read_context_file(const char *filename, char **context)
{
int ret = -1;
FILE *fp;
char *filepath = NULL;
char filepath[PATH_MAX];
char *line = NULL;
char *p;
char *p2;
size_t len = 0;
ssize_t read;
xasprintf(&filepath, "%s/%s", selinux_contexts_path(), filename);
memset(filepath, '\0', PATH_MAX);
snprintf(filepath, PATH_MAX - 1, "%s/%s", selinux_contexts_path(), filename);
fp = fopen(filepath, "r");
if (fp == NULL) {
eerror("Failed to open context file: %s", filename);
free(filepath);
return -1;
}
@@ -294,7 +294,6 @@ static int read_context_file(const char *filename, char **context)
}
free(line);
free(filepath);
fclose(fp);
return ret;
}

View File

@@ -29,33 +29,23 @@
const char *applet = NULL;
const char *extraopts = NULL;
const char *getoptstring = "cdDe:ilr:INsSZ" getoptstring_COMMON;
const char *getoptstring = "e:ilr:IN" getoptstring_COMMON;
const struct option longopts[] = {
{ "debug", 0, NULL, 'd' },
{ "nodeps", 0, NULL, 'D' },
{ "exists", 1, NULL, 'e' },
{ "ifcrashed", 0, NULL, 'c' },
{ "ifexists", 0, NULL, 'i' },
{ "ifinactive", 0, NULL, 'I' },
{ "ifnotstarted", 0, NULL, 'N' },
{ "ifstarted", 0, NULL, 's' },
{ "ifstopped", 0, NULL, 'S' },
{ "list", 0, NULL, 'l' },
{ "resolve", 1, NULL, 'r' },
{ "dry-run", 0, NULL, 'Z' },
longopts_COMMON
};
const char * const longopts_help[] = {
"set xtrace when running the command",
"ignore dependencies",
"tests if the service exists or not",
"if the service is crashed then run the command",
"if the service exists then run the command",
"if the service is inactive then run the command",
"if the service is not started then run the command",
"list all available services",
"resolve the service name to an init script",
"dry run (show what would happen)",
longopts_help_COMMON
};
const char *usagestring = "" \
@@ -71,12 +61,9 @@ int main(int argc, char **argv)
RC_STRINGLIST *list;
RC_STRING *s;
RC_SERVICE state;
bool if_crashed = false;
bool if_exists = false;
bool if_inactive = false;
bool if_notstarted = false;
bool if_started = false;
bool if_stopped = false;
applet = basename_c(argv[0]);
/* Ensure that we are only quiet when explicitly told to be */
@@ -86,21 +73,12 @@ int main(int argc, char **argv)
longopts, (int *) 0)) != -1)
{
switch (opt) {
case 'd':
setenv("RC_DEBUG", "yes", 1);
break;
case 'D':
setenv("RC_NODEPS", "yes", 1);
break;
case 'e':
service = rc_service_resolve(optarg);
opt = service ? EXIT_SUCCESS : EXIT_FAILURE;
free(service);
return opt;
/* NOTREACHED */
case 'c':
if_crashed = true;
break;
case 'i':
if_exists = true;
break;
@@ -128,15 +106,6 @@ int main(int argc, char **argv)
free(service);
return EXIT_SUCCESS;
/* NOTREACHED */
case 's':
if_started = true;
break;
case 'S':
if_stopped = true;
break;
case 'Z':
setenv("IN_DRYRUN", "yes", 1);
break;
case_RC_COMMON_GETOPT
}
@@ -152,16 +121,10 @@ int main(int argc, char **argv)
eerrorx("%s: service `%s' does not exist", applet, *argv);
}
state = rc_service_state(*argv);
if (if_crashed && ! (rc_service_daemons_crashed(*argv) && errno != EACCES))
return 0;
if (if_inactive && ! (state & RC_SERVICE_INACTIVE))
return 0;
if (if_notstarted && (state & RC_SERVICE_STARTED))
return 0;
if (if_started && ! (state & RC_SERVICE_STARTED))
return 0;
if (if_stopped && ! (state & RC_SERVICE_STOPPED))
return 0;
*argv = service;
execv(*argv, argv);
eerrorx("%s: %s", applet, strerror(errno));

View File

@@ -54,6 +54,7 @@ const char *usagestring = "" \
"Usage: rc-status [options] <runlevel>...\n" \
" or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
static bool test_crashed = false;
static RC_DEPTREE *deptree;
static RC_STRINGLIST *types;
@@ -144,7 +145,9 @@ print_service(const char *service)
color = ECOLOR_WARN;
} else if (state & RC_SERVICE_STARTED) {
errno = 0;
if (rc_service_daemons_crashed(service) && errno != EACCES)
if (test_crashed &&
rc_service_daemons_crashed(service) &&
errno != EACCES)
{
child_pid = rc_service_value_get(service, "child_pid");
start_time = rc_service_value_get(service, "start_time");
@@ -237,6 +240,8 @@ int main(int argc, char **argv)
char *p, *runlevel = NULL;
int opt, retval = 0;
test_crashed = _rc_can_find_pids();
applet = basename_c(argv[0]);
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
(int *) 0)) != -1)

View File

@@ -62,7 +62,7 @@ add(const char *runlevel, const char *service)
if (!rc_service_exists(service)) {
if (errno == ENOEXEC)
eerror("%s: service `%s' is not executable",
eerror("%s: service `%s' is not executeable",
applet, service);
else
eerror("%s: service `%s' does not exist",
@@ -166,7 +166,7 @@ show(RC_STRINGLIST *runlevels, bool verbose)
RC_STRING *runlevel;
RC_STRINGLIST *in;
bool inone;
char *buffer = NULL;
char buffer[PATH_MAX];
size_t l;
rc_stringlist_sort(&services);
@@ -182,11 +182,9 @@ show(RC_STRINGLIST *runlevels, bool verbose)
inone = true;
} else {
l = strlen(runlevel->value);
buffer = xmalloc(l+1);
memset (buffer, ' ', l);
buffer[l] = 0;
rc_stringlist_add (in, buffer);
free(buffer);
}
}

View File

@@ -78,6 +78,9 @@ const char *usagestring = "" \
#define INITSH RC_LIBEXECDIR "/sh/init.sh"
#define INITEARLYSH RC_LIBEXECDIR "/sh/init-early.sh"
#define SHUTDOWN "/sbin/shutdown"
#define SULOGIN "/sbin/sulogin"
#define INTERACTIVE RC_SVCDIR "/interactive"
#define DEVBOOT "/dev/.rcboot"
@@ -285,8 +288,8 @@ open_shell(void)
/* VSERVER systems cannot really drop to shells */
if (sys && strcmp(sys, RC_SYS_VSERVER) == 0)
{
execlp("halt", "halt", "-f", (char *) NULL);
eerrorx("%s: unable to exec `halt -f': %s",
execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
eerrorx("%s: unable to exec `/sbin/halt': %s",
applet, strerror(errno));
}
#endif
@@ -333,26 +336,26 @@ set_krunlevel(const char *level)
return true;
}
static char *get_krunlevel(void)
static size_t
get_krunlevel(char *buffer, int buffer_len)
{
char *buffer = NULL;
FILE *fp;
size_t i = 0;
if (!exists(RC_KRUNLEVEL))
return NULL;
return 0;
if (!(fp = fopen(RC_KRUNLEVEL, "r"))) {
eerror("fopen `%s': %s", RC_KRUNLEVEL, strerror(errno));
return NULL;
return 0;
}
if (getline(&buffer, &i, fp) != -1) {
if (fgets(buffer, buffer_len, fp)) {
i = strlen(buffer);
if (buffer[i - 1] == '\n')
buffer[i - 1] = 0;
}
fclose(fp);
return buffer;
return i;
}
static void
@@ -502,9 +505,6 @@ do_sysinit()
* sys */
if ((sys = rc_sys()))
setenv("RC_SYS", sys, 1);
/* force an update of the dependency tree */
if ((main_deptree = _rc_deptree_load(1, NULL)) == NULL)
eerrorx("failed to load deptree");
}
static bool
@@ -743,7 +743,7 @@ int main(int argc, char **argv)
RC_STRING *service;
bool going_down = false;
int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
char *krunlevel = NULL;
char krunlevel [PATH_MAX];
char pidstr[10];
int opt;
bool parallel;
@@ -892,8 +892,7 @@ int main(int argc, char **argv)
(strcmp(newlevel, RC_LEVEL_SYSINIT) != 0 &&
strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0))
{
krunlevel = get_krunlevel();
if (krunlevel) {
if (get_krunlevel(krunlevel, sizeof(krunlevel))) {
newlevel = krunlevel;
set_krunlevel(NULL);
}

View File

@@ -59,14 +59,13 @@ static struct pam_conv conv = { NULL, NULL};
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
#include "rc-pipes.h"
#include "rc-schedules.h"
#include "_usage.h"
#include "helpers.h"
const char *applet = NULL;
const char *extraopts = NULL;
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" \
getoptstring_COMMON;
const struct option longopts[] = {
{ "ionice", 1, NULL, 'I'},
@@ -94,8 +93,6 @@ const struct option longopts[] = {
{ "exec", 1, NULL, 'x'},
{ "stdout", 1, NULL, '1'},
{ "stderr", 1, NULL, '2'},
{ "stdout-logger",1, NULL, '3'},
{ "stderr-logger",1, NULL, '4'},
{ "progress", 0, NULL, 'P'},
longopts_COMMON
};
@@ -125,8 +122,6 @@ const char * const longopts_help[] = {
"Binary to start/stop",
"Redirect stdout to file",
"Redirect stderr to file",
"Redirect stdout to process",
"Redirect stderr to process",
"Print dots each second while waiting",
longopts_help_COMMON
};
@@ -259,7 +254,6 @@ int main(int argc, char **argv)
#endif
int opt;
size_t size = 0;
bool start = false;
bool stop = false;
bool oknodo = false;
@@ -281,8 +275,6 @@ int main(int argc, char **argv)
int tid = 0;
char *redirect_stderr = NULL;
char *redirect_stdout = NULL;
char *stderr_process = NULL;
char *stdout_process = NULL;
int stdin_fd;
int stdout_fd;
int stderr_fd;
@@ -295,10 +287,10 @@ int main(int argc, char **argv)
char *tmp, *newpath, *np;
char *p;
char *token;
char *exec_file = NULL;
char exec_file[PATH_MAX];
struct passwd *pw;
struct group *gr;
char *line = NULL;
char line[130];
FILE *fp;
size_t len;
mode_t numask = 022;
@@ -507,14 +499,6 @@ int main(int argc, char **argv)
redirect_stderr = optarg;
break;
case '3': /* --stdout-logger "command to run for stdout logging" */
stdout_process = optarg;
break;
case '4': /* --stderr-logger "command to run for stderr logging" */
stderr_process = optarg;
break;
case_RC_COMMON_GETOPT
}
@@ -566,9 +550,6 @@ int main(int argc, char **argv)
if (redirect_stdout || redirect_stderr)
eerrorx("%s: --stdout and --stderr are only relevant"
" with --start", applet);
if (stdout_process || stderr_process)
eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
" with --start", applet);
if (start_wait)
ewarn("using --wait with --stop has no effect,"
" use --retry instead");
@@ -581,15 +562,6 @@ int main(int argc, char **argv)
if ((redirect_stdout || redirect_stderr) && !background)
eerrorx("%s: --stdout and --stderr are only relevant"
" with --background", applet);
if ((stdout_process || stderr_process) && !background)
eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
" with --background", applet);
if (redirect_stdout && stdout_process)
eerrorx("%s: do not use --stdout and --stdout-logger together",
applet);
if (redirect_stderr && stderr_process)
eerrorx("%s: do not use --stderr and --stderr-logger together",
applet);
}
/* Expand ~ */
@@ -605,22 +577,26 @@ int main(int argc, char **argv)
if (*exec == '/' || *exec == '.') {
/* Full or relative path */
if (ch_root)
xasprintf(&exec_file, "%s/%s", ch_root, exec);
snprintf(exec_file, sizeof(exec_file),
"%s/%s", ch_root, exec);
else
xasprintf(&exec_file, "%s", exec);
snprintf(exec_file, sizeof(exec_file),
"%s", exec);
} else {
/* Something in $PATH */
p = tmp = xstrdup(getenv("PATH"));
exec_file = NULL;
*exec_file = '\0';
while ((token = strsep(&p, ":"))) {
if (ch_root)
xasprintf(&exec_file, "%s/%s/%s", ch_root, token, exec);
snprintf(exec_file, sizeof(exec_file),
"%s/%s/%s",
ch_root, token, exec);
else
xasprintf(&exec_file, "%s/%s", token, exec);
if (exec_file && exists(exec_file))
snprintf(exec_file, sizeof(exec_file),
"%s/%s", token, exec);
if (exists(exec_file))
break;
free(exec_file);
exec_file = NULL;
*exec_file = '\0';
}
free(tmp);
}
@@ -628,8 +604,8 @@ int main(int argc, char **argv)
if (start && !exists(exec_file)) {
eerror("%s: %s does not exist", applet,
*exec_file ? exec_file : exec);
free(exec_file);
exit(EXIT_FAILURE);
}
if (start && retry)
ewarn("using --retry with --start has no effect,"
@@ -641,10 +617,7 @@ int main(int argc, char **argv)
if (interpreted && !pidfile) {
fp = fopen(exec_file, "r");
if (fp) {
line = NULL;
if (getline(&line, &size, fp) == -1)
eerrorx("%s: %s", applet, strerror(errno));
p = line;
p = fgets(line, sizeof(line), fp);
fclose(fp);
if (p != NULL && line[0] == '#' && line[1] == '!') {
p = line + 2;
@@ -656,8 +629,7 @@ int main(int argc, char **argv)
if (p[len] == '\n')
p[len] = '\0';
token = strsep(&p, " ");
free(exec_file);
xasprintf(&exec_file, "%s", token);
strncpy(exec_file, token, sizeof(exec_file));
opt = 0;
for (nav = argv; *nav; nav++)
opt++;
@@ -685,15 +657,8 @@ int main(int argc, char **argv)
parse_schedule(applet, "0", sig);
else
parse_schedule(applet, NULL, sig);
if (pidfile) {
pid = get_pid(applet, pidfile);
if (pid == -1 && errno != ENOENT)
exit(EXIT_FAILURE);
} else {
pid = 0;
}
i = run_stop_schedule(applet, exec, (const char *const *)margv,
pid, uid, test, progress, false);
get_pid(applet, pidfile), uid, test, progress, false);
if (i < 0)
/* We failed to stop something */
@@ -912,12 +877,6 @@ int main(int argc, 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,
@@ -926,21 +885,13 @@ int main(int argc, 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));
}
if (background)
dup2(stdin_fd, STDIN_FILENO);
if (background || redirect_stdout || stdout_process
|| rc_yesno(getenv("EINFO_QUIET")))
if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
dup2(stdout_fd, STDOUT_FILENO);
if (background || redirect_stderr || stderr_process
|| rc_yesno(getenv("EINFO_QUIET")))
if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
dup2(stderr_fd, STDERR_FILENO);
for (i = getdtablesize() - 1; i >= 3; --i)

View File

@@ -159,7 +159,7 @@ static void cleanup(void)
free(changeuser);
}
static void re_exec_supervisor(void)
static void re_exec(void)
{
syslog(LOG_WARNING, "Re-executing for %s", svcname);
execlp("supervise-daemon", "supervise-daemon", svcname, "--reexec",
@@ -180,7 +180,7 @@ static void handle_signal(int sig)
/* Restore errno */
errno = serrno;
if (! exiting)
re_exec_supervisor();
re_exec();
}
static char * expand_home(const char *home, const char *path)
@@ -224,23 +224,6 @@ static char * expand_home(const char *home, const char *path)
return nh;
}
static char *make_cmdline(char **argv)
{
char **c;
char *cmdline = NULL;
size_t len = 0;
for (c = argv; c && *c; c++)
len += (strlen(*c) + 1);
cmdline = xmalloc(len+1);
memset(cmdline, 0, len+1);
for (c = argv; c && *c; c++) {
strcat(cmdline, *c);
strcat(cmdline, " ");
}
return cmdline;
}
static void child_process(char *exec, char **argv)
{
RC_STRINGLIST *env_list;
@@ -251,7 +234,8 @@ static void child_process(char *exec, char **argv)
size_t len;
char *newpath;
char *np;
char *cmdline = NULL;
char **c;
char cmdline[PATH_MAX];
time_t start_time;
char start_count_string[20];
char start_time_string[20];
@@ -411,9 +395,15 @@ static void child_process(char *exec, char **argv)
for (i = getdtablesize() - 1; i >= 3; --i)
fcntl(i, F_SETFD, FD_CLOEXEC);
cmdline = make_cmdline(argv);
*cmdline = '\0';
c = argv;
while (c && *c) {
strcat(cmdline, *c);
strcat(cmdline, " ");
c++;
}
syslog(LOG_INFO, "Child command line: %s", cmdline);
free(cmdline);
execvp(exec, argv);
#ifdef HAVE_PAM
@@ -445,9 +435,7 @@ static void supervisor(char *exec, char **argv)
signal_setup_restart(SIGUSR1, handle_signal);
signal_setup_restart(SIGUSR2, handle_signal);
signal_setup_restart(SIGBUS, handle_signal);
#ifdef SIGPOLL
signal_setup_restart(SIGPOLL, handle_signal);
#endif
signal_setup_restart(SIGPROF, handle_signal);
signal_setup_restart(SIGSYS, handle_signal);
signal_setup_restart(SIGTRAP, handle_signal);
@@ -458,9 +446,7 @@ static void supervisor(char *exec, char **argv)
signal_setup_restart(SIGEMT, handle_signal);
#endif
signal_setup_restart(SIGIO, handle_signal);
#ifdef SIGPWR
signal_setup_restart(SIGPWR, handle_signal);
#endif
#ifdef SIGUNUSED
signal_setup_restart(SIGUNUSED, handle_signal);
#endif
@@ -561,8 +547,8 @@ int main(int argc, char **argv)
char *token;
int i;
int n;
char *exec_file = NULL;
char *varbuf = NULL;
char exec_file[PATH_MAX];
char name[PATH_MAX];
struct timespec ts;
struct passwd *pw;
struct group *gr;
@@ -571,7 +557,7 @@ int main(int argc, char **argv)
int child_argc = 0;
char **child_argv = NULL;
char *str = NULL;
char *cmdline = NULL;
char cmdline[PATH_MAX];
applet = basename_c(argv[0]);
atexit(cleanup);
@@ -581,8 +567,7 @@ int main(int argc, char **argv)
openlog(applet, LOG_PID, LOG_DAEMON);
if (argc >= 1 && svcname && strcmp(argv[1], svcname))
eerrorx("%s: the first argument is %s and must be %s",
applet, argv[1], svcname);
eerrorx("%s: the first argument must be %s", applet, svcname);
if ((tmp = getenv("SSD_NICELEVEL")))
if (sscanf(tmp, "%d", &nicelevel) != 1)
@@ -604,7 +589,13 @@ int main(int argc, char **argv)
}
}
cmdline = make_cmdline(argv);
*cmdline = '\0';
c = argv;
while (c && *c) {
strcat(cmdline, *c);
strcat(cmdline, " ");
c++;
}
if (svcname) {
argc--;
argv++;
@@ -766,11 +757,9 @@ int main(int argc, char **argv)
child_argv = xmalloc((child_argc + 1) * sizeof(char *));
memset(child_argv, 0, (child_argc + 1) * sizeof(char *));
for (x = 0; x < child_argc; x++) {
xasprintf(&varbuf, "argv_%d", x);
str = rc_service_value_get(svcname, varbuf);
sprintf(name, "argv_%d", x);
str = rc_service_value_get(svcname, name);
child_argv[x] = str;
free(varbuf);
varbuf = NULL;
}
free(str);
str = rc_service_value_get(svcname, "child_pid");
@@ -799,31 +788,32 @@ int main(int argc, char **argv)
if (*exec == '/' || *exec == '.') {
/* Full or relative path */
if (ch_root)
xasprintf(&exec_file, "%s/%s", ch_root, exec);
snprintf(exec_file, sizeof(exec_file),
"%s/%s", ch_root, exec);
else
xasprintf(&exec_file, "%s", exec);
snprintf(exec_file, sizeof(exec_file),
"%s", exec);
} else {
/* Something in $PATH */
p = tmp = xstrdup(getenv("PATH"));
exec_file = NULL;
*exec_file = '\0';
while ((token = strsep(&p, ":"))) {
if (ch_root)
xasprintf(&exec_file, "%s/%s/%s", ch_root, token, exec);
snprintf(exec_file, sizeof(exec_file),
"%s/%s/%s",
ch_root, token, exec);
else
xasprintf(&exec_file, "%s/%s", token, exec);
if (exec_file && exists(exec_file))
snprintf(exec_file, sizeof(exec_file),
"%s/%s", token, exec);
if (exists(exec_file))
break;
free(exec_file);
exec_file = NULL;
*exec_file = '\0';
}
free(tmp);
}
if (!exists(exec_file)) {
eerror("%s: %s does not exist", applet,
if ( !exists(exec_file))
eerrorx("%s: %s does not exist", applet,
*exec_file ? exec_file : exec);
free(exec_file);
exit(EXIT_FAILURE);
}
} else
eerrorx("%s: nothing to start", applet);
@@ -846,8 +836,6 @@ int main(int argc, char **argv)
einfov("Detaching to start `%s'", exec);
syslog(LOG_INFO, "Supervisor command line: %s", cmdline);
free(cmdline);
cmdline = NULL;
/* Remove existing pidfile */
if (pidfile)
@@ -860,13 +848,12 @@ int main(int argc, char **argv)
fclose(fp);
rc_service_value_set(svcname, "pidfile", pidfile);
varbuf = NULL;
xasprintf(&varbuf, "%i", respawn_delay);
rc_service_value_set(svcname, "respawn_delay", varbuf);
xasprintf(&varbuf, "%i", respawn_max);
rc_service_value_set(svcname, "respawn_max", varbuf);
xasprintf(&varbuf, "%i", respawn_period);
rc_service_value_set(svcname, "respawn_period", varbuf);
sprintf(name, "%i", respawn_delay);
rc_service_value_set(svcname, "respawn_delay", name);
sprintf(name, "%i", respawn_max);
rc_service_value_set(svcname, "respawn_max", name);
sprintf(name, "%i", respawn_period);
rc_service_value_set(svcname, "respawn_period", name);
child_pid = fork();
if (child_pid == -1)
eerrorx("%s: fork: %s", applet, strerror(errno));
@@ -884,16 +871,13 @@ int main(int argc, char **argv)
c = argv;
x = 0;
while (c && *c) {
varbuf = NULL;
xasprintf(&varbuf, "argv_%-d",x);
rc_service_value_set(svcname, varbuf, *c);
free(varbuf);
varbuf = NULL;
snprintf(name, sizeof(name), "argv_%-d",x);
rc_service_value_set(svcname, name, *c);
x++;
c++;
}
xasprintf(&varbuf, "%d", x);
rc_service_value_set(svcname, "argc", varbuf);
sprintf(name, "%d", x);
rc_service_value_set(svcname, "argc", name);
rc_service_value_set(svcname, "exec", exec);
supervisor(exec, argv);
} else

View File

@@ -1,5 +1,4 @@
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

View File

@@ -1,5 +1,4 @@
deptree2dot - Graph the OpenRC Dependency Tree
==============================================
# deptree2dot - Graph the OpenRC Dependency Tree
This utility can be used to graph the OpenRC dependency tree. It
requires perl5.x and converts the tree to a .dot file which can be

View File

@@ -7,5 +7,7 @@ BIN= ${OBJS}
MK= ../../mk
SED_EXTRA+= -e 's:@VARBASE@:/var:g'
include ${MK}/os.mk
include ${MK}/scripts.mk

View File

@@ -1,6 +1,3 @@
Example OpenRC Service Scripts
##############################
The service scripts in this directory are meant as examples only.
They are not installed by default as the scripts will need tweaking on a
per distro basis. They are also non essential to the operation of the system.

View File

@@ -11,7 +11,7 @@
command=@PKG_PREFIX@/sbin/avahi-dnsconfd
command_args="$avahi_dnsconfd_args -D"
pidfile=/var/run/avahi-dnsconfd.pid
pidfile=@VARBASE@/run/avahi-dnsconfd.pid
name="Avahi DNS Configuration Daemon"
depend()

View File

@@ -11,7 +11,7 @@
command=@PKG_PREFIX@/sbin/avahi-daemon
command_args="$avahid_args -D"
pidfile=/var/run/avahi-daemon/pid
pidfile=@VARBASE@/run/avahi-daemon/pid
name="Avahi Service Advertisement Daemon"
depend()

View File

@@ -10,7 +10,7 @@
# except according to the terms contained in the LICENSE file.
command=@PKG_PREFIX@/bin/dbus-daemon
pidfile=/var/run/dbus/pid
pidfile=@VARBASE@/run/dbus/pid
command_args="${dbusd_args---system}"
name="Message Bus Daemon"

View File

@@ -11,7 +11,7 @@
command=@PKG_PREFIX@/sbin/dnsmasq
command_args=$dnsmasq_args
pidfile=/var/run/dnsmasq.pid
pidfile=@VARBASE@/run/dnsmasq.pid
required_files=/etc/dnsmasq.conf
extra_started_commands="reload"

View File

@@ -10,7 +10,7 @@
# except according to the terms contained in the LICENSE file.
command=@PKG_PREFIX@/sbin/hald
pidfile=/var/run/hald/hald.pid
pidfile=@VARBASE@/run/hald/hald.pid
command_args=$hald_args
name="Hardware Abstraction Layer Daemon"

View File

@@ -11,7 +11,7 @@
command=/usr/sbin/named
command_args=$named_args
pidfile=/var/run/named.pid
pidfile=@VARBASE@/run/named.pid
name="Domain Name server"
extra_started_commands="reload"
@@ -20,7 +20,7 @@ uid=named
case "$RC_UNAME" in
FreeBSD)
uid=bind
pidfile=/var/run/named/pid
pidfile=@VARBASE@/run/named/pid
;;
Linux)
uid=bind

View File

@@ -14,7 +14,7 @@ name="OpenVPN"
[ "$vpn" != openvpn ] && name="$name ($vpn)"
command=@PKG_PREFIX@/sbin/openvpn
pidfile=/var/run/"$RC_SVCNAME".pid
pidfile=@VARBASE@/run/"$RC_SVCNAME".pid
: ${openvpn_dir:=@PKG_PREFIX@/etc/openvpn}
: ${openvpn_config:=$openvpn_dir/$vpn.conf}
command_args="$openvpn_args --daemon --config $openvpn_config"

Some files were not shown because too many files have changed in this diff Show More