Compare commits
	
		
			3 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					a70b65f851 | ||
| 
						 | 
					0660d2455d | ||
| 
						 | 
					01c5b98d38 | 
							
								
								
									
										14
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								.travis.yml
									
									
									
									
									
								
							@@ -1,14 +0,0 @@
 | 
			
		||||
# Travis build integration.
 | 
			
		||||
# https://docs.travis-ci.com/
 | 
			
		||||
 | 
			
		||||
language: c
 | 
			
		||||
 | 
			
		||||
os:
 | 
			
		||||
  - linux
 | 
			
		||||
 | 
			
		||||
compiler:
 | 
			
		||||
  - gcc
 | 
			
		||||
  - clang
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
  - ./test/travis.sh
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
NAME=		openrc
 | 
			
		||||
VERSION=	0.40.1
 | 
			
		||||
VERSION=	0.35.1
 | 
			
		||||
PKG=		${NAME}-${VERSION}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										64
									
								
								NEWS.md
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								NEWS.md
									
									
									
									
									
								
							@@ -4,70 +4,6 @@ OpenRC NEWS
 | 
			
		||||
This file will contain a list of notable changes for each release. Note
 | 
			
		||||
the information in this file is in reverse order.
 | 
			
		||||
 | 
			
		||||
## OpenRC 0.40
 | 
			
		||||
 | 
			
		||||
In this version, the keymaps and termencoding services on Linux needed
 | 
			
		||||
to be modified so they do not write to the root file system. This was
 | 
			
		||||
done so they can run earlier in the boot sequence. AS a result, you will
 | 
			
		||||
need to add save-termencoding and save-keymaps to your boot runlevel.
 | 
			
		||||
This can be done as follows:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
# rc-update add save-keymaps boot
 | 
			
		||||
# rc-update add save-termencoding boot
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## OpenRC 0.39
 | 
			
		||||
 | 
			
		||||
This version removes the support for addons.
 | 
			
		||||
The only place I know that this was used was Gentoo Baselayout 1.x, so
 | 
			
		||||
it shouldn't affect anyone since baselayout-1 has been dead for a few
 | 
			
		||||
years.
 | 
			
		||||
 | 
			
		||||
Since all supported Linux kernel versions now make efivarfs immutable
 | 
			
		||||
and all of the tools that access efivarfs are aware of this, we no
 | 
			
		||||
longer mount efivarfs read-only. See the following github issue for more
 | 
			
		||||
information:
 | 
			
		||||
 | 
			
		||||
https://github.com/openrc/openrc/issues/238
 | 
			
		||||
 | 
			
		||||
This version adds timed shutdown and cancelation of shutdown to
 | 
			
		||||
openrc-shutdown. Shutdowns can now be delayed for a certain amount of
 | 
			
		||||
time or scheduled for an exact time.
 | 
			
		||||
 | 
			
		||||
supervise-daemon supports health checks, which are a periodic way to make sure a
 | 
			
		||||
service is healthy. For more information on setting this up, please see
 | 
			
		||||
supervise-daemon-guide.md.
 | 
			
		||||
 | 
			
		||||
The --first-time switch has been added to all modprobe commands in the
 | 
			
		||||
modules service. This means that, on Linux, you will see failures if a
 | 
			
		||||
module was loaded by an initramfs or device manager before this service
 | 
			
		||||
runs. These messages are harmless, but to clean them up, you should adjust your
 | 
			
		||||
modules autoload configuration.
 | 
			
		||||
 | 
			
		||||
## 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
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,11 @@
 | 
			
		||||
#modules_2="ipv6"
 | 
			
		||||
#modules="ohci1394"
 | 
			
		||||
 | 
			
		||||
# Linux users can give modules a different name when they load - the new name
 | 
			
		||||
# will also be used to pick arguments below.
 | 
			
		||||
# This is not supported on FreeBSD.
 | 
			
		||||
#modules="dummy:dummy1"
 | 
			
		||||
 | 
			
		||||
# Linux users can give the modules some arguments if needed, per version
 | 
			
		||||
# if necessary.
 | 
			
		||||
# Again, the most specific versioned variable will take precedence.
 | 
			
		||||
 
 | 
			
		||||
@@ -230,7 +230,7 @@ rc_tty_number=12
 | 
			
		||||
# 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_cgroup_memory_use_hierarchy="NO"
 | 
			
		||||
#rc_cggroup_memory_use_hierarchy="NO"
 | 
			
		||||
 | 
			
		||||
# The following settings allow you to set up values for the cgroups version 1
 | 
			
		||||
# controllers for your services.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								init.d/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								init.d/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -41,8 +41,6 @@ rc-enabled
 | 
			
		||||
rpcbind
 | 
			
		||||
runsvdir
 | 
			
		||||
savecore
 | 
			
		||||
save-keymaps
 | 
			
		||||
save-termencoding
 | 
			
		||||
swap-blk
 | 
			
		||||
swclock
 | 
			
		||||
syslogd
 | 
			
		||||
 
 | 
			
		||||
@@ -19,12 +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 \
 | 
			
		||||
		mixer.in nscd.in powerd.in syscons.in
 | 
			
		||||
		modules-load.in mixer.in nscd.in powerd.in syscons.in
 | 
			
		||||
 | 
			
		||||
SRCS-Linux=	agetty.in binfmt.in devfs.in cgroups.in dmesg.in hwclock.in \
 | 
			
		||||
	consolefont.in keymaps.in killprocs.in modules.in \
 | 
			
		||||
	mount-ro.in mtab.in numlock.in procfs.in net-online.in save-keymaps.in \
 | 
			
		||||
	save-termencoding.in sysfs.in termencoding.in
 | 
			
		||||
	consolefont.in keymaps.in killprocs.in modules.in modules-load.in \
 | 
			
		||||
	mount-ro.in mtab.in numlock.in procfs.in net-online.in sysfs.in \
 | 
			
		||||
termencoding.in
 | 
			
		||||
 | 
			
		||||
# Generic BSD scripts
 | 
			
		||||
SRCS-NetBSD=	hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ term_type="${term_type:-linux}"
 | 
			
		||||
command=/sbin/agetty
 | 
			
		||||
command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}"
 | 
			
		||||
pidfile="/run/${RC_SVCNAME}.pid"
 | 
			
		||||
export EINFO_QUIET="${quiet:-yes}"
 | 
			
		||||
 | 
			
		||||
depend() {
 | 
			
		||||
	after local
 | 
			
		||||
@@ -28,12 +29,5 @@ start_pre() {
 | 
			
		||||
		eerror "symbolic links to it for the ports you want to start"
 | 
			
		||||
		eerror "agetty on and add those to the appropriate runlevels."
 | 
			
		||||
		return 1
 | 
			
		||||
	else
 | 
			
		||||
		export EINFO_QUIET="${quiet:-yes}"
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
stop_pre()
 | 
			
		||||
{
 | 
			
		||||
	export EINFO_QUIET="${quiet:-yes}"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ description="Sets a font for the consoles."
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	need termencoding
 | 
			
		||||
	need localmount termencoding
 | 
			
		||||
	after hotplug bootmisc modules
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,8 @@ description="Applies a keymap for the consoles."
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	need termencoding
 | 
			
		||||
	after devfs
 | 
			
		||||
	need localmount termencoding
 | 
			
		||||
	after bootmisc clock
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -68,5 +68,10 @@ start()
 | 
			
		||||
		echo "altgr keycode 18 = U+20AC" | loadkeys -q -
 | 
			
		||||
		eend $?
 | 
			
		||||
	fi
 | 
			
		||||
	return 0
 | 
			
		||||
 | 
			
		||||
	# Save the keymapping for use immediately at boot
 | 
			
		||||
	if checkpath -W "$RC_LIBEXECDIR"; then
 | 
			
		||||
		mkdir -p "$RC_LIBEXECDIR"/console
 | 
			
		||||
		dumpkeys >"$RC_LIBEXECDIR"/console/keymap
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										72
									
								
								init.d/modules-load.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								init.d/modules-load.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
			
		||||
#!@SBINDIR@/openrc-run
 | 
			
		||||
# Copyright (c) 2016 The OpenRC Authors.
 | 
			
		||||
# See the Authors file at the top-level directory of this distribution and
 | 
			
		||||
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
 | 
			
		||||
#
 | 
			
		||||
# This file is part of OpenRC. It is subject to the license terms in
 | 
			
		||||
# the LICENSE file found in the top-level directory of this
 | 
			
		||||
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
 | 
			
		||||
# This file may not be copied, modified, propagated, or distributed
 | 
			
		||||
# except according to the terms contained in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
description="Loads a list of modules from systemd-compatible locations."
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
find_modfiles()
 | 
			
		||||
{
 | 
			
		||||
	local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
 | 
			
		||||
	local basenames files fn x y
 | 
			
		||||
	for x in $dirs; do
 | 
			
		||||
		[ ! -d $x ] && continue
 | 
			
		||||
		for y in $x/*.conf; do
 | 
			
		||||
			[ -f $y ] && basenames="${basenames}\n${y##*/}"
 | 
			
		||||
		done
 | 
			
		||||
	done
 | 
			
		||||
	basenames=$(printf "$basenames" | sort -u)
 | 
			
		||||
	for x in $basenames; do
 | 
			
		||||
		for y in $dirs; do
 | 
			
		||||
			[ -r $y/$x ] &&
 | 
			
		||||
				fn=$y/$x
 | 
			
		||||
		done
 | 
			
		||||
		files="$files $fn"
 | 
			
		||||
	done
 | 
			
		||||
	echo $files
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
load_modules()
 | 
			
		||||
{
 | 
			
		||||
	local file m modules rc x
 | 
			
		||||
	file=$1
 | 
			
		||||
	[ -z "$file" ] && return 0
 | 
			
		||||
	while read m x; do
 | 
			
		||||
		case $m in
 | 
			
		||||
			\;*) continue ;;
 | 
			
		||||
			\#*) continue ;;
 | 
			
		||||
			*) modules="$modules $m"
 | 
			
		||||
			;;
 | 
			
		||||
		esac
 | 
			
		||||
	done < $file
 | 
			
		||||
	for x in $modules; do
 | 
			
		||||
		ebegin "Loading module $x"
 | 
			
		||||
		case "$RC_UNAME" in
 | 
			
		||||
			FreeBSD) kldload "$x"; rc=$? ;;
 | 
			
		||||
			Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
 | 
			
		||||
			*) ;;
 | 
			
		||||
		esac
 | 
			
		||||
		eend $rc "Failed to load $x"
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start()
 | 
			
		||||
{
 | 
			
		||||
	local x
 | 
			
		||||
	files=$(find_modfiles)
 | 
			
		||||
	for x in $files; do
 | 
			
		||||
		load_modules $x
 | 
			
		||||
	done
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
@@ -14,66 +14,10 @@ description="Loads a user defined list of kernel modules."
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	use isapnp
 | 
			
		||||
	provide modules-load
 | 
			
		||||
	want modules-load
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
find_modfiles()
 | 
			
		||||
{
 | 
			
		||||
	local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
 | 
			
		||||
	local basenames files fn x y
 | 
			
		||||
	for x in $dirs; do
 | 
			
		||||
		[ ! -d $x ] && continue
 | 
			
		||||
		for y in $x/*.conf; do
 | 
			
		||||
			[ -f $y ] && basenames="${basenames}\n${y##*/}"
 | 
			
		||||
		done
 | 
			
		||||
	done
 | 
			
		||||
	basenames=$(printf "$basenames" | sort -u)
 | 
			
		||||
	for x in $basenames; do
 | 
			
		||||
		for y in $dirs; do
 | 
			
		||||
			[ -r $y/$x ] &&
 | 
			
		||||
				fn=$y/$x
 | 
			
		||||
		done
 | 
			
		||||
		files="$files $fn"
 | 
			
		||||
	done
 | 
			
		||||
	echo $files
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
load_modules()
 | 
			
		||||
{
 | 
			
		||||
	local file m modules rc x
 | 
			
		||||
	file=$1
 | 
			
		||||
	[ -z "$file" ] && return 0
 | 
			
		||||
	while read m x; do
 | 
			
		||||
		case $m in
 | 
			
		||||
			\;*) continue ;;
 | 
			
		||||
			\#*) continue ;;
 | 
			
		||||
			*) modules="$modules $m"
 | 
			
		||||
			;;
 | 
			
		||||
		esac
 | 
			
		||||
	done < $file
 | 
			
		||||
	for x in $modules; do
 | 
			
		||||
		ebegin "Loading module $x"
 | 
			
		||||
		case "$RC_UNAME" in
 | 
			
		||||
			FreeBSD) kldload "$x"; rc=$? ;;
 | 
			
		||||
			Linux) modprobe --first-time -q --use-blacklist "$x"; rc=$? ;;
 | 
			
		||||
			*) ;;
 | 
			
		||||
		esac
 | 
			
		||||
		eend $rc "Failed to load $x"
 | 
			
		||||
	done
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
@@ -104,7 +48,7 @@ Linux_modules()
 | 
			
		||||
		x=${x%.*}
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	local list= x= xx= y= args=
 | 
			
		||||
	local list= x= xx= y= args= mpargs= a=
 | 
			
		||||
	for x in $kv_variant_list ; do
 | 
			
		||||
		eval list=\$modules_$(shell_var "$x")
 | 
			
		||||
		[ -n "$list" ] && break
 | 
			
		||||
@@ -113,13 +57,24 @@ Linux_modules()
 | 
			
		||||
 | 
			
		||||
	[ -n "$list" ] && ebegin "Loading kernel modules"
 | 
			
		||||
	for x in $list; do
 | 
			
		||||
		a=${x#*:}
 | 
			
		||||
		if [ "$a" = "$x" ]; then
 | 
			
		||||
			unset mpargs
 | 
			
		||||
		else
 | 
			
		||||
			x=${x%%:*}
 | 
			
		||||
			mpargs="-o $a"
 | 
			
		||||
		fi
 | 
			
		||||
		aa=$(shell_var "$a")
 | 
			
		||||
		xx=$(shell_var "$x")
 | 
			
		||||
		for y in $kv_variant_list ; do
 | 
			
		||||
			eval args=\$module_${aa}_args_$(shell_var "$y")
 | 
			
		||||
			[ -n "${args}" ] && break
 | 
			
		||||
			eval args=\$module_${xx}_args_$(shell_var "$y")
 | 
			
		||||
			[ -n "${args}" ] && break
 | 
			
		||||
		done
 | 
			
		||||
		[ -z "$args" ] && eval args=\$module_${aa}_args
 | 
			
		||||
		[ -z "$args" ] && eval args=\$module_${xx}_args
 | 
			
		||||
		eval modprobe --first-time --use-blacklist --verbose "$x" "$args"
 | 
			
		||||
		eval modprobe --use-blacklist --verbose "$mpargs" "$x" "$args"
 | 
			
		||||
	done
 | 
			
		||||
	[ -n "$list" ] && eend
 | 
			
		||||
}
 | 
			
		||||
@@ -127,10 +82,7 @@ Linux_modules()
 | 
			
		||||
start()
 | 
			
		||||
{
 | 
			
		||||
	case "$RC_UNAME" in
 | 
			
		||||
		FreeBSD|Linux)
 | 
			
		||||
			modules_load_d
 | 
			
		||||
			${RC_UNAME}_modules
 | 
			
		||||
			;;
 | 
			
		||||
		FreeBSD|Linux) ${RC_UNAME}_modules ;;
 | 
			
		||||
		*) ;;
 | 
			
		||||
	esac
 | 
			
		||||
	return 0
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ description="Delays until the network is online or a specific timeout"
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	after modules net
 | 
			
		||||
	after modules
 | 
			
		||||
	need sysfs
 | 
			
		||||
	provide network-online
 | 
			
		||||
	keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -uml -vserver
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	need localmount
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ depend()
 | 
			
		||||
	after clock
 | 
			
		||||
	use devfs
 | 
			
		||||
	want modules
 | 
			
		||||
	need localmount
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,28 +0,0 @@
 | 
			
		||||
#!@SBINDIR@/openrc-run
 | 
			
		||||
# Copyright (c) 2018 Sony Interactive Entertainment, Inc.
 | 
			
		||||
#
 | 
			
		||||
# 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="Save the keymap for use as early as possible"
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	need termencoding
 | 
			
		||||
	after bootmisc clock keymaps
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start()
 | 
			
		||||
{
 | 
			
		||||
	# Save the keymapping for use immediately at boot
 | 
			
		||||
	ebegin "Saving key mapping"
 | 
			
		||||
	if checkpath -W "$RC_LIBEXECDIR"; then
 | 
			
		||||
		mkdir -p "$RC_LIBEXECDIR"/console
 | 
			
		||||
		dumpkeys >"$RC_LIBEXECDIR"/console/keymap
 | 
			
		||||
	fi
 | 
			
		||||
	eend $? "Unable to save keymapping"
 | 
			
		||||
}
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
#!@SBINDIR@/openrc-run
 | 
			
		||||
# Copyright (c) 2018 Sony Interactive Entertainment, Inc.
 | 
			
		||||
#
 | 
			
		||||
# 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="Configures terminal encoding."
 | 
			
		||||
 | 
			
		||||
ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
 | 
			
		||||
: ${unicode:=${UNICODE}}
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
			
		||||
	use root
 | 
			
		||||
	after bootmisc clock termencoding
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start()
 | 
			
		||||
{
 | 
			
		||||
	ebegin "Saving terminal encoding"
 | 
			
		||||
	# Save the encoding for use immediately at boot
 | 
			
		||||
	if checkpath -W "$RC_LIBEXECDIR"; then
 | 
			
		||||
		mkdir -p "$RC_LIBEXECDIR"/console
 | 
			
		||||
		if yesno ${unicode:-${UNICODE}}; then
 | 
			
		||||
			echo "" > "$RC_LIBEXECDIR"/console/unicode
 | 
			
		||||
		else
 | 
			
		||||
			rm -f "$RC_LIBEXECDIR"/console/unicode
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
	eend 0
 | 
			
		||||
}
 | 
			
		||||
