Compare commits
	
		
			43 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e50d51ed9f | ||
| 
						 | 
					97a254f599 | ||
| 
						 | 
					1d20aa10e6 | ||
| 
						 | 
					e92e81d9fe | ||
| 
						 | 
					bed1a45192 | ||
| 
						 | 
					34d9dbf1e3 | ||
| 
						 | 
					0287aa6588 | ||
| 
						 | 
					1732c70fb5 | ||
| 
						 | 
					263dde90c2 | ||
| 
						 | 
					422795e2ce | ||
| 
						 | 
					00ad99a292 | ||
| 
						 | 
					f026c2c541 | ||
| 
						 | 
					4d20309ffe | ||
| 
						 | 
					65439ba023 | ||
| 
						 | 
					86162f3f47 | ||
| 
						 | 
					b98e83ee91 | ||
| 
						 | 
					d59197fafe | ||
| 
						 | 
					b66c86c9ee | ||
| 
						 | 
					f7eb236f6f | ||
| 
						 | 
					1936d73eb1 | ||
| 
						 | 
					58872fc090 | ||
| 
						 | 
					fc35eb90ca | ||
| 
						 | 
					b18be3f970 | ||
| 
						 | 
					027438f775 | ||
| 
						 | 
					93e159ae85 | ||
| 
						 | 
					bcfcf50562 | ||
| 
						 | 
					d0097cc10f | ||
| 
						 | 
					eecf868e3c | ||
| 
						 | 
					a5cd486a7f | ||
| 
						 | 
					6e6b4ac5fa | ||
| 
						 | 
					558ff4d5fb | ||
| 
						 | 
					490f855aef | ||
| 
						 | 
					d1491e201d | ||
| 
						 | 
					3231af9375 | ||
| 
						 | 
					a5758e7aef | ||
| 
						 | 
					61a9393ce1 | ||
| 
						 | 
					161d22cb07 | ||
| 
						 | 
					3a96ca1c96 | ||
| 
						 | 
					934530914b | ||
| 
						 | 
					b717625cd2 | ||
| 
						 | 
					b475396134 | ||
| 
						 | 
					e7b1d898ca | ||
| 
						 | 
					5cd09a6f44 | 
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
OpenRC History
 | 
			
		||||
==============
 | 
			
		||||
# OpenRC History
 | 
			
		||||
 | 
			
		||||
This history of OpenRC was written by Daniel Robbins, Roy Marples, William
 | 
			
		||||
Hubbs and others.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Makefile
									
									
									
									
									
								
							@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
NAME=		openrc
 | 
			
		||||
VERSION=	0.35.5
 | 
			
		||||
VERSION=	0.34.11
 | 
			
		||||
