Compare commits

..

5 Commits

Author SHA1 Message Date
William Hubbs
2747f40f82 update changelog 2016-01-13 20:21:17 -06:00
William Hubbs
933972da53 fix selinux build 2016-01-13 20:15:15 -06:00
William Hubbs
dbcb8ba3fe Add LANG, LC_MESSAGES and TERM to the environment whitelist 2016-01-13 20:15:14 -06:00
William Hubbs
e462c3223e fix seg fault 2016-01-13 20:15:14 -06:00
William Hubbs
06f195ce37 increment version number 2016-01-13 19:53:03 -06:00
78 changed files with 1127 additions and 2334 deletions

1428
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -38,7 +38,7 @@ Who:
When: 1.0
Why: Deprecated in favor of extra_commands, extra_started_commands
Why: Depprecated in favor of extra_commands, extra_started_commands
and extra_stopped_commands.
Who:
@@ -47,7 +47,7 @@ Who:
When: 1.0
Why: Deprecated in favor of executable scripts in @SYSCONFDIR@/local.d
Why: Depprecated in favor of executable scripts in @SYSCONFDIR@/local.d
Who:
@@ -76,3 +76,13 @@ Why: The getline() function was standardized in POSIX.1-2008, so it
Who:
### rc_sys()
When: 1.0
Why: The OpenRC code now uses two internal functions, detect_container()
and detect_vm() to handle this. rc_sys() is broken because it
doesn't differentiate between containers and vm's.
Who:

View File

@@ -1,3 +1,3 @@
NAME= openrc
VERSION= 0.21.7
VERSION= 0.20.1
PKG= ${NAME}-${VERSION}

27
NEWS.md
View File

@@ -3,33 +3,6 @@
This file will contain a list of notable changes for each release. Note
the information in this file is in reverse order.
## OpenRC-0.21
This version adds a daemon supervisor which can start daemons and
restart them if they crash. See supervise-daemon-guide.md in the
distribution for details on its use.
It is now possible to mark certain mount points as critical. If these
mount points are unable to be mounted, localmount or netmount will fail.
This is handled in /etc/conf.d/localmount and /etc/conf.d/netmount. See
these files for the setup.
The deprecation messages in 0.13.x for runscript and rc are now
made visible in preparation for the removal of these binaries in 1.0.
The steps you should take to get rid of these warnings is to run openrc
in initialization steps instead of rc and change the shebang lines in
service scripts to refer to "openrc-run" instead of "runscript".
In 0.21.4, a modules-load service was added. This works like the
equivalent service in systemd. It looks for files named *.conf first in
/usr/lib/modules-load.d, then /run/modules-load.d, then
/etc/modules-load.d. These files contain a list of modules, one per
line, which should be loaded into the kernel. If a file name appears in
/run/modules-load.d, it overrides a file of the same name in
/usr/lib/modules-load.d. A file appearing in /etc/modules-load.d
overrides a file of the same name in both previous directories.
## OpenRC-0.19
This version adds a net-online service. By default, this

View File

@@ -9,7 +9,7 @@ wipe_tmp="YES"
# This may be useful if you need the kernel boot log afterwards
log_dmesg="YES"
# Save the previous dmesg log to dmesg.old
# Save the previous dmesg log to dmesc.old
# This may be useful if you need to compare the current boot to the
# previous one.
#previous_dmesg=no

View File

@@ -1,10 +1,3 @@
# Stop the unmounting of certain points.
# This could be useful for some NFS related work.
#no_umounts="/dir1:/var/dir2"
#
# Mark certain mount points as critical.
# This contains aspace separated list of mount points which should be
# considered critical. If one of these mount points cannot be mounted,
# localmount will fail.
# By default, this is empty.
#critical_mounts="/home /var"

View File

@@ -38,10 +38,3 @@
# other words, please change it to be more suited to your system.
#
rc_need="net"
#
# Mark certain mount points as critical.
# This contains aspace separated list of mount points which should be
# considered critical. If one of these mount points cannot be mounted,
# netmount will fail.
# By default, this is empty.
#critical_mounts="/home /var"

251
guide.md
View File

@@ -1,251 +0,0 @@
# Purpose and description
OpenRC is an init system for Unixoid operating systems. It takes care of
startup and shutdown of the whole system, including services.
It evolved out of the Gentoo "Baselayout" package which was a custom pure-shell
startup solution. (This was both hard to maintain and debug, and not very
performant)
Most of the core parts are written in C99 for performance and flexibility
reasons, while everything else is posix sh.
The License is 2-clause BSD
Current size is about 10k LoC C, and about 4k LoC shell.
OpenRC is known to work on Linux, many BSDs (FreeBSD, OpenBSD, DragonFlyBSD at
least) and HURD.
Services are stateful (i.e. start; start will lead to "it's already started")
# Startup
Usually PID1 (aka. init) calls the OpenRC binary ("/sbin/openrc" by default).
(The default setup assumes sysvinit for this)
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 init scripts are started openrc terminates. There is no persistent
daemon. (Integration with tools like monit, runit or s6 can be done)
# Shutdown
On change to runlevel 0/6 or running "reboot", "halt" etc., openrc stops all
services that are started and runs the services in the "shutdown" runlevel.
# Modifying Service Scripts
Any service can, at any time, be started/stopped/restarted by executing
"rc-service someservice start", "rc-service someservice stop", etc.
Another, less preferred method, is to run the service script directly,
e.g. "/etc/init.d/service start", "/etc/init.d/service stop", etc.
OpenRC will take care of dependencies, e.g starting apache will start network
first, and stopping network will stop apache first.
There is a special command "zap" that makes OpenRC 'forget' that a service is
started; this is mostly useful to reset a crashed service to stopped state
without invoking the (possibly broken) stop function of the service script.
Calling "openrc" without any arguments will try to reset all services so
that the current runlevel is satisfied; if you manually started apache it will be
stopped, and if squid died but is in the current runlevel it'll be restarted.
There is a "service" helper that emulates the syntax seen on e.g. older Redhat
and Ubuntu ("service nginx start" etc.)
# Runlevels
OpenRC has a concept of runlevels, similar to what sysvinit historically
offered. A runlevel is basically a collection of services that needs to be
started. Instead of random numbers they are named, and users can create their
own if needed. This allows, for example, to have a default runlevel with
"everything" enabled, and a "powersaving" runlevel where some services are
disabled.
The "rc-status" helper will print all currently active runlevels and the state
of init scripts in them:
# rc-status
* Caching service dependencies ... [ ok ]
Runlevel: default
modules [ started ]
lvm [ started ]
All runlevels are represented as folders in /etc/runlevels/ with symlinks to
the actual init scripts.
Calling openrc with an argument ("openrc default") will switch to that
runlevel; this will start and stop services as needed.
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 initscript by hand.
FIXME: Document stacked runlevels
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 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
Most service scripts need default values. It would be fragile to
explicitly source some arbitrary files. By convention openrc-run will source
the matching file in /etc/conf.d/ for any script in /etc/init.d/
This allows you to set random startup-related things easily. Example:
conf.d/foo:
START_OPTS="--extraparameter sausage"
init.d/foo:
start() {
/usr/sbin/foo-daemon ${STARTOPTS}
}
The big advantage of this split is that most of the time editing of the init
script can be avoided.
# Start-Stop-Daemon
OpenRC has its own modified version of s-s-d, which is historically related and
mostly syntax-compatible to Debian's s-s-d, but has been rewritten from scratch.
It helps with starting daemons, backgrounding, creating PID files and many
other convenience functions related to managing daemons.
# /etc/rc.conf
This file manages the default configuration for OpenRC, and it has examples of
per-service-script variables.
Among these are rc_parallel (for parallelized startup), rc_log (logs all boot
messages to a file), and a few others.
# ulimit and CGroups
Setting ulimit and nice values per service can be done through the rc_ulimit
variable.
Under Linux, OpenRC can optionally use CGroups for process management.
By default each service script's processes are migrated to their own CGroup.
By changing certain values in the conf.d file limits can be enforced per
service. It is easy to find orphan processes of a service that persist after
stop(), but by default these will NOT be terminated.
To change this add rc_cgroup_cleanup="yes" in the conf.d files for services
where you desire this functionality.
# Caching
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
change it'll re-source the relevant files and update the cache
# Convenience functions
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 initscripts all use ebegin/eend to
print nice messages.

1
init.d/.gitignore vendored
View File

@@ -1,5 +1,4 @@
binfmt
modules-load
bootmisc
fsck
hostname

View File

@@ -19,10 +19,10 @@ SRCS-FreeBSD= hostid.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 \
modules.in modules-load.in mixer.in nscd.in powerd.in syscons.in
mixer.in nscd.in powerd.in syscons.in
SRCS-Linux= 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 \
killprocs.in modules.in mount-ro.in mtab.in numlock.in \
procfs.in net-online.in sysfs.in termencoding.in tmpfiles.dev.in
# Generic BSD scripts

View File

@@ -15,7 +15,7 @@ depend()
{
after procfs
use modules devfs
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
keyword -openvz -prefix -systemd-nspawn -vserver -lxc
}
start()

View File

@@ -15,7 +15,7 @@ depend()
{
need localmount termencoding
after hotplug bootmisc modules
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc
}
start()

View File

@@ -15,7 +15,7 @@ depend()
{
provide dev-mount
before dev
keyword -docker -lxc -prefix -systemd-nspawn -vserver
keyword -prefix -systemd-nspawn -vserver -lxc
}
mount_dev()

View File

@@ -14,7 +14,7 @@ description="Set the dmesg level for a cleaner boot"
depend()
{
before dev modules
keyword -docker -lxc -prefix -systemd-nspawn -vserver
keyword -lxc -prefix -systemd-nspawn -vserver
}
start()

View File