@@ -49,7 +49,7 @@ start()
 | 
			
		||||
	fi
 | 
			
		||||
	ebegin "Saving dependency cache"
 | 
			
		||||
	local rc=0 save=
 | 
			
		||||
	for x in depconfig deptree rc.log shutdowntime softlevel; do
 | 
			
		||||
	for x in shutdowntime softlevel rc.log; do
 | 
			
		||||
		[ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x"
 | 
			
		||||
	done
 | 
			
		||||
	if [ -n "$save" ]; then
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	after clock root
 | 
			
		||||
	after clock
 | 
			
		||||
	before localmount
 | 
			
		||||
	keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -vserver
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -101,7 +101,7 @@ mount_misc()
 | 
			
		||||
	if [ -d /sys/firmware/efi/efivars ] &&
 | 
			
		||||
		! mountinfo -q /sys/firmware/efi/efivars; then
 | 
			
		||||
		ebegin "Mounting efivarfs filesystem"
 | 
			
		||||
		mount -n -t efivarfs -o ${sysfs_opts} \
 | 
			
		||||
		mount -n -t efivarfs -o ro \
 | 
			
		||||
			efivarfs /sys/firmware/efi/efivars 2> /dev/null
 | 
			
		||||
		eend 0
 | 
			
		||||
	fi
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,8 @@ ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
 | 
			
		||||
depend()
 | 
			
		||||
{
 | 
			
		||||
	keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
 | 
			
		||||
	after devfs
 | 
			
		||||
	use root
 | 
			
		||||
	after bootmisc clock
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start()
 | 
			
		||||
 
 | 
			
		||||
@@ -119,9 +119,6 @@ The amount of time, in milliseconds, s6-svc should wait for the service
 | 
			
		||||
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
 | 
			
		||||
@@ -173,23 +170,6 @@ variable is set.
 | 
			
		||||
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
 | 
			
		||||
@@ -614,7 +594,7 @@ rc_net_tap1_provide="!net"
 | 
			
		||||
# It's also possible to negate keywords. This is mainly useful for prefix
 | 
			
		||||
# users testing OpenRC.
 | 
			
		||||
rc_keyword="!-prefix"
 | 
			
		||||
# This can also be used to block a script from running in all
 | 
			
		||||
# This can also be used to block a script from runining in all
 | 
			
		||||
# containers except one or two
 | 
			
		||||
rc_keyword="!-containers !-docker"
 | 
			
		||||
.Ed
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@
 | 
			
		||||
.Nd bring the system down
 | 
			
		||||
.Sh SYNOPSIS
 | 
			
		||||
.Nm
 | 
			
		||||
.Op Fl c , -cancel
 | 
			
		||||
.Op Fl d , -no-write
 | 
			
		||||
.Op Fl D , -dry-run
 | 
			
		||||
.Op Fl H , -halt
 | 
			
		||||
@@ -33,8 +32,6 @@ is the utility that communicates with
 | 
			
		||||
to bring down the system or instruct openrc-init to re-execute itself.
 | 
			
		||||
It supports the following options:
 | 
			
		||||
.Bl -tag -width "poweroff"
 | 
			
		||||
.It Fl c , -cancel
 | 
			
		||||
Cancel a pending shutdown.
 | 
			
		||||
.It Fl d , -no-write
 | 
			
		||||
Do not write the wtmp boot record.
 | 
			
		||||
.It Fl D , -dry-run
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,6 @@
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl d , -debug
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl D , -nodeps
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Op Fl i , -ifexists
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
@@ -40,21 +32,9 @@
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Op Fl s , -ifstarted
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Op Fl S , -ifstopped
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl e , -exists
 | 
			
		||||
.Ar service
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl Z , -dry-run
 | 
			
		||||
.Ar service cmd
 | 
			
		||||
.Op Ar ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl l , -list
 | 
			
		||||
.Nm
 | 
			
		||||
.Fl r , -resolve
 | 
			
		||||
@@ -88,15 +68,6 @@ return 0 if it can find
 | 
			
		||||
otherwise -1.
 | 
			
		||||
.Fl r , -resolve
 | 
			
		||||
does the same and also prints the full path of the service to stdout.
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl d , -debug
 | 
			
		||||
sets -x when running the service script(s).
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl D , -nodeps
 | 
			
		||||
ignores dependencies when running the service.
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl Z , -dry-run
 | 
			
		||||
displays commands rather than executing them.
 | 
			
		||||
.Sh SEE ALSO
 | 
			
		||||
.Xr openrc 8 ,
 | 
			
		||||
.Xr stdout 3
 | 
			
		||||
 
 | 
			
		||||
@@ -43,8 +43,6 @@ List all defined runlevels.
 | 
			
		||||
Show all manually started services.
 | 
			
		||||
.It Fl r , -runlevel
 | 
			
		||||
Print the current runlevel name.
 | 
			
		||||
.It Fl S , -supervised
 | 
			
		||||
Show all supervised services.
 | 
			
		||||
.It Fl s , -servicelist
 | 
			
		||||
Show all services.
 | 
			
		||||
.It Fl u , -unused
 | 
			
		||||
 
 | 
			
		||||
@@ -131,34 +131,9 @@ Modifies the scheduling priority of the daemon.
 | 
			
		||||
.It Fl 1 , -stdout Ar logfile
 | 
			
		||||
Redirect the standard output of the process to logfile when started with
 | 
			
		||||
.Fl background .
 | 
			
		||||
The logfile Must be an absolute pathname, but relative to the path
 | 
			
		||||
optionally given with
 | 
			
		||||
Must be an absolute pathname, but relative to the path optionally given with
 | 
			
		||||
.Fl r , -chroot .
 | 
			
		||||
The logfile can also be a named pipe.
 | 
			
		||||
.It Fl 2 , -stderr Ar logfile
 | 
			
		||||
Redirect the standard error of the process to logfile when started with
 | 
			
		||||
.Fl background .
 | 
			
		||||
The logfile must be an absolute pathname, but relative to the path
 | 
			
		||||
optionally given with
 | 
			
		||||
.Fl r , -chroot .
 | 
			
		||||
The logfile can also be a named pipe.
 | 
			
		||||
.It Fl 3 , -stdout-logger Ar cmd
 | 
			
		||||
Run cmd as a child process redirecting the standard output to the
 | 
			
		||||
standard input of cmd when started with
 | 
			
		||||
.Fl background .
 | 
			
		||||
Cmd must be an absolute pathname, but relative to the path optionally given with
 | 
			
		||||
.Fl r , -chroot .
 | 
			
		||||
This process must be prepared to accept input on stdin and be able to
 | 
			
		||||
log it or send it to another location.
 | 
			
		||||
.It Fl 4 , -stderr-logger Ar cmd
 | 
			
		||||
Run cmd as a child process and 
 | 
			
		||||
Redirect the standard error of the process to the standard input of cmd
 | 
			
		||||
when started with
 | 
			
		||||
.Fl background .
 | 
			
		||||
Cmd must be an absolute pathname, but relative to the path optionally given with
 | 
			
		||||
.Fl r , -chroot .
 | 
			
		||||
This process must be prepared to accept input on stdin and be able to
 | 
			
		||||
log it or send it to another location.
 | 
			
		||||
.It Fl w , -wait Ar milliseconds
 | 
			
		||||
Wait
 | 
			
		||||
.Ar milliseconds
 | 
			
		||||
@@ -176,7 +151,6 @@ These options are only used for stopping daemons:
 | 
			
		||||
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
 | 
			
		||||
The retry specification can be either a timeout in seconds or multiple
 | 
			
		||||
signal/timeout pairs (like SIGTERM/5).
 | 
			
		||||
If this option is not given, the default is SIGTERM/5.
 | 
			
		||||
.El
 | 
			
		||||
.Sh ENVIRONMENT
 | 
			
		||||
.Va SSD_IONICELEVEL
 | 
			
		||||
 
 | 
			
		||||
@@ -16,11 +16,6 @@
 | 
			
		||||
.Nd starts a daemon and restarts it if it crashes
 | 
			
		||||
.Sh SYNOPSIS
 | 
			
		||||
.Nm
 | 
			
		||||
servicename
 | 
			
		||||
.Fl a , -healthcheck-timer
 | 
			
		||||
.Ar seconds
 | 
			
		||||
.Fl A , -healthcheck-delay
 | 
			
		||||
.Ar seconds
 | 
			
		||||
.Fl D , -respawn-delay
 | 
			
		||||
.Ar seconds
 | 
			
		||||
.Fl d , -chdir
 | 
			
		||||
@@ -37,6 +32,8 @@ servicename
 | 
			
		||||
.Ar count
 | 
			
		||||
.Fl N , -nicelevel
 | 
			
		||||
.Ar level
 | 
			
		||||
.Fl p , -pidfile
 | 
			
		||||
.Ar pidfile
 | 
			
		||||
.Fl P , -respawn-period
 | 
			
		||||
.Ar seconds
 | 
			
		||||
.Fl R , -retry
 | 
			
		||||
@@ -54,15 +51,10 @@ servicename
 | 
			
		||||
.Op Fl -
 | 
			
		||||
.Op Ar arguments
 | 
			
		||||
.Nm
 | 
			
		||||
servicename
 | 
			
		||||
.Fl K , -stop
 | 
			
		||||
.Ar daemon
 | 
			
		||||
.Fl r , -chroot
 | 
			
		||||
.Ar chrootpath
 | 
			
		||||
.Nm
 | 
			
		||||
servicename
 | 
			
		||||
.Fl s , -signal
 | 
			
		||||
.Ar signal
 | 
			
		||||
.Fl p , -pidfile
 | 
			
		||||
.Ar pidfile
 | 
			
		||||
.Fl r , -chroot
 | 
			
		||||
.Ar chrootpath
 | 
			
		||||
.Sh DESCRIPTION
 | 
			
		||||
@@ -70,15 +62,22 @@ servicename
 | 
			
		||||
provides a consistent method of starting, stopping and restarting
 | 
			
		||||
daemons. If
 | 
			
		||||
.Fl K , -stop
 | 
			
		||||
or
 | 
			
		||||
.Fl s , -signal
 | 
			
		||||
is not provided, then we assume we are starting the daemon.
 | 
			
		||||
.Nm
 | 
			
		||||
only works with daemons which do not fork. If your daemon has options to
 | 
			
		||||
tell it not to fork, it should be configured to not fork.
 | 
			
		||||
only works with daemons which do not fork. Also, it uses its own pid
 | 
			
		||||
file, so the daemon should not write a pid file, or the pid file passed
 | 
			
		||||
to 
 | 
			
		||||
.Nm
 | 
			
		||||
should not be the one the daemon writes.
 | 
			
		||||
.Pp
 | 
			
		||||
Here are the options to specify the daemon and how it should start or stop:
 | 
			
		||||
.Bl -tag -width indent
 | 
			
		||||
.It Fl p , -pidfile Ar pidfile
 | 
			
		||||
When starting, we write a
 | 
			
		||||
.Ar pidfile
 | 
			
		||||
so we know which supervisor to stop.  When stopping we only stop the pid(s)
 | 
			
		||||
listed in the
 | 
			
		||||
.Ar pidfile .
 | 
			
		||||
.It Fl u , -user Ar user Ns Op : Ns Ar group
 | 
			
		||||
Start the daemon as the
 | 
			
		||||
.Ar user
 | 
			
		||||
@@ -91,11 +90,6 @@ Print the action(s) that are taken just before doing them.
 | 
			
		||||
.Pp
 | 
			
		||||
The options are as follows:
 | 
			
		||||
.Bl -tag -width indent
 | 
			
		||||
.Fl a , -healthcheck-timer Ar seconds
 | 
			
		||||
Run the healthcheck() command, possibly followed by the unhealthy()
 | 
			
		||||
command every time this number of seconds passes.
 | 
			
		||||
.Fl A , -healthcheck-delay Ar seconds
 | 
			
		||||
Wait this long before the first health check.
 | 
			
		||||
.It Fl D , -respawn-delay Ar seconds
 | 
			
		||||
wait this number of seconds before restarting a daemon after it crashes.
 | 
			
		||||
The default is 0.
 | 
			
		||||
@@ -112,31 +106,23 @@ Data can be from 0 to 7 inclusive.
 | 
			
		||||
.It Fl k , -umask Ar mode
 | 
			
		||||
Set the umask of the daemon.
 | 
			
		||||
.It Fl m , -respawn-max Ar count
 | 
			
		||||
Sets the maximum number of times a daemon will be respawned. If a daemon
 | 
			
		||||
crashes more than this number of times,
 | 
			
		||||
Sets the maximum number of times a daemon will be respawned during a
 | 
			
		||||
respawn period. If a daemon dies more than this number of times during a
 | 
			
		||||
respawn period,
 | 
			
		||||
.Nm
 | 
			
		||||
will give up and exit. The default is 10 and 0 means unlimited.
 | 
			
		||||
.Pp
 | 
			
		||||
If respawn-period is also set, more than respawn-max crashes must occur
 | 
			
		||||
during respawn-period seconds to cause
 | 
			
		||||
.Nm
 | 
			
		||||
to give up and exit.
 | 
			
		||||
will give up trying to respawn it and exit. The default is 10, and 0
 | 
			
		||||
means unlimited.
 | 
			
		||||
.It Fl N , -nicelevel Ar level
 | 
			
		||||
Modifies the scheduling priority of the daemon.
 | 
			
		||||
.It Fl P , -respawn-period Ar seconds
 | 
			
		||||
Sets the length of a respawn period. See the
 | 
			
		||||
Sets the length of a respawn period. The default is 10 seconds. See the
 | 
			
		||||
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 and chdir should be relative to the chroot.
 | 
			
		||||
.It Fl  , -signal Ar signal
 | 
			
		||||
Instruct a supervisor to signal the process it is supervising. The
 | 
			
		||||
process to communicate with is determined by the name of the service
 | 
			
		||||
taken from the RC_SVCNAME environment variable.
 | 
			
		||||
as the path to the daemon, chdir and pidfile, should be relative to the chroot.
 | 
			
		||||
.It Fl u , -user Ar user
 | 
			
		||||
Start the daemon as the specified user.
 | 
			
		||||
.It Fl 1 , -stdout Ar logfile
 | 
			
		||||
@@ -149,6 +135,7 @@ The same thing as
 | 
			
		||||
.Fl 1 , -stdout
 | 
			
		||||
but with the standard error output.
 | 
			
		||||
.El
 | 
			
		||||
.El
 | 
			
		||||
.Sh ENVIRONMENT
 | 
			
		||||
.Va SSD_NICELEVEL
 | 
			
		||||
can also set the scheduling priority of the daemon, but the command line
 | 
			
		||||
@@ -170,16 +157,15 @@ make sure the settings mmake sense. For example, a respawn period of 5
 | 
			
		||||
seconds with a respawn max of 10 and a respawn delay of 1 second leads
 | 
			
		||||
to infinite respawning since there can never be 10 respawns within 5
 | 
			
		||||
seconds.
 | 
			
		||||
.Sh NOTE
 | 
			
		||||
Invoking supervise-daemon requires both the RC_SVCNAME  environment
 | 
			
		||||
variable to be set and the name of the service as the first argument on
 | 
			
		||||
the command line, so it is best to invoke it inside a service script
 | 
			
		||||
rather than manually.
 | 
			
		||||
.Sh SEE ALSO
 | 
			
		||||
.Xr chdir 2 ,
 | 
			
		||||
.Xr chroot 2 ,
 | 
			
		||||
.Xr getopt 3 ,
 | 
			
		||||
.Xr nice 2 ,
 | 
			
		||||
.Xr rc_find_pids 3
 | 
			
		||||
.Sh BUGS
 | 
			
		||||
.Nm
 | 
			
		||||
cannot stop an interpreted daemon that no longer exists without a pidfile.
 | 
			
		||||
.Sh HISTORY
 | 
			
		||||
.Nm
 | 
			
		||||
first appeared in Debian.
 | 
			
		||||
 
 | 
			
		||||
@@ -12,4 +12,4 @@
 | 
			
		||||
 | 
			
		||||
include ${MK}/os-BSD.mk
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+=	-D_BSD_SOURCE
 | 
			
		||||
CPPFLAGS+=	-D_WITH_GETLINE
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,6 @@
 | 
			
		||||
SFX=		.GNU-kFreeBSD.in
 | 
			
		||||
PKG_PREFIX?=	/usr
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+=	-D_BSD_SOURCE
 | 
			
		||||
CPPFLAGS+=	-D_BSD_SOURCE -D_XOPEN_SOURCE=700
 | 
			
		||||
LIBDL=		-Wl,-Bdynamic -ldl
 | 
			
		||||
LIBKVM?=
 | 
			
		||||
 
 | 
			
		||||
@@ -11,5 +11,5 @@
 | 
			
		||||
SFX=		.GNU.in
 | 
			
		||||
PKG_PREFIX?=	/usr
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -DMAXPATHLEN=4096 -DPATH_MAX=4096
 | 
			
		||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -DMAXPATHLEN=4096 -DPATH_MAX=4096
 | 
			
		||||
LIBDL=		-Wl,-Bdynamic -ldl
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
SFX=		.Linux.in
 | 
			
		||||
PKG_PREFIX?=	/usr
 | 
			
		||||
 | 
			
		||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L
 | 
			
		||||
CPPFLAGS+=	-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700
 | 
			
		||||
LIBDL=		-Wl,-Bdynamic -ldl
 | 
			
		||||
 | 
			
		||||
ifeq (${MKSELINUX},yes)
 | 
			
		||||
 
 | 
			
		||||
@@ -45,20 +45,20 @@ SBINDIR?=		${PREFIX}/sbin
 | 
			
		||||
SBINMODE?=		0755
 | 
			
		||||
 | 
			
		||||
INCDIR?=		${UPREFIX}/include
 | 
			
		||||
INCMODE?=		0644
 | 
			
		||||
INCMODE?=		0444
 | 
			
		||||
 | 
			
		||||
_LIBNAME_SH=		case `readlink /lib` in /lib64|lib64) echo "lib64";; *) echo "lib";; esac
 | 
			
		||||
_LIBNAME:=		$(shell ${_LIBNAME_SH})
 | 
			
		||||
LIBNAME?=		${_LIBNAME}
 | 
			
		||||
LIBDIR?=		${UPREFIX}/${LIBNAME}
 | 
			
		||||
LIBMODE?=		0644
 | 
			
		||||
LIBMODE?=		0444
 | 
			
		||||
SHLIBDIR?=		${PREFIX}/${LIBNAME}
 | 
			
		||||
 | 
			
		||||
LIBEXECDIR?=		${PREFIX}/libexec/rc
 | 
			
		||||
 | 
			
		||||
MANPREFIX?=		${UPREFIX}/share
 | 
			
		||||
MANDIR?=		${MANPREFIX}/man
 | 
			
		||||
MANMODE?=		0644
 | 
			
		||||
MANMODE?=		0444
 | 
			
		||||
 | 
			
		||||
BASHCOMPDIR?=		${UPREFIX}/share/bash-completion/completions
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -36,8 +36,7 @@ BOOT-FreeBSD+=	hostid modules newsyslog savecore syslogd
 | 
			
		||||
# FreeBSD specific stuff
 | 
			
		||||
BOOT-FreeBSD+=	adjkerntz dumpon syscons
 | 
			
		||||
 | 
			
		||||
BOOT-Linux+=	binfmt hwclock keymaps modules mtab procfs save-keymaps \
 | 
			
		||||
	save-termencoding termencoding
 | 
			
		||||
BOOT-Linux+=	binfmt hwclock keymaps modules mtab procfs termencoding
 | 
			
		||||
SHUTDOWN-Linux=	killprocs mount-ro
 | 
			
		||||
SYSINIT-Linux=	devfs cgroups dmesg sysfs
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,9 +29,7 @@ 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.
 | 
			
		||||
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:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								sh/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								sh/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,6 @@
 | 
			
		||||
functions.sh
 | 
			
		||||
gendepends.sh
 | 
			
		||||
rc-functions.sh
 | 
			
		||||
openrc-run.sh
 | 
			
		||||
cgroup-release-agent.sh
 | 
			
		||||
init.sh
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
DIR=	${LIBEXECDIR}/sh
 | 
			
		||||
SRCS=	init.sh.in functions.sh.in gendepends.sh.in \
 | 
			
		||||
	openrc-run.sh.in ${SRCS-${OS}}
 | 
			
		||||
	openrc-run.sh.in rc-functions.sh.in ${SRCS-${OS}}
 | 
			
		||||
INC=	rc-mount.sh functions.sh rc-functions.sh runit.sh s6.sh \
 | 
			
		||||
		start-stop-daemon.sh supervise-daemon.sh
 | 
			
		||||
BIN=	gendepends.sh init.sh openrc-run.sh ${BIN-${OS}}
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ yesno()
 | 
			
		||||
	case "$value" in
 | 
			
		||||
		[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0;;
 | 
			
		||||
		[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1;;
 | 
			
		||||
		*) vewarn "\$$1 is not set properly"; return 2;;
 | 
			
		||||
		*) vewarn "\$$1 is not set properly"; return 1;;
 | 
			
		||||
	esac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -133,10 +133,11 @@ _status()
 | 
			
		||||
	elif service_inactive; then
 | 
			
		||||
		ewarn "status: inactive"
 | 
			
		||||
		return 16
 | 
			
		||||
	elif service_crashed; then
 | 
			
		||||
		eerror "status: crashed"
 | 
			
		||||
		return 32
 | 
			
		||||
	elif service_started; then
 | 
			
		||||
		if service_crashed; then
 | 
			
		||||
			eerror "status: crashed"
 | 
			
		||||
			return 32
 | 
			
		||||
		fi
 | 
			
		||||
		einfo "status: started"
 | 
			
		||||
		return 0
 | 
			
		||||
	else
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ cgroup_set_values()
 | 
			
		||||
	while [ -n "$1" ] && [ "$controller" != "cpuacct" ]; do
 | 
			
		||||
		case "$1" in
 | 
			
		||||
			$controller.*)
 | 
			
		||||
				if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] &&
 | 
			
		||||
				if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] && 
 | 
			
		||||
					[ -n "${val}" ]; then
 | 
			
		||||
					veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
 | 
			
		||||
					printf "%s" "$val" > "$cgroup/$name"
 | 
			
		||||
@@ -184,17 +184,18 @@ cgroup2_set_limits()
 | 
			
		||||
	cgroup_path="$(cgroup2_find_path)"
 | 
			
		||||
	[ -d "${cgroup_path}" ] || return 0
 | 
			
		||||
	rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
 | 
			
		||||
	local OIFS="$IFS"
 | 
			
		||||
	IFS="
 | 
			
		||||
