Compare commits

..

3 Commits
0.41 ... 0.38.1

Author SHA1 Message Date
William Hubbs
11d3a8bead Update ChangeLog 2018-06-29 09:09:40 -05:00
Holger Hoffstätte
e36e9a30eb rc-status: initialize uptime pointer to prevent memory corruption
This fixes #231.
2018-06-29 09:07:47 -05:00
William Hubbs
7da99d77b5 version 0.38.1 2018-06-29 09:03:19 -05:00
81 changed files with 1832 additions and 2245 deletions

View File

@@ -1,15 +0,0 @@
# Cirrus CI integration
# https://cirrus-ci.org
test_task:
freebsd_instance:
matrix:
image: freebsd-12-0-release-amd64
image: freebsd-11-2-release-amd64
env:
OS: FreeBSD
procfs_script: >
[ -f /proc/curproc ] || mount -t procfs proc /proc
pkg_install_script: pkg install -y bash gawk gmake gsed
gsed_hack_script: rm /usr/bin/sed && ln -s /usr/local/bin/gsed /usr/bin/sed
test_script: bash ci/cirrus.sh

View File

@@ -1,28 +0,0 @@
# Travis build integration.
# https://docs.travis-ci.com/
language: c
os:
- linux
compiler:
- gcc
- clang
- musl-gcc
addons:
apt:
packages:
- musl-tools
notifications:
irc:
channels:
- "irc.freenode.org#openrc"
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
script:
- ./ci/travis.sh

2033
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -33,9 +33,8 @@ ifeq (${MKZSHCOMP},yes)
SUBDIR+= zsh-completion
endif
# We need to ensure that runlevels is done last other than test
# We need to ensure that runlevels is done last
SUBDIR+= runlevels
SUBDIR+= test
INSTALLAFTER= _installafter

View File

@@ -1,3 +1,3 @@
NAME= openrc
VERSION= 0.41
VERSION= 0.38.1
PKG= ${NAME}-${VERSION}

53
NEWS.md
View File

@@ -4,59 +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.41.
This version adds the ability to format the output of rc-status when
showing the status of services in a runlevel so that it may be parsed.
Currently, the -f switch only accepts ini as an argument which
causes the output to be in the .ini format.
This version adds an experimental build time switch to allow setting the
default shell to use for service scripts.
By default, this is set to /bin/sh if it is changed, the new shell must
be able to understand posix-compatible syntax.
## 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

View File