@@ -16,7 +16,7 @@ _IFS="
depend()
{
use dev clock modules
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -timeout -vserver -uml
keyword -jail -openvz -prefix -systemd-nspawn -timeout -vserver -lxc -uml
}
_abort() {

View File

@@ -12,7 +12,7 @@
description="Sets the hostname of the machine."
depend() {
keyword -docker -lxc -prefix -systemd-nspawn
keyword -prefix -systemd-nspawn -lxc
}
start()

View File

@@ -35,7 +35,7 @@ depend()
else
before *
fi
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc
}
setupopts()
@@ -69,16 +69,6 @@ _hwclock()
return 1
}
get_noadjfile()
{
if ! yesno $clock_adjfile; then
# Some implementations don't handle adjustments
if LC_ALL=C hwclock --help 2>&1 | grep -q "\-\-noadjfile"; then
echo --noadjfile
fi
fi
}
start()
{
local retval=0 errstr=""
@@ -101,16 +91,16 @@ start()
fi
# Always set the kernel's time zone.
_hwclock --systz $utc_cmd $(get_noadjfile) $clock_args
_hwclock --systz $utc_cmd $clock_args
: $(( retval += $? ))
if [ -e /etc/adjtime ] && yesno $clock_adjfile; then
_hwclock --adjust $utc_cmd $(get_noadjfile)
_hwclock --adjust $utc_cmd
: $(( retval += $? ))
fi
if yesno ${clock_hctosys:-YES}; then
_hwclock --hctosys $utc_cmd $(get_noadjfile) $clock_args
_hwclock --hctosys $utc_cmd $clock_args
: $(( retval += $? ))
fi
@@ -132,7 +122,14 @@ stop()
ebegin "Setting hardware clock using the system clock" "[$utc]"
_hwclock --systohc $utc_cmd $(get_noadjfile) $clock_args
if ! yesno $clock_adjfile; then
# Some implementations don't handle adjustments
if LC_ALL=C hwclock --help 2>&1 | grep -q "\-\-noadjfile"; then
utc_cmd="$utc_cmd --noadjfile"
fi
fi
_hwclock --systohc $utc_cmd $clock_args
retval=$?
eend $retval "Failed to sync clocks"
@@ -147,5 +144,5 @@ save()
show()
{
setupopts
hwclock --show "$utc_cmd" $(get_noadjfile) $clock_args
hwclock --show "$utc_cmd" $clock_args
}

View File

@@ -15,7 +15,7 @@ depend()
{
need localmount termencoding
after bootmisc
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc
}
start()

View File

@@ -20,8 +20,10 @@ start()
{
ebegin "Terminating remaining processes"
killall5 -15 ${killall5_opts}
sleep 1
eend 0
ebegin "Killing remaining processes"
killall5 -9 ${killall5_opts}
sleep 1
eend 0
}

View File

@@ -16,13 +16,13 @@ depend()
need fsck
use lvm modules mtab
after lvm modules
keyword -docker -jail -lxc -prefix -systemd-nspawn -vserver
keyword -jail -prefix -systemd-nspawn -vserver -lxc
}
start()
{
# Mount local filesystems in /etc/fstab.
local critical= types="noproc" x= no_netdev= rc=
local types="noproc" x= no_netdev= rc=
for x in $net_fs_list $extra_net_fs_list; do
types="${types},no${x}"
done
@@ -37,17 +37,8 @@ start()
mount -at "$types" $no_netdev
eend $? "Some local filesystem failed to mount"
rc=$?
if [ -z "$critical_mounts" ]; then
if [ "$RC_UNAME" != Linux ]; then
rc=0
else
for x in ${critical_mounts}; do
fstabinfo -q $x || continue
if ! mountinfo -q $x; then
critical=x
eerror "Failed to mount $x"
fi
done
[ -z "$critical" ] && rc=0
fi
return $rc
}

View File

@@ -1,72 +0,0 @@
#!@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 -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,8 +14,7 @@ description="Loads a user defined list of kernel modules."
depend()
{
use isapnp
want modules-load
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
keyword -openvz -prefix -systemd-nspawn -vserver -lxc
}
start()

View File

@@ -14,7 +14,7 @@ description="Re-mount filesytems read-only for a clean reboot."
depend()
{
need killprocs savecache
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
keyword -openvz -prefix -systemd-nspawn -vserver -lxc
}
start()

View File

@@ -15,7 +15,7 @@ depend()
{
after modules
need sysfs
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -uml -vserver
keyword -jail -lxc -openvz -prefix -systemd-nspawn -uml -vserver
}
get_interfaces()

View File

@@ -21,10 +21,10 @@ depend()
esac
done
config /etc/fstab
want $mywant
want $mywant
use afc-client amd openvpn
use dns
keyword -docker -jail -lxc -prefix -systemd-nspawn -vserver
keyword -jail -prefix -systemd-nspawn -vserver -lxc
}
start()
@@ -37,22 +37,13 @@ start()
ebegin "Mounting network filesystems"
mount -at $fs
rc=$?
if [ "$RC_UNAME" = Linux ] && [ $rc = 0 ]; then
if [ "$RC_UNAME" = Linux ]; then
mount -a -O _netdev
rc=$?
fi
ewend $rc "Could not mount all network filesystems"
if [ -z "$critical_mounts" ]; then
if [ "$RC_UNAME" != Linux ]; then
rc=0
else
for x in ${critical_mounts}; do
fstabinfo -q $x || continue
if ! mountinfo -q $x; then
critical=x
eerror "Failed to mount $x"
fi
done
[ -z "$critical" ] && rc=0
fi
return $rc
}
@@ -81,7 +72,7 @@ stop()
retval=$?
eoutdent
if [ "$RC_UNAME" = Linux ] && [ $retval = 0 ]; then
if [ "$RC_UNAME" = Linux ]; then
umount -a -O _netdev
retval=$?
fi

View File

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

View File

@@ -15,7 +15,7 @@ depend()
{
use modules devfs
need localmount
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
keyword -openvz -prefix -systemd-nspawn -vserver -lxc
}
start()

View File

@@ -14,7 +14,7 @@ description="Mount the root fs read/write"
depend()
{
need fsck
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -vserver
keyword -jail -openvz -prefix -systemd-nspawn -vserver -lxc
}
start()

View File

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

View File

@@ -12,7 +12,7 @@
depend()
{
before localmount
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -vserver
keyword -jail -openvz -prefix -systemd-nspawn -vserver -lxc
}
start()

View File

@@ -12,7 +12,7 @@
depend()
{
need localmount
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -vserver
keyword -jail -openvz -prefix -systemd-nspawn -vserver -lxc
}
start()

View File

@@ -15,7 +15,7 @@ depend()
{
before *
provide clock
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc
}
# swclock is an OpenRC built in

View File

@@ -15,7 +15,7 @@ sysfs_opts=nodev,noexec,nosuid
depend()
{
keyword -docker -lxc -prefix -systemd-nspawn -vserver
keyword -lxc -prefix -systemd-nspawn -vserver
}
mount_sys()
@@ -88,15 +88,6 @@ mount_misc()
fi
fi
# Setup Kernel Support for persistent storage
if [ -d /sys/fs/pstore ] && ! mountinfo -q /sys/fs/pstore; then
if grep -qs 'pstore$' /proc/filesystems; then
ebegin "Mounting persistent storage (pstore) filesystem"
mount -t pstore pstore -o ${sysfs_opts} /sys/fs/pstore
eend $?
fi
fi
# setup up kernel support for efivarfs
# slightly complicated, as if it's build as a module but NOT yet loaded,
# it will NOT appear in /proc/filesystems yet

View File

@@ -16,7 +16,7 @@ ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
depend()
{
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
keyword -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
use root
after bootmisc
}

View File

@@ -15,7 +15,7 @@ description="Initializes the random number generator."
depend()
{
need localmount
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn
keyword -jail -lxc -openvz -prefix -systemd-nspawn
}
save_seed()

View File

@@ -6,7 +6,7 @@ MAN3= einfo.3 \
rc_config.3 rc_deptree.3 rc_find_pids.3 rc_plugin_hook.3 \
rc_runlevel.3 rc_service.3 rc_stringlist.3
MAN8= rc-service.8 rc-status.8 rc-update.8 openrc.8 openrc-run.8 \
service.8 start-stop-daemon.8 supervise-daemon.8
service.8 start-stop-daemon.8
ifeq (${OS},Linux)
MAN8 += rc-sstat.8

View File

@@ -95,17 +95,10 @@ String describing the service.
.It Ar description_$command
String describing the extra command.
.It Ar supervisor
Supervisor to use to monitor this daemon. If this is unset or invalid,
start-stop-daemon will be used.
Currently, we support s6 from scarnet software, and supervise-daemon
which is a light-weight supervisor internal to OpenRC.
To use s6, set
Supervisor to use to monitor this daemon. If this is unset,
start-stop-daemon will be used. The only alternate supervisor we support
in this release is S6 from Skarnet software. To use this, set
supervisor=s6.
or set
supervisor=supervise-daemon
to use supervise-daemon.
Note that supervise-daemon is still in early development, so it is
considered experimental.
.It Ar s6_service_path
The path to the s6 service directory if you are monitoring this service
with S6. The default is /var/svc.d/${RC_SVCNAME}.
@@ -119,16 +112,10 @@ List of arguments passed to start-stop-daemon when starting the daemon.
.It Ar command
Daemon to start or stop via
.Nm start-stop-daemon
or
.Nm supervise-daemon
if no start or stop function is defined by the service.
.It Ar command_args
List of arguments to pass to the daemon when starting via
.Nm start-stop-daemon .
.It Ar command_args_foreground
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) to force the daemon into
the background. This implies the "--make-pidfile" and "--pidfile" option of
@@ -136,8 +123,6 @@ the background. This implies the "--make-pidfile" and "--pidfile" option of
so the pidfile variable must be set.
.It Ar chroot
.Xr start-stop-daemon 8
and
.Xr supervise-daemon 8
will chroot into this path before writing the pid file or starting the daemon.
.It Ar pidfile
Pidfile to use for the above defined command.
@@ -187,9 +172,9 @@ The service will start after these services and stop before these services.
The service will start before these services and stop after these services.
.It Ic provide
The service provides this virtual service. For example, named provides dns.
Note that it is not legal to have a virtual and real service with the
same name. If you do this, you will receive an error message, and you
must rename either the real or virtual service.
Virtual services take precedence over real services, so it is highly
recommended that you do not have a real service that has the same name
as a virtual service.
.It Ic config
We should recalculate our dependencies if the listed files have changed.
.It Ic keyword

View File