"
 | 
			
		||||
	[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
 | 
			
		||||
	[ -f "${rc_cgroup_path}"/cgroup.procs ] &&
 | 
			
		||||
		printf 0 > "${rc_cgroup_path}"/cgroup.procs
 | 
			
		||||
	[ -z "${rc_cgroup_settings}" ] && return 0
 | 
			
		||||
	echo "${rc_cgroup_settings}" | while read -r key value; do
 | 
			
		||||
		[ -z "${key}" ] && continue
 | 
			
		||||
		[ -z "${value}" ] && continue
 | 
			
		||||
		[ ! -f "${rc_cgroup_path}/${key}" ] && continue
 | 
			
		||||
		veinfo "${RC_SVCNAME}: cgroups: setting ${key} to ${value}"
 | 
			
		||||
		printf "%s\n" "${value}" > "${rc_cgroup_path}/${key}"
 | 
			
		||||
	printf "%d" 0 > "${rc_cgroup_path}/cgroup.procs"
 | 
			
		||||
	echo "${rc_cgroup_settings}" | while IFS="$OIFS" read -r key value; do
 | 
			
		||||
		[ -z "${key}" ] || [ -z "${value}" ] && continue
 | 
			
		||||
		[ ! -e "${rc_cgroup_path}/${key}" ] && continue
 | 
			
		||||
		veinfo "${RC_SVCNAME}: cgroups: ${key} ${value}"
 | 
			
		||||
		printf "%s" "${value}" > "${rc_cgroup_path}/${key}"
 | 
			
		||||
	done
 | 
			
		||||
	IFS="$OIFS"
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,42 @@
 | 
			
		||||
# Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
 | 
			
		||||
# Released under the 2-clause BSD license.
 | 
			
		||||
 | 
			
		||||
has_addon()
 | 
			
		||||
{
 | 
			
		||||
	[ -e /@LIB@/rc/addons/"$1".sh -o -e /@LIB@/rcscripts/addons/"$1".sh ]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_addon_warn()
 | 
			
		||||
{
 | 
			
		||||
	eindent
 | 
			
		||||
	ewarn "$RC_SVCNAME uses addon code which is deprecated"
 | 
			
		||||
	ewarn "and may not be available in the future."
 | 
			
		||||
	eoutdent
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
import_addon()
 | 
			
		||||
{
 | 
			
		||||
	if [ -e /@LIB@/rc/addons/"$1".sh ]; then
 | 
			
		||||
		_addon_warn
 | 
			
		||||
		. /@LIB@/rc/addons/"$1".sh
 | 
			
		||||
	elif [ -e /@LIB@/rcscripts/addons/"$1".sh ]; then
 | 
			
		||||
		_addon_warn
 | 
			
		||||
		. /@LIB@/rcscripts/addons/"$1".sh
 | 
			
		||||
	else
 | 
			
		||||
		return 1
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start_addon()
 | 
			
		||||
{
 | 
			
		||||
	( import_addon "$1-start" )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
stop_addon()
 | 
			
		||||
{
 | 
			
		||||
	( import_addon "$1-stop" )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
net_fs_list="afs ceph cifs coda davfs fuse fuse.sshfs gfs glusterfs lustre
 | 
			
		||||
ncpfs nfs nfs4 ocfs2 shfs smbfs"
 | 
			
		||||
is_net_fs()
 | 
			
		||||
							
								
								
									
										2
									
								
								sh/s6.sh
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								sh/s6.sh
									
									
									
									
									
								
							@@ -57,7 +57,7 @@ s6_stop()
 | 
			
		||||
	ebegin "Stopping ${name:-$RC_SVCNAME}"
 | 
			
		||||
	s6-svc -d -wD -T ${s6_service_timeout_stop:-60000} "${s6_service_link}"
 | 
			
		||||
	set -- $(s6-svstat "${s6_service_link}")
 | 
			
		||||
	[ "$1" = "up" ] &&
 | 
			
		||||
	[ "$1" = "up" ] && 
 | 
			
		||||
		yesno "${s6_force_kill:-yes}" &&
 | 
			
		||||
			_s6_force_kill "$@"
 | 
			
		||||
	set -- $(s6-svstat "${s6_service_link}")
 | 
			
		||||
 
 | 
			
		||||
@@ -38,10 +38,6 @@ 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.
 | 
			
		||||
@@ -51,8 +47,6 @@ ssd_start()
 | 
			
		||||
		${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 \
 | 
			
		||||
 
 | 
			
		||||
@@ -10,8 +10,6 @@
 | 
			
		||||
# This file may not be copied, modified, propagated, or distributed
 | 
			
		||||
#    except according to the terms contained in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
extra_commands="healthcheck unhealthy ${extra_commands}"
 | 
			
		||||
 | 
			
		||||
supervise_start()
 | 
			
		||||
{
 | 
			
		||||
	if [ -z "$command" ]; then
 | 
			
		||||
@@ -34,11 +32,9 @@ supervise_start()
 | 
			
		||||
		${respawn_delay:+--respawn-delay} $respawn_delay \
 | 
			
		||||
		${respawn_max:+--respawn-max} $respawn_max \
 | 
			
		||||
		${respawn_period:+--respawn-period} $respawn_period \
 | 
			
		||||
		${healthcheck_delay:+--healthcheck-delay} $healthcheck_delay \
 | 
			
		||||
		${healthcheck_timer:+--healthcheck-timer} $healthcheck_timer \
 | 
			
		||||
		${command_user+--user} $command_user \
 | 
			
		||||
		${umask+--umask} $umask \
 | 
			
		||||
		${supervise_daemon_args:-${start_stop_daemon_args}} \
 | 
			
		||||
		$supervise_daemon_args \
 | 
			
		||||
		$command \
 | 
			
		||||
		-- $command_args $command_args_foreground
 | 
			
		||||
	rc=$?
 | 
			
		||||
@@ -55,9 +51,11 @@ supervise_stop()
 | 
			
		||||
	local startpidfile="$(service_get_value "pidfile")"
 | 
			
		||||
	chroot="${startchroot:-$chroot}"
 | 
			
		||||
	pidfile="${startpidfile:-$pidfile}"
 | 
			
		||||
	[ -n "$pidfile" ] || return 0
 | 
			
		||||
	ebegin "Stopping ${name:-$RC_SVCNAME}"
 | 
			
		||||
	supervise-daemon "${RC_SVCNAME}" --stop \
 | 
			
		||||
		${pidfile:+--pidfile} $chroot$pidfile
 | 
			
		||||
		${pidfile:+--pidfile} $chroot$pidfile \
 | 
			
		||||
		${stopsig:+--signal} $stopsig
 | 
			
		||||
 | 
			
		||||
	eend $? "Failed to stop ${name:-$RC_SVCNAME}"
 | 
			
		||||
}
 | 
			
		||||
@@ -100,13 +98,3 @@ supervise_status()
 | 
			
		||||
		return 3
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
healthcheck()
 | 
			
		||||
{
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unhealthy()
 | 
			
		||||
{
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -66,6 +66,9 @@ int parse_mode(mode_t *, char *);
 | 
			
		||||
/* Handy function so we can wrap einfo around our deptree */
 | 
			
		||||
RC_DEPTREE *_rc_deptree_load (int, int *);
 | 
			
		||||
 | 
			
		||||
/* Test to see if we can see pid 1 or not */
 | 
			
		||||
bool _rc_can_find_pids(void);
 | 
			
		||||
 | 
			
		||||
RC_SERVICE lookup_service_state(const char *service);
 | 
			
		||||
void from_time_t(char *time_string, time_t tv);
 | 
			
		||||
time_t to_time_t(char *timestring);
 | 
			
		||||
 
 | 
			
		||||
@@ -883,7 +883,7 @@ eindent(void)
 | 
			
		||||
{
 | 
			
		||||
	char *env = getenv("EINFO_INDENT");
 | 
			
		||||
	int amount = 0;
 | 
			
		||||
	char *num;
 | 
			
		||||
	char num[10];
 | 
			
		||||
 | 
			
		||||
	if (env) {
 | 
			
		||||
		errno = 0;
 | 
			
		||||
@@ -894,9 +894,8 @@ eindent(void)
 | 
			
		||||
	amount += INDENT_WIDTH;
 | 
			
		||||
	if (amount > INDENT_MAX)
 | 
			
		||||
		amount = INDENT_MAX;
 | 
			
		||||
	xasprintf(&num, "%08d", amount);
 | 
			
		||||
	snprintf(num, 10, "%08d", amount);
 | 
			
		||||
	setenv("EINFO_INDENT", num, 1);
 | 
			
		||||
	free(num);
 | 
			
		||||
}
 | 
			
		||||
hidden_def(eindent)
 | 
			
		||||
 | 
			
		||||
@@ -904,7 +903,7 @@ void eoutdent(void)
 | 
			
		||||
{
 | 
			
		||||
	char *env = getenv("EINFO_INDENT");
 | 
			
		||||
	int amount = 0;
 | 
			
		||||
	char *num = NULL;
 | 
			
		||||
	char num[10];
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
 | 
			
		||||
	if (!env)
 | 
			
		||||
@@ -918,9 +917,8 @@ void eoutdent(void)
 | 
			
		||||
	if (amount <= 0)
 | 
			
		||||
		unsetenv("EINFO_INDENT");
 | 
			
		||||
	else {
 | 
			
		||||
		xasprintf(&num, "%08d", amount);
 | 
			
		||||
		snprintf(num, 10, "%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 = NULL;
 | 
			
		||||
	char buffer[32];
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	int c;
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
 | 
			
		||||
	exec = basename_c(exec);
 | 
			
		||||
	xasprintf(&buffer, "/proc/%d/stat", pid);
 | 
			
		||||
	snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
 | 
			
		||||
	if ((fp = fopen(buffer, "r"))) {
 | 
			
		||||
		while ((c = getc(fp)) != EOF && c != '(')
 | 
			
		||||
			;
 | 
			
		||||
@@ -41,27 +41,23 @@ 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 = NULL;
 | 
			
		||||
	char cmdline[32];
 | 
			
		||||
	int fd;
 | 
			
		||||
	char buffer[PATH_MAX];
 | 
			
		||||
	char *p;
 | 
			
		||||
	ssize_t bytes;
 | 
			
		||||
 | 
			
		||||
	xasprintf(&cmdline, "/proc/%u/cmdline", pid);
 | 
			
		||||
	if ((fd = open(cmdline, O_RDONLY)) < 0) {
 | 
			
		||||
		free(cmdline);
 | 
			
		||||
	snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
 | 
			
		||||
	if ((fd = open(cmdline, O_RDONLY)) < 0)
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	bytes = read(fd, buffer, sizeof(buffer));
 | 
			
		||||
	close(fd);
 | 
			
		||||
	free(cmdline);
 | 
			
		||||
	if (bytes == -1)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
@@ -92,7 +88,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 = NULL;
 | 
			
		||||
	char buffer[PATH_MAX];
 | 
			
		||||
	struct stat sb;
 | 
			
		||||
	pid_t openrc_pid = 0;
 | 
			
		||||
	char *pp;
 | 
			
		||||
@@ -153,22 +149,18 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (pid != 0 && pid != p)
 | 
			
		||||
			continue;
 | 
			
		||||
		xasprintf(&buffer, "/proc/%d/ns/pid", p);
 | 
			
		||||
		snprintf(buffer, sizeof(buffer), "/proc/%d/ns/pid", p);
 | 
			
		||||
		if (exists(buffer)) {
 | 
			
		||||
			rc = readlink(buffer, proc_ns, sizeof(proc_ns));
 | 
			
		||||
			if (rc <= 0)
 | 
			
		||||
				proc_ns[0] = '\0';
 | 
			
		||||
		}
 | 
			
		||||
		free(buffer);
 | 
			
		||||
		if (strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns))
 | 
			
		||||
			continue;
 | 
			
		||||
		if (uid) {
 | 
			
		||||
			xasprintf(&buffer, "/proc/%d", p);
 | 
			
		||||
			if (stat(buffer, &sb) != 0 || sb.st_uid != uid) {
 | 
			
		||||
				free(buffer);
 | 
			
		||||
			snprintf(buffer, sizeof(buffer), "/proc/%d", p);
 | 
			
		||||
			if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			free(buffer);
 | 
			
		||||
		}
 | 
			
		||||
		if (exec && !pid_is_exec(p, exec))
 | 
			
		||||
			continue;
 | 
			
		||||
@@ -177,10 +169,9 @@ 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) {
 | 
			
		||||
			xasprintf(&buffer, "/proc/%d/status", p);
 | 
			
		||||
			snprintf(buffer, sizeof(buffer), "/proc/%d/status", p);
 | 
			
		||||
			if (exists(buffer)) {
 | 
			
		||||
				fp = fopen(buffer, "r");
 | 
			
		||||
				free(buffer);
 | 
			
		||||
				if (! fp)
 | 
			
		||||
					continue;
 | 
			
		||||
				while (! feof(fp)) {
 | 
			
		||||
@@ -324,13 +315,12 @@ _match_daemon(const char *path, const char *file, RC_STRINGLIST *match)
 | 
			
		||||
{
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	char *ffile = NULL;
 | 
			
		||||
	char ffile[PATH_MAX];
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	RC_STRING *m;
 | 
			
		||||
 | 
			
		||||
	xasprintf(&ffile, "%s/%s", path, file);
 | 
			
		||||
	snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
 | 
			
		||||
	fp = fopen(ffile, "r");
 | 
			
		||||
	free(ffile);
 | 
			
		||||
 | 
			
		||||
	if (!fp)
 | 
			
		||||
		return false;
 | 
			
		||||
@@ -356,22 +346,29 @@ _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) {
 | 
			
		||||
		xasprintf(&m, "exec=%s", exec);
 | 
			
		||||
		l = strlen(exec) + 6;
 | 
			
		||||
		m = xmalloc(sizeof(char) * l);
 | 
			
		||||
		snprintf(m, l, "exec=%s", exec);
 | 
			
		||||
		rc_stringlist_add(match, m);
 | 
			
		||||
		free(m);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (argv && argv[i]) {
 | 
			
		||||
		xasprintf(&m, "argv_0=%s", argv[i++]);
 | 
			
		||||
		l = strlen(*argv) + strlen("argv_=") + 16;
 | 
			
		||||
		m = xmalloc(sizeof(char) * l);
 | 
			
		||||
		snprintf(m, l, "argv_0=%s", argv[i++]);
 | 
			
		||||
		rc_stringlist_add(match, m);
 | 
			
		||||
		free(m);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pidfile) {
 | 
			
		||||
		xasprintf(&m, "pidfile=%s", pidfile);
 | 
			
		||||
		l = strlen(pidfile) + 9;
 | 
			
		||||
		m = xmalloc(sizeof(char) * l);
 | 
			
		||||
		snprintf(m, l, "pidfile=%s", pidfile);
 | 
			
		||||
		rc_stringlist_add(match, m);
 | 
			
		||||
		free(m);
 | 
			
		||||
	}
 | 
			
		||||
@@ -384,8 +381,8 @@ rc_service_daemon_set(const char *service, const char *exec,
 | 
			
		||||
    const char *const *argv,
 | 
			
		||||
    const char *pidfile, bool started)
 | 
			
		||||
{
 | 
			
		||||
	char *dirpath = NULL;
 | 
			
		||||
	char *file = NULL;
 | 
			
		||||
	char dirpath[PATH_MAX];
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
	int nfiles = 0;
 | 
			
		||||
	char oldfile[PATH_MAX] = { '\0' };
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
@@ -400,7 +397,8 @@ rc_service_daemon_set(const char *service, const char *exec,
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xasprintf(&dirpath, RC_SVCDIR "/daemons/%s", basename_c(service));
 | 
			
		||||
	snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
 | 
			
		||||
	    basename_c(service));
 | 
			
		||||
 | 
			
		||||
	/* Regardless, erase any existing daemon info */
 | 
			
		||||
	if ((dp = opendir(dirpath))) {
 | 
			
		||||
@@ -409,7 +407,8 @@ rc_service_daemon_set(const char *service, const char *exec,
 | 
			
		||||
			if (d->d_name[0] == '.')
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			xasprintf(&file, "%s/%s", dirpath, d->d_name);
 | 
			
		||||
			snprintf(file, sizeof(file), "%s/%s",
 | 
			
		||||
			    dirpath, d->d_name);
 | 
			
		||||
			nfiles++;
 | 
			
		||||
 | 
			
		||||
			if (!*oldfile) {
 | 
			
		||||
@@ -422,7 +421,6 @@ 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);
 | 
			
		||||
@@ -431,7 +429,8 @@ rc_service_daemon_set(const char *service, const char *exec,
 | 
			
		||||
	/* Now store our daemon info */
 | 
			
		||||
	if (started) {
 | 
			
		||||
		if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
 | 
			
		||||
			xasprintf(&file, "%s/%03d", dirpath, nfiles + 1);
 | 
			
		||||
			snprintf(file, sizeof(file), "%s/%03d",
 | 
			
		||||
			    dirpath, nfiles + 1);
 | 
			
		||||
			if ((fp = fopen(file, "w"))) {
 | 
			
		||||
				fprintf(fp, "exec=");
 | 
			
		||||
				if (exec)
 | 
			
		||||
@@ -447,12 +446,10 @@ 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)
 | 
			
		||||
@@ -461,8 +458,8 @@ bool
 | 
			
		||||
rc_service_started_daemon(const char *service,
 | 
			
		||||
    const char *exec, const char *const *argv, int indx)
 | 
			
		||||
{
 | 
			
		||||
	char *dirpath = NULL;
 | 
			
		||||
	char *file = NULL;
 | 
			
		||||
	char dirpath[PATH_MAX];
 | 
			
		||||
	char file[16];
 | 
			
		||||
	RC_STRINGLIST *match;
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
	DIR *dp;
 | 
			
		||||
@@ -471,13 +468,13 @@ rc_service_started_daemon(const char *service,
 | 
			
		||||
	if (!service || !exec)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	xasprintf(&dirpath, RC_SVCDIR "/daemons/%s", basename_c(service));
 | 
			
		||||
	snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
 | 
			
		||||
	    basename_c(service));
 | 
			
		||||
	match = _match_list(exec, argv, NULL);
 | 
			
		||||
 | 
			
		||||
	if (indx > 0) {
 | 
			
		||||
		xasprintf(&file, "%03d", indx);
 | 
			
		||||
		snprintf(file, sizeof(file), "%03d", indx);
 | 
			
		||||
		retval = _match_daemon(dirpath, file, match);
 | 
			
		||||
		free(file);
 | 
			
		||||
	} else {
 | 
			
		||||
		if ((dp = opendir(dirpath))) {
 | 
			
		||||
			while ((d = readdir(dp))) {
 | 
			
		||||
@@ -492,7 +489,6 @@ rc_service_started_daemon(const char *service,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc_stringlist_free(match);
 | 
			
		||||
	free(dirpath);
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
librc_hidden_def(rc_service_started_daemon)
 | 
			
		||||
 
 | 
			
		||||
@@ -237,9 +237,13 @@ static void rc_config_set_value(RC_STRINGLIST *config, char *value)
 | 
			
		||||
		if (token[i] == '\n')
 | 
			
		||||
			token[i] = 0;
 | 
			
		||||
 | 
			
		||||
		xasprintf(&newline, "%s=%s", entry, token);
 | 
			
		||||
		i = strlen(entry) + strlen(token) + 2;
 | 
			
		||||
		newline = xmalloc(sizeof(char) * i);
 | 
			
		||||
		snprintf(newline, i, "%s=%s", entry, token);
 | 
			
		||||
	} else {
 | 
			
		||||
		xasprintf(&newline, "%s=", entry);
 | 
			
		||||
		i = strlen(entry) + 2;
 | 
			
		||||
		newline = xmalloc(sizeof(char) * i);
 | 
			
		||||
		snprintf(newline, i, "%s=", entry);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	replaced = false;
 | 
			
		||||
@@ -296,7 +300,8 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
 | 
			
		||||
 | 
			
		||||
		if (value != NULL) {
 | 
			
		||||
			len = varlen + strlen(value) + 2;
 | 
			
		||||
			xasprintf(&tmp, "%s=%s", override->value, value);
 | 
			
		||||
			tmp = xmalloc(sizeof(char) * len);
 | 
			
		||||
			snprintf(tmp, len, "%s=%s", override->value, value);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,6 @@ static const rc_service_state_name_t rc_service_state_names[] = {
 | 
			
		||||
	{ RC_SERVICE_HOTPLUGGED,  "hotplugged" },
 | 
			
		||||
	{ RC_SERVICE_FAILED,      "failed" },
 | 
			
		||||
	{ RC_SERVICE_SCHEDULED,   "scheduled"},
 | 
			
		||||
	{ RC_SERVICE_CRASHED,     "crashed"},
 | 
			
		||||
	{ 0, NULL}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -849,10 +848,6 @@ rc_service_state(const char *service)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (state & RC_SERVICE_STARTED) {
 | 
			
		||||
		if (rc_service_daemons_crashed(service) && errno != EACCES)
 | 
			
		||||
			state |= RC_SERVICE_CRASHED;
 | 
			
		||||
	}
 | 
			
		||||
	if (state & RC_SERVICE_STOPPED) {
 | 
			
		||||
		dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
 | 
			
		||||
		TAILQ_FOREACH(dir, dirs, entries) {
 | 
			
		||||
 
 | 
			
		||||
@@ -188,8 +188,7 @@ typedef enum
 | 
			
		||||
	/* Optional states service could also be in */
 | 
			
		||||
	RC_SERVICE_FAILED      = 0x0200,
 | 
			
		||||
	RC_SERVICE_SCHEDULED   = 0x0400,
 | 
			
		||||
	RC_SERVICE_WASINACTIVE = 0x0800,
 | 
			
		||||
	RC_SERVICE_CRASHED     = 0x1000,
 | 
			
		||||
	RC_SERVICE_WASINACTIVE = 0x0800
 | 
			
		||||
} RC_SERVICE;
 | 
			
		||||
 | 
			
		||||
/*! Add the service to the runlevel
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								src/rc/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/rc/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -56,7 +56,6 @@ 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-pipes.c \
 | 
			
		||||
		rc-plugin.c rc-service.c rc-status.c rc-update.c \
 | 
			
		||||
		rc-depend.c rc-logger.c rc-misc.c rc-plugin.c \
 | 
			
		||||
		rc-service.c rc-status.c rc-update.c \
 | 
			
		||||
		shell_var.c start-stop-daemon.c supervise-daemon.c swclock.c _usage.c
 | 
			
		||||
 | 
			
		||||
ifeq (${MKSELINUX},yes)
 | 
			
		||||
@@ -14,7 +14,7 @@ SRCS+=		rc-selinux.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq (${OS},Linux)
 | 
			
		||||
SRCS+=		kill_all.c openrc-init.c openrc-shutdown.c broadcast.c rc-wtmp.c
 | 
			
		||||
SRCS+=		kill_all.c openrc-init.c openrc-shutdown.c rc-wtmp.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
CLEANFILES=	version.h rc-selinux.o
 | 
			
		||||
@@ -41,7 +41,6 @@ RC_SBINPROGS=	mark_service_starting mark_service_started \
 | 
			
		||||
		mark_service_stopping mark_service_stopped \
 | 
			
		||||
		mark_service_inactive mark_service_wasinactive \
 | 
			
		||||
		mark_service_hotplugged mark_service_failed \
 | 
			
		||||
		mark_service_crashed \
 | 
			
		||||
		rc-abort swclock
 | 
			
		||||
 | 
			
		||||
ifeq (${OS},Linux)
 | 
			
		||||
@@ -124,8 +123,7 @@ is_older_than: is_older_than.o rc-misc.o
 | 
			
		||||
mark_service_starting mark_service_started \
 | 
			
		||||
mark_service_stopping mark_service_stopped \
 | 
			
		||||
mark_service_inactive mark_service_wasinactive \
 | 
			
		||||
mark_service_hotplugged mark_service_failed \
 | 
			
		||||
mark_service_crashed: do_mark_service.o rc-misc.o
 | 
			
		||||
mark_service_hotplugged mark_service_failed: do_mark_service.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
mountinfo: mountinfo.o _usage.o rc-misc.o
 | 
			
		||||
@@ -134,7 +132,7 @@ mountinfo: mountinfo.o _usage.o rc-misc.o
 | 
			
		||||
openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
openrc-shutdown: openrc-shutdown.o rc-misc.o _usage.o broadcast.o rc-wtmp.o
 | 
			
		||||
openrc-shutdown: openrc-shutdown.o _usage.o rc-wtmp.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
 | 
			
		||||
@@ -158,10 +156,10 @@ rc-service: rc-service.o _usage.o rc-misc.o
 | 
			
		||||
rc-update: rc-update.o _usage.o rc-misc.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-pipes.o rc-schedules.o
 | 
			
		||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-schedules.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-plugin.o rc-schedules.o
 | 
			
		||||
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o
 | 
			
		||||
	${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
 | 
			
		||||
 | 
			
		||||
service_get_value service_set_value get_options save_options: do_value.o rc-misc.o
 | 
			
		||||
 
 | 
			
		||||
@@ -1,209 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * broadcast.c
 | 
			
		||||
 * broadcast a message to every logged in user
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2018 Sony Interactive Entertainment Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <ctype.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/sysmacros.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <utmpx.h>
 | 
			
		||||
#include <pwd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <setjmp.h>
 | 
			
		||||
#include <paths.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
 | 
			
		||||
#include "broadcast.h"
 | 
			
		||||
#include "helpers.h"
 | 
			
		||||
 | 
			
		||||
#ifndef _PATH_DEV
 | 
			
		||||
# define _PATH_DEV	"/dev/"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef UT_LINESIZE
 | 
			
		||||
#define UT_LINESIZE __UT_LINESIZE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static sigjmp_buf jbuf;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *	Alarm handler
 | 
			
		||||
 */
 | 
			
		||||
/*ARGSUSED*/
 | 
			
		||||
# ifdef __GNUC__
 | 
			
		||||
static void handler(int arg __attribute__((unused)))
 | 
			
		||||
# else
 | 
			
		||||
static void handler(int arg)
 | 
			
		||||
# endif
 | 
			
		||||
{
 | 
			
		||||
	siglongjmp(jbuf, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void getuidtty(char **userp, char **ttyp)
 | 
			
		||||
{
 | 
			
		||||
	struct passwd 		*pwd;
 | 
			
		||||
	uid_t			uid;
 | 
			
		||||
	char			*tty;
 | 
			
		||||
	static char		uidbuf[32];
 | 
			
		||||
	static char		ttynm[UT_LINESIZE + 4];
 | 
			
		||||
 | 
			
		||||
	uid = getuid();
 | 
			
		||||
	if ((pwd = getpwuid(uid)) != NULL) {
 | 
			
		||||
		uidbuf[0] = 0;
 | 
			
		||||
		strncat(uidbuf, pwd->pw_name, sizeof(uidbuf) - 1);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (uid)
 | 
			
		||||
			sprintf(uidbuf, "uid %d", (int) uid);
 | 
			
		||||
		else
 | 
			
		||||
			sprintf(uidbuf, "root");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((tty = ttyname(0)) != NULL) {
 | 
			
		||||
		const size_t plen = strlen(_PATH_DEV);
 | 
			
		||||
		if (strncmp(tty, _PATH_DEV, plen) == 0) {
 | 
			
		||||
			tty += plen;
 | 
			
		||||
			if (tty[0] == '/')
 | 
			
		||||
				tty++;
 | 
			
		||||
		}
 | 
			
		||||
		snprintf(ttynm, sizeof(ttynm), "(%.*s) ",
 | 
			
		||||
				 UT_LINESIZE, tty);
 | 
			
		||||
	} else
 | 
			
		||||
		ttynm[0] = 0;
 | 
			
		||||
 | 
			
		||||
	*userp = uidbuf;
 | 
			
		||||
	*ttyp  = ttynm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *	Check whether the given filename looks like a tty device.
 | 
			
		||||
 */
 | 
			
		||||
static int file_isatty(const char *fname)
 | 
			
		||||
{
 | 
			
		||||
	struct stat		st;
 | 
			
		||||
	int			major;
 | 
			
		||||
 | 
			
		||||
	if (stat(fname, &st) < 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (st.st_nlink != 1 || !S_ISCHR(st.st_mode))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 *	It would be an impossible task to list all major/minors
 | 
			
		||||
	 *	of tty devices here, so we just exclude the obvious
 | 
			
		||||
	 *	majors of which just opening has side-effects:
 | 
			
		||||
	 *	printers and tapes.
 | 
			
		||||
	 */
 | 
			
		||||
	major = major(st.st_dev);
 | 
			
		||||
	if (major == 1 || major == 2 || major == 6 || major == 9 ||
 | 
			
		||||
	    major == 12 || major == 16 || major == 21 || major == 27 ||
 | 
			
		||||
	    major == 37 || major == 96 || major == 97 || major == 206 ||
 | 
			
		||||
	    major == 230)
 | 
			
		||||
		return 0;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *	broadcast function.
 | 
			
		||||
 */
 | 
			
		||||
void broadcast(char *text)
 | 
			
		||||
{
 | 
			
		||||
	char *tty;
 | 
			
		||||
	char *user;
 | 
			
		||||
	struct utsname name;
 | 
			
		||||
	time_t t;
 | 
			
		||||
	char	*date;
 | 
			
		||||
	char *p;
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	struct sigaction sa;
 | 
			
		||||
	int fd;
 | 
			
		||||
	FILE *tp;
 | 
			
		||||
	int	flags;
 | 
			
		||||
	char *term = NULL;
 | 
			
		||||
	struct utmpx *utmp;
 | 
			
		||||
 | 
			
		||||
	getuidtty(&user, &tty);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Get and report current hostname, to make it easier to find out
 | 
			
		||||
	 * which machine is being shut down.
 | 
			
		||||
	 */
 | 
			
		||||
	uname(&name);
 | 
			
		||||
 | 
			
		||||
	/* Get the time */
 | 
			
		||||
	time(&t);
 | 
			
		||||
	date = ctime(&t);
 | 
			
		||||
	p = strchr(date, '\n');
 | 
			
		||||
	if (p)
 | 
			
		||||
		*p = 0;
 | 
			
		||||
 | 
			
		||||
	xasprintf(&line, "\007\r\nBroadcast message from %s@%s %s(%s):\r\n\r\n",
 | 
			
		||||
			user, name.nodename, tty, date);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 *	Fork to avoid hanging in a write()
 | 
			
		||||
	 */
 | 
			
		||||
	if (fork() != 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	memset(&sa, 0, sizeof(sa));
 | 
			
		||||
	sa.sa_handler = handler;
 | 
			
		||||
	sigemptyset(&sa.sa_mask);
 | 
			
		||||
	sigaction(SIGALRM, &sa, NULL);
 | 
			
		||||
 | 
			
		||||
	setutxent();
 | 
			
		||||
 | 
			
		||||
	while ((utmp = getutxent()) != NULL) {
 | 
			
		||||
		if (utmp->ut_type != USER_PROCESS || utmp->ut_user[0] == 0)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (strncmp(utmp->ut_line, _PATH_DEV, strlen(_PATH_DEV)) == 0)
 | 
			
		||||
			xasprintf(&term, "%s", utmp->ut_line);
 | 
			
		||||
		else
 | 
			
		||||
			xasprintf(&term, "%s%s", _PATH_DEV, utmp->ut_line);
 | 
			
		||||
		if (strstr(term, "/../")) {
 | 
			
		||||
			free(term);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 *	Open it non-delay
 | 
			
		||||
		 */
 | 
			
		||||
		if (sigsetjmp(jbuf, 1) == 0) {
 | 
			
		||||
			alarm(2);
 | 
			
		||||
			flags = O_WRONLY|O_NDELAY|O_NOCTTY;
 | 
			
		||||
			if (file_isatty(term) && (fd = open(term, flags)) >= 0) {
 | 
			
		||||
				if (isatty(fd) && (tp = fdopen(fd, "w")) != NULL) {
 | 
			
		||||
					fputs(line, tp);
 | 
			
		||||
					fputs(text, tp);
 | 
			
		||||
					fflush(tp);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		alarm(0);
 | 
			
		||||
		if (fd >= 0)
 | 
			
		||||
			close(fd);
 | 
			
		||||
		if (tp != NULL)
 | 
			
		||||
			fclose(tp);
 | 
			
		||||
		free(term);
 | 
			
		||||
	}
 | 
			
		||||
	endutxent();
 | 
			
		||||
	free(line);
 | 
			
		||||
	exit(0);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2018 Sony Interactive Entertainment Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * 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 BROADCAST_H
 | 
			
		||||
#define BROADCAST_H
 | 
			
		||||
 | 
			
		||||
void broadcast(char *text);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -269,13 +269,11 @@ 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,7 +68,9 @@ int main(int argc, char **argv)
 | 
			
		||||
		ok = rc_service_started_daemon(service, exec, NULL, idx);
 | 
			
		||||
 | 
			
		||||
	} else if (strcmp(applet, "service_crashed") == 0) {
 | 
			
		||||
		ok = ( rc_service_daemons_crashed(service) && errno != EACCES);
 | 
			
		||||
		ok = (_rc_can_find_pids() &&
 | 
			
		||||
		    rc_service_daemons_crashed(service) &&
 | 
			
		||||
		    errno != EACCES);
 | 
			
		||||
	} else
 | 
			
		||||
		eerrorx("%s: unknown applet", applet);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@ static int mount_proc(void)
 | 
			
		||||
	if (exists("/proc/version"))
 | 
			
		||||
		return 0;
 | 
			
		||||
	pid = fork();
 | 
			
		||||
	switch (pid) {
 | 
			
		||||
	switch(pid) {
 | 
			
		||||
		case -1:
 | 
			
		||||
			syslog(LOG_ERR, "Unable to fork");
 | 
			
		||||
			return -1;
 | 
			
		||||
@@ -248,7 +248,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		usage(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	openlog(applet, LOG_CONS|LOG_PID, LOG_DAEMON);
 | 
			
		||||
	if (mount_proc() != 0) {
 | 
			
		||||
		rc_stringlist_free(omits);
 | 
			
		||||
 
 | 
			
		||||
@@ -24,17 +24,12 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/reboot.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_SELINUX
 | 
			
		||||
#  include <selinux/selinux.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "helpers.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-wtmp.h"
 | 
			
		||||
@@ -49,7 +44,7 @@ static pid_t do_openrc(const char *runlevel)
 | 
			
		||||
	sigset_t signals;
 | 
			
		||||
 | 
			
		||||
	pid = fork();
 | 
			
		||||
	switch (pid) {
 | 
			
		||||
	switch(pid) {
 | 
			
		||||
		case -1:
 | 
			
		||||
			perror("fork");
 | 
			
		||||
			break;
 | 
			
		||||
@@ -101,15 +96,12 @@ static void handle_reexec(char *my_name)
 | 
			
		||||
static void handle_shutdown(const char *runlevel, int cmd)
 | 
			
		||||
{
 | 
			
		||||
	pid_t pid;
 | 
			
		||||
	struct timespec ts;
 | 
			
		||||
 | 
			
		||||
	pid = do_openrc(runlevel);
 | 
			
		||||
	while (waitpid(pid, NULL, 0) != pid);
 | 
			
		||||
	printf("Sending the final term signal\n");
 | 
			
		||||
	kill(-1, SIGTERM);
 | 
			
		||||
	ts.tv_sec = 3;
 | 
			
		||||
	ts.tv_nsec = 0;
 | 
			
		||||
	nanosleep(&ts, NULL);
 | 
			
		||||
	sleep(3);
 | 
			
		||||
	printf("Sending the final kill signal\n");
 | 
			
		||||
	kill(-1, SIGKILL);
 | 
			
		||||
	sync();
 | 
			
		||||
@@ -143,7 +135,7 @@ static void reap_zombies(void)
 | 
			
		||||
 | 
			
		||||
static void signal_handler(int sig)
 | 
			
		||||
{
 | 
			
		||||
	switch (sig) {
 | 
			
		||||
	switch(sig) {
 | 
			
		||||
		case SIGINT:
 | 
			
		||||
			handle_shutdown("reboot", RB_AUTOBOOT);
 | 
			
		||||
			break;
 | 
			
		||||
@@ -165,36 +157,10 @@ int main(int argc, char **argv)
 | 
			
		||||
	bool reexec = false;
 | 
			
		||||
	sigset_t signals;
 | 
			
		||||
	struct sigaction sa;
 | 
			
		||||
#ifdef HAVE_SELINUX
 | 
			
		||||
	int			enforce = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (getpid() != 1)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_SELINUX
 | 
			
		||||
	if (getenv("SELINUX_INIT") == NULL) {
 | 
			
		||||
		if (is_selinux_enabled() != 1) {
 | 
			
		||||
			if (selinux_init_load_policy(&enforce) == 0) {
 | 
			
		||||
				putenv("SELINUX_INIT=YES");
 | 
			
		||||
				execv(argv[0], argv);
 | 
			
		||||
			} else {
 | 
			
		||||
				if (enforce > 0) {
 | 
			
		||||
					/*
 | 
			
		||||
					 * SELinux in enforcing mode but load_policy failed
 | 
			
		||||
					 * At this point, we probably can't open /dev/console,
 | 
			
		||||
					 * so log() won't work
 | 
			
		||||
					 */
 | 
			
		||||
					fprintf(stderr,"Unable to load SELinux Policy.\n");
 | 
			
		||||
					fprintf(stderr,"Machine is  in enforcing mode.\n");
 | 
			
		||||
					fprintf(stderr,"Halting now.\n");
 | 
			
		||||
					exit(1);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	printf("OpenRC init version %s starting\n", VERSION);
 | 
			
		||||
 | 
			
		||||
	if (argc > 1)
 | 
			
		||||
 
 | 
			
		||||
@@ -1152,7 +1152,7 @@ int main(int argc, char **argv)
 | 
			
		||||
	}
 | 
			
		||||
	lnk = xmalloc(4096);
 | 
			
		||||
	memset(lnk, 0, 4096);
 | 
			
		||||
	if (readlink(argv[1], lnk, 4096)) {
 | 
			
		||||
	if (readlink(argv[1], lnk, sizeof(lnk)-1)) {
 | 
			
		||||
		dir = dirname(path);
 | 
			
		||||
		if (strchr(lnk, '/')) {
 | 
			
		||||
			save = xstrdup(dir);
 | 
			
		||||
@@ -1268,9 +1268,6 @@ int main(int argc, char **argv)
 | 
			
		||||
		case_RC_COMMON_GETOPT
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if (rc_yesno(getenv("RC_NODEPS")))
 | 
			
		||||
		deps = false;
 | 
			
		||||
 | 
			
		||||
	/* If we're changing runlevels and not called by rc then we cannot
 | 
			
		||||
	   work with any dependencies */
 | 
			
		||||
	if (deps && getenv("RC_PID") == NULL &&
 | 
			
		||||
@@ -1285,8 +1282,6 @@ int main(int argc, char **argv)
 | 
			
		||||
		unsetenv("IN_BACKGROUND");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (rc_yesno(getenv("IN_DRYRUN")))
 | 
			
		||||
	dry_run = true;
 | 
			
		||||
	if (rc_yesno(getenv("IN_HOTPLUG"))) {
 | 
			
		||||
		if (!service_plugable())
 | 
			
		||||
			eerrorx("%s: not allowed to be hotplugged", applet);
 | 
			
		||||
 
 | 
			
		||||
@@ -25,24 +25,20 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
 | 
			
		||||
#include "broadcast.h"
 | 
			
		||||
#include "einfo.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "helpers.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#include "rc-wtmp.h"
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "cdDfFHKpRrsw" getoptstring_COMMON;
 | 
			
		||||
const char *getoptstring = "dDHKpRrsw" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "cancel",        no_argument, NULL, 'c'},
 | 
			
		||||
	{ "no-write",        no_argument, NULL, 'd'},
 | 
			
		||||
	{ "dry-run",        no_argument, NULL, 'D'},
 | 
			
		||||
	{ "halt",        no_argument, NULL, 'H'},
 | 
			
		||||
@@ -55,7 +51,6 @@ const struct option longopts[] = {
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"cancel a pending shutdown",
 | 
			
		||||
	"do not write wtmp record",
 | 
			
		||||
	"print actions instead of executing them",
 | 
			
		||||
	"halt the system",
 | 
			
		||||
@@ -69,12 +64,8 @@ const char * const longopts_help[] = {
 | 
			
		||||
};
 | 
			
		||||
const char *usagestring = NULL;
 | 
			
		||||
const char *exclusive = "Select one of "
 | 
			
		||||
	"--cancel, --halt, --kexec, --poweroff, --reexec, --reboot, --single or \n"
 | 
			
		||||
	"--write-only";
 | 
			
		||||
const char *nologin_file = RC_SYSCONFDIR"/nologin";
 | 
			
		||||
const char *shutdown_pid = "/run/openrc-shutdown.pid";
 | 
			
		||||
"--halt, --kexec, --poweroff, --reexec, --reboot, --single or --write-only";
 | 
			
		||||
 | 
			
		||||
static bool do_cancel = false;
 | 
			
		||||
static bool do_dryrun = false;
 | 
			
		||||
static bool do_halt = false;
 | 
			
		||||
static bool do_kexec = false;
 | 
			
		||||
@@ -85,40 +76,6 @@ static bool do_single = false;
 | 
			
		||||
static bool do_wtmp = true;
 | 
			
		||||
static bool do_wtmp_only = false;
 | 
			
		||||
 | 
			
		||||
static void cancel_shutdown(void)
 | 
			
		||||
{
 | 
			
		||||
	pid_t pid;
 | 
			
		||||
 | 
			
		||||
	pid = get_pid(applet, shutdown_pid);
 | 
			
		||||
	if (pid <= 0)
 | 
			
		||||
		eerrorx("%s: Unable to cancel shutdown", applet);
 | 
			
		||||
 | 
			
		||||
	if (kill(pid, SIGTERM) != -1)
 | 
			
		||||
		einfo("%s: shutdown canceled", applet);
 | 
			
		||||
	else
 | 
			
		||||
		eerrorx("%s: Unable to cancel shutdown", applet);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *	Create the nologin file.
 | 
			
		||||
 */
 | 
			
		||||
static void create_nologin(int mins)
 | 
			
		||||
{
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	time_t t;
 | 
			
		||||
 | 
			
		||||
	time(&t);
 | 
			
		||||
	t += 60 * mins;
 | 
			
		||||
 | 
			
		||||
	if ((fp = fopen(nologin_file, "w")) != NULL) {
 | 
			
		||||
  		fprintf(fp, "\rThe system is going down on %s\r\n", ctime(&t));
 | 
			
		||||
  		fclose(fp);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Send a command to our init
 | 
			
		||||
 */
 | 
			
		||||
static void send_cmd(const char *cmd)
 | 
			
		||||
{
 | 
			
		||||
	FILE *fifo;
 | 
			
		||||
@@ -142,59 +99,16 @@ static void send_cmd(const char *cmd)
 | 
			
		||||
	fclose(fifo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * sleep without being interrupted.
 | 
			
		||||
 * The idea for this code came from sysvinit.
 | 
			
		||||
 */
 | 
			
		||||
static void sleep_no_interrupt(int seconds)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec duration;
 | 
			
		||||
	struct timespec remaining;
 | 
			
		||||
 | 
			
		||||
	duration.tv_sec = seconds;
 | 
			
		||||
	duration.tv_nsec = 0;
 | 
			
		||||
 | 
			
		||||
	while (nanosleep(&duration, &remaining) < 0 && errno == EINTR)
 | 
			
		||||
		duration = remaining;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void stop_shutdown(int sig)
 | 
			
		||||
{
 | 
			
		||||
	/* use the sig parameter so the compiler will not complain */
 | 
			
		||||
	if (sig == SIGINT)
 | 
			
		||||
		;
 | 
			
		||||
	unlink(nologin_file);
 | 
			
		||||
	unlink(shutdown_pid);
 | 
			
		||||
einfo("Shutdown canceled");
 | 
			
		||||
exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	char *ch = NULL;
 | 
			
		||||
	int opt;
 | 
			
		||||
	int cmd_count = 0;
 | 
			
		||||
	int hour = 0;
 | 
			
		||||
	int min = 0;
 | 
			
		||||
	int shutdown_delay = 0;
 | 
			
		||||
	struct sigaction sa;
 | 
			
		||||
	struct tm *lt;
 | 
			
		||||
	time_t tv;
 | 
			
		||||
	bool need_warning = false;
 | 
			
		||||
	char *msg = NULL;
 | 
			
		||||
	char *state = NULL;
 | 
			
		||||
	char *time_arg = NULL;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
 | 
			
		||||
	applet = basename_c(argv[0]);
 | 
			
		||||
	while ((opt = getopt_long(argc, argv, getoptstring,
 | 
			
		||||
		    longopts, (int *) 0)) != -1)
 | 
			
		||||
	{
 | 
			
		||||
		switch (opt) {
 | 
			
		||||
			case 'c':
 | 
			
		||||
				do_cancel = true;
 | 
			
		||||
			cmd_count++;
 | 
			
		||||
				break;
 | 
			
		||||
			case 'd':
 | 
			
		||||
				do_wtmp = false;
 | 
			
		||||
				break;
 | 
			
		||||
@@ -203,17 +117,14 @@ int main(int argc, char **argv)
 | 
			
		||||
			break;
 | 
			
		||||
		case 'H':
 | 
			
		||||
			do_halt = true;
 | 
			
		||||
			xasprintf(&state, "%s", "halt");
 | 
			
		||||
			cmd_count++;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'K':
 | 
			
		||||
			do_kexec = true;
 | 
			
		||||
			xasprintf(&state, "%s", "reboot");
 | 
			
		||||
			cmd_count++;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'p':
 | 
			
		||||
			do_poweroff = true;
 | 
			
		||||
			xasprintf(&state, "%s", "power off");
 | 
			
		||||
			cmd_count++;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'R':
 | 
			
		||||
@@ -222,12 +133,10 @@ int main(int argc, char **argv)
 | 
			
		||||
			break;
 | 
			
		||||
		case 'r':
 | 
			
		||||
			do_reboot = true;
 | 
			
		||||
			xasprintf(&state, "%s", "reboot");
 | 
			
		||||
			cmd_count++;
 | 
			
		||||
			break;
 | 
			
		||||
		case 's':
 | 
			
		||||
			do_single = true;
 | 
			
		||||
			xasprintf(&state, "%s", "go down for maintenance");
 | 
			
		||||
			cmd_count++;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'w':
 | 
			
		||||
@@ -237,91 +146,12 @@ int main(int argc, char **argv)
 | 
			
		||||
		case_RC_COMMON_GETOPT
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (geteuid() != 0)
 | 
			
		||||
	if (geteuid() != 0 && ! do_dryrun)
 | 
			
		||||
		eerrorx("%s: you must be root\n", applet);
 | 
			
		||||
	if (cmd_count != 1) {
 | 
			
		||||
		eerror("%s: %s\n", applet, exclusive);
 | 
			
		||||
		usage(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (do_cancel) {
 | 
			
		||||
		cancel_shutdown();
 | 
			
		||||
		exit(EXIT_SUCCESS);
 | 
			
		||||
	} else if (do_reexec) {
 | 
			
		||||
		send_cmd("reexec");
 | 
			
		||||
		exit(EXIT_SUCCESS);
 | 
			
		||||
	} else if (do_wtmp_only) {
 | 
			
		||||
		log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
 | 
			
		||||
		exit(EXIT_SUCCESS);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (optind >= argc) {
 | 
			
		||||
		eerror("%s: No shutdown time specified", applet);
 | 
			
		||||
		usage(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
	time_arg = argv[optind];
 | 
			
		||||
	if (*time_arg == '+')
 | 
			
		||||
		time_arg++;
 | 
			
		||||
	if (strcasecmp(time_arg, "now") == 0)
 | 
			
		||||
		strcpy(time_arg, "0");
 | 
			
		||||
	for (ch=time_arg; *ch; ch++)
 | 
			
		||||
		if ((*ch < '0' || *ch > '9') && *ch != ':') {
 | 
			
		||||
			eerror("%s: invalid time %s", applet, time_arg);
 | 
			
		||||
			usage(EXIT_FAILURE);
 | 
			
		||||
		}
 | 
			
		||||
	if (strchr(time_arg, ':')) {
 | 
			
		||||
		if ((sscanf(time_arg, "%2d:%2d", &hour, &min) != 2) ||
 | 
			
		||||
				(hour > 23) || (min > 59)) {
 | 
			
		||||
			eerror("%s: invalid time %s", applet, time_arg);
 | 
			
		||||
			usage(EXIT_FAILURE);
 | 
			
		||||
		}
 | 
			
		||||
		time(&tv);
 | 
			
		||||
		lt = localtime(&tv);
 | 
			
		||||
		shutdown_delay = (hour * 60 + min) - (lt->tm_hour * 60 + lt->tm_min);
 | 
			
		||||
		if (shutdown_delay < 0)
 | 
			
		||||
			shutdown_delay += 1440;
 | 
			
		||||
	} else {
 | 
			
		||||
		shutdown_delay = atoi(time_arg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fp = fopen(shutdown_pid, "w");
 | 
			
		||||
	if (!fp)
 | 
			
		||||
		eerrorx("%s: fopen `%s': %s", applet, shutdown_pid, strerror(errno));
 | 
			
		||||
	fprintf(fp, "%d\n", getpid());
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
 | 
			
		||||
	openlog(applet, LOG_PID, LOG_DAEMON);
 | 
			
		||||
	memset(&sa, 0, sizeof(sa));
 | 
			
		||||
	sa.sa_handler = stop_shutdown;
 | 
			
		||||
	sigemptyset(&sa.sa_mask);
 | 
			
		||||
	sigaction(SIGINT, &sa, NULL);
 | 
			
		||||
	sigaction(SIGTERM, &sa, NULL);
 | 
			
		||||
	while (shutdown_delay > 0) {
 | 
			
		||||
		need_warning = false;
 | 
			
		||||
		if (shutdown_delay > 180)
 | 
			
		||||
			need_warning = (shutdown_delay % 60 == 0);
 | 
			
		||||
		else if (shutdown_delay > 60)
 | 
			
		||||
			need_warning = (shutdown_delay % 30 == 0);
 | 
			
		||||
		else if	(shutdown_delay > 10)
 | 
			
		||||
			need_warning = (shutdown_delay % 15 == 0);
 | 
			
		||||
		else
 | 
			
		||||
			need_warning = true;
 | 
			
		||||
		if (shutdown_delay <= 5)
 | 
			
		||||
			create_nologin(shutdown_delay);
 | 
			
		||||
		if (need_warning) {
 | 
			
		||||
		xasprintf(&msg, "\rThe system will %s in %d minutes\r\n",
 | 
			
		||||
		          state, shutdown_delay);
 | 
			
		||||
			broadcast(msg);
 | 
			
		||||
			free(msg);
 | 
			
		||||
		}
 | 
			
		||||
		sleep_no_interrupt(60);
 | 
			
		||||
		shutdown_delay--;
 | 
			
		||||
	}
 | 
			
		||||
	xasprintf(&msg, "\rThe system will %s now\r\n", state);
 | 
			
		||||
	broadcast(msg);
 | 
			
		||||
	syslog(LOG_NOTICE, "The system will %s now", state);
 | 
			
		||||
	unlink(nologin_file);
 | 
			
		||||
	unlink(shutdown_pid);
 | 
			
		||||
	if (do_halt)
 | 
			
		||||
		send_cmd("halt");
 | 
			
		||||
	else if (do_kexec)
 | 
			
		||||
@@ -330,6 +160,10 @@ int main(int argc, char **argv)
 | 
			
		||||
		send_cmd("poweroff");
 | 
			
		||||
	else if (do_reboot)
 | 
			
		||||
		send_cmd("reboot");
 | 
			
		||||
	else if (do_reexec)
 | 
			
		||||
		send_cmd("reexec");
 | 
			
		||||
	else if (do_wtmp_only)
 | 
			
		||||
		log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
 | 
			
		||||
	else if (do_single)
 | 
			
		||||
		send_cmd("single");
 | 
			
		||||
	return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -87,8 +87,6 @@ write_log(int logfd, const char *buffer, size_t bytes)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!in_escape) {
 | 
			
		||||
			if (!isprint((int) *p) && *p != '\n')
 | 
			
		||||
				goto cont;
 | 
			
		||||
			if (write(logfd, p++, 1) == -1)
 | 
			
		||||
				eerror("write: %s", strerror(errno));
 | 
			
		||||
			continue;
 | 
			
		||||
 
 | 
			
		||||
@@ -51,8 +51,7 @@ rc_conf_yesno(const char *setting)
 | 
			
		||||
 | 
			
		||||
static const char *const env_whitelist[] = {
 | 
			
		||||
	"EERROR_QUIET", "EINFO_QUIET",
 | 
			
		||||
	"IN_BACKGROUND", "IN_DRYRUN", "IN_HOTPLUG",
 | 
			
		||||
	"RC_DEBUG", "RC_NODEPS",
 | 
			
		||||
	"IN_BACKGROUND", "IN_HOTPLUG",
 | 
			
		||||
	"LANG", "LC_MESSAGES", "TERM",
 | 
			
		||||
	"EINFO_COLOR", "EINFO_VERBOSE",
 | 
			
		||||
	NULL
 | 
			
		||||
@@ -411,6 +410,34 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
 | 
			
		||||
	return rc_deptree_load();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool _rc_can_find_pids(void)
 | 
			
		||||
{
 | 
			
		||||
	RC_PIDLIST *pids;
 | 
			
		||||
	RC_PID *pid;
 | 
			
		||||
	RC_PID *pid2;
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
 | 
			
		||||
	if (geteuid() == 0)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	/* If we cannot see process 1, then we don't test to see if
 | 
			
		||||
	 * services crashed or not */
 | 
			
		||||
	pids = rc_find_pids(NULL, NULL, 0, 1);
 | 
			
		||||
	if (pids) {
 | 
			
		||||
		pid = LIST_FIRST(pids);
 | 
			
		||||
		if (pid) {
 | 
			
		||||
			retval = true;
 | 
			
		||||
			while (pid) {
 | 
			
		||||
				pid2 = LIST_NEXT(pid, entries);
 | 
			
		||||
				free(pid);
 | 
			
		||||
				pid = pid2;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		free(pids);
 | 
			
		||||
	}
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct {
 | 
			
		||||
	const char * const name;
 | 
			
		||||
	RC_SERVICE bit;
 | 
			
		||||
@@ -423,7 +450,6 @@ static const struct {
 | 
			
		||||
	{ "service_hotplugged",  RC_SERVICE_HOTPLUGGED,  },
 | 
			
		||||
	{ "service_wasinactive", RC_SERVICE_WASINACTIVE, },
 | 
			
		||||
	{ "service_failed",      RC_SERVICE_FAILED,      },
 | 
			
		||||
	{ "service_crashed",     RC_SERVICE_CRASHED,     },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RC_SERVICE lookup_service_state(const char *service)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,56 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * rc-pipes.c
 | 
			
		||||
 * Helper to handle spawning processes and connecting them to pipes.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2018 The OpenRC Authors.
 | 
			
		||||
 * See the Authors file at the top-level directory of this distribution and
 | 
			
		||||
 * https://github.com/OpenRC/openrc/blob/master/AUTHORS
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of OpenRC. It is subject to the license terms in
 | 
			
		||||
 * the LICENSE file found in the top-level directory of this
 | 
			
		||||
 * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
 | 
			
		||||
 * This file may not be copied, modified, propagated, or distributed
 | 
			
		||||
 *    except according to the terms contained in the LICENSE file.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include "rc-pipes.h"
 | 
			
		||||
 | 
			
		||||
static const int pipe_read_end = 0;
 | 
			
		||||
static const int pipe_write_end = 1;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Starts a command with stdin redirected from a pipe
 | 
			
		||||
 * Returns the write end of the pipe or -1
 | 
			
		||||
 */
 | 
			
		||||
int rc_pipe_command(char *cmd)
 | 
			
		||||
{
 | 
			
		||||
	int pfd[2];
 | 
			
		||||
	pid_t pid;
 | 
			
		||||
 | 
			
		||||
	if (pipe(pfd) < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	pid = fork();
 | 
			
		||||
	if (pid > 0) {
 | 
			
		||||
		/* 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;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2018 The OpenRC Authors.
 | 
			
		||||
 * See the Authors file at the top-level directory of this distribution and
 | 
			
		||||
 * https://github.com/OpenRC/openrc/blob/master/AUTHORS
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of OpenRC. It is subject to the license terms in
 | 
			
		||||
 * the LICENSE file found in the top-level directory of this
 | 
			
		||||
 * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
 | 
			
		||||
 * This file may not be copied, modified, propagated, or distributed
 | 
			
		||||
 *    except according to the terms contained in the LICENSE file.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RC_PIPES_H
 | 
			
		||||
#define RC_PIPES_H
 | 
			
		||||
 | 
			
		||||
int rc_pipe_command(char *cmd);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -351,9 +351,8 @@ int run_stop_schedule(const char *applet,
 | 
			
		||||
 | 
			
		||||
			tkilled += nkilled;
 | 
			
		||||
			break;
 | 
			
		||||
		case SC_FOREVER:
 | 
			
		||||
		case SC_TIMEOUT:
 | 
			
		||||
			if (item->type == SC_TIMEOUT && item->value < 1) {
 | 
			
		||||
			if (item->value < 1) {
 | 
			
		||||
				item = NULL;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
@@ -361,7 +360,7 @@ int run_stop_schedule(const char *applet,
 | 
			
		||||
			ts.tv_sec = 0;
 | 
			
		||||
			ts.tv_nsec = POLL_INTERVAL;
 | 
			
		||||
 | 
			
		||||
			for (nsecs = 0; item->type == SC_FOREVER || nsecs < item->value; nsecs++) {
 | 
			
		||||
			for (nsecs = 0; nsecs < item->value; nsecs++) {
 | 
			
		||||
				for (nloops = 0;
 | 
			
		||||
				     nloops < ONE_SECOND / POLL_INTERVAL;
 | 
			
		||||
				     nloops++)
 | 
			
		||||
@@ -376,7 +375,10 @@ int run_stop_schedule(const char *applet,
 | 
			
		||||
							printf("\n");
 | 
			
		||||
							progressed = false;
 | 
			
		||||
						}
 | 
			
		||||
						if (errno != EINTR) {
 | 
			
		||||
						if (errno == EINTR)
 | 
			
		||||
							eerror("%s: caught an"
 | 
			
		||||
							    " interrupt", applet);
 | 
			
		||||
						else {
 | 
			
		||||
							eerror("%s: nanosleep: %s",
 | 
			
		||||
							    applet, strerror(errno));
 | 
			
		||||
							return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -29,35 +29,25 @@
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "cdDe:ilr:INsSZ" getoptstring_COMMON;
 | 
			
		||||
const char *getoptstring = "ce:ilr:IN" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "debug",     0, NULL, 'd' },
 | 
			
		||||
	{ "nodeps",     0, NULL, 'D' },
 | 
			
		||||
	{ "exists",   1, NULL, 'e' },
 | 
			
		||||
	{ "ifcrashed", 0, NULL, 'c' },
 | 
			
		||||
	{ "ifexists", 0, NULL, 'i' },
 | 
			
		||||
	{ "ifinactive", 0, NULL, 'I' },
 | 
			
		||||
	{ "ifnotstarted", 0, NULL, 'N' },
 | 
			
		||||
	{ "ifstarted", 0, NULL, 's' },
 | 
			
		||||
	{ "ifstopped", 0, NULL, 'S' },
 | 
			
		||||
	{ "list",     0, NULL, 'l' },
 | 
			
		||||
	{ "resolve",  1, NULL, 'r' },
 | 
			
		||||
	{ "dry-run",     0, NULL, 'Z' },
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"set xtrace when running the command",
 | 
			
		||||
	"ignore dependencies",
 | 
			
		||||
	"tests if the service exists or not",
 | 
			
		||||
	"if the service is crashed run the command",
 | 
			
		||||
	"if the service exists run the command",
 | 
			
		||||
	"if the service is inactive run the command",
 | 
			
		||||
	"if the service is not started run the command",
 | 
			
		||||
	"if the service is started run the command",
 | 
			
		||||
	"if the service is stopped run the command",
 | 
			
		||||
	"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 = ""							\
 | 
			
		||||
@@ -77,8 +67,6 @@ int main(int argc, char **argv)
 | 
			
		||||
	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 */
 | 
			
		||||
@@ -88,12 +76,6 @@ 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;
 | 
			
		||||
@@ -130,15 +112,6 @@ int main(int argc, char **argv)
 | 
			
		||||
			free(service);
 | 
			
		||||
			return EXIT_SUCCESS;
 | 
			
		||||
			/* NOTREACHED */
 | 
			
		||||
		case 's':
 | 
			
		||||
			if_started = true;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'S':
 | 
			
		||||
			if_stopped = true;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'Z':
 | 
			
		||||
			setenv("IN_DRYRUN", "yes", 1);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case_RC_COMMON_GETOPT
 | 
			
		||||
		}
 | 
			
		||||
@@ -160,10 +133,6 @@ int main(int argc, char **argv)
 | 
			
		||||
		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));
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "aclmrsSu" getoptstring_COMMON;
 | 
			
		||||
const char *getoptstring = "aclmrsu" getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{"all",         0, NULL, 'a'},
 | 
			
		||||
	{"crashed",     0, NULL, 'c'},
 | 
			
		||||
@@ -37,7 +37,6 @@ const struct option longopts[] = {
 | 
			
		||||
	{"manual",        0, NULL, 'm'},
 | 
			
		||||
	{"runlevel",    0, NULL, 'r'},
 | 
			
		||||
	{"servicelist", 0, NULL, 's'},
 | 
			
		||||
	{"supervised", 0, NULL, 'S'},
 | 
			
		||||
	{"unused",      0, NULL, 'u'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
@@ -48,7 +47,6 @@ const char * const longopts_help[] = {
 | 
			
		||||
	"Show manually started services",
 | 
			
		||||
	"Show the name of the current runlevel",
 | 
			
		||||
	"Show service list",
 | 
			
		||||
	"show supervised services",
 | 
			
		||||
	"Show services not assigned to any runlevel",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
@@ -56,6 +54,7 @@ const char *usagestring = ""						\
 | 
			
		||||
	"Usage: rc-status [options] <runlevel>...\n"		\
 | 
			
		||||
	"   or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
 | 
			
		||||
 | 
			
		||||
static bool test_crashed = false;
 | 
			
		||||
static RC_DEPTREE *deptree;
 | 
			
		||||
static RC_STRINGLIST *types;
 | 
			
		||||
 | 
			
		||||
@@ -77,7 +76,7 @@ print_level(const char *prefix, const char *level)
 | 
			
		||||
		printf("%s\n", level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *get_uptime(const char *service)
 | 
			
		||||
static void get_uptime(const char *service, char *uptime, int uptime_size)
 | 
			
		||||
{
 | 
			
		||||
	RC_SERVICE state = rc_service_state(service);
 | 
			
		||||
	char *start_count;
 | 
			
		||||
@@ -89,8 +88,8 @@ static char *get_uptime(const char *service)
 | 
			
		||||
	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");
 | 
			
		||||
@@ -112,24 +111,23 @@ static char *get_uptime(const char *service)
 | 
			
		||||
				diff_secs %= diff_mins * (time_t) 60;
 | 
			
		||||
			}
 | 
			
		||||
			if (diff_days > 0)
 | 
			
		||||
				xasprintf(&uptime,
 | 
			
		||||
				snprintf(uptime, uptime_size,
 | 
			
		||||
						"%ld day(s) %02ld:%02ld:%02ld (%s)",
 | 
			
		||||
						diff_days, diff_hours, diff_mins, diff_secs,
 | 
			
		||||
						start_count);
 | 
			
		||||
			else
 | 
			
		||||
				xasprintf(&uptime,
 | 
			
		||||
				snprintf(uptime, uptime_size,
 | 
			
		||||
						"%02ld:%02ld:%02ld (%s)",
 | 
			
		||||
						diff_hours, diff_mins, diff_secs, start_count);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return uptime;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
print_service(const char *service)
 | 
			
		||||
{
 | 
			
		||||
	char *status = NULL;
 | 
			
		||||
	char *uptime = NULL;
 | 
			
		||||
	char status[60];
 | 
			
		||||
	char uptime [40];
 | 
			
		||||
	char *child_pid = NULL;
 | 
			
		||||
	char *start_time = NULL;
 | 
			
		||||
	int cols =  printf(" %s", service);
 | 
			
		||||
@@ -138,48 +136,42 @@ print_service(const char *service)
 | 
			
		||||
	ECOLOR color = ECOLOR_BAD;
 | 
			
		||||
 | 
			
		||||
	if (state & RC_SERVICE_STOPPING)
 | 
			
		||||
		xasprintf(&status, "stopping ");
 | 
			
		||||
		snprintf(status, sizeof(status), "stopping ");
 | 
			
		||||
	else if (state & RC_SERVICE_STARTING) {
 | 
			
		||||
		xasprintf(&status, "starting ");
 | 
			
		||||
		snprintf(status, sizeof(status), "starting ");
 | 
			
		||||
		color = ECOLOR_WARN;
 | 
			
		||||
	} else if (state & RC_SERVICE_INACTIVE) {
 | 
			
		||||
		xasprintf(&status, "inactive ");
 | 
			
		||||
		snprintf(status, sizeof(status), "inactive ");
 | 
			
		||||
		color = ECOLOR_WARN;
 | 
			
		||||
	} else if (state & RC_SERVICE_STARTED) {
 | 
			
		||||
		errno = 0;
 | 
			
		||||
		if (rc_service_daemons_crashed(service) && errno != EACCES)
 | 
			
		||||
		if (test_crashed &&
 | 
			
		||||
		    rc_service_daemons_crashed(service) &&
 | 
			
		||||
		    errno != EACCES)
 | 
			
		||||
		{
 | 
			
		||||
			child_pid = rc_service_value_get(service, "child_pid");
 | 
			
		||||
			start_time = rc_service_value_get(service, "start_time");
 | 
			
		||||
			if (start_time && child_pid)
 | 
			
		||||
				xasprintf(&status, " unsupervised ");
 | 
			
		||||
				snprintf(status, sizeof(status), " unsupervised ");
 | 
			
		||||
			else
 | 
			
		||||
				xasprintf(&status, " crashed ");
 | 
			
		||||
				snprintf(status, sizeof(status), " crashed ");
 | 
			
		||||
			free(child_pid);
 | 
			
		||||
			free(start_time);
 | 
			
		||||
		} else {
 | 
			
		||||
			uptime = get_uptime(service);
 | 
			
		||||
			if (uptime) {
 | 
			
		||||
				xasprintf(&status, " started %s", uptime);
 | 
			
		||||
				free(uptime);
 | 
			
		||||
			} else
 | 
			
		||||
				xasprintf(&status, " started ");
 | 
			
		||||
			get_uptime(service, uptime, 40);
 | 
			
		||||
			snprintf(status, sizeof(status), " started %s", uptime);
 | 
			
		||||
			color = ECOLOR_GOOD;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (state & RC_SERVICE_SCHEDULED) {
 | 
			
		||||
		xasprintf(&status, "scheduled");
 | 
			
		||||
		color = ECOLOR_WARN;
 | 
			
		||||
	} else if (state & RC_SERVICE_FAILED) {
 | 
			
		||||
		xasprintf(&status, "failed");
 | 
			
		||||
		snprintf(status, sizeof(status), "scheduled");
 | 
			
		||||
		color = ECOLOR_WARN;
 | 
			
		||||
	} else
 | 
			
		||||
		xasprintf(&status, " stopped ");
 | 
			
		||||
		snprintf(status, sizeof(status), " stopped ");
 | 
			
		||||
 | 
			
		||||
	errno = 0;
 | 
			
		||||
	if (c && *c && isatty(fileno(stdout)))
 | 
			
		||||
		printf("\n");
 | 
			
		||||
	ebracket(cols, color, status);
 | 
			
		||||
	free(status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -243,12 +235,13 @@ print_stacked_services(const char *runlevel)
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	RC_SERVICE state;
 | 
			
		||||
    RC_STRING *s, *l, *t, *level;
 | 
			
		||||
	bool show_all = false;
 | 
			
		||||
	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)
 | 
			
		||||
@@ -298,14 +291,6 @@ int main(int argc, char **argv)
 | 
			
		||||
			printf("%s\n", runlevel);
 | 
			
		||||
			goto exit;
 | 
			
		||||
			/* NOTREACHED */
 | 
			
		||||
		case 'S':
 | 
			
		||||
			services = rc_services_in_state(RC_SERVICE_STARTED);
 | 
			
		||||
			TAILQ_FOREACH_SAFE(s, services, entries, t)
 | 
			
		||||
				if (!rc_service_value_get(s->value, "child_pid"))
 | 
			
		||||
					TAILQ_REMOVE(services, s, entries);
 | 
			
		||||
			print_services(NULL, services);
 | 
			
		||||
			goto exit;
 | 
			
		||||
			/* NOTREACHED */
 | 
			
		||||
		case 's':
 | 
			
		||||
			services = rc_services_in_runlevel(NULL);
 | 
			
		||||
			print_services(NULL, services);
 | 
			
		||||
@@ -387,14 +372,11 @@ int main(int argc, char **argv)
 | 
			
		||||
			free(nservices);
 | 
			
		||||
		}
 | 
			
		||||
		TAILQ_FOREACH_SAFE(s, services, entries, t) {
 | 
			
		||||
			state = rc_service_state(s->value);
 | 
			
		||||
			if ((rc_stringlist_find(sservices, s->value) ||
 | 
			
		||||
			    (state & ( RC_SERVICE_STOPPED | RC_SERVICE_HOTPLUGGED)))) {
 | 
			
		||||
				if (! (state & RC_SERVICE_FAILED)) {
 | 
			
		||||
					TAILQ_REMOVE(services, s, entries);
 | 
			
		||||
					free(s->value);
 | 
			
		||||
					free(s);
 | 
			
		||||
				}
 | 
			
		||||
			    (rc_service_state(s->value) & ( RC_SERVICE_STOPPED | RC_SERVICE_HOTPLUGGED)))) {
 | 
			
		||||
				TAILQ_REMOVE(services, s, entries);
 | 
			
		||||
				free(s->value);
 | 
			
		||||
				free(s);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		needsme = rc_stringlist_new();
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ add(const char *runlevel, const char *service)
 | 
			
		||||
 | 
			
		||||
	if (!rc_service_exists(service)) {
 | 
			
		||||
		if (errno == ENOEXEC)
 | 
			
		||||
			eerror("%s: service `%s' is not executable",
 | 
			
		||||
			eerror("%s: service `%s' is not executeable",
 | 
			
		||||
			    applet, service);
 | 
			
		||||
		else
 | 
			
		||||
			eerror("%s: service `%s' does not exist",
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ void log_wtmp(const char *user, const char *id, pid_t pid, int type,
 | 
			
		||||
	strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
 | 
			
		||||
	strncpy(utmp.ut_id  , id  , sizeof(utmp.ut_id  ));
 | 
			
		||||
	strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        /* Put the OS version in place of the hostname */
 | 
			
		||||
        if (uname(&uname_buf) == 0)
 | 
			
		||||
		strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host));
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								src/rc/rc.c
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								src/rc/rc.c
									
									
									
									
									
								
							@@ -101,6 +101,7 @@ clean_failed(void)
 | 
			
		||||
{
 | 
			
		||||
	DIR *dp;
 | 
			
		||||
	struct dirent *d;
 | 
			
		||||
	size_t l;
 | 
			
		||||
	char *path;
 | 
			
		||||
 | 
			
		||||
	/* Clean the failed services state dir now */
 | 
			
		||||
@@ -111,11 +112,16 @@ clean_failed(void)
 | 
			
		||||
				(d->d_name[1] == '.' && d->d_name[2] == '\0')))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			xasprintf(&path, RC_SVCDIR "/failed/%s", d->d_name);
 | 
			
		||||
			if (unlink(path))
 | 
			
		||||
				eerror("%s: unlink `%s': %s",
 | 
			
		||||
				    applet, path, strerror(errno));
 | 
			
		||||
			free(path);
 | 
			
		||||
			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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		closedir(dp);
 | 
			
		||||
	}
 | 
			
		||||
@@ -385,7 +391,7 @@ static void
 | 
			
		||||
handle_signal(int sig)
 | 
			
		||||
{
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
	char *signame = NULL;
 | 
			
		||||
	char signame[10] = { '\0' };
 | 
			
		||||
	pid_t pid;
 | 
			
		||||
	RC_PID *pi;
 | 
			
		||||
	int status = 0;
 | 
			
		||||
@@ -416,16 +422,16 @@ handle_signal(int sig)
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case SIGINT:
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGINT");
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGINT");
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	case SIGTERM:
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGTERM");
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGTERM");
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	case SIGQUIT:
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGQUIT");
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGQUIT");
 | 
			
		||||
		eerrorx("%s: caught %s, aborting", applet, signame);
 | 
			
		||||
		/* NOTREACHED */
 | 
			
		||||
	case SIGUSR1:
 | 
			
		||||
@@ -506,11 +512,14 @@ 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);
 | 
			
		||||
	xasprintf(&conf, "%s/conf.d/%s.%s", dir, service, level);
 | 
			
		||||
	l = strlen(dir) + strlen(level) + strlen(service) + 10;
 | 
			
		||||
	conf = xmalloc(sizeof(char) * l);
 | 
			
		||||
	snprintf(conf, l, "%s/conf.d/%s.%s", dir, service, level);
 | 
			
		||||
	retval = exists(conf);
 | 
			
		||||
	free(conf);
 | 
			
		||||
	free(init);
 | 
			
		||||
@@ -735,7 +744,7 @@ int main(int argc, char **argv)
 | 
			
		||||
	bool going_down = false;
 | 
			
		||||
	int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
 | 
			
		||||
	char *krunlevel = NULL;
 | 
			
		||||
	char *pidstr = NULL;
 | 
			
		||||
	char pidstr[10];
 | 
			
		||||
	int opt;
 | 
			
		||||
	bool parallel;
 | 
			
		||||
	int regen = 0;
 | 
			
		||||
@@ -835,9 +844,8 @@ int main(int argc, char **argv)
 | 
			
		||||
	setenv("EINFO_LOG", "openrc", 1);
 | 
			
		||||
 | 
			
		||||
	/* Export our PID */
 | 
			
		||||
	xasprintf(&pidstr, "%d", getpid());
 | 
			
		||||
	snprintf(pidstr, sizeof(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
 | 
			
		||||
 
 | 
			
		||||
@@ -59,14 +59,13 @@ static struct pam_conv conv = { NULL, NULL};
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "rc-pipes.h"
 | 
			
		||||
#include "rc-schedules.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#include "helpers.h"
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \
 | 
			
		||||
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" \
 | 
			
		||||
	getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "ionice",       1, NULL, 'I'},
 | 
			
		||||
@@ -94,8 +93,6 @@ const struct option longopts[] = {
 | 
			
		||||
	{ "exec",         1, NULL, 'x'},
 | 
			
		||||
	{ "stdout",       1, NULL, '1'},
 | 
			
		||||
	{ "stderr",       1, NULL, '2'},
 | 
			
		||||
	{ "stdout-logger",1, NULL, '3'},
 | 
			
		||||
	{ "stderr-logger",1, NULL, '4'},
 | 
			
		||||
	{ "progress",     0, NULL, 'P'},
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
@@ -125,8 +122,6 @@ const char * const longopts_help[] = {
 | 
			
		||||
	"Binary to start/stop",
 | 
			
		||||
	"Redirect stdout to file",
 | 
			
		||||
	"Redirect stderr to file",
 | 
			
		||||
	"Redirect stdout to process",
 | 
			
		||||
	"Redirect stderr to process",
 | 
			
		||||
	"Print dots each second while waiting",
 | 
			
		||||
	longopts_help_COMMON
 | 
			
		||||
};
 | 
			
		||||
@@ -167,20 +162,20 @@ handle_signal(int sig)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
	char *signame = NULL;
 | 
			
		||||
	char signame[10] = { '\0' };
 | 
			
		||||
 | 
			
		||||
	switch (sig) {
 | 
			
		||||
	case SIGINT:
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGINT");
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGINT");
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	case SIGTERM:
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGTERM");
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGTERM");
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	case SIGQUIT:
 | 
			
		||||
		if (!signame)
 | 
			
		||||
			xasprintf(&signame, "SIGQUIT");
 | 
			
		||||
		if (!signame[0])
 | 
			
		||||
			snprintf(signame, sizeof(signame), "SIGQUIT");
 | 
			
		||||
		eerrorx("%s: caught %s, aborting", applet, signame);
 | 
			
		||||
		/* NOTREACHED */
 | 
			
		||||
 | 
			
		||||
@@ -199,9 +194,6 @@ handle_signal(int sig)
 | 
			
		||||
		eerror("%s: caught unknown signal %d", applet, sig);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* free signame */
 | 
			
		||||
	free(signame);
 | 
			
		||||
 | 
			
		||||
	/* Restore errno */
 | 
			
		||||
	errno = serrno;
 | 
			
		||||
}
 | 
			
		||||
@@ -210,6 +202,7 @@ static char *
 | 
			
		||||
expand_home(const char *home, const char *path)
 | 
			
		||||
{
 | 
			
		||||
	char *opath, *ppath, *p, *nh;
 | 
			
		||||
	size_t len;
 | 
			
		||||
	struct passwd *pw;
 | 
			
		||||
 | 
			
		||||
	if (!path || *path != '~')
 | 
			
		||||
@@ -240,7 +233,9 @@ expand_home(const char *home, const char *path)
 | 
			
		||||
		return xstrdup(home);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xasprintf(&nh, "%s%s", home, ppath);
 | 
			
		||||
	len = strlen(ppath) + strlen(home) + 1;
 | 
			
		||||
	nh = xmalloc(len);
 | 
			
		||||
	snprintf(nh, len, "%s%s", home, ppath);
 | 
			
		||||
	free(opath);
 | 
			
		||||
	return nh;
 | 
			
		||||
}
 | 
			
		||||
@@ -281,8 +276,6 @@ int main(int argc, char **argv)
 | 
			
		||||
	int tid = 0;
 | 
			
		||||
	char *redirect_stderr = NULL;
 | 
			
		||||
	char *redirect_stdout = NULL;
 | 
			
		||||
	char *stderr_process = NULL;
 | 
			
		||||
	char *stdout_process = NULL;
 | 
			
		||||
	int stdin_fd;
 | 
			
		||||
	int stdout_fd;
 | 
			
		||||
	int stderr_fd;
 | 
			
		||||
@@ -386,7 +379,6 @@ 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;
 | 
			
		||||
@@ -508,14 +500,6 @@ int main(int argc, char **argv)
 | 
			
		||||
			redirect_stderr = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case '3':   /* --stdout-logger "command to run for stdout logging" */
 | 
			
		||||
			stdout_process = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case '4':  /* --stderr-logger "command to run for stderr logging" */
 | 
			
		||||
			stderr_process = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case_RC_COMMON_GETOPT
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -567,9 +551,6 @@ int main(int argc, char **argv)
 | 
			
		||||
		if (redirect_stdout || redirect_stderr)
 | 
			
		||||
			eerrorx("%s: --stdout and --stderr are only relevant"
 | 
			
		||||
			    " with --start", applet);
 | 
			
		||||
		if (stdout_process || stderr_process)
 | 
			
		||||
			eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
 | 
			
		||||
			    " with --start", applet);
 | 
			
		||||
		if (start_wait)
 | 
			
		||||
			ewarn("using --wait with --stop has no effect,"
 | 
			
		||||
			    " use --retry instead");
 | 
			
		||||
@@ -582,15 +563,6 @@ int main(int argc, char **argv)
 | 
			
		||||
		if ((redirect_stdout || redirect_stderr) && !background)
 | 
			
		||||
			eerrorx("%s: --stdout and --stderr are only relevant"
 | 
			
		||||
			    " with --background", applet);
 | 
			
		||||
		if ((stdout_process || stderr_process) && !background)
 | 
			
		||||
			eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
 | 
			
		||||
			    " with --background", applet);
 | 
			
		||||
		if (redirect_stdout && stdout_process)
 | 
			
		||||
			eerrorx("%s: do not use --stdout and --stdout-logger together",
 | 
			
		||||
					applet);
 | 
			
		||||
		if (redirect_stderr && stderr_process)
 | 
			
		||||
			eerrorx("%s: do not use --stderr and --stderr-logger together",
 | 
			
		||||
					applet);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Expand ~ */
 | 
			
		||||
@@ -631,6 +603,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		    *exec_file ? exec_file : exec);
 | 
			
		||||
		free(exec_file);
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	if (start && retry)
 | 
			
		||||
		ewarn("using --retry with --start has no effect,"
 | 
			
		||||
@@ -688,7 +661,7 @@ int main(int argc, char **argv)
 | 
			
		||||
			parse_schedule(applet, NULL, sig);
 | 
			
		||||
		if (pidfile) {
 | 
			
		||||
			pid = get_pid(applet, pidfile);
 | 
			
		||||
			if (pid == -1 && errno != ENOENT)
 | 
			
		||||
			if (pid == -1)
 | 
			
		||||
				exit(EXIT_FAILURE);
 | 
			
		||||
		} else {
 | 
			
		||||
			pid = 0;
 | 
			
		||||
@@ -913,12 +886,6 @@ int main(int argc, char **argv)
 | 
			
		||||
				eerrorx("%s: unable to open the logfile"
 | 
			
		||||
				    " for stdout `%s': %s",
 | 
			
		||||
				    applet, redirect_stdout, strerror(errno));
 | 
			
		||||
		}else if (stdout_process) {
 | 
			
		||||
			stdout_fd = rc_pipe_command(stdout_process);
 | 
			
		||||
			if (stdout_fd == -1)
 | 
			
		||||
				eerrorx("%s: unable to open the logging process"
 | 
			
		||||
				    " for stdout `%s': %s",
 | 
			
		||||
				    applet, stdout_process, strerror(errno));
 | 
			
		||||
		}
 | 
			
		||||
		if (redirect_stderr) {
 | 
			
		||||
			if ((stderr_fd = open(redirect_stderr,
 | 
			
		||||
@@ -927,21 +894,13 @@ int main(int argc, char **argv)
 | 
			
		||||
				eerrorx("%s: unable to open the logfile"
 | 
			
		||||
				    " for stderr `%s': %s",
 | 
			
		||||
				    applet, redirect_stderr, strerror(errno));
 | 
			
		||||
		}else if (stderr_process) {
 | 
			
		||||
			stderr_fd = rc_pipe_command(stderr_process);
 | 
			
		||||
			if (stderr_fd == -1)
 | 
			
		||||
				eerrorx("%s: unable to open the logging process"
 | 
			
		||||
				    " for stderr `%s': %s",
 | 
			
		||||
				    applet, stderr_process, strerror(errno));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (background)
 | 
			
		||||
			dup2(stdin_fd, STDIN_FILENO);
 | 
			
		||||
		if (background || redirect_stdout || stdout_process
 | 
			
		||||
				|| rc_yesno(getenv("EINFO_QUIET")))
 | 
			
		||||
		if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
 | 
			
		||||
			dup2(stdout_fd, STDOUT_FILENO);
 | 
			
		||||
		if (background || redirect_stderr || stderr_process
 | 
			
		||||
				|| rc_yesno(getenv("EINFO_QUIET")))
 | 
			
		||||
		if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
 | 
			
		||||
			dup2(stderr_fd, STDERR_FILENO);
 | 
			
		||||
 | 
			
		||||
		for (i = getdtablesize() - 1; i >= 3; --i)
 | 
			
		||||
@@ -996,7 +955,9 @@ int main(int argc, char **argv)
 | 
			
		||||
		ts.tv_sec = start_wait / 1000;
 | 
			
		||||
		ts.tv_nsec = (start_wait % 1000) * ONE_MS;
 | 
			
		||||
		if (nanosleep(&ts, NULL) == -1) {
 | 
			
		||||
			if (errno != EINTR) {
 | 
			
		||||
			if (errno == EINTR)
 | 
			
		||||
				eerror("%s: caught an interrupt", applet);
 | 
			
		||||
			else {
 | 
			
		||||
				eerror("%s: nanosleep: %s",
 | 
			
		||||
				    applet, strerror(errno));
 | 
			
		||||
				return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -61,18 +61,15 @@ static struct pam_conv conv = { NULL, NULL};
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "rc.h"
 | 
			
		||||
#include "rc-misc.h"
 | 
			
		||||
#include "rc-plugin.h"
 | 
			
		||||
#include "rc-schedules.h"
 | 
			
		||||
#include "_usage.h"
 | 
			
		||||
#include "helpers.h"
 | 
			
		||||
 | 
			
		||||
const char *applet = NULL;
 | 
			
		||||
const char *extraopts = NULL;
 | 
			
		||||
const char *getoptstring = "A:a:D:d:e:g:H:I:Kk:m:N:p:R:r:s:Su:1:2:3" \
 | 
			
		||||
const char *getoptstring = "D:d:e:g:I:Kk:m:N:p:R:r:Su:1:2:3" \
 | 
			
		||||
	getoptstring_COMMON;
 | 
			
		||||
const struct option longopts[] = {
 | 
			
		||||
	{ "healthcheck-timer",        1, NULL, 'a'},
 | 
			
		||||
	{ "healthcheck-delay",        1, NULL, 'A'},
 | 
			
		||||
	{ "respawn-delay",        1, NULL, 'D'},
 | 
			
		||||
	{ "chdir",        1, NULL, 'd'},
 | 
			
		||||
	{ "env",          1, NULL, 'e'},
 | 
			
		||||
@@ -86,7 +83,6 @@ const struct option longopts[] = {
 | 
			
		||||
	{ "respawn-period",        1, NULL, 'P'},
 | 
			
		||||
	{ "retry",       1, NULL, 'R'},
 | 
			
		||||
	{ "chroot",       1, NULL, 'r'},
 | 
			
		||||
	{ "signal",       1, NULL, 's'},
 | 
			
		||||
	{ "start",        0, NULL, 'S'},
 | 
			
		||||
	{ "user",         1, NULL, 'u'},
 | 
			
		||||
	{ "stdout",       1, NULL, '1'},
 | 
			
		||||
@@ -95,8 +91,6 @@ const struct option longopts[] = {
 | 
			
		||||
	longopts_COMMON
 | 
			
		||||
};
 | 
			
		||||
const char * const longopts_help[] = {
 | 
			
		||||
	"set an initial health check delay",
 | 
			
		||||
	"set a health check timer",
 | 
			
		||||
	"Set a respawn delay",
 | 
			
		||||
	"Change the PWD",
 | 
			
		||||
	"Set an environment string",
 | 
			
		||||
@@ -110,7 +104,6 @@ const char * const longopts_help[] = {
 | 
			
		||||
	"Set respawn time period",
 | 
			
		||||
	"Retry schedule to use when stopping",
 | 
			
		||||
	"Chroot to this directory",
 | 
			
		||||
	"Send a signal to the daemon",
 | 
			
		||||
	"Start daemon",
 | 
			
		||||
	"Change the process user",
 | 
			
		||||
	"Redirect stdout to file",
 | 
			
		||||
@@ -120,10 +113,6 @@ const char * const longopts_help[] = {
 | 
			
		||||
};
 | 
			
		||||
const char *usagestring = NULL;
 | 
			
		||||
 | 
			
		||||
static int healthcheckdelay = 0;
 | 
			
		||||
static int healthchecktimer = 0;
 | 
			
		||||
static volatile sig_atomic_t do_healthcheck = 0;
 | 
			
		||||
static volatile sig_atomic_t exiting = 0;
 | 
			
		||||
static int nicelevel = 0;
 | 
			
		||||
static int ionicec = -1;
 | 
			
		||||
static int ioniced = 0;
 | 
			
		||||
@@ -136,6 +125,7 @@ static int stdout_fd;
 | 
			
		||||
static int stderr_fd;
 | 
			
		||||
static char *redirect_stderr = NULL;
 | 
			
		||||
static char *redirect_stdout = NULL;
 | 
			
		||||
static bool exiting = false;
 | 
			
		||||
#ifdef TIOCNOTTY
 | 
			
		||||
static int tty_fd = -1;
 | 
			
		||||
#endif
 | 
			
		||||
@@ -143,9 +133,7 @@ static pid_t child_pid;
 | 
			
		||||
static int respawn_count = 0;
 | 
			
		||||
static int respawn_delay = 0;
 | 
			
		||||
static int respawn_max = 10;
 | 
			
		||||
static int respawn_period = 0;
 | 
			
		||||
static char *fifopath = NULL;
 | 
			
		||||
static int fifo_fd = 0;
 | 
			
		||||
static int respawn_period = 5;
 | 
			
		||||
static char *pidfile = NULL;
 | 
			
		||||
static char *svcname = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -185,27 +173,20 @@ static void handle_signal(int sig)
 | 
			
		||||
{
 | 
			
		||||
	int serrno = errno;
 | 
			
		||||
 | 
			
		||||
	switch (sig) {
 | 
			
		||||
	case SIGALRM:
 | 
			
		||||
		do_healthcheck = 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case SIGCHLD:
 | 
			
		||||
		while (waitpid((pid_t)(-1), NULL, WNOHANG) > 0) {}
 | 
			
		||||
		break;
 | 
			
		||||
	case SIGTERM:
 | 
			
		||||
		exiting = 1;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		syslog(LOG_WARNING, "caught signal %d", sig);
 | 
			
		||||
		re_exec_supervisor();
 | 
			
		||||
	}
 | 
			
		||||
	syslog(LOG_WARNING, "caught signal %d", sig);
 | 
			
		||||
 | 
			
		||||
	if (sig == SIGTERM)
 | 
			
		||||
		exiting = true;
 | 
			
		||||
	/* Restore errno */
 | 
			
		||||
	errno = serrno;
 | 
			
		||||
	if (! exiting)
 | 
			
		||||
		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 != '~')
 | 
			
		||||
@@ -236,7 +217,9 @@ static char * expand_home(const char *home, const char *path)
 | 
			
		||||
		return xstrdup(home);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xasprintf(&nh, "%s%s", home, ppath);
 | 
			
		||||
	len = strlen(ppath) + strlen(home) + 1;
 | 
			
		||||
	nh = xmalloc(len);
 | 
			
		||||
	snprintf(nh, len, "%s%s", home, ppath);
 | 
			
		||||
	free(opath);
 | 
			
		||||
	return nh;
 | 
			
		||||
}
 | 
			
		||||
@@ -249,8 +232,8 @@ static char *make_cmdline(char **argv)
 | 
			
		||||
 | 
			
		||||
	for (c = argv; c && *c; c++)
 | 
			
		||||
		len += (strlen(*c) + 1);
 | 
			
		||||
	cmdline = xmalloc(len+1);
 | 
			
		||||
	memset(cmdline, 0, len+1);
 | 
			
		||||
	cmdline = xmalloc(len);
 | 
			
		||||
	memset(cmdline, 0, len);
 | 
			
		||||
	for (c = argv; c && *c; c++) {
 | 
			
		||||
		strcat(cmdline, *c);
 | 
			
		||||
		strcat(cmdline, " ");
 | 
			
		||||
@@ -443,37 +426,49 @@ static void child_process(char *exec, char **argv)
 | 
			
		||||
static void supervisor(char *exec, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char buf[2048];
 | 
			
		||||
	char cmd[2048];
 | 
			
		||||
	int count;
 | 
			
		||||
	int failing;
 | 
			
		||||
	int health_status;
 | 
			
		||||
	int healthcheck_respawn;
 | 
			
		||||
	int i;
 | 
			
		||||
	int nkilled;
 | 
			
		||||
	int sig_send;
 | 
			
		||||
	pid_t health_pid;
 | 
			
		||||
	pid_t wait_pid;
 | 
			
		||||
	sigset_t old_signals;
 | 
			
		||||
	sigset_t signals;
 | 
			
		||||
	struct sigaction sa;
 | 
			
		||||
	struct timespec ts;
 | 
			
		||||
	time_t respawn_now= 0;
 | 
			
		||||
	time_t first_spawn= 0;
 | 
			
		||||
 | 
			
		||||
	/* block all signals we do not handle */
 | 
			
		||||
	sigfillset(&signals);
 | 
			
		||||
	sigdelset(&signals, SIGALRM);
 | 
			
		||||
	sigdelset(&signals, SIGCHLD);
 | 
			
		||||
	sigdelset(&signals, SIGTERM);
 | 
			
		||||
	sigprocmask(SIG_SETMASK, &signals, &old_signals);
 | 
			
		||||
 | 
			
		||||
	/* install signal  handler */
 | 
			
		||||
	memset(&sa, 0, sizeof(sa));
 | 
			
		||||
	sa.sa_handler = handle_signal;
 | 
			
		||||
	sigaction(SIGALRM, &sa, NULL);
 | 
			
		||||
	sigaction(SIGCHLD, &sa, NULL);
 | 
			
		||||
	sigaction(SIGTERM, &sa, NULL);
 | 
			
		||||
#ifndef RC_DEBUG
 | 
			
		||||
	signal_setup_restart(SIGHUP, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGINT, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGQUIT, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGILL, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGABRT, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGFPE, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGSEGV, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGPIPE, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGALRM, handle_signal);
 | 
			
		||||
	signal_setup(SIGTERM, handle_signal);
 | 
			
		||||
	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);
 | 
			
		||||
	signal_setup_restart(SIGVTALRM, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGXCPU, handle_signal);
 | 
			
		||||
	signal_setup_restart(SIGXFSZ, handle_signal);
 | 
			
		||||
#ifdef SIGEMT
 | 
			
		||||
	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
 | 
			
		||||
#ifdef SIGRTMIN
 | 
			
		||||
	for (i = SIGRTMIN; i <= SIGRTMAX; i++)
 | 
			
		||||
		signal_setup_restart(i, handle_signal);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	fp = fopen(pidfile, "w");
 | 
			
		||||
	if (! fp)
 | 
			
		||||
@@ -494,129 +489,56 @@ static void supervisor(char *exec, char **argv)
 | 
			
		||||
	/*
 | 
			
		||||
	 * Supervisor main loop
 | 
			
		||||
	 */
 | 
			
		||||
	if (healthcheckdelay)
 | 
			
		||||
		alarm(healthcheckdelay);
 | 
			
		||||
	else if (healthchecktimer)
 | 
			
		||||
		alarm(healthchecktimer);
 | 
			
		||||
 fifo_fd = open(fifopath, O_RDONLY |O_NONBLOCK);
 | 
			
		||||
 failing = 0;
 | 
			
		||||
	i = 0;
 | 
			
		||||
	while (!exiting) {
 | 
			
		||||
		healthcheck_respawn = 0;
 | 
			
		||||
		wait_pid = waitpid(child_pid, &i, WNOHANG);
 | 
			
		||||
		memset(buf, 0, sizeof(buf));
 | 
			
		||||
		if (fifo_fd >= 0) {
 | 
			
		||||
			count = read(fifo_fd, buf, sizeof(buf) - 1);
 | 
			
		||||
			if (count != -1)
 | 
			
		||||
				buf[count] = 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (strlen(buf) > 0) {
 | 
			
		||||
			syslog(LOG_DEBUG, "Received %s from fifo", buf);
 | 
			
		||||
			if (strncasecmp(buf, "sig", 3) == 0) {
 | 
			
		||||
				if ((sscanf(buf, "%s %d", cmd, &sig_send) == 2)
 | 
			
		||||
						&& (sig_send >= 0 && sig_send < NSIG)) {
 | 
			
		||||
					syslog(LOG_INFO, "Sending signal %d to %d", sig_send,
 | 
			
		||||
							child_pid);
 | 
			
		||||
					if (kill(child_pid, sig_send) == -1)
 | 
			
		||||
						syslog(LOG_ERR, "Unable to send signal %d to %d",
 | 
			
		||||
								sig_send, child_pid);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (do_healthcheck) {
 | 
			
		||||
			do_healthcheck = 0;
 | 
			
		||||
			alarm(0);
 | 
			
		||||
			syslog(LOG_DEBUG, "running health check for %s", svcname);
 | 
			
		||||
			health_pid = exec_service(svcname, "healthcheck");
 | 
			
		||||
			health_status = rc_waitpid(health_pid);
 | 
			
		||||
			if (WIFEXITED(health_status) && WEXITSTATUS(health_status) == 0)
 | 
			
		||||
				alarm(healthchecktimer);
 | 
			
		||||
			else {
 | 
			
		||||
				syslog(LOG_WARNING, "health check for %s failed", svcname);
 | 
			
		||||
				health_pid = exec_service(svcname, "unhealthy");
 | 
			
		||||
				rc_waitpid(health_pid);
 | 
			
		||||
				syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
 | 
			
		||||
				nkilled = run_stop_schedule(applet, NULL, NULL, child_pid, 0,
 | 
			
		||||
						false, false, true);
 | 
			
		||||
				if (nkilled < 0)
 | 
			
		||||
					syslog(LOG_INFO, "Unable to kill %d: %s",
 | 
			
		||||
							child_pid, strerror(errno));
 | 
			
		||||
				else
 | 
			
		||||
					healthcheck_respawn = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (exiting ) {
 | 
			
		||||
			alarm(0);
 | 
			
		||||
		wait(&i);
 | 
			
		||||
		if (exiting) {
 | 
			
		||||
			signal_setup(SIGCHLD, SIG_IGN);
 | 
			
		||||
			syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
 | 
			
		||||
			nkilled = run_stop_schedule(applet, NULL, NULL, child_pid, 0,
 | 
			
		||||
			nkilled = run_stop_schedule(applet, exec, NULL, child_pid, 0,
 | 
			
		||||
					false, false, true);
 | 
			
		||||
			if (nkilled > 0)
 | 
			
		||||
				syslog(LOG_INFO, "killed %d processes", nkilled);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (wait_pid == child_pid) {
 | 
			
		||||
		} else {
 | 
			
		||||
			sleep(respawn_delay);
 | 
			
		||||
			if (respawn_max > 0 && respawn_period > 0) {
 | 
			
		||||
				respawn_now = time(NULL);
 | 
			
		||||
				if (first_spawn == 0)
 | 
			
		||||
					first_spawn = respawn_now;
 | 
			
		||||
				if (respawn_now - first_spawn > respawn_period) {
 | 
			
		||||
					respawn_count = 0;
 | 
			
		||||
					first_spawn = 0;
 | 
			
		||||
				} else
 | 
			
		||||
					respawn_count++;
 | 
			
		||||
				if (respawn_count >= respawn_max) {
 | 
			
		||||
					syslog(LOG_WARNING,
 | 
			
		||||
							"respawned \"%s\" too many times, exiting", exec);
 | 
			
		||||
					exiting = true;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (WIFEXITED(i))
 | 
			
		||||
				syslog(LOG_WARNING, "%s, pid %d, exited with return code %d",
 | 
			
		||||
						exec, child_pid, WEXITSTATUS(i));
 | 
			
		||||
			else if (WIFSIGNALED(i))
 | 
			
		||||
				syslog(LOG_WARNING, "%s, pid %d, terminated by signal %d",
 | 
			
		||||
						exec, child_pid, WTERMSIG(i));
 | 
			
		||||
		}
 | 
			
		||||
		if (wait_pid == child_pid || healthcheck_respawn) {
 | 
			
		||||
			do_healthcheck = 0;
 | 
			
		||||
			healthcheck_respawn = 0;
 | 
			
		||||
			alarm(0);
 | 
			
		||||
			respawn_now = time(NULL);
 | 
			
		||||
			if (first_spawn == 0)
 | 
			
		||||
				first_spawn = respawn_now;
 | 
			
		||||
			if ((respawn_period > 0)
 | 
			
		||||
					&& (respawn_now - first_spawn > respawn_period)) {
 | 
			
		||||
				respawn_count = 0;
 | 
			
		||||
				first_spawn = 0;
 | 
			
		||||
			} else
 | 
			
		||||
				respawn_count++;
 | 
			
		||||
			if (respawn_max > 0 && respawn_count > respawn_max) {
 | 
			
		||||
				syslog(LOG_WARNING, "respawned \"%s\" too many times, exiting",
 | 
			
		||||
						exec);
 | 
			
		||||
				exiting = 1;
 | 
			
		||||
				failing = 1;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			ts.tv_sec = respawn_delay;
 | 
			
		||||
			ts.tv_nsec = 0;
 | 
			
		||||
			nanosleep(&ts, NULL);
 | 
			
		||||
			child_pid = fork();
 | 
			
		||||
			if (child_pid == -1) {
 | 
			
		||||
				syslog(LOG_ERR, "%s: fork: %s", applet, strerror(errno));
 | 
			
		||||
				exit(EXIT_FAILURE);
 | 
			
		||||
			}
 | 
			
		||||
			if (child_pid == 0) {
 | 
			
		||||
				sigprocmask(SIG_SETMASK, &old_signals, NULL);
 | 
			
		||||
				memset(&sa, 0, sizeof(sa));
 | 
			
		||||
				sa.sa_handler = SIG_DFL;
 | 
			
		||||
				sigaction(SIGALRM, &sa, NULL);
 | 
			
		||||
				sigaction(SIGCHLD, &sa, NULL);
 | 
			
		||||
				sigaction(SIGTERM, &sa, NULL);
 | 
			
		||||
			if (child_pid == -1)
 | 
			
		||||
				eerrorx("%s: fork: %s", applet, strerror(errno));
 | 
			
		||||
			if (child_pid == 0)
 | 
			
		||||
				child_process(exec, argv);
 | 
			
		||||
			}
 | 
			
		||||
			if (healthcheckdelay)
 | 
			
		||||
				alarm(healthcheckdelay);
 | 
			
		||||
			else if (healthchecktimer)
 | 
			
		||||
				alarm(healthchecktimer);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pidfile && exists(pidfile))
 | 
			
		||||
		unlink(pidfile);
 | 
			
		||||
	if (svcname) {
 | 
			
		||||
		rc_service_daemon_set(svcname, exec, (const char *const *)argv,
 | 
			
		||||
				pidfile, false);
 | 
			
		||||
		rc_service_value_set(svcname, "child_pid", NULL);
 | 
			
		||||
		rc_service_mark(svcname, RC_SERVICE_STOPPED);
 | 
			
		||||
		if (failing)
 | 
			
		||||
			rc_service_mark(svcname, RC_SERVICE_FAILED);
 | 
			
		||||
		rc_service_value_set(svcname, "child_pid", NULL);
 | 
			
		||||
	}
 | 
			
		||||
	if (pidfile && exists(pidfile))
 | 
			
		||||
		unlink(pidfile);
 | 
			
		||||
	if (fifopath && exists(fifopath))
 | 
			
		||||
		unlink(fifopath);
 | 
			
		||||
	exit(EXIT_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -628,7 +550,6 @@ int main(int argc, char **argv)
 | 
			
		||||
	bool start = false;
 | 
			
		||||
	bool stop = false;
 | 
			
		||||
	bool reexec = false;
 | 
			
		||||
	bool sendsig = false;
 | 
			
		||||
	char *exec = NULL;
 | 
			
		||||
	char *retry = NULL;
 | 
			
		||||
	int sig = SIGTERM;
 | 
			
		||||
@@ -691,16 +612,6 @@ int main(int argc, char **argv)
 | 
			
		||||
	while ((opt = getopt_long(argc, argv, getoptstring, longopts,
 | 
			
		||||
		    (int *) 0)) != -1)
 | 
			
		||||
		switch (opt) {
 | 
			
		||||
		case 'a':  /* --healthcheck-timer <time> */
 | 
			
		||||
			if (sscanf(optarg, "%d", &healthchecktimer) != 1 || healthchecktimer < 1)
 | 
			
		||||
				eerrorx("%s: invalid health check timer %s", applet, optarg);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case 'A':  /* --healthcheck-delay <time> */
 | 
			
		||||
			if (sscanf(optarg, "%d", &healthcheckdelay) != 1 || healthcheckdelay < 1)
 | 
			
		||||
				eerrorx("%s: invalid health check delay %s", applet, optarg);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case 'D':  /* --respawn-delay time */
 | 
			
		||||
			n = sscanf(optarg, "%d", &respawn_delay);
 | 
			
		||||
			if (n	!= 1 || respawn_delay < 1)
 | 
			
		||||
@@ -734,10 +645,6 @@ int main(int argc, char **argv)
 | 
			
		||||
				eerrorx("Invalid respawn-period value '%s'", optarg);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case 's':  /* --signal */
 | 
			
		||||
			sig = parse_signal(applet, optarg);
 | 
			
		||||
			sendsig = true;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'S':  /* --start */
 | 
			
		||||
			start = true;
 | 
			
		||||
			break;
 | 
			
		||||
@@ -761,11 +668,6 @@ int main(int argc, char **argv)
 | 
			
		||||
			gid = gr->gr_gid;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case 'H':  /* --healthcheck-timer <minutes> */
 | 
			
		||||
			if (sscanf(optarg, "%d", &healthchecktimer) != 1 || healthchecktimer < 1)
 | 
			
		||||
				eerrorx("%s: invalid health check timer %s", applet, optarg);
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case 'k':
 | 
			
		||||
			if (parse_mode(&numask, optarg))
 | 
			
		||||
				eerrorx("%s: invalid mode `%s'",
 | 
			
		||||
@@ -843,6 +745,8 @@ int main(int argc, char **argv)
 | 
			
		||||
		case_RC_COMMON_GETOPT
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if (!pidfile && !reexec)
 | 
			
		||||
		eerrorx("%s: --pidfile must be specified", applet);
 | 
			
		||||
	endpwent();
 | 
			
		||||
	argc -= optind;
 | 
			
		||||
	argv += optind;
 | 
			
		||||
@@ -855,12 +759,6 @@ int main(int argc, char **argv)
 | 
			
		||||
		ch_root = expand_home(home, ch_root);
 | 
			
		||||
 | 
			
		||||
	umask(numask);
 | 
			
		||||
	if (!pidfile)
 | 
			
		||||
		xasprintf(&pidfile, "/var/run/supervise-%s.pid", svcname);
 | 
			
		||||
	xasprintf(&fifopath, "%s/supervise-%s.ctl", RC_SVCDIR, svcname);
 | 
			
		||||
	if (mkfifo(fifopath, 0600) == -1 && errno != EEXIST)
 | 
			
		||||
		eerrorx("%s: unable to create control fifo: %s",
 | 
			
		||||
				applet, strerror(errno));
 | 
			
		||||
 | 
			
		||||
	if (reexec) {
 | 
			
		||||
		str = rc_service_value_get(svcname, "argc");
 | 
			
		||||
@@ -935,9 +833,9 @@ int main(int argc, char **argv)
 | 
			
		||||
						0, false, true) > 0)
 | 
			
		||||
				eerrorx("%s: %s is already running", applet, exec);
 | 
			
		||||
 | 
			
		||||
		if (respawn_period > 0 && respawn_delay * respawn_max > respawn_period)
 | 
			
		||||
		if (respawn_delay * respawn_max > respawn_period)
 | 
			
		||||
			ewarn("%s: Please increase the value of --respawn-period to more "
 | 
			
		||||
				"than %d to avoid infinite respawning", applet,
 | 
			
		||||
				"than %d to avoid infinite respawning", applet, 
 | 
			
		||||
				respawn_delay * respawn_max);
 | 
			
		||||
 | 
			
		||||
		if (retry) {
 | 
			
		||||
@@ -965,13 +863,10 @@ int main(int argc, char **argv)
 | 
			
		||||
		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));
 | 
			
		||||
@@ -982,9 +877,6 @@ int main(int argc, char **argv)
 | 
			
		||||
		tty_fd = open("/dev/tty", O_RDWR);
 | 
			
		||||
#endif
 | 
			
		||||
		devnull_fd = open("/dev/null", O_RDWR);
 | 
			
		||||
		dup2(devnull_fd, STDIN_FILENO);
 | 
			
		||||
		dup2(devnull_fd, STDOUT_FILENO);
 | 
			
		||||
		dup2(devnull_fd, STDERR_FILENO);
 | 
			
		||||
		child_pid = fork();
 | 
			
		||||
		if (child_pid == -1)
 | 
			
		||||
			eerrorx("%s: fork: %s", applet, strerror(errno));
 | 
			
		||||
@@ -1002,7 +894,6 @@ int main(int argc, char **argv)
 | 
			
		||||
			}
 | 
			
		||||
			xasprintf(&varbuf, "%d", x);
 | 
			
		||||
				rc_service_value_set(svcname, "argc", varbuf);
 | 
			
		||||
				free(varbuf);
 | 
			
		||||
			rc_service_value_set(svcname, "exec", exec);
 | 
			
		||||
			supervisor(exec, argv);
 | 
			
		||||
		} else
 | 
			
		||||
@@ -1037,18 +928,5 @@ int main(int argc, char **argv)
 | 
			
		||||
			rc_service_mark(svcname, RC_SERVICE_STOPPED);
 | 
			
		||||
		}
 | 
			
		||||
		exit(EXIT_SUCCESS);
 | 
			
		||||
	} else if (sendsig) {
 | 
			
		||||
		fifo_fd = open(fifopath, O_WRONLY |O_NONBLOCK);
 | 
			
		||||
		if (fifo_fd < 0)
 | 
			
		||||
			eerrorx("%s: unable to open control fifo %s", applet, strerror(errno));
 | 
			
		||||
		xasprintf(&str, "sig %d", sig);
 | 
			
		||||
		x = write(fifo_fd, str, strlen(str));
 | 
			
		||||
		if (x == -1) {
 | 
			
		||||
			free(tmp);
 | 
			
		||||
			eerrorx("%s: error writing to control fifo: %s", applet,
 | 
			
		||||
					strerror(errno));
 | 
			
		||||
		}
 | 
			
		||||
		free(tmp);
 | 
			
		||||
		exit(EXIT_SUCCESS);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,13 +20,6 @@ checkit() {
 | 
			
		||||
 | 
			
		||||
ret=0
 | 
			
		||||
 | 
			
		||||
fail_on_out() {
 | 
			
		||||
	if [ -n "${out}" ]; then
 | 
			
		||||
		eerror "Last command failed; failing"
 | 
			
		||||
		exit 1
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ebegin "Checking exported symbols in libeinfo.so (data)"
 | 
			
		||||
checkit einfo.data $(
 | 
			
		||||
readelf -Ws ${libeinfo_builddir}/libeinfo.so \
 | 
			
		||||
@@ -81,7 +74,6 @@ out=$(cd ${top_srcdir}; find */ \
 | 
			
		||||
	-exec grep -n -E '[[:space:]]+$' {} +)
 | 
			
		||||
[ -z "${out}" ]
 | 
			
		||||
eend $? "Trailing whitespace needs to be deleted:"$'\n'"${out}"
 | 
			
		||||
fail_on_out
 | 
			
		||||
 | 
			
		||||
ebegin "Checking trailing newlines in code"
 | 
			
		||||
out=$(cd ${top_srcdir};
 | 
			
		||||
@@ -90,7 +82,6 @@ out=$(cd ${top_srcdir};
 | 
			
		||||
	done)
 | 
			
		||||
[ -z "${out}" ]
 | 
			
		||||
eend $? "Trailing newlines need to be deleted:"$'\n'"${out}"
 | 
			
		||||
fail_on_out
 | 
			
		||||
 | 
			
		||||
ebegin "Checking for obsolete functions"
 | 
			
		||||
out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
 | 
			
		||||
@@ -98,7 +89,6 @@ out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
 | 
			
		||||
	-exec grep -n -E '\<(malloc|memory|sys/(errno|fcntl|signal|stropts|termios|unistd))\.h\>' {} +)
 | 
			
		||||
[ -z "${out}" ]
 | 
			
		||||
eend $? "Avoid these obsolete functions:"$'\n'"${out}"
 | 
			
		||||
fail_on_out
 | 
			
		||||
 | 
			
		||||
ebegin "Checking for x* func usage"
 | 
			
		||||
out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
 | 
			
		||||
@@ -109,7 +99,6 @@ out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
 | 
			
		||||
		-e src/libeinfo/libeinfo.c)
 | 
			
		||||
[ -z "${out}" ]
 | 
			
		||||
eend $? "These need to be using the x* variant:"$'\n'"${out}"
 | 
			
		||||
fail_on_out
 | 
			
		||||
 | 
			
		||||
ebegin "Checking spacing style"
 | 
			
		||||
out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
 | 
			
		||||
@@ -124,7 +113,6 @@ out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
 | 
			
		||||
	{} +)
 | 
			
		||||
[ -z "${out}" ]
 | 
			
		||||
eend $? "These lines violate style rules:"$'\n'"${out}"
 | 
			
		||||
fail_on_out
 | 
			
		||||
 | 
			
		||||
einfo "Running unit tests"
 | 
			
		||||
eindent
 | 
			
		||||
 
 | 
			
		||||
@@ -7,100 +7,44 @@ terminates unexpectedly.
 | 
			
		||||
 | 
			
		||||
The following is a brief guide on using this capability.
 | 
			
		||||
 | 
			
		||||
* Use Default start, stop and status functions
 | 
			
		||||
  If you write your own start, stop and status functions in your service
 | 
			
		||||
  script, none of this will work. You must allow OpenRC to use the default
 | 
			
		||||
  functions.
 | 
			
		||||
## Use Default start, stop and status functions
 | 
			
		||||
 | 
			
		||||
* Daemons must not fork
 | 
			
		||||
  Any deamon that you would like to have monitored by supervise-daemon
 | 
			
		||||
  must not fork. Instead, it must stay in the foreground. If the daemon
 | 
			
		||||
  forks, the supervisor will be unable to monitor it.
 | 
			
		||||
If you write your own start, stop and status functions in your service
 | 
			
		||||
script, none of this will work. You must allow OpenRC to use the default
 | 
			
		||||
functions.
 | 
			
		||||
 | 
			
		||||
  If the daemon can be configured to not fork, this should be done in the
 | 
			
		||||
  daemon's configuration file, or by adding a command line option that
 | 
			
		||||
  instructs it not to fork to the command_args_foreground variable shown
 | 
			
		||||
  below.
 | 
			
		||||
## Daemons must not fork
 | 
			
		||||
 | 
			
		||||
# Health Checks
 | 
			
		||||
Any deamon that you would like to have monitored by supervise-daemon
 | 
			
		||||
must not fork. Instead, it must stay in the foreground. If the daemon
 | 
			
		||||
itself forks, the supervisor will be unable to monitor it.
 | 
			
		||||
 | 
			
		||||
Health checks are a way to make sure a service monitored by
 | 
			
		||||
supervise-daemon stays healthy. To configure a health check for a
 | 
			
		||||
service, you need to write a healthcheck() function, and optionally an
 | 
			
		||||
unhealthy() function in the service script. Also, you will need to set
 | 
			
		||||
the healthcheck_timer and optionally healthcheck_delay variables.
 | 
			
		||||
If the daemon can be configured to not fork, this should be done in the
 | 
			
		||||
daemon's configuration file, or by adding a command line option that
 | 
			
		||||
instructs it not to fork to the command_args_foreground variable shown
 | 
			
		||||
below.
 | 
			
		||||
 | 
			
		||||
## healthcheck() function
 | 
			
		||||
 | 
			
		||||
The healthcheck() function is run repeatedly based on the settings of
 | 
			
		||||
the healthcheck_* variables. This function should return zero if the
 | 
			
		||||
service is currently healthy or non-zero otherwise.
 | 
			
		||||
 | 
			
		||||
## unhealthy() function
 | 
			
		||||
 | 
			
		||||
If the healthcheck() function returns non-zero, the unhealthy() function
 | 
			
		||||
is run, then the service is restarted. Since the service will be
 | 
			
		||||
restarted by the supervisor, the unhealthy function should not try to
 | 
			
		||||
restart it; the purpose of the function is to allow any cleanup tasks
 | 
			
		||||
other than restarting the service to be run.
 | 
			
		||||
 | 
			
		||||
# Variable Settings
 | 
			
		||||
## Variable Settings
 | 
			
		||||
 | 
			
		||||
The most important setting is the supervisor variable. At the top of
 | 
			
		||||
your service script, you should set this variable as follows:
 | 
			
		||||
 | 
			
		||||
``` sh
 | 
			
		||||
supervisor=supervise-daemon
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Several other variables affect the way services behave under
 | 
			
		||||
supervise-daemon. They are documented on the  openrc-run man page, but I
 | 
			
		||||
will list them here for convenience:
 | 
			
		||||
 | 
			
		||||
``` sh
 | 
			
		||||
command_args_foreground="arguments"
 | 
			
		||||
```
 | 
			
		||||
pidfile=/pid/of/supervisor.pid
 | 
			
		||||
 | 
			
		||||
This 	should be used if the daemon you want to monitor
 | 
			
		||||
If you are using start-stop-daemon to monitor your scripts, the pidfile
 | 
			
		||||
is the path to the pidfile the daemon creates. If, on the other hand,
 | 
			
		||||
you are using supervise-daemon, this is the path to the pidfile the
 | 
			
		||||
supervisor creates.
 | 
			
		||||
 | 
			
		||||
command_args_foreground should be used if the daemon you want to monitor
 | 
			
		||||
forks and goes to the background by default. This should be set to the
 | 
			
		||||
command line option that instructs the daemon to stay in the foreground.
 | 
			
		||||
 | 
			
		||||
``` sh
 | 
			
		||||
healthcheck_delay=seconds
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This is the delay, in seconds, before the first health check is run.
 | 
			
		||||
If it is not set, we use the value of healthcheck_timer.
 | 
			
		||||
 | 
			
		||||
``` sh
 | 
			
		||||
healthcheck_timer=seconds
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This is the  number of seconds between health checks. If it is not set,
 | 
			
		||||
no health checks will be run.
 | 
			
		||||
 | 
			
		||||
``` sh
 | 
			
		||||
respawn_delay
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This is the number of seconds to delay before attempting to respawn a
 | 
			
		||||
supervised process after it dies unexpectedly.
 | 
			
		||||
The default is to respawn immediately.
 | 
			
		||||
 | 
			
		||||
``` sh
 | 
			
		||||
respawn_max=x
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This is the maximum number of times to respawn a supervised process
 | 
			
		||||
during the given respawn period. The default is unlimited.
 | 
			
		||||
 | 
			
		||||
``` sh
 | 
			
		||||
respawn_period=seconds
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This works in conjunction with respawn_max and respawn_delay above to
 | 
			
		||||
decide if a process should not be respawned for some reason.
 | 
			
		||||
 | 
			
		||||
For example, if respawn_period is 60, respawn_max is 2 and respawn_delay
 | 
			
		||||
is 3 and a process dies more than 4 times, the process will not be
 | 
			
		||||
respawned and the supervisor will terminate.
 | 
			
		||||
This is very early support, so feel free to file bugs if you have
 | 
			
		||||
issues.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
# Copyright (c) 2007-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.
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
set -u
 | 
			
		||||
set -x
 | 
			
		||||
 | 
			
		||||
# These are steps to run on TravisCI under a containerized Ubuntu system.
 | 
			
		||||
# See $TOP/.travis.yml for more info about the TravisCI setup.
 | 
			
		||||
 | 
			
		||||
cpus=$(getconf _NPROCESSORS_CONF || echo 1)
 | 
			
		||||
# make on TravisCI doesn't support -O yet
 | 
			
		||||
make -j"${cpus}"
 | 
			
		||||
 | 
			
		||||
make test
 | 
			
		||||
@@ -90,8 +90,8 @@ the service script by hand.
 | 
			
		||||
 | 
			
		||||
FIXME: Document stacked runlevels
 | 
			
		||||
 | 
			
		||||
The default startup uses the runlevels `sysinit`, `boot`, and `default`,
 | 
			
		||||
in that order. Shutdown uses the `shutdown` runlevel.
 | 
			
		||||
The default startup uses the runlevels `boot`, `sysinit` and `default`, in that 
 | 
			
		||||
order. Shutdown uses the `shutdown` runlevel.
 | 
			
		||||
 | 
			
		||||
# The Magic of `conf.d`
 | 
			
		||||
 | 
			
		||||
@@ -162,6 +162,7 @@ stopped, by using:
 | 
			
		||||
The `rc_cgroup_cleanup` setting can be changed to yes to make this
 | 
			
		||||
happen automatically when the service is stopped.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Caching
 | 
			
		||||
 | 
			
		||||
For performance reasons OpenRC keeps a cache of pre-parsed service metadata
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user