@@ -38,7 +38,6 @@ PKG_PREFIX=/usr/pkg
LOCAL_PREFIX=/usr/local
PREFIX=/usr/local
BRANDING=\"Gentoo/$(uname -s)\"
SH=/bin/sh
```
## Notes

View File

@@ -91,14 +91,11 @@ _rc_service()
done))
return 0
elif [[ ${COMP_CWORD} -eq 2 ]] && [[ ${prev} != -* ]]; then # if second word typed and we didn't type in a function
rc-service --exists "$prev" || return
shopt -s extglob
while read -r _ line; do
if [[ $line == +([[:alnum:]_]):* ]]; then
opts+="${line%%:*} "
fi
done < <(rc-service "$prev" describe 2>&1)
shopt -u extglob
filename=$(rc-service --resolve ${prev})
opts=$(cat ${filename} | grep "^\w*()" | sed "s/().*$//") # Greps the functions included in the init script
if [[ "x${opts}" == "x" ]] ; then # if no options found loosen the grep algorhythm
opts=$(cat ${filename} | grep "\w*()" | sed "s/().*$//")
fi
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi

View File

@@ -1,21 +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 Cirrus CI under a jailed FreeBSD system.
# See $TOP/.cirrus.yml for more info about the Cirrus CI setup.
cpus=$(getconf NPROCESSORS_CONF || echo 1)
gmake -j"${cpus}" -O
gmake test

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

2
init.d/.gitignore vendored
View File

@@ -41,8 +41,6 @@ rc-enabled
rpcbind
runsvdir
savecore
save-keymaps
save-termencoding
swap-blk
swclock
syslogd

View File

@@ -23,8 +23,8 @@ SRCS-FreeBSD+= adjkerntz.in devd.in dumpon.in encswap.in ipfw.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
mount-ro.in mtab.in numlock.in procfs.in net-online.in sysfs.in \
termencoding.in
# Generic BSD scripts
SRCS-NetBSD= hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \

View File

@@ -12,7 +12,6 @@
description="start agetty on a terminal line"
supervisor=supervise-daemon
port="${RC_SVCNAME#*.}"
respawn_period="${respawn_period:-60}"
term_type="${term_type:-linux}"
command=/sbin/agetty
command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}"

View File

@@ -14,7 +14,7 @@ description="Applies a keymap for the consoles."
depend()
{
need termencoding
after devfs
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
}

View File

@@ -56,12 +56,11 @@ load_modules()
ebegin "Loading module $x"
case "$RC_UNAME" in
FreeBSD) kldload "$x"; rc=$? ;;
Linux) modprobe --first-time -q --use-blacklist "$x"; rc=$? ;;
Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
*) ;;
esac
eend $rc "Failed to load $x"
done
return 0
}
modules_load_d()
@@ -104,7 +103,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 +112,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,7 +137,7 @@ Linux_modules()
start()
{
case "$RC_UNAME" in
FreeBSD|Linux)
FreeBSD|Linux)
modules_load_d
${RC_UNAME}_modules
;;

View File

@@ -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"
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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()

View File

@@ -16,36 +16,15 @@
.Nd bring the system down
.Sh SYNOPSIS
.Nm
.Op Fl c , -cancel
.Nm
.Op Fl R , -reexec
.Nm
.Op Fl w , -write-only
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl H , -halt
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl k , -kexec
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl p , -poweroff
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl R , -reexec
.Op Fl r , -reboot
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl s , -single
time
.Op Fl w , -write-only
.Sh DESCRIPTION
.Nm
is the utility that communicates with
@@ -53,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
@@ -76,7 +53,7 @@ Stop all services, kill all processes and reboot the system.
.It Fl s , -single
Stop all services, kill all processes and move to single user mode.
.It Fl w , -write-only
Wrrite a wtmp shutdown record and do nothing else.
Stop all services, kill all processes and move to single user mode.
.El
.Sh SEE ALSO
.Xr openrc-init 8 ,

View File

@@ -66,7 +66,6 @@ and
.Xr shutdown 8
and let them call these special runlevels.
.Sh SEE ALSO
.Xr openrc-run 8 ,
.Xr rc-status 8 ,
.Xr rc-update 8 ,
.Xr init 8 ,

View File

@@ -17,7 +17,6 @@
.Sh SYNOPSIS
.Nm
.Op Fl aclsuC
.Op Fl f Ar ini
.Op Ar runlevel
.Sh DESCRIPTION
.Nm
@@ -38,17 +37,12 @@ The options are as follows:
Show all runlevels and their services.
.It Fl c , -crashed
List all services that have crashed.
.It Fl f , -format
Select a format for the output. Currently, the only one that can be
specified is ini, which outputs in *.ini format.
.It Fl l , -list
List all defined runlevels.
.It Fl m , -manual
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

View File

@@ -9,18 +9,13 @@
.\" except according to the terms contained in the LICENSE file.
.\"
.Dd April 27, 2016
.Dt SUPERVISE-DAEMON 8 SMM
.Dt supervise-DAEMON 8 SMM
.Os OpenRC
.Sh NAME
.Nm supervise-daemon
.Nd starts a daemon and restarts it if it crashes
.Sh SYNOPSIS
.Nm
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
@@ -88,17 +87,11 @@ owned by the user. You can optionally append a
name here also.
.It Fl v , -verbose
Print the action(s) that are taken just before doing them.
.El
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl a , -healthcheck-timer Ar seconds
Run the healthcheck() command, possibly followed by the unhealthy()
command every time this number of seconds passes.
.It 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.
wait this number of seconds before restarting a daemon after it crashes.
The default is 0.
.It Fl d , -chdir Ar path
chdir to this directory before starting the daemon.
@@ -113,19 +106,16 @@ 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
@@ -133,11 +123,7 @@ 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
@@ -150,6 +136,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
@@ -171,16 +158,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.

View File

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

View File

@@ -19,7 +19,7 @@ _PKG_SED:= $(shell ${_PKG_SED_SH})
_LCL_SED_SH= if test "${PREFIX}" = "${LOCAL_PREFIX}"; then echo "-e 's:@LOCAL_PREFIX@::g'"; else echo "-e 's:@LOCAL_PREFIX@:${LOCAL_PREFIX}:g'"; fi
_LCL_SED:= $(shell ${_LCL_SED_SH})
SED_REPLACE= -e 's:@SHELL@:${SH}:' -e 's:@LIB@:${LIBNAME}:g' -e 's:@SYSCONFDIR@:${SYSCONFDIR}:g' -e 's:@LIBEXECDIR@:${LIBEXECDIR}:g' -e 's:@PREFIX@:${PREFIX}:g' -e 's:@BINDIR@:${BINDIR}:g' -e 's:@SBINDIR@:${SBINDIR}:g' ${_PKG_SED} ${_LCL_SED}
SED_REPLACE= -e 's:@SHELL@:${SH}:g' -e 's:@LIB@:${LIBNAME}:g' -e 's:@SYSCONFDIR@:${SYSCONFDIR}:g' -e 's:@LIBEXECDIR@:${LIBEXECDIR}:g' -e 's:@PREFIX@:${PREFIX}:g' -e 's:@BINDIR@:${BINDIR}:g' -e 's:@SBINDIR@:${SBINDIR}:g' ${_PKG_SED} ${_LCL_SED}
# Tweak our shell scripts
%.sh: %.sh.in
@@ -53,6 +53,7 @@ realinstall: ${BIN} ${CONF} ${INC}
install: all realinstall ${INSTALLAFTER}
check test::
@if test -e runtests.sh ; then ./runtests.sh || exit $$? ; fi
# A lot of scripts don't have anything to clean
# Also, some rm implentation require a file argument regardless of error

View File

@@ -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

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
option_arg=
poweroff_arg=
@@ -21,9 +21,4 @@ if [ -z "${poweroff_arg}" ]; then
poweroff_arg=--poweroff
fi
script_args="$@"
if [ -z "${script_args}" ]; then
script_args=now
fi
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "${script_args}"
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "$@"

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
option_arg=
poweroff_arg=
@@ -20,9 +20,4 @@ if [ -z "${poweroff_arg}" ]; then
poweroff_arg=--poweroff
fi
script_args="$@"
if [ -z "${script_args}" ]; then
script_args=now
fi
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "${script_args}"
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "$@"

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# Copyright (c) 2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
option_arg=
poweroff_arg=
@@ -22,9 +22,4 @@ if [ -z "${poweroff_arg}" ]; then
poweroff_arg=--reboot
fi
script_args="$@"
if [ -z "${script_args}" ]; then
script_args=now
fi
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "${script_args}"
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "$@"

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
shutdown_arg=
while getopts :akrhPHfFnct: opt; do

3
sh/.gitignore vendored
View File

@@ -1,7 +1,10 @@
functions.sh
gendepends.sh
rc-functions.sh
openrc-run.sh
cgroup-release-agent.sh
init.sh
init-early.sh
rc-cgroup.sh
migrate-to-run.sh
binfmt.sh

View File

@@ -1,8 +1,8 @@
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 ${INC-${OS}}
start-stop-daemon.sh supervise-daemon.sh
BIN= gendepends.sh init.sh openrc-run.sh ${BIN-${OS}}
INSTALLAFTER= _installafter
@@ -13,9 +13,10 @@ include ${MK}/os.mk
SRCS-FreeBSD=
BIN-FreeBSD=
SRCS-Linux= binfmt.sh.in cgroup-release-agent.sh.in init-early.sh.in
BIN-Linux= binfmt.sh cgroup-release-agent.sh init-early.sh
INC-Linux= rc-cgroup.sh
SRCS-Linux= binfmt.sh.in cgroup-release-agent.sh.in init-early.sh.in \
migrate-to-run.sh.in rc-cgroup.sh.in
BIN-Linux= binfmt.sh cgroup-release-agent.sh init-early.sh migrate-to-run.sh \
rc-cgroup.sh
SRCS-NetBSD=
BIN-NetBSD=
@@ -31,3 +32,4 @@ _installafter:
ln -snf ${LIBEXECDIR}/sh/functions.sh ${DESTDIR}/${INITDIR} || exit $$?
check test::
./runtests.sh

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# This is a reimplementation of the systemd binfmt.d code to register
# misc binary formats with the kernel.
#

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# This is run by the kernel after the last task is removed from a
# control group in the openrc hierarchy.

View File

@@ -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
}

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# Copyright (c) 1999-2007 Gentoo Foundation
# Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.

36
sh/migrate-to-run.sh.in Normal file
View File

@@ -0,0 +1,36 @@
#!@SHELL@
# Copyright (c) 2012-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
#
# This file is part of OpenRC. It is subject to the license terms in
# the LICENSE file found in the top-level directory of this
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
. "@LIBEXECDIR@/sh/functions.sh"
if [ -e /run/openrc/softlevel ]; then
einfo "The OpenRC dependency data has already been migrated."
exit 0
fi
if [ ! -d /run ]; then
eerror "/run is not a directory."
eerror "moving /run to /run.pre-openrc"
mv /run /run.pre-openrc
mkdir /run
fi
rm -rf /run/openrc
if ! mountinfo -q -f tmpfs /run; then
ln -s "@LIBEXECDIR@"/init.d /run/openrc
else
cp -a "@LIBEXECDIR@/init.d" /run/openrc
rc-update -u
fi
einfo "The OpenRC dependency data was migrated successfully."
exit 0

View File

@@ -1,3 +1,4 @@
#!@SHELL@
# Copyright (c) 2012-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
@@ -61,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"

View File

@@ -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()

View File

@@ -15,6 +15,7 @@
ret=0
tret=0
ebegin "Testing yesno()"
for f in yes YES Yes true TRUE True 1 ; do
if ! yesno $f; then
: $(( tret += 1 ))
@@ -27,7 +28,7 @@ for f in no NO No false FALSE False 0 ; do
echo "!$f!"
fi
done
eend $tret
: $(( ret += $tret ))
eend $ret
exit $ret

View File

@@ -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}")

View File

@@ -38,9 +38,9 @@ ssd_start()
service_inactive && _inactive=true
mark_service_inactive
fi
[ -n "$output_logger" ] &&
[ -n "$output_logger" ] &&
output_logger_arg="--stdout-logger \"$output_logger\""
[ -n "$error_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"

View File

@@ -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,8 +32,6 @@ 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}} \
@@ -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
}

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.
SUBDIR= libeinfo librc rc
SUBDIR= test libeinfo librc rc
MK= ../mk
include ${MK}/subdir.mk

View File

@@ -48,40 +48,34 @@ pid_is_exec(pid_t pid, const char *exec)
static bool
pid_is_argv(pid_t pid, const char *const *argv)
{
char *buffer = NULL;
char *cmdline = NULL;
int fd;
char buffer[PATH_MAX];
char *p;
size_t bytes;
bool rc;
ssize_t bytes;
xasprintf(&cmdline, "/proc/%u/cmdline", pid);
if (!rc_getfile(cmdline, &buffer, &bytes)) {
if ((fd = open(cmdline, O_RDONLY)) < 0) {
free(cmdline);
return false;
}
bytes = read(fd, buffer, sizeof(buffer));
close(fd);
free(cmdline);
if (bytes <= 0) {
if (buffer)
free(buffer);
if (bytes == -1)
return false;
}
p = buffer;
rc = true;
while (*argv) {
if (strcmp(*argv, p) != 0) {
rc = false;
break;
}
buffer[bytes] = '\0';
p = buffer;
while (*argv) {
if (strcmp(*argv, p) != 0)
return false;
argv++;
p += strlen(p) + 1;
if ((unsigned)(p - buffer) >= bytes) {
rc = false;
break;
}
if ((unsigned)(p - buffer) > sizeof(buffer))
return false;
}
free(buffer);
return rc;
return true;
}
RC_PIDLIST *
@@ -147,7 +141,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
memset(my_ns, 0, sizeof(my_ns));
memset(proc_ns, 0, sizeof(proc_ns));
if (exists("/proc/self/ns/pid")) {
rc = readlink("/proc/self/ns/pid", my_ns, sizeof(my_ns)-1);
rc = readlink("/proc/self/ns/pid", my_ns, sizeof(my_ns));
if (rc <= 0)
my_ns[0] = '\0';
}
@@ -161,7 +155,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
continue;
xasprintf(&buffer, "/proc/%d/ns/pid", p);
if (exists(buffer)) {
rc = readlink(buffer, proc_ns, sizeof(proc_ns)-1);
rc = readlink(buffer, proc_ns, sizeof(proc_ns));
if (rc <= 0)
proc_ns[0] = '\0';
}

View File

@@ -84,11 +84,10 @@ static RC_DEPINFO *
get_depinfo(const RC_DEPTREE *deptree, const char *service)
{
RC_DEPINFO *di;
if (deptree) {
TAILQ_FOREACH(di, deptree, entries)
if (strcmp(di->service, service) == 0)
return di;
}
TAILQ_FOREACH(di, deptree, entries)
if (strcmp(di->service, service) == 0)
return di;
return NULL;
}
@@ -97,11 +96,9 @@ get_deptype(const RC_DEPINFO *depinfo, const char *type)
{
RC_DEPTYPE *dt;
if (depinfo) {
TAILQ_FOREACH(dt, &depinfo->depends, entries)
if (strcmp(dt->type, type) == 0)
return dt;
}
TAILQ_FOREACH(dt, &depinfo->depends, entries)
if (strcmp(dt->type, type) == 0)
return dt;
return NULL;
}
@@ -619,11 +616,11 @@ mtime_check(const char *source, const char *target, bool newer,
return false;
mtime = buf.st_mtime;
retval = deep_mtime_check(target,newer,&mtime,file);
if (rel) {
*rel = mtime;
}
return retval;
retval = deep_mtime_check(target,newer,&mtime,file);
if (rel) {
*rel = mtime;
}
return retval;
}
bool

View File

@@ -277,6 +277,7 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
char *tmp = NULL;
char *value = NULL;
size_t varlen = 0;
size_t len = 0;
overrides = rc_stringlist_new();
@@ -294,6 +295,7 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
}
if (value != NULL) {
len = varlen + strlen(value) + 2;
xasprintf(&tmp, "%s=%s", override->value, value);
}
@@ -423,7 +425,7 @@ rc_conf_value(const char *setting)
}
rc_conf = rc_config_directory(rc_conf);
rc_conf = rc_config_kcl(rc_conf);
rc_conf = rc_config_kcl(rc_conf);
/* Convert old uppercase to lowercase */
TAILQ_FOREACH(s, rc_conf, entries) {

View File

@@ -558,7 +558,7 @@ rc_service_resolve(const char *service)
if (*file) {
memset(buffer, 0, sizeof(buffer));
r = readlink(file, buffer, sizeof(buffer)-1);
r = readlink(file, buffer, sizeof(buffer));
if (r > 0)
return xstrdup(buffer);
}
@@ -850,7 +850,7 @@ rc_service_state(const char *service)
}
if (state & RC_SERVICE_STARTED) {
if (rc_service_daemons_crashed(service) && errno != EACCES)
if (rc_service_daemons_crashed(service))
state |= RC_SERVICE_CRASHED;
}
if (state & RC_SERVICE_STOPPED) {
@@ -1047,6 +1047,7 @@ rc_service_add(const char *runlevel, const char *service)
char *init;
char file[PATH_MAX];
char path[MAXPATHLEN] = { '\0' };
char *p = NULL;
char binit[PATH_MAX];
char *i;
@@ -1067,7 +1068,8 @@ rc_service_add(const char *runlevel, const char *service)
/* We need to ensure that only things in /etc/init.d are added
* to the boot runlevel */
if (strcmp(runlevel, RC_LEVEL_BOOT) == 0) {
if (realpath(dirname(init), path) == NULL) {
p = realpath(dirname(init), path);
if (!*p) {
free(init);
return false;
}

View File

@@ -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
@@ -134,7 +134,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
@@ -161,7 +161,7 @@ rc-update: rc-update.o _usage.o rc-misc.o
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-pipes.o rc-schedules.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-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

View File

@@ -1,204 +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
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];
char *ttynm = NULL;
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++;
}
xasprintf(&ttynm, "(%s) ", tty);
}
*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;
volatile 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);
free(tty);
/*
* 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);
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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)

View File

@@ -1120,7 +1120,7 @@ int main(int argc, char **argv)
char *dir, *save = NULL, *saveLnk = NULL;
char *pidstr = NULL;
size_t l = 0, ll;
const char *file;
const char *file;
struct stat stbuf;
/* Show help if insufficient args */
@@ -1152,7 +1152,7 @@ int main(int argc, char **argv)
}
lnk = xmalloc(4096);
memset(lnk, 0, 4096);
if (readlink(argv[1], lnk, 4096-1)) {
if (readlink(argv[1], lnk, 4096)) {
dir = dirname(path);
if (strchr(lnk, '/')) {
save = xstrdup(dir);
@@ -1223,6 +1223,7 @@ int main(int argc, char **argv)
/* Make our prefix string */
prefix = xmalloc(sizeof(char) * l + 1);
ll = strlen(applet);
memcpy(prefix, applet, ll);
memset(prefix + ll, ' ', l - ll);
memset(prefix + l, 0, 1);

View File

@@ -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",
@@ -67,22 +62,10 @@ const char * const longopts_help[] = {
"write wtmp boot record and exit",
longopts_help_COMMON
};
const char *usagestring = "" \
"Usage: openrc-shutdown -c | --cancel\n" \
" or: openrc-shutdown -R | --reexec\n" \
" or: openrc-shutdown -w | --write-only\n" \
" or: openmrc-shutdown -H | --halt time\n" \
" or: openrc-shutdown -K | --kexec time\n" \
" or: openrc-shutdown -p | --poweroff time\n" \
" or: openrc-shutdown -r | --reboot time\n" \
" or: openrc-shutdown -s | --single time";
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;
@@ -93,44 +76,10 @@ 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;
size_t ignored;
size_t ignored;
if (do_dryrun) {
einfo("Would send %s to init", cmd);
@@ -150,57 +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)
{
(void) sig;
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;
@@ -209,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':
@@ -228,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':
@@ -243,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)
@@ -336,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;

View File

@@ -28,7 +28,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
@@ -271,11 +270,8 @@ int do_stop(const char *applet, const char *exec, const char *const *argv,
einfo("Would send signal %d to PID %d", sig, pi->pid);
nkilled++;
} else {
if (sig) {
syslog(LOG_DEBUG, "Sending signal %d to PID %d", sig, pi->pid);
if (!quiet)
ebeginv("Sending signal %d to PID %d", sig, pi->pid);
}
if (!quiet)
ebeginv("Sending signal %d to PID %d", sig, pi->pid);
errno = 0;
killed = (kill(pi->pid, sig) == 0 ||
errno == ESRCH ? true : false);
@@ -283,9 +279,6 @@ int do_stop(const char *applet, const char *exec, const char *const *argv,
eendv(killed ? 0 : 1,
"%s: failed to send signal %d to PID %d: %s",
applet, sig, pi->pid, strerror(errno));
else if (!killed)
syslog(LOG_ERR, "Failed to send signal %d to PID %d: %s",
sig, pi->pid, strerror(errno));
if (!killed) {
nkilled = -1;
} else {
@@ -317,18 +310,12 @@ int run_stop_schedule(const char *applet,
if (!(pid > 0 || exec || uid || (argv && *argv)))
return 0;
if (exec) {
if (exec)
einfov("Will stop %s", exec);
syslog(LOG_DEBUG, "Will stop %s", exec);
}
if (pid > 0) {
if (pid > 0)
einfov("Will stop PID %d", pid);
syslog(LOG_DEBUG, "Will stop PID %d", pid);
}
if (uid) {
if (uid)
einfov("Will stop processes owned by UID %d", uid);
syslog(LOG_DEBUG, "Will stop processes owned by UID %d", uid);
}
if (argv && *argv) {
einfovn("Will stop processes of `");
if (rc_yesno(getenv("EINFO_VERBOSE"))) {
@@ -364,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;
}
@@ -374,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++)
@@ -389,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;