@@ -20,14 +20,6 @@
.Ar service cmd
.Op Ar ...
.Nm
.Op Fl I , -ifinactive
.Ar service cmd
.Op Ar ...
.Nm
.Op Fl N , -ifnotstarted
.Ar service cmd
.Op Ar ...
.Nm
.Fl e , -exists
.Ar service
.Nm
@@ -44,13 +36,6 @@ If
is given then
.Nm
returns 0 even if the service does not exist.
If
.Fl I , -ifinactive
or
.Fl N , -ifnotstarted
is given then
.Nm
returns 0 if the service exists but is in the wrong state.
.Pp
If given the
.Fl l , -list

View File

@@ -1,142 +0,0 @@
.\" Copyright (c) 2007-2015 The OpenRC Authors.
.\" See the Authors file at the top-level directory of this distribution and
.\" https://github.com/OpenRC/openrc/blob/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.
.\"
.Dd April 27, 2016
.Dt supervise-DAEMON 8 SMM
.Os OpenRC
.Sh NAME
.Nm supervise-daemon
.Nd starts a daemon and restarts it if it crashes
.Sh SYNOPSIS
.Nm
.Fl d , -chdir
.Ar path
.Fl e , -env
.Ar var=value
.Fl g , -group
.Ar group
.Fl I , -ionice
.Ar arg
.Fl k , -umask
.Ar value
.Fl N , -nicelevel
.Ar level
.Fl p , -pidfile
.Ar pidfile
.Fl u , -user
.Ar user
.Fl r , -chroot
.Ar chrootpath
.Fl 1 , -stdout
.Ar logfile
.Fl 2 , -stderr
.Ar logfile
.Fl S , -start
.Ar daemon
.Op Fl -
.Op Ar arguments
.Nm
.Fl K , -stop
.Ar daemon
.Fl p , -pidfile
.Ar pidfile
.Fl r , -chroot
.Ar chrootpath
.Sh DESCRIPTION
.Nm
provides a consistent method of starting, stopping and restarting
daemons. If
.Fl K , -stop
is not provided, then we assume we are starting the daemon.
.Nm
only works with daemons which do not fork. Also, it uses its own pid
file, so the daemon should not write a pid file, or the pid file passed
to
.Nm
should not be the one the daemon writes.
.Pp
Here are the options to specify the daemon and how it should start or stop:
.Bl -tag -width indent
.It Fl p , -pidfile Ar pidfile
When starting, we write a
.Ar pidfile
so we know which supervisor to stop. When stopping we only stop the pid(s)
listed in the
.Ar pidfile .
.It Fl u , -user Ar user Ns Op : Ns Ar group
Start the daemon as the
.Ar user
and update $HOME accordingly or stop daemons
owned by the user. You can optionally append a
.Ar group
name here also.
.It Fl v , -verbose
Print the action(s) that are taken just before doing them.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl d , -chdir Ar path
chdir to this directory before starting the daemon.
.It Fl e , -env Ar VAR=VALUE
Set the environment variable VAR to VALUE.
.It Fl g , -group Ar group
Start the daemon as in the group.
.It Fl I , -ionice Ar class Ns Op : Ns Ar data
Modifies the IO scheduling priority of the daemon.
Class can be 0 for none, 1 for real time, 2 for best effort and 3 for idle.
Data can be from 0 to 7 inclusive.
.It Fl k , -umask Ar mode
Set the umask of the daemon.
.It Fl N , -nicelevel Ar level
Modifies the scheduling priority of the daemon.
.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.
.It Fl u , -user Ar user
Start the daemon as the specified user.
.It Fl 1 , -stdout Ar logfile
Redirect the standard output of the process to 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 2 , -stderr Ar logfile
The same thing as
.Fl 1 , -stdout
but with the standard error output.
.El
.Sh ENVIRONMENT
.Va SSD_NICELEVEL
can also set the scheduling priority of the daemon, but the command line
option takes precedence.
.Sh NOTE
.Nm
uses
.Xr getopt 3
to parse its options, which allows it to accept the `--' option which will
cause it to stop processing options at that point. Any subsequent arguments
are passed as arguments to the daemon to start and used when finding a daemon
to stop or signal.
.Sh SEE ALSO
.Xr chdir 2 ,
.Xr chroot 2 ,
.Xr getopt 3 ,
.Xr nice 2 ,
.Xr rc_find_pids 3
.Sh BUGS
.Nm
cannot stop an interpreted daemon that no longer exists without a pidfile.
.Sh HISTORY
.Nm
first appeared in Debian.
.Pp
This is a complete re-implementation with the process finding code in the
OpenRC library (librc, -lrc) so other programs can make use of it.
.Sh AUTHORS
.An William Hubbs <w.d.hubbs@gmail.com>

View File

@@ -3,6 +3,4 @@
ifeq (${MKPREFIX},yes)
CPPFLAGS+= -DPREFIX
PKG_PREFIX?= $(PREFIX)/usr
SED_EXTRA= -e '/_PATH=.*usr.bin/d'
endif

View File

@@ -13,7 +13,7 @@
_OS_SH= uname -s | tr '/' '-'
_OS:= $(shell ${_OS_SH})
OS?= ${_OS}
include ${MK}/os-prefix.mk
include ${MK}/os-${OS}.mk
include ${MK}/os-prefix.mk
RC_LIB= /$(LIBNAME)/rc

View File

@@ -11,7 +11,6 @@
AR?= ar
CP?= cp
PKG_CONFIG?= pkg-config
ECHO?= echo
INSTALL?= install
RANLIB?= ranlib
@@ -27,7 +26,7 @@ ifeq (${MKPREFIX},yes)
UPREFIX= ${PREFIX}/usr
endif
endif
LOCAL_PREFIX= $(UPREFIX)/local
LOCAL_PREFIX= /usr/local
PICFLAG?= -fPIC

View File

@@ -1,6 +1,6 @@
ifeq (${MKTERMCAP},ncurses)
TERMCAP_CFLAGS:= $(shell ${PKG_CONFIG} ncurses --cflags 2> /dev/null)
LTERMCAP:= $(shell ${PKG_CONFIG} ncurses --libs 2> /dev/null)
TERMCAP_CFLAGS:= $(shell pkg-config ncurses --cflags 2> /dev/null)
LTERMCAP:= $(shell pkg-config ncurses --libs 2> /dev/null)
ifeq ($(LTERMCAP),)
LIBTERMCAP?= -lncurses
else

View File

@@ -3,7 +3,6 @@ include ../mk/net.mk
BOOT= bootmisc fsck hostname localmount loopback \
root swap swapfiles sysctl urandom ${BOOT-${OS}}
DEFAULT= local netmount
NONETWORK= local
SHUTDOWN= savecache ${SHUTDOWN-${OS}}
SYSINIT= ${SYSINIT-${OS}}
@@ -11,7 +10,6 @@ LEVELDIR= ${DESTDIR}/${SYSCONFDIR}/runlevels
SYSINITDIR= ${LEVELDIR}/sysinit
BOOTDIR= ${LEVELDIR}/boot
DEFAULTDIR= ${LEVELDIR}/default
NONETWORKDIR= ${LEVELDIR}/nonetwork
SHUTDOWNDIR= ${LEVELDIR}/shutdown
ifeq (${MKNET},yes)
@@ -74,14 +72,6 @@ install:
fi; \
ln -snf ${INITDIR}/"$$x" ${DEFAULTDIR}/"$$x" || exit $$?; done \
fi
if ! test -d "${NONETWORKDIR}"; then \
${INSTALL} -d ${NONETWORKDIR} || exit $$?; \
for x in ${NONETWORK}; do \
if test "${MKPREFIX}" = yes; then \
grep -q "keyword .*-prefix" ${INITFILES}/"$$x" && continue; \
fi; \
ln -snf ${INITDIR}/"$$x" ${NONETWORKDIR}/"$$x" || exit $$?; done \
fi
if ! test -d "${SHUTDOWNDIR}"; then \
${INSTALL} -d ${SHUTDOWNDIR} || exit $$?; \
for x in ${SHUTDOWN}; do \

View File

@@ -52,8 +52,8 @@ if [ ! -d $scandir ]; then
exit 1
fi
# Make sure s6-svscan is running
if ! pgrep s6-svscan >/dev/null ; then
# Make sure s6-svscan is running
if ! pgrep s6-svscan >/dev/null ; then
printf "s6-svscan is not running\n"
exit 1
fi
@@ -141,7 +141,7 @@ do
fi
done
# Cleanup
# Cleanup
rm -f $statfile 2>/dev/null
printf "\n\n"

View File

@@ -1,8 +1,7 @@
DIR= ${LIBEXECDIR}/sh
SRCS= init.sh.in functions.sh.in gendepends.sh.in \
openrc-run.sh.in rc-functions.sh.in tmpfiles.sh.in ${SRCS-${OS}}
INC= functions.sh rc-mount.sh rc-functions.sh s6.sh start-stop-daemon.sh \
supervise-daemon.sh
INC= rc-mount.sh functions.sh rc-functions.sh s6.sh start-stop-daemon.sh
BIN= gendepends.sh init.sh openrc-run.sh tmpfiles.sh ${BIN-${OS}}
INSTALLAFTER= _installafter

View File

@@ -22,7 +22,7 @@ apply_file() {
### FILE FORMAT ###
# See https://www.kernel.org/doc/Documentation/binfmt_misc.txt
while read -r line; do
while read line; do
LINENUM=$(( LINENUM+1 ))
case $line in
\#*) continue ;;

View File

@@ -154,7 +154,6 @@ start()
local func=ssd_start
case "$supervisor" in
s6) func=s6_start ;;
supervise-daemon) func=supervise_start ;;
?*)
ewarn "Invalid supervisor, \"$supervisor\", using start-stop-daemon"
;;
@@ -167,7 +166,6 @@ stop()
local func=ssd_stop
case "$supervisor" in
s6) func=s6_stop ;;
supervise-daemon) func=supervise_stop ;;
?*)
ewarn "Invalid supervisor, \"$supervisor\", using start-stop-daemon"
;;
@@ -180,7 +178,6 @@ status()
local func=ssd_status
case "$supervisor" in
s6) func=s6_status ;;
supervise-daemon) func=supervise_status ;;
?*)
ewarn "Invalid supervisor, \"$supervisor\", using start-stop-daemon"
;;
@@ -218,7 +215,6 @@ fi
# load service supervisor functions
sourcex "@LIBEXECDIR@/sh/s6.sh"
sourcex "@LIBEXECDIR@/sh/start-stop-daemon.sh"
sourcex "@LIBEXECDIR@/sh/supervise-daemon.sh"
# Set verbose mode
if yesno "${rc_verbose:-$RC_VERBOSE}"; then
@@ -248,7 +244,7 @@ for _cmd; do
break
fi
done
# Load our script
sourcex "$RC_SERVICE"

View File

@@ -41,7 +41,7 @@ s6_stop()
fi
s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}"
ebegin "Stopping ${name:-$RC_SVCNAME}"
s6-svc -wD -d -T ${s6_service_timeout_stop:-10000} "${s6_service_link}"
s6-svc -Dd -T ${s6_service_timeout_stop:-10000} "${s6_service_link}"
set -- $(s6-svstat "${s6_service_link}")
[ "$1" = "down" ]
eend $? "Failed to stop $RC_SVCNAME"

View File

@@ -40,7 +40,6 @@ ssd_start()
fi
eval start-stop-daemon --start \
--exec $command \
${chroot:+--chroot} $chroot \
${procname:+--name} $procname \
${pidfile:+--pidfile} $pidfile \
${command_user+--user} $command_user \
@@ -48,7 +47,6 @@ ssd_start()
-- $command_args $command_args_background
if eend $? "Failed to start $RC_SVCNAME"; then
service_set_value "command" "${command}"
[ -n "${chroot}" ] && service_set_value "chroot" "${chroot}"
[ -n "${pidfile}" ] && service_set_value "pidfile" "${pidfile}"
[ -n "${procname}" ] && service_set_value "procname" "${procname}"
return 0
@@ -64,11 +62,9 @@ ssd_start()
ssd_stop()
{
local startcommand="$(service_get_value "command")"
local startchroot="$(service_get_value "chroot")"
local startpidfile="$(service_get_value "pidfile")"
local startprocname="$(service_get_value "procname")"
command="${startcommand:-$command}"
chroot="${startchroot:-$chroot}"
pidfile="${startpidfile:-$pidfile}"
procname="${startprocname:-$procname}"
[ -n "$command" -o -n "$procname" -o -n "$pidfile" ] || return 0
@@ -77,7 +73,7 @@ ssd_stop()
${retry:+--retry} $retry \
${command:+--exec} $command \
${procname:+--name} $procname \
${pidfile:+--pidfile} $chroot$pidfile \
${pidfile:+--pidfile} $pidfile \
${stopsig:+--signal} $stopsig
eend $? "Failed to stop $RC_SVCNAME"

View File

@@ -1,55 +0,0 @@
# start / stop / status functions for supervise-daemon
# 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.
supervise_start()
{
if [ -z "$command" ]; then
ewarn "The command variable is undefined."
ewarn "There is nothing for ${name:-$RC_SVCNAME} to start."
return 1
fi
ebegin "Starting ${name:-$RC_SVCNAME}"
eval supervise-daemon --start \
${chroot:+--chroot} $chroot \
${pidfile:+--pidfile} $pidfile \
${command_user+--user} $command_user \
$supervise_daemon_args \
$command \
-- $command_args $command_args_foreground
rc=$?
if [ $rc = 0 ]; then
[ -n "${chroot}" ] && service_set_value "chroot" "${chroot}"
[ -n "${pidfile}" ] && service_set_value "pidfile" "${pidfile}"
fi
eend $rc "failed to start $RC_SVCNAME"
}
supervise_stop()
{
local startchroot="$(service_get_value "chroot")"
local startpidfile="$(service_get_value "pidfile")"
chroot="${startchroot:-$chroot}"
pidfile="${startpidfile:-$pidfile}"
[ -n "$pidfile" ] || return 0
ebegin "Stopping ${name:-$RC_SVCNAME}"
supervise-daemon --stop \
${pidfile:+--pidfile} $chroot$pidfile \
${stopsig:+--signal} $stopsig
eend $? "Failed to stop $RC_SVCNAME"
}
supervise_status()
{
_status
}

View File

@@ -26,6 +26,7 @@
#include <unistd.h>
#include "helpers.h"
#include "rc.h"
#define RC_LEVEL_BOOT "boot"
#define RC_LEVEL_DEFAULT "default"
@@ -60,6 +61,10 @@ int is_writable(const char *);
#define service_stop(service) exec_service(service, "stop");
int parse_mode(mode_t *, char *);
const char *detect_prefix(void);
const char *get_systype(void);
const char *detect_container(void);
const char *detect_vm(void);
/* Handy function so we can wrap einfo around our deptree */
RC_DEPTREE *_rc_deptree_load (int, int *);

View File

@@ -717,16 +717,14 @@ rc_deptree_update_needed(time_t *newest, char *file)
}
librc_hidden_def(rc_deptree_update_needed)
/* This is a 7 phase operation
/* This is a 6 phase operation
Phase 1 is a shell script which loads each init script and config in turn
and echos their dependency info to stdout
Phase 2 takes that and populates a depinfo object with that data
Phase 3 adds any provided services to the depinfo object
Phase 4 scans that depinfo object and puts in backlinks
Phase 5 removes broken before dependencies
Phase 6 looks for duplicate services indicating a real and virtual service
with the same names
Phase 7 saves the depinfo object to disk
Phase 6 saves the depinfo object to disk
*/
bool
rc_deptree_update(void)
@@ -735,16 +733,15 @@ rc_deptree_update(void)
RC_DEPTREE *deptree, *providers;
RC_DEPINFO *depinfo = NULL, *depinfo_np, *di;
RC_DEPTYPE *deptype = NULL, *dt_np, *dt, *provide;
RC_STRINGLIST *config, *dupes, *types, *sorted, *visited;
RC_STRINGLIST *config, *types, *sorted, *visited;
RC_STRING *s, *s2, *s2_np, *s3, *s4;
char *line = NULL;
size_t len = 0;
char *depend, *depends, *service, *type, *nosys, *onosys;
size_t i, k, l;
bool retval = true;
const char *sys = rc_sys();
const char *sys = NULL;
struct utsname uts;
int serrno;
/* Some init scripts need RC_LIBEXECDIR to source stuff
Ideally we should be setting our full env instead */
@@ -850,6 +847,9 @@ rc_deptree_update(void)
/* Phase 2 - if we're a special system, remove services that don't
* work for them. This doesn't stop them from being run directly. */
sys = detect_container();
if (!sys)
sys = detect_vm();
if (sys) {
len = strlen(sys);
nosys = xmalloc(len + 2);
@@ -999,22 +999,7 @@ rc_deptree_update(void)
}
rc_stringlist_free(types);
/* Phase 6 - Print errors for duplicate services */
dupes = rc_stringlist_new();
TAILQ_FOREACH(depinfo, deptree, entries) {
serrno = errno;
errno = 0;
rc_stringlist_addu(dupes,depinfo->service);
if (errno == EEXIST) {
fprintf(stderr,
"Error: %s is the name of a real and virtual service.\n",
depinfo->service);
}
errno = serrno;
}
rc_stringlist_free(dupes);
/* Phase 7 - save to disk
/* Phase 6 - save to disk
Now that we're purely in C, do we need to keep a shell parseable file?
I think yes as then it stays human readable
This works and should be entirely shell parseable provided that depend

View File

@@ -198,9 +198,13 @@ found:
#endif
static const char *
get_systype(void)
const char *
rc_sys(void)
{
#ifdef PREFIX
return RC_SYS_PREFIX;
#endif
char *systype = rc_conf_value("rc_sys");
if (systype) {
char *s = systype;
@@ -211,37 +215,10 @@ get_systype(void)
s++;
}
}
return systype;
}
static const char *
detect_prefix(const char *systype)
{
#ifdef PREFIX
return RC_SYS_PREFIX;
#else
if (systype) {
if (strcmp(systype, RC_SYS_NONE) == 0)
return NULL;
if (strcmp(systype, RC_SYS_PREFIX) == 0)
return RC_SYS_PREFIX;
}
return NULL;
#endif
}
static const char *
detect_container(const char *systype)
{
#ifdef __FreeBSD__
if (systype) {
if (strcmp(systype, RC_SYS_NONE) == 0)
return NULL;
if (strcmp(systype, RC_SYS_JAIL) == 0)
return RC_SYS_JAIL;
}
if (systype && strcmp(systype, RC_SYS_JAIL) == 0)
return RC_SYS_JAIL;
int jailed = 0;
size_t len = sizeof(jailed);
@@ -250,10 +227,25 @@ detect_container(const char *systype)
return RC_SYS_JAIL;
#endif
#ifdef __NetBSD__
if (systype) {
if(strcmp(systype, RC_SYS_XEN0) == 0)
return RC_SYS_XEN0;
if (strcmp(systype, RC_SYS_XENU) == 0)
return RC_SYS_XENU;
}
if (exists("/kern/xen/privcmd"))
return RC_SYS_XEN0;
if (exists("/kern/xen"))
return RC_SYS_XENU;
#endif
#ifdef __linux__
if (systype) {
if (strcmp(systype, RC_SYS_NONE) == 0)
return NULL;
if (strcmp(systype, RC_SYS_XEN0) == 0)
return RC_SYS_XEN0;
if (strcmp(systype, RC_SYS_XENU) == 0)
return RC_SYS_XENU;
if (strcmp(systype, RC_SYS_UML) == 0)
return RC_SYS_UML;
if (strcmp(systype, RC_SYS_VSERVER) == 0)
@@ -269,7 +261,11 @@ detect_container(const char *systype)
if (strcmp(systype, RC_SYS_DOCKER) == 0)
return RC_SYS_DOCKER;
}
if (file_regex("/proc/cpuinfo", "UML"))
if (exists("/proc/xen")) {
if (file_regex("/proc/xen/capabilities", "control_d"))
return RC_SYS_XEN0;
return RC_SYS_XENU;
} else if (file_regex("/proc/cpuinfo", "UML"))
return RC_SYS_UML;
else if (file_regex("/proc/self/status",
"(s_context|VxID):[[:space:]]*[1-9]"))
@@ -285,70 +281,12 @@ detect_container(const char *systype)
return RC_SYS_RKT;
else if (file_regex("/proc/1/environ", "container=systemd-nspawn"))
return RC_SYS_SYSTEMD_NSPAWN;
else if (exists("/.dockerenv"))
return RC_SYS_DOCKER;
/* old test, I'm not sure when this was valid. */
else if (file_regex("/proc/1/environ", "container=docker"))
return RC_SYS_DOCKER;
#endif
return NULL;
}
static const char *
detect_vm(const char *systype)
{
#ifdef __NetBSD__
if (systype) {
if (strcmp(systype, RC_SYS_NONE) == 0)
return NULL;
if (strcmp(systype, RC_SYS_XEN0) == 0)
return RC_SYS_XEN0;
if (strcmp(systype, RC_SYS_XENU) == 0)
return RC_SYS_XENU;
}
if (exists("/kern/xen/privcmd"))
return RC_SYS_XEN0;
if (exists("/kern/xen"))
return RC_SYS_XENU;
#endif
#ifdef __linux__
if (systype) {
if (strcmp(systype, RC_SYS_NONE) == 0)
return NULL;
if (strcmp(systype, RC_SYS_XEN0) == 0)
return RC_SYS_XEN0;
if (strcmp(systype, RC_SYS_XENU) == 0)
return RC_SYS_XENU;
}
if (exists("/proc/xen")) {
if (file_regex("/proc/xen/capabilities", "control_d"))
return RC_SYS_XEN0;
return RC_SYS_XENU;
}
#endif
return NULL;
}
const char *
rc_sys(void)
{
const char *systype;
const char *sys;
systype = get_systype();
sys = detect_prefix(systype);
if (!sys) {
sys = detect_container(systype);
if (!sys) {
sys = detect_vm(systype);
}
}
return sys;
}
librc_hidden_def(rc_sys)
static const char *

View File

@@ -318,7 +318,6 @@ bool rc_service_daemons_crashed(const char *);
* Some services cannot work in these systems, or we do something else. */
#define RC_SYS_DOCKER "DOCKER"
#define RC_SYS_JAIL "JAIL"
#define RC_SYS_NONE ""
#define RC_SYS_OPENVZ "OPENVZ"
#define RC_SYS_LXC "LXC"
#define RC_SYS_PREFIX "PREFIX"

1
src/rc/.gitignore vendored
View File

@@ -5,7 +5,6 @@ rc-update
runscript
service
start-stop-daemon
supervise-daemon
einfon
einfo
ewarnn

View File

@@ -1,9 +1,4 @@
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-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
SRCS= rc.c rc-logger.c rc-misc.c rc-plugin.c
ifeq (${MKSELINUX},yes)
SRCS+= rc-selinux.c
@@ -16,8 +11,7 @@ SBINDIR= ${PREFIX}/sbin
LINKDIR= ${LIBEXECDIR}
BINPROGS= rc-status
SBINPROGS = openrc openrc-run rc rc-service rc-update runscript service \
start-stop-daemon supervise-daemon
SBINPROGS = openrc openrc-run rc rc-service rc-update runscript service start-stop-daemon
RC_BINPROGS= einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
eindent eoutdent esyslog eval_ecolors ewaitfile \
veinfo vewarn vebegin veend vewend veindent veoutdent \
@@ -75,7 +69,6 @@ install: all
if test "${MKPAM}" = pam; then \
${INSTALL} -d ${DESTDIR}${PAMDIR}; \
${INSTALL} -m ${PAMMODE} start-stop-daemon.pam ${DESTDIR}${PAMDIR}/start-stop-daemon; \
${INSTALL} -m ${PAMMODE} supervise-daemon.pam ${DESTDIR}${PAMDIR}/supervise-daemon; \
fi
check test::
@@ -112,12 +105,12 @@ mountinfo: mountinfo.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o
ifeq (${MKSELINUX},yes)
openrc rc: rc-selinux.o
endif
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
ifeq (${MKSELINUX},yes)
openrc-run runscript: rc-selinux.o
endif
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
rc-abort: rc-abort.o
@@ -138,9 +131,6 @@ rc-update: rc-update.o _usage.o rc-misc.o
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
service_get_value service_set_value get_options save_options: do_value.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}

View File

@@ -13,7 +13,6 @@
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "rc.h"
#include "rc-misc.h"
#include "_usage.h"
#include "version.h"
@@ -47,7 +46,10 @@ _noreturn void show_version(void)
const char *systype = NULL;
printf("%s (OpenRC", applet);
if ((systype = rc_sys()))
systype = detect_container();
if (!systype)
systype = detect_vm();
if (systype)
printf(" [%s]", systype);
printf(") %s", VERSION);
#ifdef BRANDING

View File

@@ -30,7 +30,6 @@
#include <unistd.h>
#include "einfo.h"
#include "rc.h"
#include "rc-misc.h"
#include "rc-selinux.h"
#include "_usage.h"

View File

@@ -28,7 +28,6 @@
#include <unistd.h>
#include "einfo.h"
#include "rc.h"
#include "rc-misc.h"
const char *applet = NULL;

View File

@@ -178,9 +178,6 @@ int main(int argc, char **argv)
FILE *fp;
#endif
/* fail if there is no /etc/fstab */
if (!exists("/etc/fstab"))
eerrorx("/etc/fstab does not exist");
/* Ensure that we are only quiet when explicitly told to be */
unsetenv("EINFO_QUIET");

View File

@@ -15,7 +15,6 @@
#include <stdio.h>
#include <stdlib.h>
#include "rc.h"
#include "rc-misc.h"
int main(int argc, char **argv)

View File

@@ -15,7 +15,6 @@
#include <stdio.h>
#include <stdlib.h>
#include "rc.h"
#include "rc-misc.h"
int main(int argc, char **argv)

View File

@@ -297,9 +297,6 @@ getmntfile(const char *file)
struct mntent *ent = NULL;
FILE *fp;
if (!exists("/etc/fstab"))
return NULL;
fp = setmntent("/etc/fstab", "r");
while ((ent = getmntent(fp)))
if (strcmp(file, ent->mnt_dir) == 0)

View File

@@ -390,14 +390,6 @@ svc_exec(const char *arg1, const char *arg2)
}
if (exists(RC_SVCDIR "/openrc-run.sh")) {
if (arg2)
einfov("Executing: %s %s %s %s %s",
RC_SVCDIR "/openrc-run.sh", RC_SVCDIR "/openrc-run.sh",
service, arg1, arg2);
else
einfov("Executing: %s %s %s %s",
RC_SVCDIR "/openrc-run.sh", RC_SVCDIR "/openrc-run.sh",
service, arg1);
execl(RC_SVCDIR "/openrc-run.sh",
RC_SVCDIR "/openrc-run.sh",
service, arg1, arg2, (char *) NULL);
@@ -405,16 +397,6 @@ svc_exec(const char *arg1, const char *arg2)
service, strerror(errno));
_exit(EXIT_FAILURE);
} else {
if (arg2)
einfov("Executing: %s %s %s %s %s",
RC_LIBEXECDIR "/sh/openrc-run.sh",
RC_LIBEXECDIR "/sh/openrc-run.sh",
service, arg1, arg2);
else
einfov("Executing: %s %s %s %s",
RC_LIBEXECDIR "/sh/openrc-run.sh",
RC_LIBEXECDIR "/sh/openrc-run.sh",
service, arg1);
execl(RC_LIBEXECDIR "/sh/openrc-run.sh",
RC_LIBEXECDIR "/sh/openrc-run.sh",
service, arg1, arg2, (char *) NULL);
@@ -1106,7 +1088,6 @@ service_plugable(void)
int main(int argc, char **argv)
{
bool doneone = false;
bool runscript = false;
int retval, opt, depoptions = RC_DEP_TRACE;
RC_STRING *svc;
char path[PATH_MAX], lnk[PATH_MAX];
@@ -1122,10 +1103,6 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
applet = basename_c(argv[0]);
if (strcmp(applet, "runscript") == 0)
runscript = true;
if (stat(argv[1], &stbuf) != 0) {
fprintf(stderr, "openrc-run `%s': %s\n",
argv[1], strerror(errno));
@@ -1292,9 +1269,6 @@ int main(int argc, char **argv)
applet_list = rc_stringlist_new();
rc_stringlist_add(applet_list, applet);
if (runscript)
ewarn("%s uses runscript, please convert to openrc-run.", service);
/* Now run each option */
retval = EXIT_SUCCESS;
while (optind < argc) {

View File

@@ -247,10 +247,6 @@ rc_logger_open(const char *level)
logfile = rc_conf_value("rc_log_path");
if (logfile == NULL)
logfile = DEFAULTLOG;
if (!strcmp(logfile, TMPLOG)) {
eerror("Cowardly refusing to concatenate a logfile into itself.");
eerrorx("Please change rc_log_path to something other than %s to get rid of this message", TMPLOG);
}
if ((plog = fopen(logfile, "ae"))) {
if ((log = fopen(TMPLOG, "re"))) {

View File

@@ -27,6 +27,7 @@
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
# include <regex.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -68,12 +69,6 @@ env_filter(void)
/* Add the user defined list of vars */
env_allow = rc_stringlist_split(rc_conf_value("rc_env_allow"), " ");
/*
* If '*' is an entry in rc_env_allow, do nothing as we are to pass
* through all environment variables.
*/
if (rc_stringlist_find(env_allow, "*"))
return;
profile = rc_config_load(RC_PROFILE_ENV);
/* Copy the env and work from this so we can manipulate it safely */
@@ -131,7 +126,7 @@ env_config(void)
char *np;
char *npp;
char *tok;
const char *sys = rc_sys();
const char *sys = NULL;
char buffer[PATH_MAX];
/* Ensure our PATH is prefixed with the system locations first
@@ -182,6 +177,10 @@ env_config(void)
} else
setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1);
sys = detect_container();
if (!sys)
sys = detect_vm();
if (sys)
setenv("RC_SYS", sys, 1);
@@ -339,6 +338,163 @@ is_writable(const char *path)
return 0;
}
static bool file_regex(const char *file, const char *regex)
{
FILE *fp;
char *line = NULL;
size_t len = 0;
regex_t re;
bool retval = true;
int result;
if (!(fp = fopen(file, "r")))
return false;
if ((result = regcomp(&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) {
fclose(fp);
line = xmalloc(sizeof(char) * BUFSIZ);
regerror(result, &re, line, BUFSIZ);
fprintf(stderr, "file_regex: %s", line);
free(line);
return false;
}
while ((rc_getline(&line, &len, fp))) {
char *str = line;
/* some /proc files have \0 separated content so we have to
loop through the 'line' */
do {
if (regexec(&re, str, 0, NULL, 0) == 0)
goto found;
str += strlen(str) + 1;
/* len is the size of allocated buffer and we don't
want call regexec BUFSIZE times. find next str */
while (str < line + len && *str == '\0')
str++;
} while (str < line + len);
}
retval = false;
found:
fclose(fp);
free(line);
regfree(&re);
return retval;
}
const char *detect_prefix(void)
{
#ifdef PREFIX
return RC_SYS_PREFIX;
#else
return NULL;
#endif
}
const char *get_systype(void)
{
char *systype = rc_conf_value("rc_sys");
if (systype) {
char *s = systype;
/* Convert to uppercase */
while (s && *s) {
if (islower((unsigned char) *s))
*s = toupper((unsigned char) *s);
s++;
}
}
return systype;
}
const char *detect_container(void)
{
const char *systype = get_systype();
#ifdef __FreeBSD__
if (systype && strcmp(systype, RC_SYS_JAIL) == 0)
return RC_SYS_JAIL;
int jailed = 0;
size_t len = sizeof(jailed);
if (sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0) == 0)
if (jailed == 1)
return RC_SYS_JAIL;
#endif
#ifdef __linux__
if (systype) {
if (strcmp(systype, RC_SYS_UML) == 0)
return RC_SYS_UML;
if (strcmp(systype, RC_SYS_VSERVER) == 0)
return RC_SYS_VSERVER;
if (strcmp(systype, RC_SYS_OPENVZ) == 0)
return RC_SYS_OPENVZ;
if (strcmp(systype, RC_SYS_LXC) == 0)
return RC_SYS_LXC;
if (strcmp(systype, RC_SYS_RKT) == 0)
return RC_SYS_RKT;
if (strcmp(systype, RC_SYS_SYSTEMD_NSPAWN) == 0)
return RC_SYS_SYSTEMD_NSPAWN;
if (strcmp(systype, RC_SYS_DOCKER) == 0)
return RC_SYS_DOCKER;
}
if (file_regex("/proc/cpuinfo", "UML"))
return RC_SYS_UML;
else if (file_regex("/proc/self/status",
"(s_context|VxID):[[:space:]]*[1-9]"))
return RC_SYS_VSERVER;
else if (exists("/proc/vz/veinfo") && !exists("/proc/vz/version"))
return RC_SYS_OPENVZ;
else if (file_regex("/proc/self/status",
"envID:[[:space:]]*[1-9]"))
return RC_SYS_OPENVZ; /* old test */
else if (file_regex("/proc/1/environ", "container=lxc"))
return RC_SYS_LXC;
else if (file_regex("/proc/1/environ", "container=rkt"))
return RC_SYS_RKT;
else if (file_regex("/proc/1/environ", "container=systemd-nspawn"))
return RC_SYS_SYSTEMD_NSPAWN;
else if (file_regex("/proc/1/environ", "container=docker"))
return RC_SYS_DOCKER;
#endif
return NULL;
}
const char *detect_vm(void)
{
const char *systype = get_systype();
#ifdef __NetBSD__
if (systype) {
if(strcmp(systype, RC_SYS_XEN0) == 0)
return RC_SYS_XEN0;
if (strcmp(systype, RC_SYS_XENU) == 0)
return RC_SYS_XENU;
}
if (exists("/kern/xen/privcmd"))
return RC_SYS_XEN0;
if (exists("/kern/xen"))
return RC_SYS_XENU;
#endif
#ifdef __linux__
if (systype) {
if (strcmp(systype, RC_SYS_XEN0) == 0)
return RC_SYS_XEN0;
if (strcmp(systype, RC_SYS_XENU) == 0)
return RC_SYS_XENU;
}
if (exists("/proc/xen")) {
if (file_regex("/proc/xen/capabilities", "control_d"))
return RC_SYS_XEN0;
return RC_SYS_XENU;
}
#endif
return NULL;
}
RC_DEPTREE * _rc_deptree_load(int force, int *regen)
{
int fd;

View File

@@ -370,7 +370,7 @@ void selinux_setup(char **argv)
* which will open the pty with initrc_devpts_t, if it doesnt exist,
* fall back to plain exec
*/
if (!access("/usr/sbin/open_init_pty", X_OK)) {
if (access("/usr/sbin/open_init_pty", X_OK)) {
if (execvp("/usr/sbin/open_init_pty", argv)) {
perror("execvp");
exit(-1);

View File

@@ -25,10 +25,10 @@ void selinux_setup(char **argv);
/* always return false for selinux_util_open() */
#define selinux_util_open() (0)
#define selinux_util_label(x) do { } while (0)
#define selinux_util_close() do { } while (0)
#define selinux_util_label(x) do { } while(0)
#define selinux_util_close() do { } while(0)
#define selinux_setup(x) do { } while (0)
#define selinux_setup(x) do { } while(0)
#endif

View File

@@ -29,12 +29,10 @@
const char *applet = NULL;
const char *extraopts = NULL;
const char *getoptstring = "e:ilr:IN" getoptstring_COMMON;
const char *getoptstring = "e:ilr:" getoptstring_COMMON;
const struct option longopts[] = {
{ "exists", 1, NULL, 'e' },
{ "ifexists", 0, NULL, 'i' },
{ "ifinactive", 0, NULL, 'I' },
{ "ifnotstarted", 0, NULL, 'N' },
{ "list", 0, NULL, 'l' },
{ "resolve", 1, NULL, 'r' },
longopts_COMMON
@@ -42,8 +40,6 @@ const struct option longopts[] = {
const char * const longopts_help[] = {
"tests if the service exists or not",
"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",
longopts_help_COMMON
@@ -60,10 +56,7 @@ int main(int argc, char **argv)
char *service;
RC_STRINGLIST *list;
RC_STRING *s;
RC_SERVICE state;
bool if_exists = false;
bool if_inactive = false;
bool if_notstarted = false;
applet = basename_c(argv[0]);
/* Ensure that we are only quiet when explicitly told to be */
@@ -84,12 +77,6 @@ int main(int argc, char **argv)
case 'i':
if_exists = true;
break;
case 'I':
if_inactive = true;
break;
case 'N':
if_notstarted = true;
break;
case 'l':
list = rc_services_in_runlevel(NULL);
if (TAILQ_FIRST(list) == NULL)
@@ -126,11 +113,6 @@ int main(int argc, char **argv)
return 0;
eerrorx("%s: service `%s' does not exist", applet, *argv);
}
state = rc_service_state(*argv);
if (if_inactive && ! (state & RC_SERVICE_INACTIVE))
return 0;
if (if_notstarted && (state & RC_SERVICE_STARTED))
return 0;
*argv = service;
execv(*argv, argv);
eerrorx("%s: %s", applet, strerror(errno));

View File

@@ -281,10 +281,15 @@ open_shell(void)
struct passwd *pw;
#ifdef __linux__
const char *sys = rc_sys();
const char *sys = NULL;
sys = detect_container();
if (!sys)
sys = detect_vm();
/* VSERVER systems cannot really drop to shells */
if (sys && strcmp(sys, RC_SYS_VSERVER) == 0)
/* VSERVER and OPENVZ systems cannot really drop to shells */
if (sys &&
(strcmp(sys, "VSERVER") == 0 || strcmp(sys, "OPENVZ") == 0))
{
execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
eerrorx("%s: unable to exec `/sbin/halt': %s",
@@ -486,7 +491,10 @@ do_sysinit()
uts.machine);
#endif
if ((sys = rc_sys()))
sys = detect_container();
if (!sys)
sys = detect_vm();
if (sys)
printf(" [%s]", sys);
printf("%s\n\n", ecolor(ECOLOR_NORMAL));
@@ -501,7 +509,10 @@ do_sysinit()
/* init may have mounted /proc so we can now detect or real
* sys */
if ((sys = rc_sys()))
sys = detect_container();
if (!sys)
sys = detect_vm();
if (sys)
setenv("RC_SYS", sys, 1);
}
@@ -821,7 +832,9 @@ int main(int argc, char **argv)
eerrorx("%s: %s", applet, strerror(errno));
/* NOTREACHED */
case 'S':
systype = rc_sys();
systype = detect_container();
if (!systype)
systype = detect_vm();
if (systype)
printf("%s\n", systype);
exit(EXIT_SUCCESS);
@@ -830,8 +843,6 @@ int main(int argc, char **argv)
}
}
if (strcmp(applet, "rc") == 0)
ewarn("rc is deprecated, please use openrc instead.");
newlevel = argv[optind++];
/* To make life easier, we only have the shutdown runlevel as
* nothing really needs to know that we're rebooting.

View File

@@ -1242,7 +1242,7 @@ int main(int argc, char **argv)
if (redirect_stdout) {
if ((stdout_fd = open(redirect_stdout,
O_WRONLY | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) == -1)
S_IRUSR | S_IWUSR)) == -1)
eerrorx("%s: unable to open the logfile"
" for stdout `%s': %s",
applet, redirect_stdout, strerror(errno));
@@ -1250,7 +1250,7 @@ int main(int argc, char **argv)
if (redirect_stderr) {
if ((stderr_fd = open(redirect_stderr,
O_WRONLY | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) == -1)
S_IRUSR | S_IWUSR)) == -1)
eerrorx("%s: unable to open the logfile"
" for stderr `%s': %s",
applet, redirect_stderr, strerror(errno));

View File

@@ -1,726 +0,0 @@
/*
* supervise-daemon
* This is an experimental supervisor for daemons.
* It will start a deamon and make sure it restarts if it crashes.
*/
/*
* 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.
*/
/* nano seconds */
#define POLL_INTERVAL 20000000
#define WAIT_PIDFILE 500000000
#define ONE_SECOND 1000000000
#define ONE_MS 1000000
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <termios.h>
#include <sys/time.h>
#include <sys/wait.h>
#ifdef __linux__
#include <sys/syscall.h> /* For io priority */
#endif
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
#ifdef HAVE_PAM
#include <security/pam_appl.h>
/* We are not supporting authentication conversations */
static struct pam_conv conv = { NULL, NULL};
#endif
#include "einfo.h"
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
#include "_usage.h"
const char *applet = NULL;
const char *extraopts = NULL;
const char *getoptstring = "d:e:g:I:Kk:N:p:r:Su:1:2:" \
getoptstring_COMMON;
const struct option longopts[] = {
{ "chdir", 1, NULL, 'd'},
{ "env", 1, NULL, 'e'},
{ "group", 1, NULL, 'g'},
{ "ionice", 1, NULL, 'I'},
{ "stop", 0, NULL, 'K'},
{ "umask", 1, NULL, 'k'},
{ "nicelevel", 1, NULL, 'N'},
{ "pidfile", 1, NULL, 'p'},
{ "user", 1, NULL, 'u'},
{ "chroot", 1, NULL, 'r'},
{ "start", 0, NULL, 'S'},
{ "stdout", 1, NULL, '1'},
{ "stderr", 1, NULL, '2'},
longopts_COMMON
};
const char * const longopts_help[] = {
"Change the PWD",
"Set an environment string",
"Change the process group",
"Set an ionice class:data when starting",
"Stop daemon",
"Set the umask for the daemon",
"Set a nicelevel when starting",
"Match pid found in this file",
"Change the process user",
"Chroot to this directory",
"Start daemon",
"Redirect stdout to file",
"Redirect stderr to file",
longopts_help_COMMON
};
const char *usagestring = NULL;
static int nicelevel = 0;
static int ionicec = -1;
static int ioniced = 0;
static char *changeuser, *ch_root, *ch_dir;
static uid_t uid = 0;
static gid_t gid = 0;
static int devnull_fd = -1;
static int stdin_fd;
static int stdout_fd;
static int stderr_fd;
static char *redirect_stderr = NULL;
static char *redirect_stdout = NULL;
static bool exiting = false;
#ifdef TIOCNOTTY
static int tty_fd = -1;
#endif
extern char **environ;
#if !defined(SYS_ioprio_set) && defined(__NR_ioprio_set)
# define SYS_ioprio_set __NR_ioprio_set
#endif
#if !defined(__DragonFly__)
static inline int ioprio_set(int which, int who, int ioprio)
{
#ifdef SYS_ioprio_set
return syscall(SYS_ioprio_set, which, who, ioprio);
#else
return 0;
#endif
}
#endif
static void cleanup(void)
{
free(changeuser);
}
static pid_t get_pid(const char *pidfile)
{
FILE *fp;
pid_t pid;
if (! pidfile)
return -1;
if ((fp = fopen(pidfile, "r")) == NULL) {
ewarnv("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
return -1;
}
if (fscanf(fp, "%d", &pid) != 1) {
ewarnv("%s: no pid found in `%s'", applet, pidfile);
fclose(fp);
return -1;
}
fclose(fp);
return pid;
}
static void child_process(char *exec, char **argv)
{
RC_STRINGLIST *env_list;
RC_STRING *env;
int i;
char *p;
char *token;
size_t len;
char *newpath;
char *np;
char **c;
char cmdline[PATH_MAX];
#ifdef HAVE_PAM
pam_handle_t *pamh = NULL;
int pamr;
const char *const *pamenv = NULL;
#endif
setsid();
if (nicelevel) {
if (setpriority(PRIO_PROCESS, getpid(), nicelevel) == -1)
eerrorx("%s: setpriority %d: %s", applet, nicelevel,
strerror(errno));
}
if (ionicec != -1 && ioprio_set(1, getpid(), ionicec | ioniced) == -1)
eerrorx("%s: ioprio_set %d %d: %s", applet, ionicec, ioniced,
strerror(errno));
if (ch_root && chroot(ch_root) < 0)
eerrorx("%s: chroot `%s': %s", applet, ch_root, strerror(errno));
if (ch_dir && chdir(ch_dir) < 0)
eerrorx("%s: chdir `%s': %s", applet, ch_dir, strerror(errno));
#ifdef HAVE_PAM
if (changeuser != NULL) {
pamr = pam_start("supervise-daemon",
changeuser, &conv, &pamh);
if (pamr == PAM_SUCCESS)
pamr = pam_acct_mgmt(pamh, PAM_SILENT);
if (pamr == PAM_SUCCESS)
pamr = pam_open_session(pamh, PAM_SILENT);
if (pamr != PAM_SUCCESS)
eerrorx("%s: pam error: %s", applet, pam_strerror(pamh, pamr));
}
#endif
if (gid && setgid(gid))
eerrorx("%s: unable to set groupid to %d", applet, gid);
if (changeuser && initgroups(changeuser, gid))
eerrorx("%s: initgroups (%s, %d)", applet, changeuser, gid);
if (uid && setuid(uid))
eerrorx ("%s: unable to set userid to %d", applet, uid);
/* Close any fd's to the passwd database */
endpwent();
#ifdef TIOCNOTTY
ioctl(tty_fd, TIOCNOTTY, 0);
close(tty_fd);
#endif
/* Clean the environment of any RC_ variables */
env_list = rc_stringlist_new();
i = 0;
while (environ[i])
rc_stringlist_add(env_list, environ[i++]);
#ifdef HAVE_PAM
if (changeuser != NULL) {
pamenv = (const char *const *)pam_getenvlist(pamh);
if (pamenv) {
while (*pamenv) {
/* Don't add strings unless they set a var */
if (strchr(*pamenv, '='))
putenv(xstrdup(*pamenv));
else
unsetenv(*pamenv);
pamenv++;
}
}
}
#endif
TAILQ_FOREACH(env, env_list, entries) {
if ((strncmp(env->value, "RC_", 3) == 0 &&
strncmp(env->value, "RC_SERVICE=", 10) != 0 &&
strncmp(env->value, "RC_SVCNAME=", 10) != 0) ||
strncmp(env->value, "SSD_NICELEVEL=", 14) == 0)
{
p = strchr(env->value, '=');
*p = '\0';
unsetenv(env->value);
continue;
}
}
rc_stringlist_free(env_list);
/* For the path, remove the rcscript bin dir from it */
if ((token = getenv("PATH"))) {
len = strlen(token);
newpath = np = xmalloc(len + 1);
while (token && *token) {
p = strchr(token, ':');
if (p) {
*p++ = '\0';
while (*p == ':')
p++;
}
if (strcmp(token, RC_LIBEXECDIR "/bin") != 0 &&
strcmp(token, RC_LIBEXECDIR "/sbin") != 0)
{
len = strlen(token);
if (np != newpath)
*np++ = ':';
memcpy(np, token, len);
np += len;
}
token = p;
}
*np = '\0';
unsetenv("PATH");
setenv("PATH", newpath, 1);
}
stdin_fd = devnull_fd;
stdout_fd = devnull_fd;
stderr_fd = devnull_fd;
if (redirect_stdout) {
if ((stdout_fd = open(redirect_stdout,
O_WRONLY | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR)) == -1)
eerrorx("%s: unable to open the logfile"
" for stdout `%s': %s",
applet, redirect_stdout, strerror(errno));
}
if (redirect_stderr) {
if ((stderr_fd = open(redirect_stderr,
O_WRONLY | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR)) == -1)
eerrorx("%s: unable to open the logfile"
" for stderr `%s': %s",
applet, redirect_stderr, strerror(errno));
}
dup2(stdin_fd, STDIN_FILENO);
if (redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
dup2(stdout_fd, STDOUT_FILENO);
if (redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
dup2(stderr_fd, STDERR_FILENO);
for (i = getdtablesize() - 1; i >= 3; --i)
close(i);
*cmdline = '\0';
c = argv;
while (*c) {
strcat(cmdline, *c);
strcat(cmdline, " ");
c++;
}
syslog(LOG_INFO, "Running command line: %s", cmdline);
execvp(exec, argv);
#ifdef HAVE_PAM
if (changeuser != NULL && pamr == PAM_SUCCESS)
pam_close_session(pamh, PAM_SILENT);
#endif
eerrorx("%s: failed to exec `%s': %s", applet, exec,strerror(errno));
}
static void handle_signal(int sig)
{
int serrno = errno;
char signame[10] = { '\0' };
switch (sig) {
case SIGINT:
snprintf(signame, sizeof(signame), "SIGINT");
break;
case SIGTERM:
snprintf(signame, sizeof(signame), "SIGTERM");
break;
case SIGQUIT:
snprintf(signame, sizeof(signame), "SIGQUIT");
break;
}
if (*signame != 0) {
syslog(LOG_INFO, "%s: caught signal %s, exiting", applet, signame);
exiting = true;
} else
syslog(LOG_INFO, "%s: caught unknown signal %d", applet, sig);
/* Restore errno */
errno = serrno;
}
static char * expand_home(const char *home, const char *path)
{
char *opath, *ppath, *p, *nh;
size_t len;
struct passwd *pw;
if (!path || *path != '~')
return xstrdup(path);
opath = ppath = xstrdup(path);
if (ppath[1] != '/' && ppath[1] != '\0') {
p = strchr(ppath + 1, '/');
if (p)
*p = '\0';
pw = getpwnam(ppath + 1);
if (pw) {
home = pw->pw_dir;
ppath = p;
if (ppath)
*ppath = '/';
} else
home = NULL;
} else
ppath++;
if (!home) {
free(opath);
return xstrdup(path);
}
if (!ppath) {
free(opath);
return xstrdup(home);
}
len = strlen(ppath) + strlen(home) + 1;
nh = xmalloc(len);
snprintf(nh, len, "%s%s", home, ppath);
free(opath);
return nh;
}
int main(int argc, char **argv)
{
int opt;
bool start = false;
bool stop = false;
char *exec = NULL;
char *pidfile = NULL;
char *home = NULL;
int tid = 0;
pid_t child_pid, pid;
char *svcname = getenv("RC_SVCNAME");
char *tmp;
char *p;
char *token;
int i;
char exec_file[PATH_MAX];
struct passwd *pw;
struct group *gr;
FILE *fp;
mode_t numask = 022;
applet = basename_c(argv[0]);
atexit(cleanup);
signal_setup(SIGINT, handle_signal);
signal_setup(SIGQUIT, handle_signal);
signal_setup(SIGTERM, handle_signal);
openlog(applet, LOG_PID, LOG_DAEMON);
if ((tmp = getenv("SSD_NICELEVEL")))
if (sscanf(tmp, "%d", &nicelevel) != 1)
eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
applet, tmp);
/* Get our user name and initial dir */
p = getenv("USER");
home = getenv("HOME");
if (home == NULL || p == NULL) {
pw = getpwuid(getuid());
if (pw != NULL) {
if (p == NULL)
setenv("USER", pw->pw_name, 1);
if (home == NULL) {
setenv("HOME", pw->pw_dir, 1);
home = pw->pw_dir;
}
}
}
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
(int *) 0)) != -1)
switch (opt) {
case 'I': /* --ionice */
if (sscanf(optarg, "%d:%d", &ionicec, &ioniced) == 0)
eerrorx("%s: invalid ionice `%s'",
applet, optarg);
if (ionicec == 0)
ioniced = 0;
else if (ionicec == 3)
ioniced = 7;
ionicec <<= 13; /* class shift */
break;
case 'K': /* --stop */
stop = true;
break;
case 'N': /* --nice */
if (sscanf(optarg, "%d", &nicelevel) != 1)
eerrorx("%s: invalid nice level `%s'",
applet, optarg);
break;
case 'S': /* --start */
start = true;
break;
case 'd': /* --chdir /new/dir */
ch_dir = optarg;
break;
case 'e': /* --env */
putenv(optarg);
break;
case 'g': /* --group <group>|<gid> */
if (sscanf(optarg, "%d", &tid) != 1)
gr = getgrnam(optarg);
else
gr = getgrgid((gid_t)tid);
if (gr == NULL)
eerrorx("%s: group `%s' not found",
applet, optarg);
gid = gr->gr_gid;
break;
case 'k':
if (parse_mode(&numask, optarg))
eerrorx("%s: invalid mode `%s'",
applet, optarg);
break;
case 'p': /* --pidfile <pid-file> */
pidfile = optarg;
break;
case 'r': /* --chroot /new/root */
ch_root = optarg;
break;
case 'u': /* --user <username>|<uid> */
{
p = optarg;
tmp = strsep(&p, ":");
changeuser = xstrdup(tmp);
if (sscanf(tmp, "%d", &tid) != 1)
pw = getpwnam(tmp);
else
pw = getpwuid((uid_t)tid);
if (pw == NULL)
eerrorx("%s: user `%s' not found",
applet, tmp);
uid = pw->pw_uid;
home = pw->pw_dir;
unsetenv("HOME");
if (pw->pw_dir)
setenv("HOME", pw->pw_dir, 1);
unsetenv("USER");
if (pw->pw_name)
setenv("USER", pw->pw_name, 1);
if (gid == 0)
gid = pw->pw_gid;
if (p) {
tmp = strsep (&p, ":");
if (sscanf(tmp, "%d", &tid) != 1)
gr = getgrnam(tmp);
else
gr = getgrgid((gid_t) tid);
if (gr == NULL)
eerrorx("%s: group `%s'"
" not found",
applet, tmp);
gid = gr->gr_gid;
}
}
break;
case '1': /* --stdout /path/to/stdout.lgfile */
redirect_stdout = optarg;
break;
case '2': /* --stderr /path/to/stderr.logfile */
redirect_stderr = optarg;
break;
case_RC_COMMON_GETOPT
}
if (!pidfile)
eerrorx("%s: --pidfile must be specified", applet);
endpwent();
argc -= optind;
argv += optind;
exec = *argv;
if (start) {
if (!exec)
eerrorx("%s: nothing to start", applet);
}
/* Expand ~ */
if (ch_dir && *ch_dir == '~')
ch_dir = expand_home(home, ch_dir);
if (ch_root && *ch_root == '~')
ch_root = expand_home(home, ch_root);
if (exec) {
if (*exec == '~')
exec = expand_home(home, exec);
/* Validate that the binary exists if we are starting */
if (*exec == '/' || *exec == '.') {
/* Full or relative path */
if (ch_root)
snprintf(exec_file, sizeof(exec_file),
"%s/%s", ch_root, exec);
else
snprintf(exec_file, sizeof(exec_file),
"%s", exec);
} else {
/* Something in $PATH */
p = tmp = xstrdup(getenv("PATH"));
*exec_file = '\0';
while ((token = strsep(&p, ":"))) {
if (ch_root)
snprintf(exec_file, sizeof(exec_file),
"%s/%s/%s",
ch_root, token, exec);
else
snprintf(exec_file, sizeof(exec_file),
"%s/%s", token, exec);
if (exists(exec_file))
break;
*exec_file = '\0';
}
free(tmp);
}
}
if (start && !exists(exec_file))
eerrorx("%s: %s does not exist", applet,
*exec_file ? exec_file : exec);
if (stop) {
pid = get_pid(pidfile);
if (pid == -1)
i = pid;
else
i = kill(pid, SIGTERM);
if (i != 0)
/* We failed to stop something */
exit(EXIT_FAILURE);
/* Even if we have not actually killed anything, we should
* remove information about it as it may have unexpectedly
* crashed out. We should also return success as the end
* result would be the same. */
if (pidfile && exists(pidfile))
unlink(pidfile);
if (svcname)
rc_service_daemon_set(svcname, exec,
(const char *const *)argv,
pidfile, false);
exit(EXIT_SUCCESS);
}
pid = get_pid(pidfile);
if (pid != -1)
if (kill(pid, 0) == 0)
eerrorx("%s: %s is already running", applet, exec);
einfov("Detaching to start `%s'", exec);
eindentv();
/* Remove existing pidfile */
if (pidfile)
unlink(pidfile);
/*
* Make sure we can write a pid file
*/
fp = fopen(pidfile, "w");
if (! fp)
eerrorx("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
fclose(fp);
child_pid = fork();
if (child_pid == -1)
eerrorx("%s: fork: %s", applet, strerror(errno));
/* first parent process, do nothing. */
if (child_pid != 0)
exit(EXIT_SUCCESS);
child_pid = fork();
if (child_pid == -1)
eerrorx("%s: fork: %s", applet, strerror(errno));
if (child_pid != 0) {
/* this is the supervisor */
umask(numask);
#ifdef TIOCNOTTY
tty_fd = open("/dev/tty", O_RDWR);
#endif
devnull_fd = open("/dev/null", O_RDWR);
fp = fopen(pidfile, "w");
if (! fp)
eerrorx("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
fprintf(fp, "%d\n", getpid());
fclose(fp);
/*
* Supervisor main loop
*/
i = 0;
while (!exiting) {
wait(&i);
if (exiting) {
syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
kill(child_pid, SIGTERM);
} else {
if (WIFEXITED(i))
syslog(LOG_INFO, "%s, pid %d, exited with return code %d",
exec, child_pid, WEXITSTATUS(i));
else if (WIFSIGNALED(i))
syslog(LOG_INFO, "%s, pid %d, terminated by signal %d",
exec, child_pid, WTERMSIG(i));
child_pid = fork();
if (child_pid == -1)
eerrorx("%s: fork: %s", applet, strerror(errno));
if (child_pid == 0)
child_process(exec, argv);
}
}
if (svcname)
rc_service_daemon_set(svcname, exec,
(const char * const *) argv, pidfile, true);
exit(EXIT_SUCCESS);
} else if (child_pid == 0)
child_process(exec, argv);
}

View File

@@ -1,6 +0,0 @@
#%PAM-1.0
auth required pam_permit.so
account required pam_permit.so
password required pam_deny.so
session optional pam_limits.so

View File

@@ -30,7 +30,6 @@
#include <utime.h>
#include "einfo.h"
#include "rc.h"
#include "rc-misc.h"
#include "_usage.h"

View File

@@ -85,14 +85,12 @@ eend $? "Trailing newlines need to be deleted:"$'\n'"${out}"
ebegin "Checking for obsolete functions"
out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
! -name queue.h \
-exec grep -n -E '\<(malloc|memory|sys/(errno|fcntl|signal|stropts|termios|unistd))\.h\>' {} +)
[ -z "${out}" ]
eend $? "Avoid these obsolete functions:"$'\n'"${out}"
ebegin "Checking for x* func usage"
out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
! -name queue.h \
-exec grep -n -E '\<(malloc|strdup)[[:space:]]*\(' {} + \
| grep -v \
-e src/includes/helpers.h \
@@ -102,7 +100,6 @@ eend $? "These need to be using the x* variant:"$'\n'"${out}"
ebegin "Checking spacing style"
out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
! -name queue.h \
-exec grep -n -E \
-e '\<(for|if|switch|while)\(' \
-e '\<(for|if|switch|while) \( ' \

View File

@@ -1,49 +0,0 @@
# 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
terminates unexpectedly.
The following is a brief guide on using this capability.
## Use Default start, stop and status functions
If you write your own start, stop and status functions in your service
script, none of this will work. You must allow OpenRC to use the default
functions.
## Daemons must not fork
Any deamon that you would like to have monitored by supervise-daemon
must not fork. Instead, it must stay in the foreground. If the daemon
itself forks, the supervisor will be unable to monitor it.
If the daemon can be configured to not fork, this should be done in the
daemon's configuration file, or by adding a command line option that
instructs it not to fork to the command_args_foreground variable shown
below.
## Variable Settings
The most important setting is the supervisor variable. At the top of
your service script, you should set this variable as follows:
supervisor=supervise-daemon
Several other variables affect the way services behave under
supervise-daemon. They are documented on the openrc-run man page, but I
will list them here for convenience:
pidfile=/pid/of/supervisor.pid
If you are using start-stop-daemon to monitor your scripts, the pidfile
is the path to the pidfile the daemon creates. If, on the other hand,
you are using supervise-daemon, this is the path to the pidfile the
supervisor creates.
command_args_foreground should be used if the daemon you want to monitor
forks and goes to the background by default. This should be set to the
command line option that instructs the daemon to stay in the foreground.
This is very early support, so feel free to file bugs if you have
issues.

View File

@@ -21,3 +21,7 @@ LD_LIBRARY_PATH=${top_builddir}/src/libeinfo:${top_builddir}/src/librc:${LD_LIBR
PATH=${top_builddir}/src/rc:${PATH}
export LD_LIBRARY_PATH PATH
cd ${top_srcdir}/src/rc
${MAKE:-make} links >/dev/null
cd -