Compare commits
	
		
			166 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					60f42c415d | ||
| 
						 | 
					93c8cbe684 | ||
| 
						 | 
					386bdf66f9 | ||
| 
						 | 
					81ab30c51d | ||
| 
						 | 
					d05c8c2159 | ||
| 
						 | 
					7850e12071 | ||
| 
						 | 
					11d3a8bead | ||
| 
						 | 
					e36e9a30eb | ||
| 
						 | 
					7da99d77b5 | ||
| 
						 | 
					01c34c28e6 | ||
| 
						 | 
					56ddda54b5 | ||
| 
						 | 
					3a803b3135 | ||
| 
						 | 
					72df51e17b | ||
| 
						 | 
					b2f5531194 | ||
| 
						 | 
					19bf49a710 | ||
| 
						 | 
					64354831da | ||
| 
						 | 
					e14edd765f | ||
| 
						 | 
					f9d41243d8 | ||
| 
						 | 
					be7ad06d4a | ||
| 
						 | 
					a616516895 | ||
| 
						 | 
					04721ece03 | ||
| 
						 | 
					c7e8f1133a | ||
| 
						 | 
					47e4bfae57 | ||
| 
						 | 
					8a945194af | ||
| 
						 | 
					aa4a004c29 | ||
| 
						 | 
					9ec5d36bdd | ||
| 
						 | 
					a097933eda | ||
| 
						 | 
					a6f5b1bb63 | ||
| 
						 | 
					e6d01471fe | ||
| 
						 | 
					d4501a9f06 | ||
| 
						 | 
					ec8abea460 | ||
| 
						 | 
					e4ddfa38e0 | ||
| 
						 | 
					21d30bc6d9 | ||
| 
						 | 
					2a1ff6e49c | ||
| 
						 | 
					6762cb875c | ||
| 
						 | 
					6edf516a1f | ||
| 
						 | 
					7e56a49e23 | ||
| 
						 | 
					fa5aea80c5 | ||
| 
						 | 
					0f4fa41574 | ||
| 
						 | 
					5d6dd97bba | ||
| 
						 | 
					37e2944272 | ||
| 
						 | 
					4e0eace837 | ||
| 
						 | 
					faa8318b3b | ||
| 
						 | 
					08da36149c | ||
| 
						 | 
					56870d0db1 | ||
| 
						 | 
					4d47ce440c | ||
| 
						 | 
					958f57d895 | ||
| 
						 | 
					04886efd85 | ||
| 
						 | 
					d980798d64 | ||
| 
						 | 
					414a9aae6c | ||
| 
						 | 
					a7f475ca04 | ||
| 
						 | 
					3c53680018 | ||
| 
						 | 
					f0ad647303 | ||
| 
						 | 
					b35e03b6b1 | ||
| 
						 | 
					2b1392af2f | ||
| 
						 | 
					a3d0e293ee | ||
| 
						 | 
					0200002b8c | ||
| 
						 | 
					f4e2142089 | ||
| 
						 | 
					49a90f27a8 | ||
| 
						 | 
					2ae60ca041 | ||
| 
						 | 
					6b475ab269 | ||
| 
						 | 
					b302b0c094 | ||
| 
						 | 
					40aa69cf3a | ||
| 
						 | 
					5346fbf2c9 | ||
| 
						 | 
					92e6bdee12 | ||
| 
						 | 
					71f275b2aa | ||
| 
						 | 
					6dc0d0af33 | ||
| 
						 | 
					59a9e53378 | ||
| 
						 | 
					122768d339 | ||
| 
						 | 
					fa3c60c0d8 | ||
| 
						 | 
					61905bfcf5 | ||
| 
						 | 
					3e68013631 | ||
| 
						 | 
					b46123f2e1 | ||
| 
						 | 
					109869641f | ||
| 
						 | 
					e8a2305de0 | ||
| 
						 | 
					f62975a1f8 | ||
| 
						 | 
					5bb6f9aa31 | ||
| 
						 | 
					1ab8541a6c | ||
| 
						 | 
					038c03bef3 | ||
| 
						 | 
					e51dc29e2f | ||
| 
						 | 
					c6047f887a | ||
| 
						 | 
					0506d68427 | ||
| 
						 | 
					c3d666acaf | ||
| 
						 | 
					e93b1d76d1 | ||
| 
						 | 
					acf1e43f81 | ||
| 
						 | 
					f383fd87b1 | ||
| 
						 | 
					cfded513cd | ||
| 
						 | 
					16ff3cd8df | ||
| 
						 | 
					38032626a6 | ||
| 
						 | 
					aa7d3a7911 | ||
| 
						 | 
					98262647a9 | ||
| 
						 | 
					5868abe97b | ||
| 
						 | 
					71aad16256 | ||
| 
						 | 
					e275da84de | ||
| 
						 | 
					a6cc7f06cf | ||
| 
						 | 
					c1178c8eeb | ||
| 
						 | 
					3c031ca978 | ||
| 
						 | 
					8e02406d8f | ||
| 
						 | 
					8dbdabcc5e | ||
| 
						 | 
					488d8989c5 | ||
| 
						 | 
					9e14b35da8 | ||
| 
						 | 
					7b4879cb72 | ||
| 
						 | 
					74cfb455c5 | ||
| 
						 | 
					0110487722 | ||
| 
						 | 
					68b9b0bc2a | ||
| 
						 | 
					4616f8f809 | ||
| 
						 | 
					287d71bd25 | ||
| 
						 | 
					c1ffe4d9f2 | ||
| 
						 | 
					4c517bdb2b | ||
| 
						 | 
					110582491f | ||
| 
						 | 
					5dd1d39d20 | ||
| 
						 | 
					1771bc2a83 | ||
| 
						 | 
					87c98ebb01 | ||
| 
						 | 
					4af5a80b0c | ||
| 
						 | 
					fee2ffe559 | ||
| 
						 | 
					8878f8916b | ||
| 
						 | 
					14e3359a9e | ||
| 
						 | 
					918d955fd2 | ||
| 
						 | 
					92cfa0e543 | ||
| 
						 | 
					c2bd33e483 | ||
| 
						 | 
					f42ec82f21 | ||
| 
						 | 
					7affff568a | ||
| 
						 | 
					4f750933fd | ||
| 
						 | 
					50b69d564a | ||
| 
						 | 
					eb18f4f348 | ||
| 
						 | 
					d5f3fe52c8 | ||
| 
						 | 
					bb1bc6eeb7 | ||
| 
						 | 
					53844fd0dc | ||
| 
						 | 
					14938c29ce | ||
| 
						 | 
					8bf501aaf2 | ||
| 
						 | 
					9d05f68b51 | ||
| 
						 | 
					ee2524cd1d | ||
| 
						 | 
					5c81661d47 | ||
| 
						 | 
					fb96c9c127 | ||
| 
						 | 
					6c456f9383 | ||
| 
						 | 
					d220fc2723 | ||
| 
						 | 
					a2447dfb42 | ||
| 
						 | 
					cee3919908 | ||
| 
						 | 
					0feadd2922 | ||
| 
						 | 
					a7c99506d9 | ||
| 
						 | 
					f012930775 | ||
| 
						 | 
					ddbdb69658 | ||
| 
						 | 
					c84ebb94d1 | ||
| 
						 | 
					3de6395ae3 | ||
| 
						 | 
					6bb7ebec48 | ||
| 
						 | 
					a192caf88f | ||
| 
						 | 
					e805c74d31 | ||
| 
						 | 
					318e873481 | ||
| 
						 | 
					0d15898f58 | ||
| 
						 | 
					971e82784c | ||
| 
						 | 
					90d9ea656f | ||
| 
						 | 
					a3d1c8a0e7 | ||
| 
						 | 
					913b2ca537 | ||
| 
						 | 
					3fe99c8b82 | ||
| 
						 | 
					27b8183de2 | ||
| 
						 | 
					f32d8e1bfe | ||
| 
						 | 
					d019f34a83 | ||
| 
						 | 
					bb9c481f02 | ||
| 
						 | 
					82da844b42 | ||
| 
						 | 
					667a09983c | ||
| 
						 | 
					cf429ee359 | ||
| 
						 | 
					6f3e2e2d7d | ||
| 
						 | 
					35b88fb42b | ||
| 
						 | 
					a428c325a9 | ||
| 
						 | 
					3219ecd608 | ||
| 
						 | 
					0d8dc4f798 | 
@@ -1,4 +1,5 @@
 | 
			
		||||
# 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,11 +1,12 @@
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
@@ -13,7 +14,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
 | 
			
		||||
 | 
			
		||||
@@ -25,7 +26,7 @@ Why: Obsolete or replaced by other options.
 | 
			
		||||
 | 
			
		||||
Who:
 | 
			
		||||
 | 
			
		||||
## runscript and rc symbolic links
 | 
			
		||||
# runscript and rc symbolic links
 | 
			
		||||
 | 
			
		||||
When: 1.0
 | 
			
		||||
 | 
			
		||||
@@ -34,7 +35,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
 | 
			
		||||
 | 
			
		||||
@@ -43,7 +44,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
 | 
			
		||||
 | 
			
		||||
@@ -51,7 +52,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
 | 
			
		||||
@@ -61,13 +62,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,4 +1,5 @@
 | 
			
		||||
# OpenRC History
 | 
			
		||||
OpenRC History
 | 
			
		||||
==============
 | 
			
		||||
 | 
			
		||||
This history of OpenRC was written by Daniel Robbins, Roy Marples, William
 | 
			
		||||
Hubbs and others.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Makefile
									
									
									
									
									
								
							@@ -15,12 +15,24 @@ 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.34.4
 | 
			
		||||
VERSION=	0.38.3
 | 
			
		||||
PKG=		${NAME}-${VERSION}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										58
									
								
								NEWS.md
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								NEWS.md
									
									
									
									
									
								
							@@ -1,8 +1,64 @@
 | 
			
		||||
# OpenRC NEWS
 | 
			
		||||
OpenRC NEWS
 | 
			
		||||
===========
 | 
			
		||||
 | 
			
		||||
This file will contain a list of notable changes for each release. Note
 | 
			
		||||
the information in this file is in reverse order.
 | 
			
		||||
 | 
			
		||||
## OpenRC 0.37
 | 
			
		||||
 | 
			
		||||
start-stop-daemon now supports logging stdout and stderr of daemons to
 | 
			
		||||
processes instead of files. These processes are defined by the
 | 
			
		||||
output_logger and error_logger variables in standard service scripts, or
 | 
			
		||||
by the  -3/--output-logger or -4/--error-logger switches if you use
 | 
			
		||||
start-stop-daemon directly. For more information on this, see the
 | 
			
		||||
start-stop-daemon man page.
 | 
			
		||||
 | 
			
		||||
## OpenRC 0.36
 | 
			
		||||
 | 
			
		||||
In this release, the modules-load service has been combined into the
 | 
			
		||||
modules service since there is no reason I know of to keep them
 | 
			
		||||
separate. However, modules also provides modules-load in case you were
 | 
			
		||||
using modules-load in  your dependencies.
 | 
			
		||||
 | 
			
		||||
The consolefont, keymaps, numlock and procfs service scripts no longer
 | 
			
		||||
have a dependency on localmount.
 | 
			
		||||
If you are a linux user and are still separaating / from /usr,
 | 
			
		||||
you will need to add the following line to the appropriate conf.d files:
 | 
			
		||||
 | 
			
		||||
rc_need="localmount"
 | 
			
		||||
 | 
			
		||||
## OpenRC 0.35
 | 
			
		||||
 | 
			
		||||
In this version, the cgroups mounting logic has been moved from the
 | 
			
		||||
sysfs service to the cgroups service. This was done so cgroups can be
 | 
			
		||||
mounted inside an lxc/lxd container without using the other parts of the
 | 
			
		||||
sysfs service.
 | 
			
		||||
 | 
			
		||||
?As a result of this change, if you are upgrading, you need to add
 | 
			
		||||
cgroups to your sysinit runlevel by running the following command as
 | 
			
		||||
root:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
# rc-update add cgroups sysinit
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
For more information, see the following issue:
 | 
			
		||||
 | 
			
		||||
https://github.com/openrc/openrc/issues/187
 | 
			
		||||
 | 
			
		||||
Consider this your second notification with regard to /etc/mtab being a
 | 
			
		||||
file instead of a symbolic link.
 | 
			
		||||
 | 
			
		||||
In this version, the mtab service will complain loudly if you have
 | 
			
		||||
mtab_is_file set to yes and recommend that you change this to no and
 | 
			
		||||
restart the mtab service to migrate /etc/mtab to a symbolic link.
 | 
			
		||||
 | 
			
		||||
If there is a valid technical reason to keep /etc/mtab as a flat file
 | 
			
		||||
instead of a symbolic link to /proc/self/mounts, we are interested and
 | 
			
		||||
we will keep the support in that case. Please open an issue and let us
 | 
			
		||||
know however. Otherwise, consider this your final notice that the mtab
 | 
			
		||||
service will be removed in the future.
 | 
			
		||||
 | 
			
		||||
## OpenRC 0.33
 | 
			
		||||
 | 
			
		||||
This version removes the "service" binary which was just a copy of
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
# 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
 | 
			
		||||
@@ -22,6 +23,7 @@ below arguments to the make command
 | 
			
		||||
PROGLDFLAGS=-static
 | 
			
		||||
LIBNAME=lib64
 | 
			
		||||
DESTDIR=/tmp/openrc-image
 | 
			
		||||
MKBASHCOMP=no
 | 
			
		||||
MKNET=no
 | 
			
		||||
MKPAM=pam
 | 
			
		||||
MKPREFIX=yes
 | 
			
		||||
@@ -31,6 +33,7 @@ MKSTATICLIBS=no
 | 
			
		||||
MKSYSVINIT=yes
 | 
			
		||||
MKTERMCAP=ncurses
 | 
			
		||||
MKTERMCAP=termcap
 | 
			
		||||
MKZSHCOMP=no
 | 
			
		||||
PKG_PREFIX=/usr/pkg
 | 
			
		||||
LOCAL_PREFIX=/usr/local
 | 
			
		||||
PREFIX=/usr/local
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
# OpenRC Style Guide
 | 
			
		||||
OpenRC Coding 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,4 +1,5 @@
 | 
			
		||||
# Setting up the agetty service in OpenRC
 | 
			
		||||
Setting up the agetty service in OpenRC
 | 
			
		||||
=================================xxxxxx
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								bash-completion/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								bash-completion/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
DIR=	${BASHCOMPDIR}
 | 
			
		||||
CONF=	openrc \
 | 
			
		||||
		openrc-service-script \
 | 
			
		||||
		rc-service \
 | 
			
		||||
		rc-status \
 | 
			
		||||
		rc-update \
 | 
			
		||||
 | 
			
		||||
MK=	../mk
 | 
			
		||||
include ${MK}/os.mk
 | 
			
		||||
 | 
			
		||||
include ${MK}/scripts.mk
 | 
			
		||||
							
								
								
									
										24
									
								
								bash-completion/openrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								bash-completion/openrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
# 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
 | 
			
		||||
							
								
								
									
										29
									
								
								bash-completion/openrc-service-script
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								bash-completion/openrc-service-script
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
# 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/*
 | 
			
		||||
							
								
								
									
										113
									
								
								bash-completion/rc-service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								bash-completion/rc-service
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
# 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
 | 
			
		||||
							
								
								
									
										31
									
								
								bash-completion/rc-status
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								bash-completion/rc-status
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
# 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
 | 
			
		||||
							
								
								
									
										42
									
								
								bash-completion/rc-update
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								bash-completion/rc-update
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
# 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,5 +1,13 @@
 | 
			
		||||
# 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,6 +227,11 @@ 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
									
								
								init.d/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								init.d/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,6 @@
 | 
			
		||||
agetty
 | 
			
		||||
binfmt
 | 
			
		||||
cgroups
 | 
			
		||||
modules-load
 | 
			
		||||
bootmisc
 | 
			
		||||
fsck
 | 
			
		||||
 
 | 
			
		||||
@@ -19,11 +19,12 @@ SRCS-FreeBSD=	hostid.in modules.in moused.in newsyslog.in pf.in rarpd.in \
 | 
			
		||||
		rc-enabled.in rpcbind.in savecore.in syslogd.in
 | 
			
		||||
# These are FreeBSD specific
 | 
			
		||||
SRCS-FreeBSD+=	adjkerntz.in devd.in dumpon.in encswap.in ipfw.in \
 | 
			
		||||
		modules-load.in mixer.in nscd.in powerd.in syscons.in
 | 
			
		||||
		mixer.in nscd.in powerd.in syscons.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
 | 
			
		||||
SRCS-Linux=	agetty.in binfmt.in devfs.in cgroups.in dmesg.in hwclock.in \
 | 
			
		||||
	consolefont.in keymaps.in killprocs.in modules.in \
 | 
			
		||||
	mount-ro.in mtab.in numlock.in procfs.in net-online.in sysfs.in \
 | 
			
		||||
termencoding.in
 | 
			
		||||
 | 
			
		||||
# Generic BSD scripts
 | 
			
		||||
SRCS-NetBSD=	hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@ 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
 | 
			
		||||
@@ -29,5 +28,12 @@ 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}"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										149
									
								
								init.d/cgroups.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								init.d/cgroups.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
			
		||||
#!@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
 | 
			
		||||
}
 | 
			
		||||
@@ -13,7 +13,7 @@ description="Sets a font for the consoles."
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	need localmount termencoding
 | 
			
		||||
	need termencoding
 | 
			
		||||
	after hotplug bootmisc modules
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,9 +20,12 @@ depend()
 | 
			
		||||
 | 
			
		||||