View File

@@ -49,12 +49,10 @@ 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)",

View File

@@ -27,40 +27,31 @@
#include "rc-misc.h"
#include "_usage.h"
enum format_t {
FORMAT_DEFAULT,
FORMAT_INI,
};
const char *applet = NULL;
const char *extraopts = NULL;
const char *getoptstring = "acf:lmrsSu" getoptstring_COMMON;
const char *getoptstring = "aclmrsu" getoptstring_COMMON;
const struct option longopts[] = {
{"all", 0, NULL, 'a'},
{"crashed", 0, NULL, 'c'},
{"format", 1, NULL, 'f'},
{"list", 0, NULL, 'l'},
{"manual", 0, NULL, 'm'},
{"runlevel", 0, NULL, 'r'},
{"servicelist", 0, NULL, 's'},
{"supervised", 0, NULL, 'S'},
{"unused", 0, NULL, 'u'},
longopts_COMMON
};
const char * const longopts_help[] = {
"Show services from all run levels",
"Show crashed services",
"format status to be parsable (currently arg must be ini)",
"Show list of run levels",
"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
};
const char *usagestring = "" \
"Usage: rc-status [options] -f ini <runlevel>...\n" \
"Usage: rc-status [options] <runlevel>...\n" \
" or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
static RC_DEPTREE *deptree;
@@ -69,27 +60,19 @@ static RC_STRINGLIST *types;
static RC_STRINGLIST *levels, *services, *tmp, *alist;
static RC_STRINGLIST *sservices, *nservices, *needsme;
static void print_level(const char *prefix, const char *level,
enum format_t format)
static void
print_level(const char *prefix, const char *level)
{
switch (format) {
case FORMAT_DEFAULT:
if (prefix)
printf("%s ", prefix);
printf ("Runlevel: ");
if (isatty(fileno(stdout)))
printf("%s%s%s\n",
ecolor(ECOLOR_HILITE), level, ecolor(ECOLOR_NORMAL));
else
printf("%s\n", level);
break;
case FORMAT_INI:
printf("%s", "[");
if (prefix)
printf("%s ", prefix);
printf("%s]\n", level);
break;
}
if (prefix)
printf("%s ", prefix);
printf ("Runlevel: ");
if (isatty(fileno(stdout)))
printf("%s%s%s\n",
ecolor(ECOLOR_HILITE),
level,
ecolor(ECOLOR_NORMAL));
else
printf("%s\n", level);
}
static char *get_uptime(const char *service)
@@ -140,13 +123,14 @@ static char *get_uptime(const char *service)
return uptime;
}
static void print_service(const char *service, enum format_t format)
static void
print_service(const char *service)
{
char *status = NULL;
char *uptime = NULL;
char *child_pid = NULL;
char *start_time = NULL;
int cols;
int cols = printf(" %s", service);
const char *c = ecolor(ECOLOR_GOOD);
RC_SERVICE state = rc_service_state(service);
ECOLOR color = ECOLOR_BAD;
@@ -183,29 +167,18 @@ static void print_service(const char *service, enum format_t format)
} else if (state & RC_SERVICE_SCHEDULED) {
xasprintf(&status, "scheduled");
color = ECOLOR_WARN;
} else if (state & RC_SERVICE_FAILED) {
xasprintf(&status, "failed");
color = ECOLOR_WARN;
} else
xasprintf(&status, " stopped ");
errno = 0;
switch (format) {
case FORMAT_DEFAULT:
cols = printf(" %s", service);
if (c && *c && isatty(fileno(stdout)))
printf("\n");
ebracket(cols, color, status);
break;
case FORMAT_INI:
printf("%s = %s\n", service, status);
break;
}
if (c && *c && isatty(fileno(stdout)))
printf("\n");
ebracket(cols, color, status);
free(status);
}
static void print_services(const char *runlevel, RC_STRINGLIST *svcs,
enum format_t format)
static void
print_services(const char *runlevel, RC_STRINGLIST *svcs)
{
RC_STRINGLIST *l = NULL;
RC_STRING *s;
@@ -219,7 +192,7 @@ static void print_services(const char *runlevel, RC_STRINGLIST *svcs,
TAILQ_FOREACH(s, svcs, entries)
if (!runlevel ||
rc_service_in_runlevel(s->value, runlevel))
print_service(s->value, format);
print_service(s->value);
return;
}
if (!types) {
@@ -239,12 +212,13 @@ static void print_services(const char *runlevel, RC_STRINGLIST *svcs,
if (!rc_stringlist_find(svcs, s->value))
continue;
if (!runlevel || rc_service_in_runlevel(s->value, runlevel))
print_service(s->value, format);
print_service(s->value);
}
rc_stringlist_free(l);
}
static void print_stacked_services(const char *runlevel, enum format_t format)
static void
print_stacked_services(const char *runlevel)
{
RC_STRINGLIST *stackedlevels, *servicelist;
RC_STRING *stackedlevel;
@@ -253,9 +227,9 @@ static void print_stacked_services(const char *runlevel, enum format_t format)
TAILQ_FOREACH(stackedlevel, stackedlevels, entries) {
if (rc_stringlist_find(levels, stackedlevel->value) != NULL)
continue;
print_level("Stacked", stackedlevel->value, format);
print_level("Stacked", stackedlevel->value);
servicelist = rc_services_in_runlevel(stackedlevel->value);
print_services(stackedlevel->value, servicelist, format);
print_services(stackedlevel->value, servicelist);
rc_stringlist_free(servicelist);
}
rc_stringlist_free(stackedlevels);
@@ -264,10 +238,7 @@ static void print_stacked_services(const char *runlevel, enum format_t format)
int main(int argc, char **argv)
{
RC_SERVICE state;
RC_STRING *s, *l, *t, *level;
enum format_t format = FORMAT_DEFAULT;
bool levels_given = false;
RC_STRING *s, *l, *t, *level;
bool show_all = false;
char *p, *runlevel = NULL;
int opt, retval = 0;
@@ -290,12 +261,6 @@ int main(int argc, char **argv)
}
goto exit;
/* NOTREACHED */
case 'f':
if (strcasecmp(optarg, "ini") == 0)
format = FORMAT_INI;
else
eerrorx("%s: invalid argument to --format switch\n", applet);
break;
case 'l':
levels = rc_runlevel_list();
TAILQ_FOREACH(l, levels, entries)
@@ -320,24 +285,16 @@ int main(int argc, char **argv)
free(s->value);
free(s);
}
print_services(NULL, services, FORMAT_DEFAULT);
print_services(NULL, services);
goto exit;
case 'r':
runlevel = rc_runlevel_get();
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, FORMAT_DEFAULT);
goto exit;
/* NOTREACHED */
case 's':
services = rc_services_in_runlevel(NULL);
print_services(NULL, services, FORMAT_DEFAULT);
print_services(NULL, services);
goto exit;
/* NOTREACHED */
case 'u':
@@ -352,7 +309,7 @@ int main(int argc, char **argv)
break;
}
}
print_services(NULL, services, FORMAT_DEFAULT);
print_services(NULL, services);
goto exit;
/* NOTREACHED */
@@ -364,7 +321,6 @@ int main(int argc, char **argv)
opt = (optind < argc) ? 0 : 1;
while (optind < argc) {
if (rc_runlevel_exists(argv[optind])) {
levels_given = true;
rc_stringlist_add(levels, argv[optind++]);
opt++;
} else
@@ -381,21 +337,21 @@ int main(int argc, char **argv)
deptree = _rc_deptree_load(0, NULL);
TAILQ_FOREACH(l, levels, entries) {
print_level(NULL, l->value, format);
print_level(NULL, l->value);
services = rc_services_in_runlevel(l->value);
print_services(l->value, services, format);
print_stacked_services(l->value, format);
print_services(l->value, services);
print_stacked_services(l->value);
rc_stringlist_free(nservices);
nservices = NULL;
rc_stringlist_free(services);
services = NULL;
}
if (show_all || !levels_given) {
if (show_all || argc < 2) {
/* Show hotplugged services */
print_level("Dynamic", "hotplugged", format);
print_level("Dynamic", "hotplugged");
services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
print_services(NULL, services, format);
print_services(NULL, services);
rc_stringlist_free(services);
services = NULL;
@@ -417,14 +373,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();
@@ -452,10 +405,10 @@ int main(int argc, char **argv)
* be added to the list
*/
unsetenv("RC_SVCNAME");
print_level("Dynamic", "needed/wanted", format);
print_services(NULL, nservices, format);
print_level("Dynamic", "manual", format);
print_services(NULL, services, format);
print_level("Dynamic", "needed/wanted");
print_services(NULL, nservices);
print_level("Dynamic", "manual");
print_services(NULL, services);
}
exit:

View File

@@ -42,9 +42,9 @@ 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)
/* 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));
updwtmp(WTMP_FILE, &utmp);

View File

@@ -492,7 +492,7 @@ int main(int argc, char **argv)
startas = optarg;
break;
case 'w':
if (sscanf(optarg, "%u", &start_wait) != 1)
if (sscanf(optarg, "%d", &start_wait) != 1)
eerrorx("%s: `%s' not a number",
applet, optarg);
break;
@@ -547,7 +547,7 @@ int main(int argc, char **argv)
} else if (name) {
*--argv = name;
++argc;
} else if (exec) {
} else if (exec) {
*--argv = exec;
++argc;
};
@@ -996,7 +996,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;

View File

@@ -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;
@@ -184,32 +172,15 @@ static void re_exec_supervisor(void)
static void handle_signal(int sig)
{
int serrno = errno;
pid_t pid;
switch (sig) {
case SIGALRM:
do_healthcheck = 1;
break;
case SIGCHLD:
if (exiting)
while (waitpid((pid_t)(-1), NULL, WNOHANG) > 0) {}
else {
while ((pid = waitpid((pid_t)(-1), NULL, WNOHANG|WNOWAIT)) > 0) {
if (pid == child_pid)
break;
pid = waitpid(pid, NULL, WNOHANG);
}
}
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)
@@ -237,7 +208,7 @@ static char * expand_home(const char *home, const char *path)
ppath++;
if (!home) {
free(opath);
free(opath);
return xstrdup(path);
}
if (!ppath) {
@@ -267,56 +238,6 @@ static char *make_cmdline(char **argv)
return cmdline;
}
static pid_t exec_command(const char *cmd)
{
char *file;
pid_t pid = -1;
sigset_t full;
sigset_t old;
struct sigaction sa;
file = rc_service_resolve(svcname);
if (!exists(file)) {
free(file);
return 0;
}
/* We need to block signals until we have forked */
memset(&sa, 0, sizeof (sa));
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
sigfillset(&full);
sigprocmask(SIG_SETMASK, &full, &old);
pid = fork();
if (pid == 0) {
/* Restore default handlers */
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGWINCH, &sa, NULL);
/* Unmask signals */
sigprocmask(SIG_SETMASK, &old, NULL);
/* Safe to run now */
execl(file, file, cmd, (char *) NULL);
syslog(LOG_ERR, "unable to exec `%s': %s\n",
file, strerror(errno));
_exit(EXIT_FAILURE);
}
if (pid == -1)
syslog(LOG_ERR, "fork: %s\n",strerror (errno));
sigprocmask(SIG_SETMASK, &old, NULL);
free(file);
return pid;
}
static void child_process(char *exec, char **argv)
{
RC_STRINGLIST *env_list;
@@ -502,40 +423,52 @@ 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)
if (! fp)
eerrorx("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
fprintf(fp, "%d\n", getpid());
fclose(fp);
@@ -553,131 +486,56 @@ static void supervisor(char *exec, char **argv)
/*
* Supervisor main loop
*/
if (healthcheckdelay)
alarm(healthcheckdelay);
else if (healthchecktimer)
alarm(healthchecktimer);
failing = 0;
i = 0;
while (!exiting) {
healthcheck_respawn = 0;
fifo_fd = open(fifopath, O_RDONLY);
if (fifo_fd > 0) {
memset(buf, 0, sizeof(buf));
count = read(fifo_fd, buf, sizeof(buf) - 1);
close(fifo_fd);
if (count != -1)
buf[count] = 0;
if (count == 0)
continue;
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);
}
}
continue;
}
if (do_healthcheck) {
do_healthcheck = 0;
alarm(0);
syslog(LOG_DEBUG, "running health check for %s", svcname);
health_pid = exec_command("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_command("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;
}
}
wait(&i);
if (exiting) {
alarm(0);
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;
}
wait_pid = waitpid(child_pid, &i, WNOHANG);
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);
}
@@ -689,7 +547,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;
@@ -720,7 +577,7 @@ int main(int argc, char **argv)
eerrorx("%s: The RC_SVCNAME environment variable is not set", applet);
openlog(applet, LOG_PID, LOG_DAEMON);
if (argc <= 1 || strcmp(argv[1], svcname))
if (argc >= 1 && svcname && strcmp(argv[1], svcname))
eerrorx("%s: the first argument is %s and must be %s",
applet, argv[1], svcname);
@@ -752,16 +609,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)
@@ -795,10 +642,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;
@@ -822,11 +665,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'",
@@ -904,6 +742,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;
@@ -916,12 +756,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");
@@ -996,9 +830,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) {
@@ -1043,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));
@@ -1062,8 +893,8 @@ int main(int argc, char **argv)
c++;
}
xasprintf(&varbuf, "%d", x);
rc_service_value_set(svcname, "argc", varbuf);
free(varbuf);
rc_service_value_set(svcname, "argc", varbuf);
free(varbuf);
rc_service_value_set(svcname, "exec", exec);
supervisor(exec, argv);
} else
@@ -1098,18 +929,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);
}
}