PKG=		${NAME}-${VERSION}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								NEWS.md
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								NEWS.md
									
									
									
									
									
								
							@@ -1,41 +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.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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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/*
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
							
								
								
									
										14
									
								
								conf.d/mtab
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								conf.d/mtab
									
									
									
									
									
								
							@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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,13 +83,122 @@ 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 `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`
 | 
			
		||||
 | 
			
		||||
Most service scripts need default values. It would be fragile to
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -165,7 +271,7 @@ 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
 | 
			
		||||
@@ -175,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
									
									
								
							
							
						
						
									
										1
									
								
								init.d/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,5 @@
 | 
			
		||||
agetty
 | 
			
		||||
binfmt
 | 
			
		||||
cgroups
 | 
			
		||||
modules-load
 | 
			
		||||
bootmisc
 | 
			
		||||
fsck
 | 
			
		||||
 
 | 
			
		||||
@@ -21,10 +21,9 @@ SRCS-FreeBSD=	hostid.in modules.in moused.in newsyslog.in pf.in rarpd.in \
 | 
			
		||||
SRCS-FreeBSD+=	adjkerntz.in devd.in dumpon.in encswap.in ipfw.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 modules-load.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 \
 | 
			
		||||
 
 | 
			
		||||
@@ -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}"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -27,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"
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	after clock root
 | 
			
		||||
	after clock
 | 
			
		||||
	before localmount
 | 
			
		||||
	keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										112
									
								
								init.d/sysfs.in
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								init.d/sysfs.in
									
									
									
									
									
								
							@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -142,39 +142,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 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
 | 
			
		||||
@@ -219,8 +201,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
 | 
			
		||||
@@ -470,7 +450,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
 | 
			
		||||
@@ -487,7 +466,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
 | 
			
		||||
@@ -502,7 +480,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
 | 
			
		||||
@@ -733,8 +711,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>
 | 
			
		||||
 
 | 
			
		||||
@@ -16,10 +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
 | 
			
		||||
.Op Fl i , -ifexists
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
 
 | 
			
		||||
@@ -151,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
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -11,5 +11,3 @@
 | 
			
		||||
# Generic definitions
 | 
			
		||||
 | 
			
		||||
include ${MK}/os-BSD.mk
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+=	-D_BSD_SOURCE
 | 
			
		||||
 
 | 
			
		||||
@@ -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?=
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
SFX=		.Linux.in
 | 
			
		||||
PKG_PREFIX?=	/usr
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+=	-D_DEFAULT_SOURCE
 | 
			
		||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700
 | 
			
		||||
LIBDL=		-Wl,-Bdynamic -ldl
 | 
			
		||||
 | 
			
		||||
ifeq (${MKSELINUX},yes)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -60,12 +59,10 @@ MANPREFIX?=		${UPREFIX}/share
 | 
			
		||||
MANDIR?=		${MANPREFIX}/man
 | 
			
		||||
MANMODE?=		0444
 | 
			
		||||
 | 
			
		||||
BASHCOMPDIR?=		${UPREFIX}/share/bash-completion/completions
 | 
			
		||||
 | 
			
		||||
DATADIR?=		${UPREFIX}/share/openrc
 | 
			
		||||
DATAMODE?=		0644
 | 
			
		||||
 | 
			
		||||
DOCDIR?=		${UPREFIX}/share/doc
 | 
			
		||||
DOCMODE?=		0644
 | 
			
		||||
 | 
			
		||||
ZSHCOMPDIR?=		${UPREFIX}/share/zsh/site-functions
 | 
			
		||||
CONFMODE?=		0644
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,493 +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.
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -260,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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -44,13 +44,9 @@ ssd_start()
 | 
			
		||||
	eval start-stop-daemon --start \
 | 
			
		||||
		--exec $command \
 | 
			
		||||
		${chroot:+--chroot} $chroot \
 | 
			
		||||
		${directory:+--chdir} $directory \
 | 
			
		||||
		${output_log+--stdout} $output_log \
 | 
			
		||||
		${error_log+--stderr} $error_log \
 | 
			
		||||
		${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
 | 
			
		||||
 
 | 
			
		||||
@@ -24,16 +24,12 @@ 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 \
 | 
			
		||||
		$command \
 | 
			
		||||
		-- $command_args $command_args_foreground
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -131,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 */
 | 
			
		||||
@@ -171,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;
 | 
			
		||||
@@ -181,7 +181,6 @@ env_config(void)
 | 
			
		||||
	} else
 | 
			
		||||
		setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1);
 | 
			
		||||
 | 
			
		||||
	free(buffer);
 | 
			
		||||
	if (sys)
 | 
			
		||||
		setenv("RC_SYS", sys, 1);
 | 
			
		||||
 | 
			
		||||
@@ -233,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) {
 | 
			
		||||
@@ -252,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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -361,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;
 | 
			
		||||
@@ -383,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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,10 +29,9 @@
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "ce:ilr:IN" getoptstring_COMMON;
 | 
			
		||||
const char *getoptstring = "e:ilr:IN" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "exists",   1, NULL, 'e' },
 | 
			
		||||
	{ "ifcrashed", 0, NULL, 'c' },
 | 
			
		||||
	{ "ifexists", 0, NULL, 'i' },
 | 
			
		||||
	{ "ifinactive", 0, NULL, 'I' },
 | 
			
		||||
	{ "ifnotstarted", 0, NULL, 'N' },
 | 
			
		||||