mount_dev()
 | 
			
		||||
{
 | 
			
		||||
	local action=--mount devfstype msg=Mounting
 | 
			
		||||
	local action conf_d_dir devfstype msg mountopts
 | 
			
		||||
	action=--mount
 | 
			
		||||
	conf_d_dir="${RC_SERVICE%/*/*}/conf.d"
 | 
			
		||||
	msg=Mounting
 | 
			
		||||
	# Some devices require exec, Bug #92921
 | 
			
		||||
	local mountopts="exec,nosuid,mode=0755"
 | 
			
		||||
	mountopts="exec,nosuid,mode=0755"
 | 
			
		||||
	if yesno ${skip_mount_dev:-no} ; then
 | 
			
		||||
		einfo "/dev will not be mounted due to user request"
 | 
			
		||||
		return 0
 | 
			
		||||
@@ -33,7 +36,7 @@ mount_dev()
 | 
			
		||||
		msg=Remounting
 | 
			
		||||
	fi
 | 
			
		||||
	if fstabinfo -q /dev; then
 | 
			
		||||
		ebegin "$msg /dev according to @SYSCONFDIR@/fstab"
 | 
			
		||||
		ebegin "$msg /dev according to fstab"
 | 
			
		||||
		fstabinfo -q $action /dev
 | 
			
		||||
		eend $?
 | 
			
		||||
		return 0
 | 
			
		||||
@@ -54,7 +57,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 @SYSCONFDIR@/conf.d/devfs"
 | 
			
		||||
		ewarn "in your kernel configuration or see ${conf_d_dir}/${RC_SVCNAME}"
 | 
			
		||||
	fi
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,9 +20,9 @@ depend()
 | 
			
		||||
start()
 | 
			
		||||
{
 | 
			
		||||
	local h source x
 | 
			
		||||
	if [ -s @SYSCONFDIR@/hostname ] && [ -r @SYSCONFDIR@/hostname ]; then
 | 
			
		||||
		read h x <@SYSCONFDIR@/hostname
 | 
			
		||||
		source="from @SYSCONFDIR@/hostname"
 | 
			
		||||
	if [ -s /etc/hostname ] && [ -r /etc/hostname ]; then
 | 
			
		||||
		read h x </etc/hostname
 | 
			
		||||
		source="from /etc/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" \
 | 
			
		||||
					"@SYSCONFDIR@/conf.d/modules or built in."
 | 
			
		||||
					"${RC_SERVICE%/*/*}/conf.d/modules or built in."
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ description="Applies a keymap for the consoles."
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	need localmount termencoding
 | 
			
		||||
	need termencoding
 | 
			
		||||
	after bootmisc clock
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,10 @@
 | 
			
		||||
# This file may not be copied, modified, propagated, or distributed
 | 
			
		||||
# except according to the terms contained in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
description="Executes user programs in @SYSCONFDIR@/local.d"
 | 
			
		||||
conf_d_dir="${RC_SERVICE%/*/*}/conf.d"
 | 
			
		||||
local_d_dir="${RC_SERVICE%/*/*}/local.d"
 | 
			
		||||
 | 
			
		||||
description="Executes user programs in ${local_d_dir}"
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
@@ -19,12 +22,12 @@ depend()
 | 
			
		||||
 | 
			
		||||
start()
 | 
			
		||||
{
 | 
			
		||||
	ebegin "Starting local"
 | 
			
		||||
 | 
			
		||||
	local file has_errors=0 redirect retval
 | 
			
		||||
	local file has_errors redirect retval
 | 
			
		||||
	has_errors=0
 | 
			
		||||
	yesno $rc_verbose || redirect='> /dev/null 2>&1'
 | 
			
		||||
	ebegin "Starting local"
 | 
			
		||||
	eindent
 | 
			
		||||
	for file in @SYSCONFDIR@/local.d/*.start; do
 | 
			
		||||
	for file in "${local_d_dir}"/*.start; do
 | 
			
		||||
		if [ -x "${file}" ]; then
 | 
			
		||||
			vebegin "Executing \"${file}\""
 | 
			
		||||
			eval "${file}" $redirect
 | 
			
		||||
@@ -38,32 +41,32 @@ start()
 | 
			
		||||
	eoutdent
 | 
			
		||||
 | 
			
		||||
	if command -v local_start >/dev/null 2>&1; then
 | 
			
		||||
		ewarn "\"@SYSCONFDIR@/conf.d/local\" should be removed."
 | 
			
		||||
		ewarn "\"${conf_d_dir}/local\" should be removed."
 | 
			
		||||
		ewarn "Please move the code from the local_start function"
 | 
			
		||||
		ewarn "to executable scripts with an .start extension"
 | 
			
		||||
		ewarn "in \"@SYSCONFDIR@/local.d\""
 | 
			
		||||
		ewarn "in \"${local_d_dir}\""
 | 
			
		||||
		local_start
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	eend ${has_errors}
 | 
			
		||||
 | 
			
		||||
	# We have to end with a zero exit code, because a failed execution
 | 
			
		||||
	# of an executable @SYSCONFDIR@/local.d/*.start file shouldn't result in
 | 
			
		||||
	# of an executable ${local_d_dir}/*.start file shouldn't result in
 | 
			
		||||
	# marking the local service as failed. Otherwise we are unable to
 | 
			
		||||
	# execute any executable @SYSCONFDIR@/local.d/*.stop file, because a failed
 | 
			
		||||
	# execute any executable ${local_d_dir}/*.stop file, because a failed
 | 
			
		||||
	# marked service cannot be stopped (and the stop function would
 | 
			
		||||
	# actually call the executable @SYSCONFDIR@/local.d/*.stop file(s)).
 | 
			
		||||
	# actually call the executable ${local_d_dir}/*.stop file(s)).
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
stop()
 | 
			
		||||
{
 | 
			
		||||
	ebegin "Stopping local"
 | 
			
		||||
 | 
			
		||||
	local file has_errors=0 redirect retval
 | 
			
		||||
	local file has_errors redirect retval
 | 
			
		||||
	has_errors=0
 | 
			
		||||
	yesno $rc_verbose || redirect='> /dev/null 2>&1'
 | 
			
		||||
	ebegin "Stopping local"
 | 
			
		||||
	eindent
 | 
			
		||||
	for file in @SYSCONFDIR@/local.d/*.stop; do
 | 
			
		||||
	for file in "${local_d_dir}"/*.stop; do
 | 
			
		||||
		if [ -x "${file}" ]; then
 | 
			
		||||
			vebegin "Executing \"${file}\""
 | 
			
		||||
			eval "${file}" $redirect
 | 
			
		||||
@@ -77,16 +80,16 @@ stop()
 | 
			
		||||
	eoutdent
 | 
			
		||||
 | 
			
		||||
	if command -v local_stop >/dev/null 2>&1; then
 | 
			
		||||
		ewarn "\"@SYSCONFDIR@/conf.d/local\" should be removed."
 | 
			
		||||
		ewarn "\"${conf_d_dir}/local\" should be removed."
 | 
			
		||||
		ewarn "Please move the code from the local_stop function"
 | 
			
		||||
		ewarn "to executable scripts with an .stop extension"
 | 
			
		||||
		ewarn "in \"@SYSCONFDIR@/local.d\""
 | 
			
		||||
		ewarn "in \"${local_d_dir}\""
 | 
			
		||||
		local_stop
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	eend ${has_errors}
 | 
			
		||||
 | 
			
		||||
	# An executable @SYSCONFDIR@/local.d/*.stop file which failed with a
 | 
			
		||||
	# An executable ${local_d_dir}/*.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 mtab root
 | 
			
		||||
	use lvm modules root
 | 
			
		||||
	after clock lvm modules root
 | 
			
		||||
	keyword -docker -jail -lxc -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,72 +0,0 @@
 | 
			
		||||
#!@SBINDIR@/openrc-run
 | 
			
		||||
# Copyright (c) 2016 The OpenRC Authors.
 | 
			
		||||
# See the Authors file at the top-level directory of this distribution and
 | 
			
		||||
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
 | 
			
		||||
#
 | 
			
		||||
# This file is part of OpenRC. It is subject to the license terms in
 | 
			
		||||
# the LICENSE file found in the top-level directory of this
 | 
			
		||||
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
 | 
			
		||||
# This file may not be copied, modified, propagated, or distributed
 | 
			
		||||
# except according to the terms contained in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
description="Loads a list of modules from systemd-compatible locations."
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
find_modfiles()
 | 
			
		||||
{
 | 
			
		||||
	local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
 | 
			
		||||
	local basenames files fn x y
 | 
			
		||||
	for x in $dirs; do
 | 
			
		||||
		[ ! -d $x ] && continue
 | 
			
		||||
		for y in $x/*.conf; do
 | 
			
		||||
			[ -f $y ] && basenames="${basenames}\n${y##*/}"
 | 
			
		||||
		done
 | 
			
		||||
	done
 | 
			
		||||
	basenames=$(printf "$basenames" | sort -u)
 | 
			
		||||
	for x in $basenames; do
 | 
			
		||||
		for y in $dirs; do
 | 
			
		||||
			[ -r $y/$x ] &&
 | 
			
		||||
				fn=$y/$x
 | 
			
		||||
		done
 | 
			
		||||
		files="$files $fn"
 | 
			
		||||
	done
 | 
			
		||||
	echo $files
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
load_modules()
 | 
			
		||||
{
 | 
			
		||||
	local file m modules rc x
 | 
			
		||||
	file=$1
 | 
			
		||||
	[ -z "$file" ] && return 0
 | 
			
		||||
	while read m x; do
 | 
			
		||||
		case $m in
 | 
			
		||||
			\;*) continue ;;
 | 
			
		||||
			\#*) continue ;;
 | 
			
		||||
			*) modules="$modules $m"
 | 
			
		||||
			;;
 | 
			
		||||
		esac
 | 
			
		||||
	done < $file
 | 
			
		||||
	for x in $modules; do
 | 
			
		||||
		ebegin "Loading module $x"
 | 
			
		||||
		case "$RC_UNAME" in
 | 
			
		||||
			FreeBSD) kldload "$x"; rc=$? ;;
 | 
			
		||||
			Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
 | 
			
		||||
			*) ;;
 | 
			
		||||
		esac
 | 
			
		||||
		eend $rc "Failed to load $x"
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start()
 | 
			
		||||
{
 | 
			
		||||
	local x
 | 
			
		||||
	files=$(find_modfiles)
 | 
			
		||||
	for x in $files; do
 | 
			
		||||
		load_modules $x
 | 
			
		||||
	done
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
@@ -14,10 +14,65 @@ description="Loads a user defined list of kernel modules."
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	use isapnp
 | 
			
		||||
	want modules-load
 | 
			
		||||
	provide modules-load
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
find_modfiles()
 | 
			
		||||
{
 | 
			
		||||
	local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
 | 
			
		||||
	local basenames files fn x y
 | 
			
		||||
	for x in $dirs; do
 | 
			
		||||
		[ ! -d $x ] && continue
 | 
			
		||||
		for y in $x/*.conf; do
 | 
			
		||||
			[ -f $y ] && basenames="${basenames}\n${y##*/}"
 | 
			
		||||
		done
 | 
			
		||||
	done
 | 
			
		||||
	basenames=$(printf "$basenames" | sort -u)
 | 
			
		||||
	for x in $basenames; do
 | 
			
		||||
		for y in $dirs; do
 | 
			
		||||
			[ -r $y/$x ] &&
 | 
			
		||||
				fn=$y/$x
 | 
			
		||||
		done
 | 
			
		||||
		files="$files $fn"
 | 
			
		||||
	done
 | 
			
		||||
	echo $files
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
load_modules()
 | 
			
		||||
{
 | 
			
		||||
	local file m modules rc x
 | 
			
		||||
	file=$1
 | 
			
		||||
	[ -z "$file" ] && return 0
 | 
			
		||||
	while read m x; do
 | 
			
		||||
		case $m in
 | 
			
		||||
			\;*) continue ;;
 | 
			
		||||
			\#*) continue ;;
 | 
			
		||||
			*) modules="$modules $m"
 | 
			
		||||
			;;
 | 
			
		||||
		esac
 | 
			
		||||
	done < $file
 | 
			
		||||
	for x in $modules; do
 | 
			
		||||
		ebegin "Loading module $x"
 | 
			
		||||
		case "$RC_UNAME" in
 | 
			
		||||
			FreeBSD) kldload "$x"; rc=$? ;;
 | 
			
		||||
			Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
 | 
			
		||||
			*) ;;
 | 
			
		||||
		esac
 | 
			
		||||
		eend $rc "Failed to load $x"
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
modules_load_d()
 | 
			
		||||
{
 | 
			
		||||
	local x
 | 
			
		||||
	files=$(find_modfiles)
 | 
			
		||||
	for x in $files; do
 | 
			
		||||
		load_modules $x
 | 
			
		||||
	done
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FreeBSD_modules()
 | 
			
		||||
{
 | 
			
		||||
	local cnt=0 x
 | 
			
		||||
@@ -82,7 +137,10 @@ Linux_modules()
 | 
			
		||||
start()
 | 
			
		||||
{
 | 
			
		||||
	case "$RC_UNAME" in
 | 
			
		||||
		FreeBSD|Linux) ${RC_UNAME}_modules ;;
 | 
			
		||||
		FreeBSD|Linux) 
 | 
			
		||||
			modules_load_d
 | 
			
		||||
			${RC_UNAME}_modules
 | 
			
		||||
			;;
 | 
			
		||||
		*) ;;
 | 
			
		||||
	esac
 | 
			
		||||
	return 0
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ description="Update /etc/mtab to match what the kernel knows about"
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	after clock
 | 
			
		||||
	before localmount
 | 
			
		||||
	need root
 | 
			
		||||
	keyword -prefix -systemd-nspawn
 | 
			
		||||
}
 | 
			
		||||
@@ -30,6 +31,10 @@ 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"
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ description="Delays until the network is online or a specific timeout"
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	after modules
 | 
			
		||||
	after modules net
 | 
			
		||||
	need sysfs
 | 
			
		||||
	provide network-online
 | 
			
		||||
	keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -uml -vserver
 | 
			
		||||
@@ -23,6 +23,7 @@ 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
 | 
			
		||||
@@ -31,7 +32,7 @@ get_interfaces()
 | 
			
		||||
start ()
 | 
			
		||||
{
 | 
			
		||||
	local carriers configured dev gateway ifcount infinite
 | 
			
		||||
	local rc state x
 | 
			
		||||
	local carrier operstate rc
 | 
			
		||||
 | 
			
		||||
	ebegin "Checking to see if the network is online"
 | 
			
		||||
	rc=0
 | 
			
		||||
@@ -44,10 +45,12 @@ start ()
 | 
			
		||||
	ifcount=0
 | 
			
		||||
 	for dev in ${interfaces}; do
 | 
			
		||||
		: $((ifcount += 1))
 | 
			
		||||
		read x < /sys/class/net/$dev/carrier
 | 
			
		||||
		[ $x -eq 1 ] && : $((carriers += 1))
 | 
			
		||||
		read x < /sys/class/net/$dev/operstate
 | 
			
		||||
		[ "$x" = up ] && : $((configured += 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))
 | 
			
		||||
	done
 | 
			
		||||
	[ $configured -eq $ifcount ] && [ $carriers -ge 1 ] && break
 | 
			
		||||
	sleep 1
 | 
			
		||||
@@ -61,8 +64,12 @@ 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
 | 
			
		||||
		ping -c 1 $ping_test_host > /dev/null 2>&1
 | 
			
		||||
		rc=$?
 | 
			
		||||
		while $infinite || [ $timeout -gt 0 ]; do
 | 
			
		||||
			ping -c 1 $ping_test_host > /dev/null 2>&1
 | 
			
		||||
			rc=$?
 | 
			
		||||
			[ $rc -eq 0 ] && break
 | 
			
		||||
			: $((timeout -= 1))
 | 
			
		||||
		done
 | 
			
		||||
	fi
 | 
			
		||||
 fi
 | 
			
		||||
 eend $rc "The network is offline"
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ tentative()
 | 
			
		||||
 | 
			
		||||
	case "$RC_UNAME" in
 | 
			
		||||
	Linux)
 | 
			
		||||
		[ -x /sbin/ip ] || [ -x /bin/ip ] || return 1
 | 
			
		||||
		[ -n "$(command -v ip)" ] || return 1
 | 
			
		||||
		[ -n "$(ip -f inet6 addr show tentative)" ]
 | 
			
		||||
		;;
 | 
			
		||||
	*)
 | 
			
		||||
@@ -174,7 +174,7 @@ runip()
 | 
			
		||||