6
src/test/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
einfo.data.out
einfo.funcs.out
librc.funcs.hidden.out
librc.funcs.hidden.list
rc.data.out
rc.funcs.out

1
src/test/einfo.data.list Normal file
View File

@@ -0,0 +1 @@
EINFO_1.0

52
src/test/einfo.funcs.list Normal file
View File

@@ -0,0 +1,52 @@
ebegin
ebegin@@EINFO_1.0
ebeginv
ebeginv@@EINFO_1.0
ebracket
ebracket@@EINFO_1.0
ecolor
ecolor@@EINFO_1.0
eend
eend@@EINFO_1.0
eendv
eendv@@EINFO_1.0
eerror
eerror@@EINFO_1.0
eerrorn
eerrorn@@EINFO_1.0
eerrorx
eerrorx@@EINFO_1.0
eindent
eindent@@EINFO_1.0
eindentv
eindentv@@EINFO_1.0
einfo
einfo@@EINFO_1.0
einfon
einfon@@EINFO_1.0
einfov
einfov@@EINFO_1.0
einfovn
einfovn@@EINFO_1.0
elog
elog@@EINFO_1.0
eoutdent
eoutdent@@EINFO_1.0
eoutdentv
eoutdentv@@EINFO_1.0
eprefix
eprefix@@EINFO_1.0
ewarn
ewarn@@EINFO_1.0
ewarnn
ewarnn@@EINFO_1.0
ewarnv
ewarnv@@EINFO_1.0
ewarnvn
ewarnvn@@EINFO_1.0
ewarnx
ewarnx@@EINFO_1.0
ewend
ewend@@EINFO_1.0
ewendv
ewendv@@EINFO_1.0