@@ -42,7 +41,6 @@ const struct option longopts[] = {
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"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",
 | 
			
		||||
@@ -63,7 +61,6 @@ 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;
 | 
			
		||||
@@ -82,9 +79,6 @@ int main(int argc, char **argv)
 | 
			
		||||
			free(service);
 | 
			
		||||
			return opt;
 | 
			
		||||
			/* NOTREACHED */
 | 
			
		||||
		case 'c':
 | 
			
		||||
			if_crashed = true;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'i':
 | 
			
		||||
			if_exists = true;
 | 
			
		||||
			break;
 | 
			
		||||
@@ -127,8 +121,6 @@ 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))
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								src/rc/rc.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								src/rc/rc.c
									
									
									
									
									
								
							@@ -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);
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -254,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;
 | 
			
		||||
@@ -288,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;
 | 
			
		||||
@@ -578,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);
 | 
			
		||||
		}
 | 
			
		||||
@@ -601,7 +604,6 @@ 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);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
@@ -615,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;
 | 
			
		||||
@@ -630,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++;
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -561,8 +551,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 +561,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 +571,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 +593,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 +761,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 +792,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 +840,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 +852,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 +875,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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -7,5 +7,7 @@ BIN=	${OBJS}
 | 
			
		||||
 | 
			
		||||
MK=	../../mk
 | 
			
		||||
 | 
			
		||||
SED_EXTRA+= -e 's:@VARBASE@:/var:g'
 | 
			
		||||
 | 
			
		||||
include ${MK}/os.mk
 | 
			
		||||
include ${MK}/scripts.mk
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
# except according to the terms contained in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
command=@PKG_PREFIX@/sbin/polkitd
 | 
			
		||||
pidfile=/var/run/polkitd/polkitd.pid
 | 
			
		||||
pidfile=@VARBASE@/run/polkitd/polkitd.pid
 | 
			
		||||
command_args="$polkitd_args"
 | 
			
		||||
name="PolicyKit Daemon"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
command=/usr/sbin/sshd
 | 
			
		||||
command_args=$sshd_args
 | 
			
		||||
pidfile=/var/run/sshd.pid
 | 
			
		||||
pidfile=@VARBASE@/run/sshd.pid
 | 
			
		||||
required_files=/etc/ssh/sshd_config
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,3 @@
 | 
			
		||||
Example OpenVPN Scripts
 | 
			
		||||
=======================
 | 
			
		||||
 | 
			
		||||
These handy scripts setup any dns information that OpenVPN may push.
 | 
			
		||||
They also handle the interaction with OpenRC so that the OpenVPN service
 | 
			
		||||
can become "inactive". This means that when it starts, it goes inactive and
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,2 @@
 | 
			
		||||
OpenRC Sysvinit Support
 | 
			
		||||
========================
 | 
			
		||||
 | 
			
		||||
Here's a sample inittab for use with sysvinit for Linux based systems.
 | 
			
		||||
We don't install it by default as sysvinit packages normally own this file.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
DIR=	${ZSHCOMPDIR}
 | 
			
		||||
CONF=	_openrc \
 | 
			
		||||
		_rc-service \
 | 
			
		||||
		_rc-status \
 | 
			
		||||
		_rc-update \
 | 
			
		||||
 | 
			
		||||
MK=	../mk
 | 
			
		||||
include ${MK}/os.mk
 | 
			
		||||
 | 
			
		||||
include ${MK}/scripts.mk
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
#compdef openrc
 | 
			
		||||
 | 
			
		||||
if (( CURRENT == 2 )); then
 | 
			
		||||
	_values "runlevels" $(rc-status --list)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# vim: set et sw=2 ts=2 ft=zsh:
 | 
			
		||||
@@ -1,27 +0,0 @@
 | 
			
		||||
#compdef rc-service
 | 
			
		||||
 | 
			
		||||
if (( CURRENT == 2 )); then
 | 
			
		||||
  _arguments -s \
 | 
			
		||||
    '(-e --exists)'{-e,--exists}"[tests if the service exists or not]" \
 | 
			
		||||
    '(-l --list)'{-l,--list}'[list all available services]' \
 | 
			
		||||
    '(-r --resolve)'{-r,--resolve}'[resolve the service name to an init script]' \
 | 
			
		||||
    '(-C --nocolor)'{-C,--nocolor}'[Disable color output]' \
 | 
			
		||||
    '(-v --verbose)'{-v,--verbose}'[Run verbosely]' \
 | 
			
		||||
    '(-q --quiet)'{-q,--quiet}'[Run quietly]'
 | 
			
		||||
  _values "service" $(rc-service --list)
 | 
			
		||||