routeflush()
 | 
			
		||||
{
 | 
			
		||||
	if [ "$RC_UNAME" = Linux ]; then
 | 
			
		||||
		if [ -x /sbin/ip ] || [ -x /bin/ip ]; then
 | 
			
		||||
		if [ -n "$(command -v 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 [ -x /sbin/ip ] || [ -x /bin/ip ]; then
 | 
			
		||||
			if [ -n "$(command -v 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
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,6 @@ ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	need localmount
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@ depend()
 | 
			
		||||
	after clock
 | 
			
		||||
	use devfs
 | 
			
		||||
	want modules
 | 
			
		||||
	need localmount
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -27,8 +26,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 configured in" \
 | 
			
		||||
				"@SYSCONFDIR@/conf.d/modules or built in."
 | 
			
		||||
			ewarn "The binfmt-misc module needs to be loaded by" \
 | 
			
		||||
				"the modules service or built in."
 | 
			
		||||
		fi
 | 
			
		||||
		if grep -qs binfmt_misc /proc/filesystems; then
 | 
			
		||||
			ebegin "Mounting misc binary format filesystem"
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ start()
 | 
			
		||||
	fi
 | 
			
		||||
	ebegin "Saving dependency cache"
 | 
			
		||||
	local rc=0 save=
 | 
			
		||||
	for x in shutdowntime softlevel rc.log; do
 | 
			
		||||
	for x in depconfig deptree rc.log shutdowntime softlevel; do
 | 
			
		||||
		[ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x"
 | 
			
		||||
	done
 | 
			
		||||
	if [ -n "$save" ]; then
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	after clock
 | 
			
		||||
	after clock root
 | 
			
		||||
	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 @SYSCONFDIR@/sysctl.conf @SYSCONFDIR@/sysctl.d/*.conf; do
 | 
			
		||||
	for conf in /etc/sysctl.conf /etc/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,122 +107,11 @@ 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
 | 
			
		||||
}
 | 
			
		||||
@@ -231,7 +120,6 @@ 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 December 31, 2011
 | 
			
		||||
.Dd November 30, 2017
 | 
			
		||||
.Dt openrc-run 8 SMM
 | 
			
		||||
.Os OpenRC
 | 
			
		||||
.Sh NAME
 | 
			
		||||
@@ -111,11 +111,17 @@ The path to the s6 service directory if you are monitoring this service
 | 
			
		||||
with S6. The default is /var/svc.d/${RC_SVCNAME}.
 | 
			
		||||
.It Ar s6_svwait_options_start
 | 
			
		||||
The options to pass to s6-svwait when starting the service via s6.
 | 
			
		||||
.It Ar s6_force_kill
 | 
			
		||||
Should we force-kill this service if s6_service_timeout_stop expires
 | 
			
		||||
but the service doesn't go down during shutdown? The default is yes.
 | 
			
		||||
.It Ar s6_service_timeout_stop
 | 
			
		||||
The amount of time, in milliseconds, s6-svc should wait for the service
 | 
			
		||||
to go down when stopping the service. The default is 10000.
 | 
			
		||||
to go down when stopping the service. The default is 60000.
 | 
			
		||||
.It Ar start_stop_daemon_args
 | 
			
		||||
List of arguments passed to start-stop-daemon when starting the daemon.
 | 
			
		||||
.It Ar supervise_daemon_args
 | 
			
		||||
List of arguments passed to supervise-daemon when starting the daemon.
 | 
			
		||||
If undefined, start_stop_daemon_args is used as a fallback.
 | 
			
		||||
.It Ar command
 | 
			
		||||
Daemon to start or stop via
 | 
			
		||||
.Nm start-stop-daemon
 | 
			
		||||
@@ -139,21 +145,56 @@ 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 before
 | 
			
		||||
use this to change the user id, and optionally group id,  before
 | 
			
		||||
.Xr start-stop-daemon 8
 | 
			
		||||
or
 | 
			
		||||
.Xr supervise-daemon 8
 | 
			
		||||
launches the daemon
 | 
			
		||||
launches the daemon.
 | 
			
		||||
.It Ar output_log
 | 
			
		||||
This is the path to a file or named pipe where the standard output from
 | 
			
		||||
the service will be redirected. If you are starting this service with
 | 
			
		||||
.Xr start-stop-daemon 8 ,
 | 
			
		||||
,  you must set
 | 
			
		||||
.Pa command_background
 | 
			
		||||
to true. Keep in mind that this path will be inside the chroot if the
 | 
			
		||||
.Pa chroot
 | 
			
		||||
variable is set.
 | 
			
		||||
.It Ar error_log
 | 
			
		||||
The same thing as
 | 
			
		||||
.Pa output_log
 | 
			
		||||
but for the standard error output.
 | 
			
		||||
.It Ar output_logger
 | 
			
		||||
This is a process which will be used to log the standard output from the
 | 
			
		||||
service.  If you are starting this service with
 | 
			
		||||
.Xr start-stop-daemon 8 ,
 | 
			
		||||
,  you must set
 | 
			
		||||
.Pa command_background
 | 
			
		||||
to true. Keep in mind that this command must be executable as a shell
 | 
			
		||||
command inside the chroot if the
 | 
			
		||||
.Pa chroot
 | 
			
		||||
variable is set. Keep in mind also that this command works by accepting
 | 
			
		||||
the stdout of the service on stdin.
 | 
			
		||||
An example of a command that can be run this way is logger if you want
 | 
			
		||||
your service output to go to syslog.
 | 
			
		||||
.It Ar error_logger
 | 
			
		||||
The same thing as
 | 
			
		||||
.Pa output_logger
 | 
			
		||||
but for the standard error output.
 | 
			
		||||
.It Ar directory
 | 
			
		||||
.Xr start-stop-daemon 8
 | 
			
		||||
and
 | 
			
		||||
.Xr supervise-daemon 8
 | 
			
		||||
will chdir to this directory before starting the daemon.
 | 
			
		||||
.It Ar chroot
 | 
			
		||||
.Xr start-stop-daemon 8
 | 
			
		||||
and
 | 
			
		||||
@@ -198,6 +239,8 @@ 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
 | 
			
		||||
@@ -447,6 +490,7 @@ 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
 | 
			
		||||
@@ -463,6 +507,7 @@ 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
 | 
			
		||||
@@ -477,7 +522,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
 | 
			
		||||
@@ -569,7 +614,7 @@ rc_net_tap1_provide="!net"
 | 
			
		||||
# It's also possible to negate keywords. This is mainly useful for prefix
 | 
			
		||||
# users testing OpenRC.
 | 
			
		||||
rc_keyword="!-prefix"
 | 
			
		||||
# This can also be used to block a script from runining in all
 | 
			
		||||
# This can also be used to block a script from running in all
 | 
			
		||||
# containers except one or two
 | 
			
		||||
rc_keyword="!-containers !-docker"
 | 
			
		||||
.Ed
 | 
			
		||||
@@ -708,6 +753,8 @@ 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,6 +16,18 @@
 | 
			
		||||
.Nd locate and run an OpenRC service with the given arguments
 | 
			
		||||
.Sh SYNOPSIS
 | 
			
		||||
.Nm
 | 
			
		||||
.Op Fl c , -ifcrashed
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl d , -debug
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl D , -nodeps
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Op Fl i , -ifexists
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
@@ -28,9 +40,21 @@
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Op Fl s , -ifstarted
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Op Fl S , -ifstopped
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl e , -exists
 | 
			
		||||
.Ar service
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl Z , -dry-run
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl l , -list
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl r , -resolve
 | 
			
		||||
@@ -64,6 +88,15 @@ return 0 if it can find
 | 
			
		||||
otherwise -1.
 | 
			
		||||
.Fl r , -resolve
 | 
			
		||||
does the same and also prints the full path of the service to stdout.
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl d , -debug
 | 
			
		||||
sets -x when running the service script(s).
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl D , -nodeps
 | 
			
		||||
ignores dependencies when running the service.
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl Z , -dry-run
 | 
			
		||||
displays commands rather than executing them.
 | 
			
		||||
.Sh SEE ALSO
 | 
			
		||||
.Xr openrc 8 ,
 | 
			
		||||
.Xr stdout 3
 | 
			
		||||
 
 | 
			
		||||
@@ -131,9 +131,34 @@ Modifies the scheduling priority of the daemon.
 | 
			
		||||
.It Fl 1 , -stdout Ar logfile
 | 
			
		||||
Redirect the standard output of the process to logfile when started with
 | 
			
		||||
.Fl background .
 | 
			
		||||
Must be an absolute pathname, but relative to the path optionally given with
 | 
			
		||||
The logfile Must be an absolute pathname, but relative to the path
 | 
			
		||||
optionally given with
 | 
			
		||||
.Fl r , -chroot .
 | 
			
		||||
The logfile can also be a named pipe.
 | 
			
		||||
.It Fl 2 , -stderr Ar logfile
 | 
			
		||||
Redirect the standard error of the process to logfile when started with
 | 
			
		||||
.Fl background .
 | 
			
		||||
The logfile must be an absolute pathname, but relative to the path
 | 
			
		||||
optionally given with
 | 
			
		||||
.Fl r , -chroot .
 | 
			
		||||
The logfile can also be a named pipe.
 | 
			
		||||
.It Fl 3 , -stdout-logger Ar cmd
 | 
			
		||||
Run cmd as a child process redirecting the standard output to the
 | 
			
		||||
standard input of cmd when started with
 | 
			
		||||
.Fl background .
 | 
			
		||||
Cmd must be an absolute pathname, but relative to the path optionally given with
 | 
			
		||||
.Fl r , -chroot .
 | 
			
		||||
This process must be prepared to accept input on stdin and be able to
 | 
			
		||||
log it or send it to another location.
 | 
			
		||||
.It Fl 4 , -stderr-logger Ar cmd
 | 
			
		||||
Run cmd as a child process and 
 | 
			
		||||
Redirect the standard error of the process to the standard input of cmd
 | 
			
		||||
when started with
 | 
			
		||||
.Fl background .
 | 
			
		||||
Cmd must be an absolute pathname, but relative to the path optionally given with
 | 
			
		||||
.Fl r , -chroot .
 | 
			
		||||
This process must be prepared to accept input on stdin and be able to
 | 
			
		||||
log it or send it to another location.
 | 
			
		||||
.It Fl w , -wait Ar milliseconds
 | 
			
		||||
Wait
 | 
			
		||||
.Ar milliseconds
 | 
			
		||||
@@ -151,6 +176,7 @@ 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,6 +120,7 @@ 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,3 +11,5 @@
 | 
			
		||||
# 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 -D_XOPEN_SOURCE=700
 | 
			
		||||
CPPFLAGS+=	-D_BSD_SOURCE
 | 
			
		||||
LIBDL=		-Wl,-Bdynamic -ldl
 | 
			
		||||
LIBKVM?=
 | 
			
		||||
 
 | 
			
		||||
@@ -11,5 +11,5 @@
 | 
			
		||||
SFX=		.GNU.in
 | 
			
		||||
PKG_PREFIX?=	/usr
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -DMAXPATHLEN=4096 -DPATH_MAX=4096
 | 
			
		||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -DMAXPATHLEN=4096 -DPATH_MAX=4096
 | 
			
		||||
LIBDL=		-Wl,-Bdynamic -ldl
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
SFX=		.Linux.in
 | 
			
		||||
PKG_PREFIX?=	/usr
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700
 | 
			
		||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L
 | 
			
		||||
LIBDL=		-Wl,-Bdynamic -ldl
 | 
			
		||||
 | 
			
		||||
ifeq (${MKSELINUX},yes)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								mk/sys.mk
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								mk/sys.mk
									
									
									
									
									
								
							@@ -34,6 +34,7 @@ PICFLAG?=		-fPIC
 | 
			
		||||
SYSCONFDIR?=		${PREFIX}/etc
 | 
			
		||||
INITDIR?=		${SYSCONFDIR}/init.d
 | 
			
		||||
CONFDIR?=		${SYSCONFDIR}/conf.d
 | 
			
		||||
CONFMODE?=		0644
 | 
			
		||||
LOCALDIR?=		${SYSCONFDIR}/local.d
 | 
			
		||||
SYSCTLDIR?=		${SYSCONFDIR}/sysctl.d
 | 
			
		||||
 | 
			
		||||
@@ -44,20 +45,22 @@ SBINDIR?=		${PREFIX}/sbin
 | 
			
		||||
SBINMODE?=		0755
 | 
			
		||||
 | 
			
		||||
INCDIR?=		${UPREFIX}/include
 | 
			
		||||
INCMODE?=		0444
 | 
			
		||||
INCMODE?=		0644
 | 
			
		||||
 | 
			
		||||
_LIBNAME_SH=		case `readlink /lib` in /lib64|lib64) echo "lib64";; *) echo "lib";; esac
 | 
			
		||||
_LIBNAME:=		$(shell ${_LIBNAME_SH})
 | 
			
		||||
LIBNAME?=		${_LIBNAME}
 | 
			
		||||
LIBDIR?=		${UPREFIX}/${LIBNAME}
 | 
			
		||||
LIBMODE?=		0444
 | 
			
		||||
LIBMODE?=		0644
 | 
			
		||||
SHLIBDIR?=		${PREFIX}/${LIBNAME}
 | 
			
		||||
 | 
			
		||||
LIBEXECDIR?=		${PREFIX}/libexec/rc
 | 
			
		||||
 | 
			
		||||
MANPREFIX?=		${UPREFIX}/share
 | 
			
		||||
MANDIR?=		${MANPREFIX}/man
 | 
			
		||||
MANMODE?=		0444
 | 
			
		||||
MANMODE?=		0644
 | 
			
		||||
 | 
			
		||||
BASHCOMPDIR?=		${UPREFIX}/share/bash-completion/completions
 | 
			
		||||
 | 
			
		||||
DATADIR?=		${UPREFIX}/share/openrc
 | 
			
		||||
DATAMODE?=		0644
 | 
			
		||||
@@ -65,4 +68,4 @@ DATAMODE?=		0644
 | 
			
		||||
DOCDIR?=		${UPREFIX}/share/doc
 | 
			
		||||
DOCMODE?=		0644
 | 
			
		||||
 | 
			
		||||
CONFMODE?=		0644
 | 
			
		||||
ZSHCOMPDIR?=		${UPREFIX}/share/zsh/site-functions
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
# 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 dmesg sysfs
 | 
			
		||||
SYSINIT-Linux=	devfs cgroups dmesg sysfs
 | 
			
		||||
 | 
			
		||||
# Generic BSD stuff
 | 
			
		||||
BOOT-NetBSD+=	hostid newsyslog savecore syslogd
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
# 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
 | 
			
		||||
@@ -39,6 +40,10 @@ s6_service_path - the path to the s6 service directory. The default is
 | 
			
		||||
s6_svwait_options_start - the options to pass to s6-svwait when starting
 | 
			
		||||
the service. If this is not set, s6-svwait will not be called.
 | 
			
		||||
 | 
			
		||||
s6_force_kill - Should we try to force kill this service if the
 | 
			
		||||
s6_service_timeout_stop timeout expires when shutting down this service?
 | 
			
		||||
The default is yes.
 | 
			
		||||
 | 
			
		||||
s6_service_timeout_stop - the amount of time, in milliseconds, s6-svc
 | 
			
		||||
should wait for a service to go down when stopping.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										495
									
								
								service-script-guide.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										495
									
								
								service-script-guide.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,495 @@
 | 
			
		||||
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,6 +33,9 @@ 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,6 +83,7 @@ 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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -133,11 +133,10 @@ _status()
 | 
			
		||||
	elif service_inactive; then
 | 
			
		||||
		ewarn "status: inactive"
 | 
			
		||||
		return 16
 | 
			
		||||
	elif service_crashed; then
 | 
			
		||||
		eerror "status: crashed"
 | 
			
		||||
		return 32
 | 
			
		||||
	elif service_started; then
 | 
			
		||||
		if service_crashed; then
 | 
			
		||||
			eerror "status: crashed"
 | 
			
		||||
			return 32
 | 
			
		||||
		fi
 | 
			
		||||
		einfo "status: started"
 | 
			
		||||
		return 0
 | 
			
		||||
	else
 | 
			
		||||
@@ -260,12 +259,14 @@ for _cmd; do
 | 
			
		||||
		# Apply cgroups settings if defined
 | 
			
		||||
		if [ "$(command -v cgroup_add_service)" = "cgroup_add_service" ]
 | 
			
		||||
		then
 | 
			
		||||
			if [ -d /sys/fs/cgroup -a ! -w /sys/fs/cgroup ]; then
 | 
			
		||||
				eerror "No permission to apply cgroup settings"
 | 
			
		||||
				break
 | 
			
		||||
			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
 | 
			
		||||
			fi
 | 
			
		||||
			cgroup_add_service /sys/fs/cgroup/openrc
 | 
			
		||||
			cgroup_add_service /sys/fs/cgroup/systemd/system
 | 
			
		||||
			cgroup_add_service
 | 
			
		||||
		fi
 | 
			
		||||
		[ "$(command -v cgroup_set_limits)" = "cgroup_set_limits" ] &&
 | 
			
		||||
			cgroup_set_limits
 | 
			
		||||
 
 | 
			
		||||
@@ -184,18 +184,17 @@ 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}"
 | 
			
		||||
	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}"
 | 
			
		||||
	[ -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}"
 | 
			
		||||
	done
 | 
			
		||||
	IFS="$OIFS"
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								sh/s6.sh
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								sh/s6.sh
									
									
									
									
									
								
							@@ -12,6 +12,20 @@
 | 
			
		||||
 | 
			
		||||
[ -z "${s6_service_path}" ] && s6_service_path="/var/svc.d/${RC_SVCNAME}"
 | 
			
		||||
 | 
			
		||||
_s6_force_kill() {
 | 
			
		||||
	local pid
 | 
			
		||||
	s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}"
 | 
			
		||||
	pid="${3%)}"
 | 
			
		||||
	[ -z "${pid}" ] && return 0
 | 
			
		||||
	if kill -0 "${pid}" 2> /dev/null; then
 | 
			
		||||
		ewarn "Sending DOWN & KILL for ${RC_SVCNAME}"
 | 
			
		||||
		s6-svc -dk "${s6_service_link}"
 | 
			
		||||
		sleep 1
 | 
			
		||||
		kill -0 "${pid}" 2>/dev/null && return 1
 | 
			
		||||
	fi
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
s6_start()
 | 
			
		||||
{
 | 
			
		||||
	if [ ! -d "${s6_service_path}" ]; then
 | 
			
		||||
@@ -41,7 +55,11 @@ s6_stop()
 | 
			
		||||
 fi
 | 
			
		||||
	s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}"
 | 
			
		||||
	ebegin "Stopping ${name:-$RC_SVCNAME}"
 | 
			
		||||
	s6-svc -wD -d -T ${s6_service_timeout_stop:-10000} "${s6_service_link}"
 | 
			
		||||
	s6-svc -d -wD -T ${s6_service_timeout_stop:-60000} "${s6_service_link}"
 | 
			
		||||
	set -- $(s6-svstat "${s6_service_link}")
 | 
			
		||||
	[ "$1" = "up" ] && 
 | 
			
		||||
		yesno "${s6_force_kill:-yes}" &&
 | 
			
		||||
			_s6_force_kill "$@"
 | 
			
		||||
	set -- $(s6-svstat "${s6_service_link}")
 | 
			
		||||
	[ "$1" = "down" ]
 | 
			
		||||
	eend $? "Failed to stop ${name:-$RC_SVCNAME}"
 | 
			
		||||
 
 | 
			
		||||
@@ -38,15 +38,25 @@ ssd_start()
 | 
			
		||||
		service_inactive && _inactive=true
 | 
			
		||||
		mark_service_inactive
 | 
			
		||||
	fi
 | 
			
		||||
	[ -n "$output_logger" ] && 
 | 
			
		||||
		output_logger_arg="--stdout-logger \"$output_logger\""
 | 
			
		||||
	[ -n "$error_logger" ] && 
 | 
			
		||||
		error_logger_arg="--stderr-logger \"$error_logger\""
 | 
			
		||||
	#the eval call is necessary for cases like:
 | 
			
		||||
	# command_args="this \"is a\" test"
 | 
			
		||||
	# to work properly.
 | 
			
		||||
	eval start-stop-daemon --start \
 | 
			
		||||
		--exec $command \
 | 
			
		||||
		${chroot:+--chroot} $chroot \
 | 
			
		||||
		${directory:+--chdir} $directory \
 | 
			
		||||
		${output_log+--stdout} $output_log \
 | 
			
		||||
		${error_log+--stderr} $error_log \
 | 
			
		||||
		${output_logger_arg} \
 | 
			
		||||
		${error_logger_arg} \
 | 
			
		||||
		${procname:+--name} $procname \
 | 
			
		||||
		${pidfile:+--pidfile} $pidfile \
 | 
			
		||||
		${command_user+--user} $command_user \
 | 
			
		||||
		${umask+--umask} $umask \
 | 
			
		||||
		$_background $start_stop_daemon_args \
 | 
			
		||||
		-- $command_args $command_args_background
 | 
			
		||||
	if eend $? "Failed to start ${name:-$RC_SVCNAME}"; then
 | 
			
		||||
 
 | 
			
		||||
@@ -24,13 +24,17 @@ 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 \
 | 
			
		||||
		$supervise_daemon_args \
 | 
			
		||||
		${umask+--umask} $umask \
 | 
			
		||||
		${supervise_daemon_args:-${start_stop_daemon_args}} \
 | 
			
		||||
		$command \
 | 
			
		||||
		-- $command_args $command_args_foreground
 | 
			
		||||
	rc=$?
 | 
			
		||||
 
 | 
			
		||||
@@ -28,9 +28,11 @@
 | 
			
		||||
#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]))
 | 
			
		||||
@@ -53,6 +55,7 @@
 | 
			
		||||
	} while (/* CONSTCOND */ 0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
 | 
			
		||||
@@ -96,8 +99,10 @@ _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, '/');
 | 
			
		||||
@@ -121,4 +126,49 @@ _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
 | 
			
		||||
 
 | 
			
		||||
@@ -66,9 +66,6 @@ int parse_mode(mode_t *, char *);
 | 
			
		||||
/* Handy function so we can wrap einfo around our deptree */
 | 
			
		||||
RC_DEPTREE *_rc_deptree_load (int, int *);
 | 
			
		||||
 | 
			
		||||
/* Test to see if we can see pid 1 or not */
 | 
			
		||||
bool _rc_can_find_pids(void);
 | 
			
		||||
 | 
			
		||||
RC_SERVICE lookup_service_state(const char *service);
 | 
			
		||||
void from_time_t(char *time_string, time_t tv);
 | 
			
		||||
time_t to_time_t(char *timestring);
 | 
			
		||||
 
 | 
			
		||||
@@ -883,7 +883,7 @@ eindent(void)
 | 
			
		||||
{
 | 
			
		||||
	char *env = getenv("EINFO_INDENT");
 | 
			
		||||
	int amount = 0;
 | 
			
		||||
	char num[10];
 | 
			
		||||
	char *num;
 | 
			
		||||
 | 
			
		||||
	if (env) {
 | 
			
		||||
		errno = 0;
 | 
			
		||||
@@ -894,8 +894,9 @@ eindent(void)
 | 
			
		||||
	amount += INDENT_WIDTH;
 | 
			
		||||
	if (amount > INDENT_MAX)
 | 
			
		||||
		amount = INDENT_MAX;
 | 
			
		||||
	snprintf(num, 10, "%08d", amount);
 | 
			
		||||
	xasprintf(&num, "%08d", amount);
 | 
			
		||||
	setenv("EINFO_INDENT", num, 1);
 | 
			
		||||
	free(num);
 | 
			
		||||
}
 | 
			
		||||
hidden_def(eindent)
 | 
			
		||||
 | 
			
		||||
@@ -903,7 +904,7 @@ void eoutdent(void)
 | 
			
		||||
{
 | 
			
		||||
	char *env = getenv("EINFO_INDENT");
 | 
			
		||||
	int amount = 0;
 | 
			
		||||
	char num[10];
 | 
			
		||||
	char *num = NULL;
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
 | 
			
		||||
	if (!env)
 | 
			
		||||
@@ -917,8 +918,9 @@ void eoutdent(void)
 | 
			
		||||
	if (amount <= 0)
 | 
			
		||||
		unsetenv("EINFO_INDENT");
 | 
			
		||||
	else {
 | 
			
		||||
		snprintf(num, 10, "%08d", amount);
 | 
			
		||||
		xasprintf(&num, "%08d", amount);
 | 
			
		||||
		setenv("EINFO_INDENT", num, 1);
 | 
			
		||||
		free(num);
 | 
			
		||||
	}
 | 
			
		||||
	errno = serrno;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,13 +23,13 @@
 | 
			
		||||
static bool
 | 
			
		||||
pid_is_exec(pid_t pid, const char *exec)
 | 
			
		||||
{
 | 
			
		||||
	char buffer[32];
 | 
			
		||||
	char *buffer = NULL;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	int c;
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
 | 
			
		||||
	exec = basename_c(exec);
 | 
			
		||||
	snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
 | 
			
		||||
	xasprintf(&buffer, "/proc/%d/stat", pid);
 | 
			
		||||
	if ((fp = fopen(buffer, "r"))) {
 | 
			
		||||
		while ((c = getc(fp)) != EOF && c != '(')
 | 
			
		||||
			;
 | 
			
		||||
@@ -41,23 +41,27 @@ pid_is_exec(pid_t pid, const char *exec)
 | 
			
		||||
		}
 | 
			
		||||
		fclose(fp);
 | 
			
		||||
	}
 | 
			
		||||
	free(buffer);
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
pid_is_argv(pid_t pid, const char *const *argv)
 | 
			
		||||
{
 | 
			
		||||
	char cmdline[32];
 | 
			
		||||
	char *cmdline = NULL;
 | 
			
		||||
	int fd;
 | 
			
		||||
	char buffer[PATH_MAX];
 | 
			
		||||
	char *p;
 | 
			
		||||
	ssize_t bytes;
 | 
			
		||||
 | 
			
		||||
	snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
 | 
			
		||||
	if ((fd = open(cmdline, O_RDONLY)) < 0)
 | 
			
		||||
	xasprintf(&cmdline, "/proc/%u/cmdline", pid);
 | 
			
		||||
	if ((fd = open(cmdline, O_RDONLY)) < 0) {
 | 
			
		||||
		free(cmdline);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	bytes = read(fd, buffer, sizeof(buffer));
 | 
			
		||||
	close(fd);
 | 
			
		||||
	free(cmdline);
 | 
			
		||||
	if (bytes == -1)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
@@ -88,7 +92,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
 | 
			
		||||
	char proc_ns[30];
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	pid_t p;
 | 
			
		||||
	char buffer[PATH_MAX];
 | 
			
		||||
	char *buffer = NULL;
 | 
			
		||||
	struct stat sb;
 | 
			
		||||
	pid_t openrc_pid = 0;
 | 
			
		||||
	char *pp;
 | 
			
		||||
@@ -149,18 +153,22 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (pid != 0 && pid != p)
 | 
			
		||||
			continue;
 | 
			
		||||
		snprintf(buffer, sizeof(buffer), "/proc/%d/ns/pid", p);
 | 
			
		||||
		xasprintf(&buffer, "/proc/%d/ns/pid", p);
 | 
			
		||||
		if (exists(buffer)) {
 | 
			
		||||
			rc = readlink(buffer, proc_ns, sizeof(proc_ns));
 | 
			
		||||
			if (rc <= 0)
 | 
			
		||||
				proc_ns[0] = '\0';
 | 
			
		||||
		}
 | 
			
		||||
		if (strcmp(my_ns, proc_ns))
 | 
			
		||||
		free(buffer);
 | 
			
		||||
		if (strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns))
 | 
			
		||||
			continue;
 | 
			
		||||
		if (uid) {
 | 
			
		||||
			snprintf(buffer, sizeof(buffer), "/proc/%d", p);
 | 
			
		||||
			if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
 | 
			
		||||
			xasprintf(&buffer, "/proc/%d", p);
 | 
			
		||||
			if (stat(buffer, &sb) != 0 || sb.st_uid != uid) {
 | 
			
		||||
				free(buffer);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			free(buffer);
 | 
			
		||||
		}
 | 
			
		||||
		if (exec && !pid_is_exec(p, exec))
 | 
			
		||||
			continue;
 | 
			
		||||
@@ -169,9 +177,10 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
 | 
			
		||||
			continue;
 | 
			
		||||
		/* If this is an OpenVZ host, filter out container processes */
 | 
			
		||||
		if (openvz_host) {
 | 
			
		||||
			snprintf(buffer, sizeof(buffer), "/proc/%d/status", p);
 | 
			
		||||
			xasprintf(&buffer, "/proc/%d/status", p);
 | 
			
		||||
			if (exists(buffer)) {
 | 
			
		||||
				fp = fopen(buffer, "r");
 | 
			
		||||
				free(buffer);
 | 
			
		||||
				if (! fp)
 | 
			
		||||
					continue;
 | 
			
		||||
				while (! feof(fp)) {
 | 
			
		||||
@@ -315,12 +324,13 @@ _match_daemon(const char *path, const char *file, RC_STRINGLIST *match)
 | 
			
		||||
{
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	char ffile[PATH_MAX];
 | 
			
		||||
	char *ffile = NULL;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	RC_STRING *m;
 | 
			
		||||
 | 
			
		||||
	snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
 | 
			
		||||
	xasprintf(&ffile, "%s/%s", path, file);
 | 
			
		||||
	fp = fopen(ffile, "r");
 | 
			
		||||
	free(ffile);
 | 
			
		||||
 | 
			
		||||
	if (!fp)
 | 
			
		||||
		return false;
 | 
			
		||||
@@ -346,29 +356,22 @@ _match_list(const char *exec, const char *const *argv, const char *pidfile)
 | 
			
		||||
{
 | 
			
		||||
	RC_STRINGLIST *match = rc_stringlist_new();
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	size_t l;
 | 
			
		||||
	char *m;
 | 
			
		||||
 | 
			
		||||
	if (exec) {
 | 
			
		||||
		l = strlen(exec) + 6;
 | 
			
		||||
		m = xmalloc(sizeof(char) * l);
 | 
			
		||||
		snprintf(m, l, "exec=%s", exec);
 | 
			
		||||
		xasprintf(&m, "exec=%s", exec);
 | 
			
		||||
		rc_stringlist_add(match, m);
 | 
			
		||||
		free(m);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (argv && argv[i]) {
 | 
			
		||||
		l = strlen(*argv) + strlen("argv_=") + 16;
 | 
			
		||||
		m = xmalloc(sizeof(char) * l);
 | 
			
		||||
		snprintf(m, l, "argv_0=%s", argv[i++]);
 | 
			
		||||
		xasprintf(&m, "argv_0=%s", argv[i++]);
 | 
			
		||||
		rc_stringlist_add(match, m);
 | 
			
		||||
		free(m);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pidfile) {
 | 
			
		||||
		l = strlen(pidfile) + 9;
 | 
			
		||||
		m = xmalloc(sizeof(char) * l);
 | 
			
		||||
		snprintf(m, l, "pidfile=%s", pidfile);
 | 
			
		||||
		xasprintf(&m, "pidfile=%s", pidfile);
 | 
			
		||||
		rc_stringlist_add(match, m);
 | 
			
		||||
		free(m);
 | 
			
		||||
	}
 | 
			
		||||
@@ -381,8 +384,8 @@ rc_service_daemon_set(const char *service, const char *exec,
 | 
			
		||||
    const char *const *argv,
 | 
			
		||||
    const char *pidfile, bool started)
 | 
			
		||||
{
 | 
			
		||||
	char dirpath[PATH_MAX];
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	char *dirpath = NULL;
 | 
			
		||||
	char *file = NULL;
 | 
			
		||||
	int nfiles = 0;
 | 
			
		||||
	char oldfile[PATH_MAX] = { '\0' };
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
@@ -397,8 +400,7 @@ rc_service_daemon_set(const char *service, const char *exec,
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
 | 
			
		||||
	    basename_c(service));
 | 
			
		||||
	xasprintf(&dirpath, RC_SVCDIR "/daemons/%s", basename_c(service));
 | 
			
		||||
 | 
			
		||||
	/* Regardless, erase any existing daemon info */
 | 
			
		||||
	if ((dp = opendir(dirpath))) {
 | 
			
		||||
@@ -407,8 +409,7 @@ rc_service_daemon_set(const char *service, const char *exec,
 | 
			
		||||
			if (d->d_name[0] == '.')
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			snprintf(file, sizeof(file), "%s/%s",
 | 
			
		||||
			    dirpath, d->d_name);
 | 
			
		||||
			xasprintf(&file, "%s/%s", dirpath, d->d_name);
 | 
			
		||||
			nfiles++;
 | 
			
		||||
 | 
			
		||||
			if (!*oldfile) {
 | 
			
		||||
@@ -421,6 +422,7 @@ rc_service_daemon_set(const char *service, const char *exec,
 | 
			
		||||
				rename(file, oldfile);
 | 
			
		||||
				strlcpy(oldfile, file, sizeof(oldfile));
 | 
			
		||||
			}
 | 
			
		||||
			free(file);
 | 
			
		||||
		}
 | 
			
		||||
		closedir(dp);
 | 
			
		||||
		rc_stringlist_free(match);
 | 
			
		||||
@@ -429,8 +431,7 @@ rc_service_daemon_set(const char *service, const char *exec,
 | 
			
		||||
	/* Now store our daemon info */
 | 
			
		||||
	if (started) {
 | 
			
		||||
		if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
 | 
			
		||||
			snprintf(file, sizeof(file), "%s/%03d",
 | 
			
		||||
			    dirpath, nfiles + 1);
 | 
			
		||||
			xasprintf(&file, "%s/%03d", dirpath, nfiles + 1);
 | 
			
		||||
			if ((fp = fopen(file, "w"))) {
 | 
			
		||||
				fprintf(fp, "exec=");
 | 
			
		||||
				if (exec)
 | 
			
		||||
@@ -446,10 +447,12 @@ rc_service_daemon_set(const char *service, const char *exec,
 | 
			
		||||
				fclose(fp);
 | 
			
		||||
				retval = true;
 | 
			
		||||
			}
 | 
			
		||||
			free(file);
 | 
			
		||||
		}
 | 
			
		||||
	} else
 | 
			
		||||
		retval = true;
 | 
			
		||||
 | 
			
		||||
	free(dirpath);
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
librc_hidden_def(rc_service_daemon_set)
 | 
			
		||||
@@ -458,8 +461,8 @@ bool
 | 
			
		||||
rc_service_started_daemon(const char *service,
 | 
			
		||||
    const char *exec, const char *const *argv, int indx)
 | 
			
		||||
{
 | 
			
		||||
	char dirpath[PATH_MAX];
 | 
			
		||||
	char file[16];
 | 
			
		||||
	char *dirpath = NULL;
 | 
			
		||||
	char *file = NULL;
 | 
			
		||||
	RC_STRINGLIST *match;
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
	DIR *dp;
 | 
			
		||||
@@ -468,13 +471,13 @@ rc_service_started_daemon(const char *service,
 | 
			
		||||
	if (!service || !exec)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
 | 
			
		||||
	    basename_c(service));
 | 
			
		||||
	xasprintf(&dirpath, RC_SVCDIR "/daemons/%s", basename_c(service));
 | 
			
		||||
	match = _match_list(exec, argv, NULL);
 | 
			
		||||
 | 
			
		||||
	if (indx > 0) {
 | 
			
		||||
		snprintf(file, sizeof(file), "%03d", indx);
 | 
			
		||||
		xasprintf(&file, "%03d", indx);
 | 
			
		||||
		retval = _match_daemon(dirpath, file, match);
 | 
			
		||||
		free(file);
 | 
			
		||||
	} else {
 | 
			
		||||
		if ((dp = opendir(dirpath))) {
 | 
			
		||||
			while ((d = readdir(dp))) {
 | 
			
		||||
@@ -489,6 +492,7 @@ rc_service_started_daemon(const char *service,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc_stringlist_free(match);
 | 
			
		||||
	free(dirpath);
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
librc_hidden_def(rc_service_started_daemon)
 | 
			
		||||
 
 | 
			
		||||
@@ -542,52 +542,41 @@ 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
 | 
			
		||||
mtime_check(const char *source, const char *target, bool newer,
 | 
			
		||||
deep_mtime_check(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 (mtime < buf.st_mtime) {
 | 
			
		||||
			if (rel == NULL)
 | 
			
		||||
				return false;
 | 
			
		||||
		if (*rel < buf.st_mtime) {
 | 
			
		||||
			retval = false;
 | 
			
		||||
		}
 | 
			
		||||
		if (rel != NULL) {
 | 
			
		||||
			if (*rel < buf.st_mtime) {
 | 
			
		||||
				if (file)
 | 
			
		||||
					strlcpy(file, target, PATH_MAX);
 | 
			
		||||
				*rel = buf.st_mtime;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (file)
 | 
			
		||||
				strlcpy(file, target, PATH_MAX);
 | 
			
		||||
			*rel = buf.st_mtime;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (mtime > buf.st_mtime) {
 | 
			
		||||
			if (rel == NULL)
 | 
			
		||||
				return false;
 | 
			
		||||
		if (*rel > buf.st_mtime) {
 | 
			
		||||
			retval = false;
 | 
			
		||||
		}
 | 
			
		||||
		if (rel != NULL) {
 | 
			
		||||
			if (*rel > buf.st_mtime) {
 | 
			
		||||
				if (file)
 | 
			
		||||
					strlcpy(file, target, PATH_MAX);
 | 
			
		||||
				*rel = buf.st_mtime;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (file)
 | 
			
		||||
				strlcpy(file, target, PATH_MAX);
 | 
			
		||||
			*rel = buf.st_mtime;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -602,16 +591,38 @@ mtime_check(const char *source, const char *target, bool newer,
 | 
			
		||||
		if (d->d_name[0] == '.')
 | 
			
		||||
			continue;
 | 
			
		||||
		snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
 | 
			
		||||
		if (!mtime_check(source, path, newer, rel, file)) {
 | 
			
		||||
		if (!deep_mtime_check(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)
 | 
			
		||||
@@ -670,6 +681,8 @@ 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++)
 | 
			
		||||
@@ -677,42 +690,48 @@ 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 (!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;
 | 
			
		||||
	 * 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);
 | 
			
		||||
#ifdef RC_PKG_INITDIR
 | 
			
		||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR, newest, file))
 | 
			
		||||
		return true;
 | 
			
		||||
    newer |= !deep_mtime_check(RC_PKG_INITDIR,true,&mtime,file);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RC_PKG_CONFDIR
 | 
			
		||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR, newest, file))
 | 
			
		||||
		return true;
 | 
			
		||||
    newer |= !deep_mtime_check(RC_PKG_CONFDIR,true,&mtime,file);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RC_LOCAL_INITDIR
 | 
			
		||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR, newest, file))
 | 
			
		||||
		return true;
 | 
			
		||||
#ifdef RC_LOCAL_INITDIRs
 | 
			
		||||
    newer |= !deep_mtime_check(RC_LOCAL_INITDIR,true,&mtime,file);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RC_LOCAL_CONFDIR
 | 
			
		||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR, newest, file))
 | 
			
		||||
		return true;
 | 
			
		||||
    newer |= !deep_mtime_check(RC_LOCAL_CONFDIR,true,&mtime,file);
 | 
			
		||||
#endif
 | 
			
		||||
	if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONF, newest, file))
 | 
			
		||||
		return true;
 | 
			
		||||
    newer |= !deep_mtime_check(RC_CONF,true,&mtime,file);
 | 
			
		||||
 | 
			
		||||
	/* 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) {
 | 
			
		||||
		if (!rc_newer_than(RC_DEPTREE_CACHE, s->value, newest, file)) {
 | 
			
		||||
			newer = true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		newer |= !deep_mtime_check(s->value, true, &mtime, file);
 | 
			
		||||
	}
 | 
			
		||||
	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)
 | 
			
		||||
 
 | 
			
		||||
@@ -237,13 +237,9 @@ static void rc_config_set_value(RC_STRINGLIST *config, char *value)
 | 
			
		||||
		if (token[i] == '\n')
 | 
			
		||||
			token[i] = 0;
 | 
			
		||||
 | 
			
		||||
		i = strlen(entry) + strlen(token) + 2;
 | 
			
		||||
		newline = xmalloc(sizeof(char) * i);
 | 
			
		||||
		snprintf(newline, i, "%s=%s", entry, token);
 | 
			
		||||
		xasprintf(&newline, "%s=%s", entry, token);
 | 
			
		||||
	} else {
 | 
			
		||||
		i = strlen(entry) + 2;
 | 
			
		||||
		newline = xmalloc(sizeof(char) * i);
 | 
			
		||||
		snprintf(newline, i, "%s=", entry);
 | 
			
		||||
		xasprintf(&newline, "%s=", entry);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	replaced = false;
 | 
			
		||||
@@ -300,8 +296,7 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
 | 
			
		||||
 | 
			
		||||
		if (value != NULL) {
 | 
			
		||||
			len = varlen + strlen(value) + 2;
 | 
			
		||||
			tmp = xmalloc(sizeof(char) * len);
 | 
			
		||||
			snprintf(tmp, len, "%s=%s", override->value, value);
 | 
			
		||||
			xasprintf(&tmp, "%s=%s", override->value, value);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,7 @@ static const rc_service_state_name_t rc_service_state_names[] = {
 | 
			
		||||
	{ RC_SERVICE_HOTPLUGGED,  "hotplugged" },
 | 
			
		||||
	{ RC_SERVICE_FAILED,      "failed" },
 | 
			
		||||
	{ RC_SERVICE_SCHEDULED,   "scheduled"},
 | 
			
		||||
	{ RC_SERVICE_CRASHED,     "crashed"},
 | 
			
		||||
	{ 0, NULL}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -848,6 +849,10 @@ rc_service_state(const char *service)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (state & RC_SERVICE_STARTED) {
 | 
			
		||||
		if (rc_service_daemons_crashed(service) && errno != EACCES)
 | 
			
		||||
			state |= RC_SERVICE_CRASHED;
 | 
			
		||||
	}
 | 
			
		||||
	if (state & RC_SERVICE_STOPPED) {
 | 
			
		||||
		dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
 | 
			
		||||
		TAILQ_FOREACH(dir, dirs, entries) {
 | 
			
		||||
 
 | 
			
		||||
@@ -188,7 +188,8 @@ typedef enum
 | 
			
		||||
	/* Optional states service could also be in */
 | 
			
		||||
	RC_SERVICE_FAILED      = 0x0200,
 | 
			
		||||
	RC_SERVICE_SCHEDULED   = 0x0400,
 | 
			
		||||
	RC_SERVICE_WASINACTIVE = 0x0800
 | 
			
		||||
	RC_SERVICE_WASINACTIVE = 0x0800,
 | 
			
		||||
	RC_SERVICE_CRASHED     = 0x1000,
 | 
			
		||||
} RC_SERVICE;
 | 
			
		||||
 | 
			
		||||
/*! Add the service to the runlevel
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								src/rc/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/rc/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -56,6 +56,7 @@ mark_service_inactive
 | 
			
		||||
mark_service_wasinactive
 | 
			
		||||
mark_service_hotplugged
 | 
			
		||||
mark_service_failed
 | 
			
		||||
mark_service_crashed
 | 
			
		||||
rc-abort
 | 
			
		||||
rc
 | 
			
		||||
openrc
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@ include ${MK}/os.mk
 | 
			
		||||
SRCS=	checkpath.c do_e.c do_mark_service.c do_service.c \
 | 
			
		||||
		do_value.c fstabinfo.c is_newer_than.c is_older_than.c \
 | 
			
		||||
		mountinfo.c openrc-run.c rc-abort.c rc.c \
 | 
			
		||||
		rc-depend.c rc-logger.c rc-misc.c rc-plugin.c \
 | 
			
		||||
		rc-service.c rc-status.c rc-update.c \
 | 
			
		||||
		rc-depend.c rc-logger.c rc-misc.c rc-pipes.c \
 | 
			
		||||
		rc-plugin.c rc-service.c rc-status.c rc-update.c \
 | 
			
		||||
		shell_var.c start-stop-daemon.c supervise-daemon.c swclock.c _usage.c
 | 
			
		||||
 | 
			
		||||
ifeq (${MKSELINUX},yes)
 | 
			
		||||
@@ -41,6 +41,7 @@ RC_SBINPROGS=	mark_service_starting mark_service_started \
 | 
			
		||||
		mark_service_stopping mark_service_stopped \
 | 
			
		||||
		mark_service_inactive mark_service_wasinactive \
 | 
			
		||||
		mark_service_hotplugged mark_service_failed \
 | 
			
		||||
		mark_service_crashed \
 | 
			
		||||
		rc-abort swclock
 | 
			
		||||
 | 
			
		||||
ifeq (${OS},Linux)
 | 
			
		||||
@@ -123,7 +124,8 @@ is_older_than: is_older_than.o rc-misc.o
 | 
			
		||||
mark_service_starting mark_service_started \
 | 
			
		||||
mark_service_stopping mark_service_stopped \
 | 
			
		||||
mark_service_inactive mark_service_wasinactive \
 | 
			
		||||
mark_service_hotplugged mark_service_failed: do_mark_service.o rc-misc.o
 | 
			
		||||
mark_service_hotplugged mark_service_failed \
 | 
			
		||||
mark_service_crashed: do_mark_service.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
mountinfo: mountinfo.o _usage.o rc-misc.o
 | 
			
		||||
@@ -156,7 +158,7 @@ rc-service: rc-service.o _usage.o rc-misc.o
 | 
			
		||||
rc-update: rc-update.o _usage.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-schedules.o
 | 
			
		||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-pipes.o rc-schedules.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o
 | 
			
		||||
 
 | 
			
		||||
@@ -73,25 +73,32 @@ 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, flags;
 | 
			
		||||
	int fd;
 | 
			
		||||
	int flags;
 | 
			
		||||
	int r;
 | 
			
		||||
	int readfd;
 | 
			
		||||
	int readflags;
 | 
			
		||||
	int u;
 | 
			
		||||
 | 
			
		||||
	memset(&st, 0, sizeof(st));
 | 
			
		||||
	if (lstat(path, &st) || trunc) {
 | 
			
		||||
	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 (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);
 | 
			
		||||
@@ -99,7 +106,9 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
 | 
			
		||||
				eerror("%s: open: %s", applet, strerror(errno));
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
			close (fd);
 | 
			
		||||
			if (readfd != -1 && trunc)
 | 
			
		||||
				close(readfd);
 | 
			
		||||
			readfd = fd;
 | 
			
		||||
		} else if (type == inode_dir) {
 | 
			
		||||
			einfo("%s: creating directory", path);
 | 
			
		||||
			if (!mode) /* 775 */
 | 
			
		||||
@@ -113,7 +122,12 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
 | 
			
		||||
				    strerror (errno));
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
			mode = 0;
 | 
			
		||||
			readfd = open(path, readflags);
 | 
			
		||||
			if (readfd == -1) {
 | 
			
		||||
				eerror("%s: unable to open directory: %s", applet,
 | 
			
		||||
						strerror(errno));
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (type == inode_fifo) {
 | 
			
		||||
			einfo("%s: creating fifo", path);
 | 
			
		||||
			if (!mode) /* 600 */
 | 
			
		||||
@@ -126,56 +140,76 @@ 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;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
	}
 | 
			
		||||
	if (fstat(readfd, &st) != -1) {
 | 
			
		||||
		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);
 | 
			
		||||
			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 (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 (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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (selinux_on)
 | 
			
		||||
		selinux_util_label(path);
 | 
			
		||||
	close(readfd);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -235,11 +269,13 @@ int main(int argc, char **argv)
 | 
			
		||||
		switch (opt) {
 | 
			
		||||
		case 'D':
 | 
			
		||||
			trunc = true;
 | 
			
		||||
			/* falls through */
 | 
			
		||||
		case 'd':
 | 
			
		||||
			type = inode_dir;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'F':
 | 
			
		||||
			trunc = true;
 | 
			
		||||
			/* falls through */
 | 
			
		||||
		case 'f':
 | 
			
		||||
			type = inode_file;
 | 
			
		||||
			break;
 | 
			
		||||
 
 | 
			
		||||
@@ -68,9 +68,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		ok = rc_service_started_daemon(service, exec, NULL, idx);
 | 
			
		||||
 | 
			
		||||
	} else if (strcmp(applet, "service_crashed") == 0) {
 | 
			
		||||
		ok = (_rc_can_find_pids() &&
 | 
			
		||||
		    rc_service_daemons_crashed(service) &&
 | 
			
		||||
		    errno != EACCES);
 | 
			
		||||
		ok = ( rc_service_daemons_crashed(service) && errno != EACCES);
 | 
			
		||||
	} else
 | 
			
		||||
		eerrorx("%s: unknown applet", applet);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -141,7 +141,7 @@ do_mount(struct ENT *ent, bool remount)
 | 
			
		||||
		/* NOTREACHED */
 | 
			
		||||
	case 0:
 | 
			
		||||
		execvp(argv[0], argv);
 | 
			
		||||
		eerror("%s: execv: %s", applet, strerror(errno));
 | 
			
		||||
		eerror("%s: execvp: %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 */
 | 
			
		||||
			execl("mount", "mount", "-t", "proc", "proc", "/proc", NULL);
 | 
			
		||||
			execlp("mount", "mount", "-t", "proc", "proc", "/proc", NULL);
 | 
			
		||||
			syslog(LOG_ERR, "Unable to execute mount");
 | 
			
		||||
			exit(1);
 | 
			
		||||
			break;
 | 
			
		||||
@@ -87,10 +87,11 @@ static int mount_proc(void)
 | 
			
		||||
 | 
			
		||||
static bool is_user_process(pid_t pid)
 | 
			
		||||
{
 | 
			
		||||
	char buf[PATH_MAX+1];
 | 
			
		||||
	char *buf = NULL;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char path[PATH_MAX+1];
 | 
			
		||||
	char *path = NULL;
 | 
			
		||||
	pid_t temp_pid;
 | 
			
		||||
	size_t size;
 | 
			
		||||
	bool user_process = true;
 | 
			
		||||
 | 
			
		||||
	while (pid >0 && user_process) {
 | 
			
		||||
@@ -98,8 +99,9 @@ static bool is_user_process(pid_t pid)
 | 
			
		||||
			user_process = false;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		snprintf(path, sizeof(path), "/proc/%d/status", pid);
 | 
			
		||||
		xasprintf(&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
 | 
			
		||||
@@ -112,11 +114,14 @@ static bool is_user_process(pid_t pid)
 | 
			
		||||
		}
 | 
			
		||||
		temp_pid = -1;
 | 
			
		||||
		while (! feof(fp)) {
 | 
			
		||||
			buf[0] = 0;
 | 
			
		||||
			if (fgets(buf, sizeof(buf), fp))
 | 
			
		||||
			buf = NULL;
 | 
			
		||||
			if (getline(&buf, &size, fp) != -1) {
 | 
			
		||||
				sscanf(buf, "PPid: %d", &temp_pid);
 | 
			
		||||
			else
 | 
			
		||||
				free(buf);
 | 
			
		||||
			} else {
 | 
			
		||||
				free(buf);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		fclose(fp);
 | 
			
		||||
		if (temp_pid == -1) {
 | 
			
		||||
@@ -135,7 +140,7 @@ static int signal_processes(int sig, RC_STRINGLIST *omits, bool dryrun)
 | 
			
		||||
	sigset_t oldsigs;
 | 
			
		||||
	DIR *dir;
 | 
			
		||||
	struct dirent	*d;
 | 
			
		||||
	char buf[PATH_MAX+1];
 | 
			
		||||
	char *buf = NULL;
 | 
			
		||||
	pid_t pid;
 | 
			
		||||
	int sendcount = 0;
 | 
			
		||||
 | 
			
		||||
@@ -170,7 +175,11 @@ static int signal_processes(int sig, RC_STRINGLIST *omits, bool dryrun)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* Is this a process we have been requested to omit? */
 | 
			
		||||
		sprintf(buf, "%d", pid);
 | 
			
		||||
		if (buf) {
 | 
			
		||||
			free(buf);
 | 
			
		||||
			buf = NULL;
 | 
			
		||||
		}
 | 
			
		||||
		xasprintf(&buf, "%d", pid);
 | 
			
		||||
		if (rc_stringlist_find(omits, buf))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -248,7 +248,6 @@ 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));
 | 
			
		||||
@@ -264,11 +263,7 @@ find_mounts(struct args *args)
 | 
			
		||||
				if (! options)
 | 
			
		||||
					options = xstrdup(o->o_name);
 | 
			
		||||
				else {
 | 
			
		||||
					l = strlen(options) +
 | 
			
		||||
					    strlen(o->o_name) + 2;
 | 
			
		||||
					tmp = xmalloc(sizeof (char) * l);
 | 
			
		||||
					snprintf(tmp, l, "%s,%s", options,
 | 
			
		||||
					    o->o_name);
 | 
			
		||||
					xasprintf(&tmp, "%s,%s", options, o->o_name);
 | 
			
		||||
					free(options);
 | 
			
		||||
					options = tmp;
 | 
			
		||||
				}
 | 
			
		||||
@@ -315,6 +310,7 @@ find_mounts(struct args *args)
 | 
			
		||||
{
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char *buffer;
 | 
			
		||||
	size_t size;
 | 
			
		||||
	char *p;
 | 
			
		||||
	char *from;
 | 
			
		||||
	char *to;
 | 
			
		||||
@@ -329,8 +325,8 @@ find_mounts(struct args *args)
 | 
			
		||||
 | 
			
		||||
	list = rc_stringlist_new();
 | 
			
		||||
 | 
			
		||||
	buffer = xmalloc(sizeof(char) * PATH_MAX * 3);
 | 
			
		||||
	while (fgets(buffer, PATH_MAX * 3, fp)) {
 | 
			
		||||
	buffer = NULL;
 | 
			
		||||
	while (getline(&buffer, &size, fp) != -1) {
 | 
			
		||||
		netdev = -1;
 | 
			
		||||
		p = buffer;
 | 
			
		||||
		from = strsep(&p, " ");
 | 
			
		||||
@@ -346,6 +342,8 @@ find_mounts(struct args *args)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		process_mount(list, args, from, to, fst, opts, netdev);
 | 
			
		||||
		free(buffer);
 | 
			
		||||
		buffer = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	free(buffer);
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
@@ -380,7 +378,7 @@ int main(int argc, char **argv)
 | 
			
		||||
	regex_t *skip_point_regex = NULL;
 | 
			
		||||
	RC_STRINGLIST *nodes;
 | 
			
		||||
	RC_STRING *s;
 | 
			
		||||
	char real_path[PATH_MAX + 1];
 | 
			
		||||
	char *real_path = NULL;
 | 
			
		||||
	int opt;
 | 
			
		||||
	int result;
 | 
			
		||||
	char *this_path;
 | 
			
		||||
@@ -450,9 +448,12 @@ int main(int argc, char **argv)
 | 
			
		||||
			eerrorx("%s: `%s' is not a mount point",
 | 
			
		||||
			    argv[0], argv[optind]);
 | 
			
		||||
		this_path = argv[optind++];
 | 
			
		||||
		if (realpath(this_path, real_path))
 | 
			
		||||
		real_path = realpath(this_path, NULL);
 | 
			
		||||
		if (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,6 +35,7 @@
 | 
			
		||||
#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)
 | 
			
		||||
@@ -53,7 +54,7 @@ static pid_t do_openrc(const char *runlevel)
 | 
			
		||||
			sigemptyset(&signals);
 | 
			
		||||
			sigprocmask(SIG_SETMASK, &signals, NULL);
 | 
			
		||||
			printf("Starting %s runlevel\n", runlevel);
 | 
			
		||||
			execl("/sbin/openrc", "/sbin/openrc", runlevel, NULL);
 | 
			
		||||
			execlp("openrc", "openrc", runlevel, NULL);
 | 
			
		||||
			perror("exec");
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
@@ -88,7 +89,7 @@ static void init(const char *default_runlevel)
 | 
			
		||||
 | 
			
		||||
static void handle_reexec(char *my_name)
 | 
			
		||||
{
 | 
			
		||||
	execl(my_name, my_name, "reexec", NULL);
 | 
			
		||||
	execlp(my_name, my_name, "reexec", NULL);
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -183,6 +184,9 @@ 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[10] = { '\0' };
 | 
			
		||||
	char *signame = NULL;
 | 
			
		||||
	struct winsize ws;
 | 
			
		||||
 | 
			
		||||
	switch (sig) {
 | 
			
		||||
@@ -134,20 +134,22 @@ handle_signal(int sig)
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case SIGINT:
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGINT");
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGINT");
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	case SIGTERM:
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGTERM");
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGTERM");
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	case SIGQUIT:
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGQUIT");
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGQUIT");
 | 
			
		||||
		/* Send the signal to our children too */
 | 
			
		||||
		if (service_pid > 0)
 | 
			
		||||
			kill(service_pid, sig);
 | 
			
		||||
		eerrorx("%s: caught %s, aborting", applet, signame);
 | 
			
		||||
		eerror("%s: caught %s, aborting", applet, signame);
 | 
			
		||||
		free(signame);
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
		/* NOTREACHED */
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
@@ -161,11 +163,12 @@ handle_signal(int sig)
 | 
			
		||||
static void
 | 
			
		||||
unhotplug()
 | 
			
		||||
{
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	char *file = NULL;
 | 
			
		||||
 | 
			
		||||
	snprintf(file, sizeof(file), RC_SVCDIR "/hotplugged/%s", applet);
 | 
			
		||||
	xasprintf(&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
 | 
			
		||||
@@ -485,7 +488,7 @@ svc_exec(const char *arg1, const char *arg2)
 | 
			
		||||
static bool
 | 
			
		||||
svc_wait(const char *svc)
 | 
			
		||||
{
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	char *file = NULL;
 | 
			
		||||
	int fd;
 | 
			
		||||
	bool forever = false;
 | 
			
		||||
	RC_STRINGLIST *keywords;
 | 
			
		||||
@@ -498,8 +501,7 @@ svc_wait(const char *svc)
 | 
			
		||||
		forever = true;
 | 
			
		||||
	rc_stringlist_free(keywords);
 | 
			
		||||
 | 
			
		||||
	snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s",
 | 
			
		||||
	    basename_c(svc));
 | 
			
		||||
	xasprintf(&file, RC_SVCDIR "/exclusive/%s", basename_c(svc));
 | 
			
		||||
 | 
			
		||||
	interval.tv_sec = 0;
 | 
			
		||||
	interval.tv_nsec = WAIT_INTERVAL;
 | 
			
		||||
@@ -512,23 +514,29 @@ 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)
 | 
			
		||||
		if (errno == ENOENT) {
 | 
			
		||||
			free(file);
 | 
			
		||||
			return true;
 | 
			
		||||
		if (errno != EWOULDBLOCK)
 | 
			
		||||
			eerrorx("%s: open `%s': %s", applet, file,
 | 
			
		||||
		}
 | 
			
		||||
		if (errno != EWOULDBLOCK) {
 | 
			
		||||
			eerror("%s: open `%s': %s", applet, file,
 | 
			
		||||
			    strerror(errno));
 | 
			
		||||
			free(file);
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
		}
 | 
			
		||||
		if (nanosleep(&interval, NULL) == -1) {
 | 
			
		||||
			if (errno != EINTR)
 | 
			
		||||
				return false;
 | 
			
		||||
				goto finish;
 | 
			
		||||
		}
 | 
			
		||||
		if (!forever) {
 | 
			
		||||
			timespecsub(&timeout, &interval, &timeout);
 | 
			
		||||
			if (timeout.tv_sec <= 0)
 | 
			
		||||
				return false;
 | 
			
		||||
				goto finish;
 | 
			
		||||
			timespecsub(&warn, &interval, &warn);
 | 
			
		||||
			if (warn.tv_sec <= 0) {
 | 
			
		||||
				ewarn("%s: waiting for %s (%d seconds)",
 | 
			
		||||
@@ -538,6 +546,8 @@ svc_wait(const char *svc)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
finish:
 | 
			
		||||
	free(file);
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1105,9 +1115,10 @@ int main(int argc, char **argv)
 | 
			
		||||
	bool runscript = false;
 | 
			
		||||
	int retval, opt, depoptions = RC_DEP_TRACE;
 | 
			
		||||
	RC_STRING *svc;
 | 
			
		||||
	char path[PATH_MAX], lnk[PATH_MAX];
 | 
			
		||||
	char *path = NULL;
 | 
			
		||||
	char *lnk = NULL;
 | 
			
		||||
	char *dir, *save = NULL, *saveLnk = NULL;
 | 
			
		||||
	char pidstr[10];
 | 
			
		||||
	char *pidstr = NULL;
 | 
			
		||||
	size_t l = 0, ll;
 | 
			
		||||
 	const char *file;
 | 
			
		||||
	struct stat stbuf;
 | 
			
		||||
@@ -1134,12 +1145,14 @@ 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. */
 | 
			
		||||
	if (!realpath(argv[1], path)) {
 | 
			
		||||
	path = realpath(argv[1], NULL);
 | 
			
		||||
	if (!path) {
 | 
			
		||||
		fprintf(stderr, "realpath: %s\n", strerror(errno));
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
	memset(lnk, 0, sizeof(lnk));
 | 
			
		||||
	if (readlink(argv[1], lnk, sizeof(lnk)-1)) {
 | 
			
		||||
	lnk = xmalloc(4096);
 | 
			
		||||
	memset(lnk, 0, 4096);
 | 
			
		||||
	if (readlink(argv[1], lnk, 4096)) {
 | 
			
		||||
		dir = dirname(path);
 | 
			
		||||
		if (strchr(lnk, '/')) {
 | 
			
		||||
			save = xstrdup(dir);
 | 
			
		||||
@@ -1153,8 +1166,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		} else
 | 
			
		||||
			file = basename_c(argv[1]);
 | 
			
		||||
		ll = strlen(dir) + strlen(file) + 2;
 | 
			
		||||
		service = xmalloc(ll);
 | 
			
		||||
		snprintf(service, ll, "%s/%s", dir, file);
 | 
			
		||||
		xasprintf(&service, "%s/%s", dir, file);
 | 
			
		||||
		if (stat(service, &stbuf) != 0) {
 | 
			
		||||
			free(service);
 | 
			
		||||
			service = xstrdup(lnk);
 | 
			
		||||
@@ -1162,6 +1174,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		free(save);
 | 
			
		||||
		free(saveLnk);
 | 
			
		||||
	}
 | 
			
		||||
	free(lnk);
 | 
			
		||||
	if (!service)
 | 
			
		||||
		service = xstrdup(path);
 | 
			
		||||
	applet = basename_c(service);
 | 
			
		||||
@@ -1185,7 +1198,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 */
 | 
			
		||||
	snprintf(pidstr, sizeof(pidstr), "%d", (int) getpid());
 | 
			
		||||
	xasprintf(&pidstr, "%d", (int) getpid());
 | 
			
		||||
	setenv("RC_OPENRC_PID", pidstr, 1);
 | 
			
		||||
	/*
 | 
			
		||||
	 * RC_RUNSCRIPT_PID is deprecated, but we will keep it for a while
 | 
			
		||||
@@ -1255,6 +1268,9 @@ int main(int argc, char **argv)
 | 
			
		||||
		case_RC_COMMON_GETOPT
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if (rc_yesno(getenv("RC_NODEPS")))
 | 
			
		||||
		deps = false;
 | 
			
		||||
 | 
			
		||||
	/* If we're changing runlevels and not called by rc then we cannot
 | 
			
		||||
	   work with any dependencies */
 | 
			
		||||
	if (deps && getenv("RC_PID") == NULL &&
 | 
			
		||||
@@ -1269,6 +1285,8 @@ int main(int argc, char **argv)
 | 
			
		||||
		unsetenv("IN_BACKGROUND");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (rc_yesno(getenv("IN_DRYRUN")))
 | 
			
		||||
	dry_run = true;
 | 
			
		||||
	if (rc_yesno(getenv("IN_HOTPLUG"))) {
 | 
			
		||||
		if (!service_plugable())
 | 
			
		||||
			eerrorx("%s: not allowed to be hotplugged", applet);
 | 
			
		||||
 
 | 
			
		||||
@@ -87,6 +87,8 @@ write_log(int logfd, const char *buffer, size_t bytes)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!in_escape) {
 | 
			
		||||
			if (!isprint((int) *p) && *p != '\n')
 | 
			
		||||
				goto cont;
 | 
			
		||||
			if (write(logfd, p++, 1) == -1)
 | 
			
		||||
				eerror("write: %s", strerror(errno));
 | 
			
		||||
			continue;
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,8 @@ rc_conf_yesno(const char *setting)
 | 
			
		||||
 | 
			
		||||
static const char *const env_whitelist[] = {
 | 
			
		||||
	"EERROR_QUIET", "EINFO_QUIET",
 | 
			
		||||
	"IN_BACKGROUND", "IN_HOTPLUG",
 | 
			
		||||
	"IN_BACKGROUND", "IN_DRYRUN", "IN_HOTPLUG",
 | 
			
		||||
	"RC_DEBUG", "RC_NODEPS",
 | 
			
		||||
	"LANG", "LC_MESSAGES", "TERM",
 | 
			
		||||
	"EINFO_COLOR", "EINFO_VERBOSE",
 | 
			
		||||
	NULL
 | 
			
		||||
@@ -131,7 +132,8 @@ env_config(void)
 | 
			
		||||
	char *npp;
 | 
			
		||||
	char *tok;
 | 
			
		||||
	const char *sys = rc_sys();
 | 
			
		||||
	char buffer[PATH_MAX];
 | 
			
		||||
	char *buffer = NULL;
 | 
			
		||||
	size_t size = 0;
 | 
			
		||||
 | 
			
		||||
	/* Ensure our PATH is prefixed with the system locations first
 | 
			
		||||
	   for a little extra security */
 | 
			
		||||
@@ -170,8 +172,7 @@ env_config(void)
 | 
			
		||||
	free(e);
 | 
			
		||||
 | 
			
		||||
	if ((fp = fopen(RC_KRUNLEVEL, "r"))) {
 | 
			
		||||
		memset(buffer, 0, sizeof (buffer));
 | 
			
		||||
		if (fgets(buffer, sizeof (buffer), fp)) {
 | 
			
		||||
		if (getline(&buffer, &size, fp) != -1) {
 | 
			
		||||
			l = strlen (buffer) - 1;
 | 
			
		||||
			if (buffer[l] == '\n')
 | 
			
		||||
				buffer[l] = 0;
 | 
			
		||||
@@ -181,6 +182,7 @@ env_config(void)
 | 
			
		||||
	} else
 | 
			
		||||
		setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1);
 | 
			
		||||
 | 
			
		||||
	free(buffer);
 | 
			
		||||
	if (sys)
 | 
			
		||||
		setenv("RC_SYS", sys, 1);
 | 
			
		||||
 | 
			
		||||
@@ -232,11 +234,12 @@ signal_setup_restart(int sig, void (*handler)(int))
 | 
			
		||||
int
 | 
			
		||||
svc_lock(const char *applet)
 | 
			
		||||
{
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	char *file = NULL;
 | 
			
		||||
	int fd;
 | 
			
		||||
 | 
			
		||||
	snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s", applet);
 | 
			
		||||
	xasprintf(&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) {
 | 
			
		||||
@@ -250,11 +253,12 @@ svc_lock(const char *applet)
 | 
			
		||||
int
 | 
			
		||||
svc_unlock(const char *applet, int fd)
 | 
			
		||||
{
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	char *file = NULL;
 | 
			
		||||
 | 
			
		||||
	snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s", applet);
 | 
			
		||||
	xasprintf(&file, RC_SVCDIR "/exclusive/%s", applet);
 | 
			
		||||
	close(fd);
 | 
			
		||||
	unlink(file);
 | 
			
		||||
	free(file);
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -358,7 +362,7 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
	int merrno;
 | 
			
		||||
	time_t t;
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	char *file = NULL;
 | 
			
		||||
	struct stat st;
 | 
			
		||||
	struct utimbuf ut;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
@@ -380,7 +384,10 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
 | 
			
		||||
		eend (retval, "Failed to update the dependency tree");
 | 
			
		||||
 | 
			
		||||
		if (retval == 0) {
 | 
			
		||||
			stat(RC_DEPTREE_CACHE, &st);
 | 
			
		||||
			if (stat(RC_DEPTREE_CACHE, &st) != 0) {
 | 
			
		||||
				eerror("stat(%s): %s", RC_DEPTREE_CACHE, strerror(errno));
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
			if (st.st_mtime < t) {
 | 
			
		||||
				eerror("Clock skew detected with `%s'", file);
 | 
			
		||||
				eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
 | 
			
		||||
@@ -404,34 +411,6 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
 | 
			
		||||
	return rc_deptree_load();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool _rc_can_find_pids(void)
 | 
			
		||||
{
 | 
			
		||||
	RC_PIDLIST *pids;
 | 
			
		||||
	RC_PID *pid;
 | 
			
		||||
	RC_PID *pid2;
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
 | 
			
		||||
	if (geteuid() == 0)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	/* If we cannot see process 1, then we don't test to see if
 | 
			
		||||
	 * services crashed or not */
 | 
			
		||||
	pids = rc_find_pids(NULL, NULL, 0, 1);
 | 
			
		||||
	if (pids) {
 | 
			
		||||
		pid = LIST_FIRST(pids);
 | 
			
		||||
		if (pid) {
 | 
			
		||||
			retval = true;
 | 
			
		||||
			while (pid) {
 | 
			
		||||
				pid2 = LIST_NEXT(pid, entries);
 | 
			
		||||
				free(pid);
 | 
			
		||||
				pid = pid2;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		free(pids);
 | 
			
		||||
	}
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct {
 | 
			
		||||
	const char * const name;
 | 
			
		||||
	RC_SERVICE bit;
 | 
			
		||||
@@ -444,6 +423,7 @@ static const struct {
 | 
			
		||||
	{ "service_hotplugged",  RC_SERVICE_HOTPLUGGED,  },
 | 
			
		||||
	{ "service_wasinactive", RC_SERVICE_WASINACTIVE, },
 | 
			
		||||
	{ "service_failed",      RC_SERVICE_FAILED,      },
 | 
			
		||||
	{ "service_crashed",     RC_SERVICE_CRASHED,     },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RC_SERVICE lookup_service_state(const char *service)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										56
									
								
								src/rc/rc-pipes.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/rc/rc-pipes.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
/*
 | 
			
		||||
 * rc-pipes.c
 | 
			
		||||
 * Helper to handle spawning processes and connecting them to pipes.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2018 The OpenRC Authors.
 | 
			
		||||
 * See the Authors file at the top-level directory of this distribution and
 | 
			
		||||
 * https://github.com/OpenRC/openrc/blob/master/AUTHORS
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of OpenRC. It is subject to the license terms in
 | 
			
		||||
 * the LICENSE file found in the top-level directory of this
 | 
			
		||||
 * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
 | 
			
		||||
 * This file may not be copied, modified, propagated, or distributed
 | 
			
		||||
 *    except according to the terms contained in the LICENSE file.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include "rc-pipes.h"
 | 
			
		||||
 | 
			
		||||
static const int pipe_read_end = 0;
 | 
			
		||||
static const int pipe_write_end = 1;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Starts a command with stdin redirected from a pipe
 | 
			
		||||
 * Returns the write end of the pipe or -1
 | 
			
		||||
 */
 | 
			
		||||
int rc_pipe_command(char *cmd)
 | 
			
		||||
{
 | 
			
		||||
	int pfd[2];
 | 
			
		||||
	pid_t pid;
 | 
			
		||||
 | 
			
		||||
	if (pipe(pfd) < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	pid = fork();
 | 
			
		||||
	if (pid > 0) {
 | 
			
		||||
		/* parent */
 | 
			
		||||
		close(pfd[pipe_read_end]);
 | 
			
		||||
		return pfd[pipe_write_end];
 | 
			
		||||
	} else if (pid == 0) {
 | 
			
		||||
		/* child */
 | 
			
		||||
		close(pfd[pipe_write_end]);
 | 
			
		||||
		if (pfd[pipe_read_end] != STDIN_FILENO) {
 | 
			
		||||
			if (dup2(pfd[pipe_read_end], STDIN_FILENO) < 0)
 | 
			
		||||
				exit(1);
 | 
			
		||||
			close(pfd[pipe_read_end]);
 | 
			
		||||
		}
 | 
			
		||||
		execl("/bin/sh", "sh", "-c", cmd, NULL);
 | 
			
		||||
		exit(1);
 | 
			
		||||
	}
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								src/rc/rc-pipes.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/rc/rc-pipes.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2018 The OpenRC Authors.
 | 
			
		||||
 * See the Authors file at the top-level directory of this distribution and
 | 
			
		||||
 * https://github.com/OpenRC/openrc/blob/master/AUTHORS
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of OpenRC. It is subject to the license terms in
 | 
			
		||||
 * the LICENSE file found in the top-level directory of this
 | 
			
		||||
 * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
 | 
			
		||||
 * This file may not be copied, modified, propagated, or distributed
 | 
			
		||||
 *    except according to the terms contained in the LICENSE file.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RC_PIPES_H
 | 
			
		||||
#define RC_PIPES_H
 | 
			
		||||
 | 
			
		||||
int rc_pipe_command(char *cmd);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -68,7 +68,7 @@ rc_plugin_load(void)
 | 
			
		||||
	DIR *dp;
 | 
			
		||||
	struct dirent *d;
 | 
			
		||||
	PLUGIN *plugin;
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	char *file = NULL;
 | 
			
		||||
	void *h;
 | 
			
		||||
	int (*fptr)(RC_HOOK, const char *);
 | 
			
		||||
 | 
			
		||||
@@ -85,8 +85,9 @@ rc_plugin_load(void)
 | 
			
		||||
		if (d->d_name[0] == '.')
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		snprintf(file, sizeof(file), RC_PLUGINDIR "/%s",  d->d_name);
 | 
			
		||||
		xasprintf(&file, RC_PLUGINDIR "/%s",  d->d_name);
 | 
			
		||||
		h = dlopen(file, RTLD_LAZY);
 | 
			
		||||
		free(file);
 | 
			
		||||
		if (h == NULL) {
 | 
			
		||||
			eerror("dlopen: %s", dlerror());
 | 
			
		||||
			continue;
 | 
			
		||||
 
 | 
			
		||||
@@ -307,6 +307,9 @@ int run_stop_schedule(const char *applet,
 | 
			
		||||
	const char *const *p;
 | 
			
		||||
	bool progressed = false;
 | 
			
		||||
 | 
			
		||||
	if (!(pid > 0 || exec || uid || (argv && *argv)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (exec)
 | 
			
		||||
		einfov("Will stop %s", exec);
 | 
			
		||||
	if (pid > 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -256,19 +256,19 @@ static int read_context_file(const char *filename, char **context)
 | 
			
		||||
{
 | 
			
		||||
	int ret = -1;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char filepath[PATH_MAX];
 | 
			
		||||
	char *filepath = NULL;
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	char *p;
 | 
			
		||||
	char *p2;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	ssize_t read;
 | 
			
		||||
 | 
			
		||||
	memset(filepath, '\0', PATH_MAX);
 | 
			
		||||
	snprintf(filepath, PATH_MAX - 1, "%s/%s", selinux_contexts_path(), filename);
 | 
			
		||||
	xasprintf(&filepath, "%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,6 +294,7 @@ static int read_context_file(const char *filename, char **context)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	free(line);
 | 
			
		||||
	free(filepath);
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,23 +29,33 @@
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "e:ilr:IN" getoptstring_COMMON;
 | 
			
		||||
const char *getoptstring = "cdDe:ilr:INsSZ" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "debug",     0, NULL, 'd' },
 | 
			
		||||
	{ "nodeps",     0, NULL, 'D' },
 | 
			
		||||
	{ "exists",   1, NULL, 'e' },
 | 
			
		||||
	{ "ifcrashed", 0, NULL, 'c' },
 | 
			
		||||
	{ "ifexists", 0, NULL, 'i' },
 | 
			
		||||
	{ "ifinactive", 0, NULL, 'I' },
 | 
			
		||||
	{ "ifnotstarted", 0, NULL, 'N' },
 | 
			
		||||
	{ "ifstarted", 0, NULL, 's' },
 | 
			
		||||
	{ "ifstopped", 0, NULL, 'S' },
 | 
			
		||||
	{ "list",     0, NULL, 'l' },
 | 
			
		||||
	{ "resolve",  1, NULL, 'r' },
 | 
			
		||||
	{ "dry-run",     0, NULL, 'Z' },
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"set xtrace when running the command",
 | 
			
		||||
	"ignore dependencies",
 | 
			
		||||
	"tests if the service exists or not",
 | 
			
		||||
	"if the service is crashed then run the command",
 | 
			
		||||
	"if the service exists then run the command",
 | 
			
		||||
	"if the service is inactive then run the command",
 | 
			
		||||
	"if the service is not started then run the command",
 | 
			
		||||
	"list all available services",
 | 
			
		||||
	"resolve the service name to an init script",
 | 
			
		||||
	"dry run (show what would happen)",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char *usagestring = ""							\
 | 
			
		||||
@@ -61,9 +71,12 @@ int main(int argc, char **argv)
 | 
			
		||||
	RC_STRINGLIST *list;
 | 
			
		||||
	RC_STRING *s;
 | 
			
		||||
	RC_SERVICE state;
 | 
			
		||||
	bool if_crashed = false;
 | 
			
		||||
	bool if_exists = false;
 | 
			
		||||
	bool if_inactive = false;
 | 
			
		||||
	bool if_notstarted = false;
 | 
			
		||||
	bool if_started = false;
 | 
			
		||||
	bool if_stopped = false;
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	/* Ensure that we are only quiet when explicitly told to be */
 | 
			
		||||
@@ -73,12 +86,21 @@ int main(int argc, char **argv)
 | 
			
		||||
		    longopts, (int *) 0)) != -1)
 | 
			
		||||
	{
 | 
			
		||||
		switch (opt) {
 | 
			
		||||
		case 'd':
 | 
			
		||||
			setenv("RC_DEBUG", "yes", 1);
 | 
			
		||||
			break;
 | 
			
		||||
		case 'D':
 | 
			
		||||
			setenv("RC_NODEPS", "yes", 1);
 | 
			
		||||
			break;
 | 
			
		||||
		case 'e':
 | 
			
		||||
			service = rc_service_resolve(optarg);
 | 
			
		||||
			opt = service ? EXIT_SUCCESS : EXIT_FAILURE;
 | 
			
		||||
			free(service);
 | 
			
		||||
			return opt;
 | 
			
		||||
			/* NOTREACHED */
 | 
			
		||||
		case 'c':
 | 
			
		||||
			if_crashed = true;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'i':
 | 
			
		||||
			if_exists = true;
 | 
			
		||||
			break;
 | 
			
		||||
@@ -106,6 +128,15 @@ int main(int argc, char **argv)
 | 
			
		||||
			free(service);
 | 
			
		||||
			return EXIT_SUCCESS;
 | 
			
		||||
			/* NOTREACHED */
 | 
			
		||||
		case 's':
 | 
			
		||||
			if_started = true;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'S':
 | 
			
		||||
			if_stopped = true;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'Z':
 | 
			
		||||
			setenv("IN_DRYRUN", "yes", 1);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case_RC_COMMON_GETOPT
 | 
			
		||||
		}
 | 
			
		||||
@@ -121,10 +152,16 @@ int main(int argc, char **argv)
 | 
			
		||||
		eerrorx("%s: service `%s' does not exist", applet, *argv);
 | 
			
		||||
	}
 | 
			
		||||
	state = rc_service_state(*argv);
 | 
			
		||||
	if (if_crashed &&  ! (rc_service_daemons_crashed(*argv) && errno != EACCES))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (if_inactive && ! (state & RC_SERVICE_INACTIVE))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (if_notstarted && (state & RC_SERVICE_STARTED))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (if_started && ! (state & RC_SERVICE_STARTED))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (if_stopped && ! (state & RC_SERVICE_STOPPED))
 | 
			
		||||
		return 0;
 | 
			
		||||
	*argv = service;
 | 
			
		||||
	execv(*argv, argv);
 | 
			
		||||
	eerrorx("%s: %s", applet, strerror(errno));
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,6 @@ const char *usagestring = ""						\
 | 
			
		||||
	"Usage: rc-status [options] <runlevel>...\n"		\
 | 
			
		||||
	"   or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
 | 
			
		||||
 | 
			
		||||
static bool test_crashed = false;
 | 
			
		||||
static RC_DEPTREE *deptree;
 | 
			
		||||
static RC_STRINGLIST *types;
 | 
			
		||||
 | 
			
		||||
@@ -76,7 +75,7 @@ print_level(const char *prefix, const char *level)
 | 
			
		||||
		printf("%s\n", level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void get_uptime(const char *service, char *uptime, int uptime_size)
 | 
			
		||||
static char *get_uptime(const char *service)
 | 
			
		||||
{
 | 
			
		||||
	RC_SERVICE state = rc_service_state(service);
 | 
			
		||||
	char *start_count;
 | 
			
		||||
@@ -88,8 +87,8 @@ static void get_uptime(const char *service, char *uptime, int uptime_size)
 | 
			
		||||
	time_t diff_hours = (time_t) 0;
 | 
			
		||||
	time_t diff_mins = (time_t) 0;
 | 
			
		||||
	time_t diff_secs = (time_t) 0;
 | 
			
		||||
	char *uptime = NULL;
 | 
			
		||||
 | 
			
		||||
	uptime[0] = '\0';
 | 
			
		||||
	if (state & RC_SERVICE_STARTED) {
 | 
			
		||||
		start_count = rc_service_value_get(service, "start_count");
 | 
			
		||||
		start_time_string = rc_service_value_get(service, "start_time");
 | 
			
		||||
@@ -111,23 +110,24 @@ static void get_uptime(const char *service, char *uptime, int uptime_size)
 | 
			
		||||
				diff_secs %= diff_mins * (time_t) 60;
 | 
			
		||||
			}
 | 
			
		||||
			if (diff_days > 0)
 | 
			
		||||
				snprintf(uptime, uptime_size,
 | 
			
		||||
				xasprintf(&uptime,
 | 
			
		||||
						"%ld day(s) %02ld:%02ld:%02ld (%s)",
 | 
			
		||||
						diff_days, diff_hours, diff_mins, diff_secs,
 | 
			
		||||
						start_count);
 | 
			
		||||
			else
 | 
			
		||||
				snprintf(uptime, uptime_size,
 | 
			
		||||
				xasprintf(&uptime,
 | 
			
		||||
						"%02ld:%02ld:%02ld (%s)",
 | 
			
		||||
						diff_hours, diff_mins, diff_secs, start_count);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return uptime;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
print_service(const char *service)
 | 
			
		||||
{
 | 
			
		||||
	char status[60];
 | 
			
		||||
	char uptime [40];
 | 
			
		||||
	char *status = NULL;
 | 
			
		||||
	char *uptime = NULL;
 | 
			
		||||
	char *child_pid = NULL;
 | 
			
		||||
	char *start_time = NULL;
 | 
			
		||||
	int cols =  printf(" %s", service);
 | 
			
		||||
@@ -136,42 +136,45 @@ print_service(const char *service)
 | 
			
		||||
	ECOLOR color = ECOLOR_BAD;
 | 
			
		||||
 | 
			
		||||
	if (state & RC_SERVICE_STOPPING)
 | 
			
		||||
		snprintf(status, sizeof(status), "stopping ");
 | 
			
		||||
		xasprintf(&status, "stopping ");
 | 
			
		||||
	else if (state & RC_SERVICE_STARTING) {
 | 
			
		||||
		snprintf(status, sizeof(status), "starting ");
 | 
			
		||||
		xasprintf(&status, "starting ");
 | 
			
		||||
		color = ECOLOR_WARN;
 | 
			
		||||
	} else if (state & RC_SERVICE_INACTIVE) {
 | 
			
		||||
		snprintf(status, sizeof(status), "inactive ");
 | 
			
		||||
		xasprintf(&status, "inactive ");
 | 
			
		||||
		color = ECOLOR_WARN;
 | 
			
		||||
	} else if (state & RC_SERVICE_STARTED) {
 | 
			
		||||
		errno = 0;
 | 
			
		||||
		if (test_crashed &&
 | 
			
		||||
		    rc_service_daemons_crashed(service) &&
 | 
			
		||||
		    errno != EACCES)
 | 
			
		||||
		if (rc_service_daemons_crashed(service) && errno != EACCES)
 | 
			
		||||
		{
 | 
			
		||||
			child_pid = rc_service_value_get(service, "child_pid");
 | 
			
		||||
			start_time = rc_service_value_get(service, "start_time");
 | 
			
		||||
			if (start_time && child_pid)
 | 
			
		||||
				snprintf(status, sizeof(status), " unsupervised ");
 | 
			
		||||
				xasprintf(&status, " unsupervised ");
 | 
			
		||||
			else
 | 
			
		||||
				snprintf(status, sizeof(status), " crashed ");
 | 
			
		||||
				xasprintf(&status, " crashed ");
 | 
			
		||||
			free(child_pid);
 | 
			
		||||
			free(start_time);
 | 
			
		||||
		} else {
 | 
			
		||||
			get_uptime(service, uptime, 40);
 | 
			
		||||
			snprintf(status, sizeof(status), " started %s", uptime);
 | 
			
		||||
			uptime = get_uptime(service);
 | 
			
		||||
			if (uptime) {
 | 
			
		||||
				xasprintf(&status, " started %s", uptime);
 | 
			
		||||
				free(uptime);
 | 
			
		||||
			} else
 | 
			
		||||
				xasprintf(&status, " started ");
 | 
			
		||||
			color = ECOLOR_GOOD;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (state & RC_SERVICE_SCHEDULED) {
 | 
			
		||||
		snprintf(status, sizeof(status), "scheduled");
 | 
			
		||||
		xasprintf(&status, "scheduled");
 | 
			
		||||
		color = ECOLOR_WARN;
 | 
			
		||||
	} else
 | 
			
		||||
		snprintf(status, sizeof(status), " stopped ");
 | 
			
		||||
		xasprintf(&status, " stopped ");
 | 
			
		||||
 | 
			
		||||
	errno = 0;
 | 
			
		||||
	if (c && *c && isatty(fileno(stdout)))
 | 
			
		||||
		printf("\n");
 | 
			
		||||
	ebracket(cols, color, status);
 | 
			
		||||
	free(status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -240,8 +243,6 @@ int main(int argc, char **argv)
 | 
			
		||||
	char *p, *runlevel = NULL;
 | 
			
		||||
	int opt, retval = 0;
 | 
			
		||||
 | 
			
		||||
	test_crashed = _rc_can_find_pids();
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	while ((opt = getopt_long(argc, argv, getoptstring, longopts,
 | 
			
		||||
				  (int *) 0)) != -1)
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ add(const char *runlevel, const char *service)
 | 
			
		||||
 | 
			
		||||
	if (!rc_service_exists(service)) {
 | 
			
		||||
		if (errno == ENOEXEC)
 | 
			
		||||
			eerror("%s: service `%s' is not executeable",
 | 
			
		||||
			eerror("%s: service `%s' is not executable",
 | 
			
		||||
			    applet, service);
 | 
			
		||||
		else
 | 
			
		||||
			eerror("%s: service `%s' does not exist",
 | 
			
		||||
@@ -166,7 +166,7 @@ show(RC_STRINGLIST *runlevels, bool verbose)
 | 
			
		||||
	RC_STRING *runlevel;
 | 
			
		||||
	RC_STRINGLIST *in;
 | 
			
		||||
	bool inone;
 | 
			
		||||
	char buffer[PATH_MAX];
 | 
			
		||||
	char *buffer = NULL;
 | 
			
		||||
	size_t l;
 | 
			
		||||
 | 
			
		||||
	rc_stringlist_sort(&services);
 | 
			
		||||
@@ -182,9 +182,11 @@ 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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										67
									
								
								src/rc/rc.c
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								src/rc/rc.c
									
									
									
									
									
								
							@@ -78,9 +78,6 @@ 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"
 | 
			
		||||
@@ -104,7 +101,6 @@ clean_failed(void)
 | 
			
		||||
{
 | 
			
		||||
	DIR *dp;
 | 
			
		||||
	struct dirent *d;
 | 
			
		||||
	size_t l;
 | 
			
		||||
	char *path;
 | 
			
		||||
 | 
			
		||||
	/* Clean the failed services state dir now */
 | 
			
		||||
@@ -115,16 +111,11 @@ clean_failed(void)
 | 
			
		||||
				(d->d_name[1] == '.' && d->d_name[2] == '\0')))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			l = strlen(RC_SVCDIR "/failed/") +
 | 
			
		||||
			    strlen(d->d_name) + 1;
 | 
			
		||||
			path = xmalloc(sizeof(char) * l);
 | 
			
		||||
			snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name);
 | 
			
		||||
			if (path) {
 | 
			
		||||
				if (unlink(path))
 | 
			
		||||
					eerror("%s: unlink `%s': %s",
 | 
			
		||||
					    applet, path, strerror(errno));
 | 
			
		||||
				free(path);
 | 
			
		||||
			}
 | 
			
		||||
			xasprintf(&path, RC_SVCDIR "/failed/%s", d->d_name);
 | 
			
		||||
			if (unlink(path))
 | 
			
		||||
				eerror("%s: unlink `%s': %s",
 | 
			
		||||
				    applet, path, strerror(errno));
 | 
			
		||||
			free(path);
 | 
			
		||||
		}
 | 
			
		||||
		closedir(dp);
 | 
			
		||||
	}
 | 
			
		||||
@@ -288,8 +279,8 @@ open_shell(void)
 | 
			
		||||
	/* VSERVER systems cannot really drop to shells */
 | 
			
		||||
	if (sys && strcmp(sys, RC_SYS_VSERVER) == 0)
 | 
			
		||||
	{
 | 
			
		||||
		execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
 | 
			
		||||
		eerrorx("%s: unable to exec `/sbin/halt': %s",
 | 
			
		||||
		execlp("halt", "halt", "-f", (char *) NULL);
 | 
			
		||||
		eerrorx("%s: unable to exec `halt -f': %s",
 | 
			
		||||
		    applet, strerror(errno));
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -336,26 +327,26 @@ set_krunlevel(const char *level)
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t
 | 
			
		||||
get_krunlevel(char *buffer, int buffer_len)
 | 
			
		||||
static char *get_krunlevel(void)
 | 
			
		||||
{
 | 
			
		||||
	char *buffer = NULL;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	size_t i = 0;
 | 
			
		||||
 | 
			
		||||
	if (!exists(RC_KRUNLEVEL))
 | 
			
		||||
		return 0;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	if (!(fp = fopen(RC_KRUNLEVEL, "r"))) {
 | 
			
		||||
		eerror("fopen `%s': %s", RC_KRUNLEVEL, strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fgets(buffer, buffer_len, fp)) {
 | 
			
		||||
	if (getline(&buffer, &i, fp) != -1) {
 | 
			
		||||
		i = strlen(buffer);
 | 
			
		||||
		if (buffer[i - 1] == '\n')
 | 
			
		||||
			buffer[i - 1] = 0;
 | 
			
		||||
	}
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	return i;
 | 
			
		||||
	return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -394,7 +385,7 @@ static void
 | 
			
		||||
handle_signal(int sig)
 | 
			
		||||
{
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
	char signame[10] = { '\0' };
 | 
			
		||||
	char *signame = NULL;
 | 
			
		||||
	pid_t pid;
 | 
			
		||||
	RC_PID *pi;
 | 
			
		||||
	int status = 0;
 | 
			
		||||
@@ -425,16 +416,16 @@ handle_signal(int sig)
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case SIGINT:
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGINT");
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGINT");
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	case SIGTERM:
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGTERM");
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGTERM");
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	case SIGQUIT:
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGQUIT");
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGQUIT");
 | 
			
		||||
		eerrorx("%s: caught %s, aborting", applet, signame);
 | 
			
		||||
		/* NOTREACHED */
 | 
			
		||||
	case SIGUSR1:
 | 
			
		||||
@@ -505,6 +496,9 @@ 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
 | 
			
		||||
@@ -512,14 +506,11 @@ runlevel_config(const char *service, const char *level)
 | 
			
		||||
{
 | 
			
		||||
	char *init = rc_service_resolve(service);
 | 
			
		||||
	char *conf, *dir;
 | 
			
		||||
	size_t l;
 | 
			
		||||
	bool retval;
 | 
			
		||||
 | 
			
		||||
	dir = dirname(init);
 | 
			
		||||
	dir = dirname(init);
 | 
			
		||||
	l = strlen(dir) + strlen(level) + strlen(service) + 10;
 | 
			
		||||
	conf = xmalloc(sizeof(char) * l);
 | 
			
		||||
	snprintf(conf, l, "%s/conf.d/%s.%s", dir, service, level);
 | 
			
		||||
	xasprintf(&conf, "%s/conf.d/%s.%s", dir, service, level);
 | 
			
		||||
	retval = exists(conf);
 | 
			
		||||
	free(conf);
 | 
			
		||||
	free(init);
 | 
			
		||||
@@ -743,8 +734,8 @@ int main(int argc, char **argv)
 | 
			
		||||
	RC_STRING *service;
 | 
			
		||||
	bool going_down = false;
 | 
			
		||||
	int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
 | 
			
		||||
	char krunlevel [PATH_MAX];
 | 
			
		||||
	char pidstr[10];
 | 
			
		||||
	char *krunlevel = NULL;
 | 
			
		||||
	char *pidstr = NULL;
 | 
			
		||||
	int opt;
 | 
			
		||||
	bool parallel;
 | 
			
		||||
	int regen = 0;
 | 
			
		||||
@@ -844,8 +835,9 @@ int main(int argc, char **argv)
 | 
			
		||||
	setenv("EINFO_LOG", "openrc", 1);
 | 
			
		||||
 | 
			
		||||
	/* Export our PID */
 | 
			
		||||
	snprintf(pidstr, sizeof(pidstr), "%d", getpid());
 | 
			
		||||
	xasprintf(&pidstr, "%d", getpid());
 | 
			
		||||
	setenv("RC_PID", pidstr, 1);
 | 
			
		||||
	free(pidstr);
 | 
			
		||||
 | 
			
		||||
	/* Create a list of all services which should be started for the new or
 | 
			
		||||
	* current runlevel including those in boot, sysinit and hotplugged
 | 
			
		||||
@@ -892,7 +884,8 @@ int main(int argc, char **argv)
 | 
			
		||||
		    (strcmp(newlevel, RC_LEVEL_SYSINIT) != 0 &&
 | 
			
		||||
			strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0))
 | 
			
		||||
		{
 | 
			
		||||
			if (get_krunlevel(krunlevel, sizeof(krunlevel))) {
 | 
			
		||||
			krunlevel = get_krunlevel();
 | 
			
		||||
			if (krunlevel) {
 | 
			
		||||
				newlevel = krunlevel;
 | 
			
		||||
				set_krunlevel(NULL);
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -59,13 +59,14 @@ static struct pam_conv conv = { NULL, NULL};
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "rc-pipes.h"
 | 
			
		||||
#include "rc-schedules.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#include "helpers.h"
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" \
 | 
			
		||||
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \
 | 
			
		||||
	getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "ionice",       1, NULL, 'I'},
 | 
			
		||||
@@ -93,6 +94,8 @@ const struct option longopts[] = {
 | 
			
		||||
	{ "exec",         1, NULL, 'x'},
 | 
			
		||||
	{ "stdout",       1, NULL, '1'},
 | 
			
		||||
	{ "stderr",       1, NULL, '2'},
 | 
			
		||||
	{ "stdout-logger",1, NULL, '3'},
 | 
			
		||||
	{ "stderr-logger",1, NULL, '4'},
 | 
			
		||||
	{ "progress",     0, NULL, 'P'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
@@ -122,6 +125,8 @@ const char * const longopts_help[] = {
 | 
			
		||||
	"Binary to start/stop",
 | 
			
		||||
	"Redirect stdout to file",
 | 
			
		||||
	"Redirect stderr to file",
 | 
			
		||||
	"Redirect stdout to process",
 | 
			
		||||
	"Redirect stderr to process",
 | 
			
		||||
	"Print dots each second while waiting",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
@@ -162,20 +167,20 @@ handle_signal(int sig)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
	char signame[10] = { '\0' };
 | 
			
		||||
	char *signame = NULL;
 | 
			
		||||
 | 
			
		||||
	switch (sig) {
 | 
			
		||||
	case SIGINT:
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGINT");
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGINT");
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	case SIGTERM:
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGTERM");
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGTERM");
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	case SIGQUIT:
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGQUIT");
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGQUIT");
 | 
			
		||||
		eerrorx("%s: caught %s, aborting", applet, signame);
 | 
			
		||||
		/* NOTREACHED */
 | 
			
		||||
 | 
			
		||||
@@ -194,6 +199,9 @@ handle_signal(int sig)
 | 
			
		||||
		eerror("%s: caught unknown signal %d", applet, sig);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* free signame */
 | 
			
		||||
	free(signame);
 | 
			
		||||
 | 
			
		||||
	/* Restore errno */
 | 
			
		||||
	errno = serrno;
 | 
			
		||||
}
 | 
			
		||||
@@ -202,7 +210,6 @@ static char *
 | 
			
		||||
expand_home(const char *home, const char *path)
 | 
			
		||||
{
 | 
			
		||||
	char *opath, *ppath, *p, *nh;
 | 
			
		||||
	size_t len;
 | 
			
		||||
	struct passwd *pw;
 | 
			
		||||
 | 
			
		||||
	if (!path || *path != '~')
 | 
			
		||||
@@ -233,9 +240,7 @@ expand_home(const char *home, const char *path)
 | 
			
		||||
		return xstrdup(home);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	len = strlen(ppath) + strlen(home) + 1;
 | 
			
		||||
	nh = xmalloc(len);
 | 
			
		||||
	snprintf(nh, len, "%s%s", home, ppath);
 | 
			
		||||
	xasprintf(&nh, "%s%s", home, ppath);
 | 
			
		||||
	free(opath);
 | 
			
		||||
	return nh;
 | 
			
		||||
}
 | 
			
		||||
@@ -254,6 +259,7 @@ int main(int argc, char **argv)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	int opt;
 | 
			
		||||
	size_t size = 0;
 | 
			
		||||
	bool start = false;
 | 
			
		||||
	bool stop = false;
 | 
			
		||||
	bool oknodo = false;
 | 
			
		||||
@@ -275,10 +281,13 @@ int main(int argc, char **argv)
 | 
			
		||||
	int tid = 0;
 | 
			
		||||
	char *redirect_stderr = NULL;
 | 
			
		||||
	char *redirect_stdout = NULL;
 | 
			
		||||
	char *stderr_process = NULL;
 | 
			
		||||
	char *stdout_process = NULL;
 | 
			
		||||
	int stdin_fd;
 | 
			
		||||
	int stdout_fd;
 | 
			
		||||
	int stderr_fd;
 | 
			
		||||
	pid_t pid, spid;
 | 
			
		||||
	RC_PIDLIST *pids;
 | 
			
		||||
	int i;
 | 
			
		||||
	char *svcname = getenv("RC_SVCNAME");
 | 
			
		||||
	RC_STRINGLIST *env_list;
 | 
			
		||||
@@ -286,10 +295,10 @@ int main(int argc, char **argv)
 | 
			
		||||
	char *tmp, *newpath, *np;
 | 
			
		||||
	char *p;
 | 
			
		||||
	char *token;
 | 
			
		||||
	char exec_file[PATH_MAX];
 | 
			
		||||
	char *exec_file = NULL;
 | 
			
		||||
	struct passwd *pw;
 | 
			
		||||
	struct group *gr;
 | 
			
		||||
	char line[130];
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	size_t len;
 | 
			
		||||
	mode_t numask = 022;
 | 
			
		||||
@@ -377,6 +386,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		case 'c':  /* --chuid <username>|<uid> */
 | 
			
		||||
			/* DEPRECATED */
 | 
			
		||||
			ewarn("WARNING: -c/--chuid is deprecated and will be removed in the future, please use -u/--user instead");
 | 
			
		||||
			/* falls through */
 | 
			
		||||
		case 'u':  /* --user <username>|<uid> */
 | 
			
		||||
		{
 | 
			
		||||
			p = optarg;
 | 
			
		||||
@@ -498,6 +508,14 @@ int main(int argc, char **argv)
 | 
			
		||||
			redirect_stderr = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case '3':   /* --stdout-logger "command to run for stdout logging" */
 | 
			
		||||
			stdout_process = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case '4':  /* --stderr-logger "command to run for stderr logging" */
 | 
			
		||||
			stderr_process = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case_RC_COMMON_GETOPT
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -549,6 +567,9 @@ int main(int argc, char **argv)
 | 
			
		||||
		if (redirect_stdout || redirect_stderr)
 | 
			
		||||
			eerrorx("%s: --stdout and --stderr are only relevant"
 | 
			
		||||
			    " with --start", applet);
 | 
			
		||||
		if (stdout_process || stderr_process)
 | 
			
		||||
			eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
 | 
			
		||||
			    " with --start", applet);
 | 
			
		||||
		if (start_wait)
 | 
			
		||||
			ewarn("using --wait with --stop has no effect,"
 | 
			
		||||
			    " use --retry instead");
 | 
			
		||||
@@ -561,6 +582,15 @@ int main(int argc, char **argv)
 | 
			
		||||
		if ((redirect_stdout || redirect_stderr) && !background)
 | 
			
		||||
			eerrorx("%s: --stdout and --stderr are only relevant"
 | 
			
		||||
			    " with --background", applet);
 | 
			
		||||
		if ((stdout_process || stderr_process) && !background)
 | 
			
		||||
			eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
 | 
			
		||||
			    " with --background", applet);
 | 
			
		||||
		if (redirect_stdout && stdout_process)
 | 
			
		||||
			eerrorx("%s: do not use --stdout and --stdout-logger together",
 | 
			
		||||
					applet);
 | 
			
		||||
		if (redirect_stderr && stderr_process)
 | 
			
		||||
			eerrorx("%s: do not use --stderr and --stderr-logger together",
 | 
			
		||||
					applet);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Expand ~ */
 | 
			
		||||
@@ -576,26 +606,22 @@ int main(int argc, char **argv)
 | 
			
		||||
		if (*exec == '/' || *exec == '.') {
 | 
			
		||||
			/* Full or relative path */
 | 
			
		||||
			if (ch_root)
 | 
			
		||||
				snprintf(exec_file, sizeof(exec_file),
 | 
			
		||||
				    "%s/%s", ch_root, exec);
 | 
			
		||||
				xasprintf(&exec_file, "%s/%s", ch_root, exec);
 | 
			
		||||
			else
 | 
			
		||||
				snprintf(exec_file, sizeof(exec_file),
 | 
			
		||||
				    "%s", exec);
 | 
			
		||||
				xasprintf(&exec_file, "%s", exec);
 | 
			
		||||
		} else {
 | 
			
		||||
			/* Something in $PATH */
 | 
			
		||||
			p = tmp = xstrdup(getenv("PATH"));
 | 
			
		||||
			*exec_file = '\0';
 | 
			
		||||
			exec_file = NULL;
 | 
			
		||||
			while ((token = strsep(&p, ":"))) {
 | 
			
		||||
				if (ch_root)
 | 
			
		||||
					snprintf(exec_file, sizeof(exec_file),
 | 
			
		||||
					    "%s/%s/%s",
 | 
			
		||||
					    ch_root, token, exec);
 | 
			
		||||
					xasprintf(&exec_file, "%s/%s/%s", ch_root, token, exec);
 | 
			
		||||
				else
 | 
			
		||||
					snprintf(exec_file, sizeof(exec_file),
 | 
			
		||||
					    "%s/%s", token, exec);
 | 
			
		||||
				if (exists(exec_file))
 | 
			
		||||
					xasprintf(&exec_file, "%s/%s", token, exec);
 | 
			
		||||
				if (exec_file && exists(exec_file))
 | 
			
		||||
					break;
 | 
			
		||||
				*exec_file = '\0';
 | 
			
		||||
				free(exec_file);
 | 
			
		||||
				exec_file = NULL;
 | 
			
		||||
			}
 | 
			
		||||
			free(tmp);
 | 
			
		||||
		}
 | 
			
		||||
@@ -603,8 +629,8 @@ int main(int argc, char **argv)
 | 
			
		||||
	if (start && !exists(exec_file)) {
 | 
			
		||||
		eerror("%s: %s does not exist", applet,
 | 
			
		||||
		    *exec_file ? exec_file : exec);
 | 
			
		||||
		free(exec_file);
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	if (start && retry)
 | 
			
		||||
		ewarn("using --retry with --start has no effect,"
 | 
			
		||||
@@ -616,7 +642,10 @@ int main(int argc, char **argv)
 | 
			
		||||
	if (interpreted && !pidfile) {
 | 
			
		||||
		fp = fopen(exec_file, "r");
 | 
			
		||||
		if (fp) {
 | 
			
		||||
			p = fgets(line, sizeof(line), fp);
 | 
			
		||||
			line = NULL;
 | 
			
		||||
			if (getline(&line, &size, fp) == -1)
 | 
			
		||||
				eerrorx("%s: %s", applet, strerror(errno));
 | 
			
		||||
			p = line;
 | 
			
		||||
			fclose(fp);
 | 
			
		||||
			if (p != NULL && line[0] == '#' && line[1] == '!') {
 | 
			
		||||
				p = line + 2;
 | 
			
		||||
@@ -628,7 +657,8 @@ int main(int argc, char **argv)
 | 
			
		||||
				if (p[len] == '\n')
 | 
			
		||||
					p[len] = '\0';
 | 
			
		||||
				token = strsep(&p, " ");
 | 
			
		||||
				strncpy(exec_file, token, sizeof(exec_file));
 | 
			
		||||
				free(exec_file);
 | 
			
		||||
				xasprintf(&exec_file, "%s", token);
 | 
			
		||||
				opt = 0;
 | 
			
		||||
				for (nav = argv; *nav; nav++)
 | 
			
		||||
					opt++;
 | 
			
		||||
@@ -656,8 +686,15 @@ int main(int argc, char **argv)
 | 
			
		||||
			parse_schedule(applet, "0", sig);
 | 
			
		||||
		else
 | 
			
		||||
			parse_schedule(applet, NULL, sig);
 | 
			
		||||
		if (pidfile) {
 | 
			
		||||
			pid = get_pid(applet, pidfile);
 | 
			
		||||
			if (pid == -1 && errno != ENOENT)
 | 
			
		||||
				exit(EXIT_FAILURE);
 | 
			
		||||
		} else {
 | 
			
		||||
			pid = 0;
 | 
			
		||||
		}
 | 
			
		||||
		i = run_stop_schedule(applet, exec, (const char *const *)margv,
 | 
			
		||||
		    get_pid(applet, pidfile), uid, test, progress, false);
 | 
			
		||||
		    pid, uid, test, progress, false);
 | 
			
		||||
 | 
			
		||||
		if (i < 0)
 | 
			
		||||
			/* We failed to stop something */
 | 
			
		||||
@@ -683,10 +720,14 @@ int main(int argc, char **argv)
 | 
			
		||||
	else
 | 
			
		||||
		pid = 0;
 | 
			
		||||
 | 
			
		||||
	if (do_stop(applet, exec, (const char * const *)margv, pid, uid,
 | 
			
		||||
		0, test, false) > 0)
 | 
			
		||||
	if (pid)
 | 
			
		||||
		pids = rc_find_pids(NULL, NULL, 0, pid);
 | 
			
		||||
	else
 | 
			
		||||
		pids = rc_find_pids(exec, (const char * const *) argv, uid, 0);
 | 
			
		||||
	if (pids)
 | 
			
		||||
		eerrorx("%s: %s is already running", applet, exec);
 | 
			
		||||
 | 
			
		||||
	free(pids);
 | 
			
		||||
	if (test) {
 | 
			
		||||
		if (rc_yesno(getenv("EINFO_QUIET")))
 | 
			
		||||
			exit (EXIT_SUCCESS);
 | 
			
		||||
@@ -872,6 +913,12 @@ int main(int argc, char **argv)
 | 
			
		||||
				eerrorx("%s: unable to open the logfile"
 | 
			
		||||
				    " for stdout `%s': %s",
 | 
			
		||||
				    applet, redirect_stdout, strerror(errno));
 | 
			
		||||
		}else if (stdout_process) {
 | 
			
		||||
			stdout_fd = rc_pipe_command(stdout_process);
 | 
			
		||||
			if (stdout_fd == -1)
 | 
			
		||||
				eerrorx("%s: unable to open the logging process"
 | 
			
		||||
				    " for stdout `%s': %s",
 | 
			
		||||
				    applet, stdout_process, strerror(errno));
 | 
			
		||||
		}
 | 
			
		||||
		if (redirect_stderr) {
 | 
			
		||||
			if ((stderr_fd = open(redirect_stderr,
 | 
			
		||||
@@ -880,13 +927,21 @@ int main(int argc, char **argv)
 | 
			
		||||
				eerrorx("%s: unable to open the logfile"
 | 
			
		||||
				    " for stderr `%s': %s",
 | 
			
		||||
				    applet, redirect_stderr, strerror(errno));
 | 
			
		||||
		}else if (stderr_process) {
 | 
			
		||||
			stderr_fd = rc_pipe_command(stderr_process);
 | 
			
		||||
			if (stderr_fd == -1)
 | 
			
		||||
				eerrorx("%s: unable to open the logging process"
 | 
			
		||||
				    " for stderr `%s': %s",
 | 
			
		||||
				    applet, stderr_process, strerror(errno));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (background)
 | 
			
		||||
			dup2(stdin_fd, STDIN_FILENO);
 | 
			
		||||
		if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
 | 
			
		||||
		if (background || redirect_stdout || stdout_process
 | 
			
		||||
				|| rc_yesno(getenv("EINFO_QUIET")))
 | 
			
		||||
			dup2(stdout_fd, STDOUT_FILENO);
 | 
			
		||||
		if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
 | 
			
		||||
		if (background || redirect_stderr || stderr_process
 | 
			
		||||
				|| rc_yesno(getenv("EINFO_QUIET")))
 | 
			
		||||
			dup2(stderr_fd, STDERR_FILENO);
 | 
			
		||||
 | 
			
		||||
		for (i = getdtablesize() - 1; i >= 3; --i)
 | 
			
		||||
 
 | 
			
		||||
@@ -159,10 +159,11 @@ static void cleanup(void)
 | 
			
		||||
	free(changeuser);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void re_exec(void)
 | 
			
		||||
static void re_exec_supervisor(void)
 | 
			
		||||
{
 | 
			
		||||
	syslog(LOG_WARNING, "Re-executing for %s", svcname);
 | 
			
		||||
	execlp("supervise-daemon", "supervise-daemon", "--reexec", (char *) NULL);
 | 
			
		||||
	execlp("supervise-daemon", "supervise-daemon", svcname, "--reexec",
 | 
			
		||||
			(char *) NULL);
 | 
			
		||||
	syslog(LOG_ERR, "Unable to execute supervise-daemon: %s",
 | 
			
		||||
			strerror(errno));
 | 
			
		||||
	exit(EXIT_FAILURE);
 | 
			
		||||
@@ -179,13 +180,12 @@ static void handle_signal(int sig)
 | 
			
		||||
	/* Restore errno */
 | 
			
		||||
	errno = serrno;
 | 
			
		||||
	if (! exiting)
 | 
			
		||||
		re_exec();
 | 
			
		||||
		re_exec_supervisor();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char * expand_home(const char *home, const char *path)
 | 
			
		||||
{
 | 
			
		||||
	char *opath, *ppath, *p, *nh;
 | 
			
		||||
	size_t len;
 | 
			
		||||
	struct passwd *pw;
 | 
			
		||||
 | 
			
		||||
	if (!path || *path != '~')
 | 
			
		||||
@@ -216,13 +216,28 @@ static char * expand_home(const char *home, const char *path)
 | 
			
		||||
		return xstrdup(home);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	len = strlen(ppath) + strlen(home) + 1;
 | 
			
		||||
	nh = xmalloc(len);
 | 
			
		||||
	snprintf(nh, len, "%s%s", home, ppath);
 | 
			
		||||
	xasprintf(&nh, "%s%s", home, ppath);
 | 
			
		||||
	free(opath);
 | 
			
		||||
	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;
 | 
			
		||||
@@ -233,8 +248,7 @@ static void child_process(char *exec, char **argv)
 | 
			
		||||
	size_t len;
 | 
			
		||||
	char *newpath;
 | 
			
		||||
	char *np;
 | 
			
		||||
	char **c;
 | 
			
		||||
	char cmdline[PATH_MAX];
 | 
			
		||||
	char *cmdline = NULL;
 | 
			
		||||
	time_t start_time;
 | 
			
		||||
	char start_count_string[20];
 | 
			
		||||
	char start_time_string[20];
 | 
			
		||||
@@ -394,15 +408,9 @@ static void child_process(char *exec, char **argv)
 | 
			
		||||
 | 
			
		||||
	for (i = getdtablesize() - 1; i >= 3; --i)
 | 
			
		||||
		fcntl(i, F_SETFD, FD_CLOEXEC);
 | 
			
		||||
 | 
			
		||||
	*cmdline = '\0';
 | 
			
		||||
	c = argv;
 | 
			
		||||
	while (c && *c) {
 | 
			
		||||
		strcat(cmdline, *c);
 | 
			
		||||
		strcat(cmdline, " ");
 | 
			
		||||
		c++;
 | 
			
		||||
	}
 | 
			
		||||
	cmdline = make_cmdline(argv);
 | 
			
		||||
	syslog(LOG_INFO, "Child command line: %s", cmdline);
 | 
			
		||||
	free(cmdline);
 | 
			
		||||
	execvp(exec, argv);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_PAM
 | 
			
		||||
@@ -434,7 +442,9 @@ static void supervisor(char *exec, char **argv)
 | 
			
		||||
	signal_setup_restart(SIGUSR1, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGUSR2, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGBUS, handle_signal);
 | 
			
		||||
#ifdef SIGPOLL
 | 
			
		||||
	signal_setup_restart(SIGPOLL, handle_signal);
 | 
			
		||||
#endif
 | 
			
		||||
	signal_setup_restart(SIGPROF, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGSYS, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGTRAP, handle_signal);
 | 
			
		||||
@@ -445,7 +455,9 @@ static void supervisor(char *exec, char **argv)
 | 
			
		||||
	signal_setup_restart(SIGEMT, handle_signal);
 | 
			
		||||
#endif
 | 
			
		||||
	signal_setup_restart(SIGIO, handle_signal);
 | 
			
		||||
#ifdef SIGPWR
 | 
			
		||||
	signal_setup_restart(SIGPWR, handle_signal);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SIGUNUSED
 | 
			
		||||
	signal_setup_restart(SIGUNUSED, handle_signal);
 | 
			
		||||
#endif
 | 
			
		||||
@@ -495,7 +507,7 @@ static void supervisor(char *exec, char **argv)
 | 
			
		||||
					first_spawn = 0;
 | 
			
		||||
				} else
 | 
			
		||||
					respawn_count++;
 | 
			
		||||
				if (respawn_count >= respawn_max) {
 | 
			
		||||
				if (respawn_count > respawn_max) {
 | 
			
		||||
					syslog(LOG_WARNING,
 | 
			
		||||
							"respawned \"%s\" too many times, exiting", exec);
 | 
			
		||||
					exiting = true;
 | 
			
		||||
@@ -546,8 +558,8 @@ int main(int argc, char **argv)
 | 
			
		||||
	char *token;
 | 
			
		||||
	int i;
 | 
			
		||||
	int n;
 | 
			
		||||
	char exec_file[PATH_MAX];
 | 
			
		||||
	char name[PATH_MAX];
 | 
			
		||||
	char *exec_file = NULL;
 | 
			
		||||
	char *varbuf = NULL;
 | 
			
		||||
	struct timespec ts;
 | 
			
		||||
	struct passwd *pw;
 | 
			
		||||
	struct group *gr;
 | 
			
		||||
@@ -556,7 +568,7 @@ int main(int argc, char **argv)
 | 
			
		||||
	int child_argc = 0;
 | 
			
		||||
	char **child_argv = NULL;
 | 
			
		||||
	char *str = NULL;
 | 
			
		||||
	char cmdline[PATH_MAX];
 | 
			
		||||
	char *cmdline = NULL;
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	atexit(cleanup);
 | 
			
		||||
@@ -566,7 +578,8 @@ 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 must be %s", applet, svcname);
 | 
			
		||||
		eerrorx("%s: the first argument is %s and must be %s",
 | 
			
		||||
				applet, argv[1], svcname);
 | 
			
		||||
 | 
			
		||||
	if ((tmp = getenv("SSD_NICELEVEL")))
 | 
			
		||||
		if (sscanf(tmp, "%d", &nicelevel) != 1)
 | 
			
		||||
@@ -588,13 +601,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*cmdline = '\0';
 | 
			
		||||
	c = argv;
 | 
			
		||||
	while (c && *c) {
 | 
			
		||||
		strcat(cmdline, *c);
 | 
			
		||||
		strcat(cmdline, " ");
 | 
			
		||||
		c++;
 | 
			
		||||
	}
 | 
			
		||||
	cmdline = make_cmdline(argv);
 | 
			
		||||
	if (svcname) {
 | 
			
		||||
		argc--;
 | 
			
		||||
		argv++;
 | 
			
		||||
@@ -756,9 +763,11 @@ 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++) {
 | 
			
		||||
			sprintf(name, "argv_%d", x);
 | 
			
		||||
			str = rc_service_value_get(svcname, name);
 | 
			
		||||
			xasprintf(&varbuf, "argv_%d", x);
 | 
			
		||||
			str = rc_service_value_get(svcname, varbuf);
 | 
			
		||||
			child_argv[x] = str;
 | 
			
		||||
			free(varbuf);
 | 
			
		||||
			varbuf = NULL;
 | 
			
		||||
		}
 | 
			
		||||
		free(str);
 | 
			
		||||
		str = rc_service_value_get(svcname, "child_pid");
 | 
			
		||||
@@ -787,32 +796,31 @@ int main(int argc, char **argv)
 | 
			
		||||
			if (*exec == '/' || *exec == '.') {
 | 
			
		||||
				/* Full or relative path */
 | 
			
		||||
				if (ch_root)
 | 
			
		||||
					snprintf(exec_file, sizeof(exec_file),
 | 
			
		||||
				    	"%s/%s", ch_root, exec);
 | 
			
		||||
					xasprintf(&exec_file, "%s/%s", ch_root, exec);
 | 
			
		||||
				else
 | 
			
		||||
					snprintf(exec_file, sizeof(exec_file),
 | 
			
		||||
				    "%s", exec);
 | 
			
		||||
					xasprintf(&exec_file, "%s", exec);
 | 
			
		||||
			} else {
 | 
			
		||||
				/* Something in $PATH */
 | 
			
		||||
				p = tmp = xstrdup(getenv("PATH"));
 | 
			
		||||
				*exec_file = '\0';
 | 
			
		||||
				exec_file = NULL;
 | 
			
		||||
				while ((token = strsep(&p, ":"))) {
 | 
			
		||||
					if (ch_root)
 | 
			
		||||
						snprintf(exec_file, sizeof(exec_file),
 | 
			
		||||
					    	"%s/%s/%s",
 | 
			
		||||
					    	ch_root, token, exec);
 | 
			
		||||
						xasprintf(&exec_file, "%s/%s/%s", ch_root, token, exec);
 | 
			
		||||
					else
 | 
			
		||||
						snprintf(exec_file, sizeof(exec_file),
 | 
			
		||||
					    	"%s/%s", token, exec);
 | 
			
		||||
					if (exists(exec_file))
 | 
			
		||||
						xasprintf(&exec_file, "%s/%s", token, exec);
 | 
			
		||||
					if (exec_file && exists(exec_file))
 | 
			
		||||
						break;
 | 
			
		||||
					*exec_file = '\0';
 | 
			
		||||
					free(exec_file);
 | 
			
		||||
					exec_file = NULL;
 | 
			
		||||
				}
 | 
			
		||||
				free(tmp);
 | 
			
		||||
			}
 | 
			
		||||
			if ( !exists(exec_file))
 | 
			
		||||
				eerrorx("%s: %s does not exist", applet,
 | 
			
		||||
			if (!exists(exec_file)) {
 | 
			
		||||
				eerror("%s: %s does not exist", applet,
 | 
			
		||||
				    *exec_file ? exec_file : exec);
 | 
			
		||||
				free(exec_file);
 | 
			
		||||
				exit(EXIT_FAILURE);
 | 
			
		||||
			}
 | 
			
		||||
		} else
 | 
			
		||||
			eerrorx("%s: nothing to start", applet);
 | 
			
		||||
 | 
			
		||||
@@ -835,6 +843,8 @@ 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)
 | 
			
		||||
@@ -847,12 +857,16 @@ int main(int argc, char **argv)
 | 
			
		||||
		fclose(fp);
 | 
			
		||||
 | 
			
		||||
		rc_service_value_set(svcname, "pidfile", pidfile);
 | 
			
		||||
		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);
 | 
			
		||||
		varbuf = NULL;
 | 
			
		||||
		xasprintf(&varbuf, "%i", respawn_delay);
 | 
			
		||||
		rc_service_value_set(svcname, "respawn_delay", varbuf);
 | 
			
		||||
		free(varbuf);
 | 
			
		||||
		xasprintf(&varbuf, "%i", respawn_max);
 | 
			
		||||
		rc_service_value_set(svcname, "respawn_max", varbuf);
 | 
			
		||||
		free(varbuf);
 | 
			
		||||
		xasprintf(&varbuf, "%i", respawn_period);
 | 
			
		||||
		rc_service_value_set(svcname, "respawn_period", varbuf);
 | 
			
		||||
		free(varbuf);
 | 
			
		||||
		child_pid = fork();
 | 
			
		||||
		if (child_pid == -1)
 | 
			
		||||
			eerrorx("%s: fork: %s", applet, strerror(errno));
 | 
			
		||||
@@ -870,13 +884,17 @@ int main(int argc, char **argv)
 | 
			
		||||
			c = argv;
 | 
			
		||||
			x = 0;
 | 
			
		||||
			while (c && *c) {
 | 
			
		||||
				snprintf(name, sizeof(name), "argv_%-d",x);
 | 
			
		||||
				rc_service_value_set(svcname, name, *c);
 | 
			
		||||
				varbuf = NULL;
 | 
			
		||||
				xasprintf(&varbuf, "argv_%-d",x);
 | 
			
		||||
				rc_service_value_set(svcname, varbuf, *c);
 | 
			
		||||
				free(varbuf);
 | 
			
		||||
				varbuf = NULL;
 | 
			
		||||
				x++;
 | 
			
		||||
				c++;
 | 
			
		||||
			}
 | 
			
		||||
			sprintf(name, "%d", x);
 | 
			
		||||
				rc_service_value_set(svcname, "argc", name);
 | 
			
		||||
			xasprintf(&varbuf, "%d", x);
 | 
			
		||||
				rc_service_value_set(svcname, "argc", varbuf);
 | 
			
		||||
				free(varbuf);
 | 
			
		||||
			rc_service_value_set(svcname, "exec", exec);
 | 
			
		||||
			supervisor(exec, argv);
 | 
			
		||||
		} else
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
# 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,4 +1,5 @@
 | 
			
		||||
# 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,7 +7,5 @@ BIN=	${OBJS}
 | 
			
		||||
 | 
			
		||||
MK=	../../mk
 | 
			
		||||
 | 
			
		||||
SED_EXTRA+= -e 's:@VARBASE@:/var:g'
 | 
			
		||||
 | 
			
		||||
include ${MK}/os.mk
 | 
			
		||||
include ${MK}/scripts.mk
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
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=@VARBASE@/run/avahi-dnsconfd.pid
 | 
			
		||||
pidfile=/var/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=@VARBASE@/run/avahi-daemon/pid
 | 
			
		||||
pidfile=/var/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=@VARBASE@/run/dbus/pid
 | 
			
		||||
pidfile=/var/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=@VARBASE@/run/dnsmasq.pid
 | 
			
		||||
pidfile=/var/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=@VARBASE@/run/hald/hald.pid
 | 
			
		||||
pidfile=/var/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=@VARBASE@/run/named.pid
 | 
			
		||||
pidfile=/var/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=@VARBASE@/run/named/pid
 | 
			
		||||
		pidfile=/var/run/named/pid
 | 
			
		||||
		;;
 | 
			
		||||
	Linux)
 | 
			
		||||
		uid=bind
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user