3
src/test/rc.data.list Normal file
View File

@@ -0,0 +1,3 @@
RC_1.0
rc_environ_fd
rc_environ_fd@@RC_1.0

116
src/test/rc.funcs.list Normal file
View File

@@ -0,0 +1,116 @@
rc_conf_value
rc_conf_value@@RC_1.0
rc_config_list
rc_config_list@@RC_1.0
rc_config_load
rc_config_load@@RC_1.0
rc_config_value
rc_config_value@@RC_1.0
rc_deptree_depend
rc_deptree_depend@@RC_1.0
rc_deptree_depends
rc_deptree_depends@@RC_1.0
rc_deptree_free
rc_deptree_free@@RC_1.0
rc_deptree_load
rc_deptree_load@@RC_1.0
rc_deptree_load_file
rc_deptree_load_file@@RC_1.0
rc_deptree_order
rc_deptree_order@@RC_1.0
rc_deptree_update
rc_deptree_update@@RC_1.0
rc_deptree_update_needed
rc_deptree_update_needed@@RC_1.0
rc_find_pids
rc_find_pids@@RC_1.0
rc_getfile
rc_getfile@@RC_1.0
rc_getline
rc_getline@@RC_1.0
rc_newer_than
rc_newer_than@@RC_1.0
rc_older_than
rc_older_than@@RC_1.0
rc_proc_getent
rc_proc_getent@@RC_1.0
rc_runlevel_exists
rc_runlevel_exists@@RC_1.0
rc_runlevel_get
rc_runlevel_get@@RC_1.0
rc_runlevel_list
rc_runlevel_list@@RC_1.0
rc_runlevel_set
rc_runlevel_set@@RC_1.0
rc_runlevel_stack
rc_runlevel_stack@@RC_1.0
rc_runlevel_stacks
rc_runlevel_stacks@@RC_1.0
rc_runlevel_starting
rc_runlevel_starting@@RC_1.0
rc_runlevel_stopping
rc_runlevel_stopping@@RC_1.0
rc_runlevel_unstack
rc_runlevel_unstack@@RC_1.0
rc_service_add
rc_service_add@@RC_1.0
rc_service_daemon_set
rc_service_daemon_set@@RC_1.0
rc_service_daemons_crashed
rc_service_daemons_crashed@@RC_1.0
rc_service_delete
rc_service_delete@@RC_1.0
rc_service_description
rc_service_description@@RC_1.0
rc_service_exists
rc_service_exists@@RC_1.0
rc_service_extra_commands
rc_service_extra_commands@@RC_1.0
rc_service_in_runlevel
rc_service_in_runlevel@@RC_1.0
rc_service_mark
rc_service_mark@@RC_1.0
rc_service_resolve
rc_service_resolve@@RC_1.0
rc_service_schedule_clear
rc_service_schedule_clear@@RC_1.0
rc_service_schedule_start
rc_service_schedule_start@@RC_1.0
rc_service_started_daemon
rc_service_started_daemon@@RC_1.0
rc_service_state
rc_service_state@@RC_1.0
rc_service_value_get
rc_service_value_get@@RC_1.0
rc_service_value_set
rc_service_value_set@@RC_1.0
rc_services_in_runlevel
rc_services_in_runlevel@@RC_1.0
rc_services_in_runlevel_stacked
rc_services_in_runlevel_stacked@@RC_1.0
rc_services_in_state
rc_services_in_state@@RC_1.0
rc_services_scheduled
rc_services_scheduled@@RC_1.0
rc_services_scheduled_by
rc_services_scheduled_by@@RC_1.0
rc_stringlist_add
rc_stringlist_add@@RC_1.0
rc_stringlist_addu
rc_stringlist_addu@@RC_1.0
rc_stringlist_delete
rc_stringlist_delete@@RC_1.0
rc_stringlist_find
rc_stringlist_find@@RC_1.0
rc_stringlist_free
rc_stringlist_free@@RC_1.0
rc_stringlist_new
rc_stringlist_new@@RC_1.0
rc_stringlist_sort
rc_stringlist_sort@@RC_1.0
rc_stringlist_split
rc_stringlist_split@@RC_1.0
rc_sys
rc_sys@@RC_1.0
rc_yesno
rc_yesno@@RC_1.0