else
 | 
			
		||||
  case $words[2] in
 | 
			
		||||
    -e|--exists|-r|--resolve)
 | 
			
		||||
      (( CURRENT > 3 )) && return 0
 | 
			
		||||
	  _values "service" $(rc-service --list)
 | 
			
		||||
      ;;
 | 
			
		||||
    -*)
 | 
			
		||||
          return 0
 | 
			
		||||
          ;;
 | 
			
		||||
    *)
 | 
			
		||||
      _values "action" stop start restart describe zap
 | 
			
		||||
  ;;
 | 
			
		||||
  esac
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# vim: set et sw=2 ts=2 ft=zsh:
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
#compdef rc-status
 | 
			
		||||
 | 
			
		||||
_arguments -s \
 | 
			
		||||
  {'(--all)-a','(-a)--all'}'[Show services at all runlevels]' \
 | 
			
		||||
  {'(--crashed)-c','(-c)--crashed'}'[Show crashed services]' \
 | 
			
		||||
  {'(--list)-l','(-l)--list'}'[Show list of runlevels]' \
 | 
			
		||||
  {'(--runlevel)-r','(-r)--runlevel'}'[Show the name of the current runlevel]' \
 | 
			
		||||
  {'(--servicelist)-s','(-s)--servicelist'}'[Show all services]' \
 | 
			
		||||
  {'(--unused)-u','(-u)--unused'}'[Show services not assigned to any run level]' \
 | 
			
		||||
  {'(--help)-h','(-h)--help'}'[Print this help output]' \
 | 
			
		||||
  {'(--nocolor)-C','(-C)--nocolor'}'[Disable color output]' \
 | 
			
		||||
  {'(--version)-V','(-V)--version'}'[Display software version]' \
 | 
			
		||||
  {'(--verbose)-v','(-v)--verbose'}'[Run verbosely]' \
 | 
			
		||||
  {'(--quiet)-q','(-q)--quiet'}'[Run quietly (Does not affect errors)]'
 | 
			
		||||
 | 
			
		||||
_values 'runlevels' $(rc-status --list)
 | 
			
		||||
 | 
			
		||||
# vim: set et sw=2 ts=2 ft=zsh:
 | 
			
		||||
@@ -1,31 +0,0 @@
 | 
			
		||||
#compdef rc-update
 | 
			
		||||
 | 
			
		||||
local used_init
 | 
			
		||||
used_init=(${=${(M)${(f)"$(rc-update show 2>/dev/null)"}:#*|*[a-z]*}% |*})
 | 
			
		||||
 | 
			
		||||
if (( CURRENT == 2 )); then
 | 
			
		||||
  _values "rc-update actions" \
 | 
			
		||||
    'add[Add script to a runlevel]' \
 | 
			
		||||
    'del[Delete script from a runlevel]' \
 | 
			
		||||
    'show[Show scripts in  a runlevel]' \
 | 
			
		||||
    '-a[Process all runlevels]' \
 | 
			
		||||
    '-s[Stack a runlevel instead of a service]'
 | 
			
		||||
elif (( CURRENT == 3 )); then
 | 
			
		||||
  case "$words[2]" in
 | 
			
		||||
    add)
 | 
			
		||||
      _values "service" $(rc-service --list)
 | 
			
		||||
      ;;
 | 
			
		||||
    del)
 | 
			
		||||
      _values "service" $used_init
 | 
			
		||||
      ;;
 | 
			
		||||
    show)
 | 
			
		||||
      _values "runlevels" $(rc-status --list) \
 | 
			
		||||
        '-v[Show all service scripts]' \
 | 
			
		||||
        '--verbose[Show all service scripts]'
 | 
			
		||||
      ;;
 | 
			
		||||
  esac
 | 
			
		||||
elif (( CURRENT == 4 )); then
 | 
			
		||||
  _values "runlevels" $(rc-status --list)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# vim: set et sw=2 ts=2 ft=zsh:
 | 
			
		||||
		Reference in New Issue
	
	Block a user