View File

@@ -1,6 +1,6 @@
#!/bin/sh
top_srcdir=${top_srcdir:-..}
top_srcdir=${top_srcdir:-../..}
. ${top_srcdir}/test/setup_env.sh
libeinfo_srcdir="${srcdir}/../libeinfo"
@@ -20,12 +20,52 @@ 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 \
| awk '$4 == "OBJECT" && $5 == "GLOBAL" && $7 != "UND" {print $NF}' \
| LC_ALL=C sort -u
)
ebegin "Checking exported symbols in libeinfo.so (functions)"
checkit einfo.funcs $(
readelf -Ws ${libeinfo_builddir}/libeinfo.so \
| awk '$4 == "FUNC" && $5 == "GLOBAL" && $7 != "UND" {print $NF}' \
| LC_ALL=C sort -u \
| egrep -v \
-e '^_(init|fini)$'
)
ebegin "Checking exported symbols in librc.so (data)"
checkit rc.data $(
readelf -Ws ${librc_builddir}/librc.so \
| awk '$4 == "OBJECT" && $5 == "GLOBAL" && $7 != "UND" {print $NF}' \
| LC_ALL=C sort -u
)
ebegin "Checking exported symbols in librc.so (functions)"
checkit rc.funcs $(
readelf -Ws ${librc_builddir}/librc.so \
| awk '$4 == "FUNC" && $5 == "GLOBAL" && $7 != "UND" {print $NF}' \
| LC_ALL=C sort -u \
| egrep -v \
-e '^_(init|fini)$'
)
ebegin "Checking hidden functions in librc.so"
sed -n '/^librc_hidden_proto/s:.*(\(.*\))$:\1:p' ${librc_srcdir}/librc.h \
| LC_ALL=C sort -u \
> librc.funcs.hidden.list
readelf -Wr $(grep -l '#include[[:space:]]"librc\.h"' ${librc_srcdir}/*.c | sed 's:\.c$:.o:') \
| egrep -v -e 'R_PARISC_(DP|SEG)REL' \
| awk '$5 ~ /^rc_/ {print $5}' \
| LC_ALL=C sort -u \
| egrep -v '^rc_environ_fd$' \
> librc.funcs.hidden.out
syms=$(diff -u librc.funcs.hidden.list librc.funcs.hidden.out | sed -n '/^+[^+]/s:^+::p')
[ -z "${syms}" ]
eend $? "Missing hidden defs:"$'\n'"${syms}"
: $(( ret += $? ))
ebegin "Checking trailing whitespace in code"
# XXX: Should we check man pages too ?
@@ -34,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};
@@ -43,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]' \
@@ -51,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]' \
@@ -62,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]' \
@@ -77,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

View File

@@ -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.

5
test/skel.runtests.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
# top_srcdir=${top_srcdir:-SET/THIS/PATH/OK!?}
. ${top_srcdir}/test/setup_env.sh

View File

@@ -1,37 +1,27 @@
#compdef rc-service
_rc_services() {
if [[ -n "${opt_args[(i)-l|--list]}" ]]; then
_nothing
else
_values 'service' $(rc-service -l)
fi
}
_rc_actions() {
local service="${line[1]}"
if [[ -n "${opt_args[(i)-e|--exists|-r|--resolve]}" ]] || ! $(rc-service -e $service) ; then
_nothing
else
local -a actions=(${(f)"$(rc-service -C $service describe 2>&1)"})
shift actions
actions=(${actions# \* })
actions=(${actions/:*})
actions=(stop start restart describe zap ${actions[@]})
_describe -V 'action' actions
fi
}
_arguments -C -s \
'(-e --exists)'{-e,--exists}'[tests if the service exists or not]' \
'(-l --list)'{-l,--list}'[list all available services]' \
'(-r --resolve)'{-r,--resolve}'[resolve the service name to an init script]' \
'(-C --nocolor)'{-C,--nocolor}'[Disable color output]' \
'(-v --verbose)'{-v,--verbose}'[Run verbosely]' \
'(-q --quiet)'{-q,--quiet}'[Run quietly]' \
'1:service:_rc_services' \
'2:action:_rc_actions'
if (( CURRENT == 2 )); then
_arguments -s \
'(-e --exists)'{-e,--exists}"[tests if the service exists or not]" \
'(-l --list)'{-l,--list}'[list all available services]' \
'(-r --resolve)'{-r,--resolve}'[resolve the service name to an init script]' \
'(-C --nocolor)'{-C,--nocolor}'[Disable color output]' \
'(-v --verbose)'{-v,--verbose}'[Run verbosely]' \
'(-q --quiet)'{-q,--quiet}'[Run quietly]'
_values "service" $(rc-service --list)
else
case $words[2] in
-e|--exists|-r|--resolve)
(( CURRENT > 3 )) && return 0
_values "service" $(rc-service --list)
;;
-*)
return 0
;;
*)
_values "action" stop start restart describe zap
;;
esac
fi
# vim: set et sw=2 ts=2 ft=zsh: