Compare commits

..

9 Commits

Author SHA1 Message Date
William Hubbs
60f42c415d Update ChangeLog 2018-10-19 16:03:36 -05:00
Zac Medico
93c8cbe684 supervise-daemon: fix respawn_max off by one
Fix the comparison between respawn_count and respawn_max so that
respawn_max = 1 will allow for one respawn. Since respawn_count is
incremented before the comparison, use a 'greater than' comparison
so that respawn will be triggered when respawn_count is equal to
respawn_max.

Fixes: https://github.com/OpenRC/openrc/issues/247
Fixes: https://github.com/OpenRC/openrc/issues/248
2018-10-19 16:01:07 -05:00
William Hubbs
386bdf66f9 version 0.38.3 2018-10-19 15:58:07 -05:00
William Hubbs
81ab30c51d Update ChangeLog 2018-08-06 17:51:56 -05:00
Zac Medico
d05c8c2159 librc: fix EACCES errno false-positive crash
Use errno != EACCES to fix false-positive for non-root users
with grsecurity kernels.

Fixes: 37e2944272 ("librc: Add check for crashed state")
This fixes #237
2018-08-06 17:51:27 -05:00
William Hubbs
7850e12071 version 0.38.2 2018-08-06 17:44:43 -05:00
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
111 changed files with 2157 additions and 2537 deletions

View File

@@ -1,15 +0,0 @@
# Cirrus CI integration
# https://cirrus-ci.org
test_task:
freebsd_instance:
matrix:
image: freebsd-12-1-release-amd64
image: freebsd-11-4-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,32 +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.libera.chat#openrc"
on_success: always # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
before_install:
- sudo apt-get update
- sudo apt-get install -y shellcheck
script:
- ./ci/travis.sh

View File

@@ -82,7 +82,6 @@ Semen Maryasin <marsoft@ya.ru>
Sergei Trofimovich <slyfox@gentoo.org> Sergei Trofimovich <slyfox@gentoo.org>
Seth Robertson <in-gentoo@baka.org> Seth Robertson <in-gentoo@baka.org>
S. Gilles <sgilles@umd.edu> S. Gilles <sgilles@umd.edu>
Sony Interactive Entertainment, llc.
Stefan Knoblich <s.knoblich@axsentis.de> Stefan Knoblich <s.knoblich@axsentis.de>
Stef Simoens <stef.simoens@scarlet.be> Stef Simoens <stef.simoens@scarlet.be>
Steve L <slong@rathaus.eclipse.co.uk> Steve L <slong@rathaus.eclipse.co.uk>

1561
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -33,9 +33,8 @@ ifeq (${MKZSHCOMP},yes)
SUBDIR+= zsh-completion SUBDIR+= zsh-completion
endif 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+= runlevels
SUBDIR+= test
INSTALLAFTER= _installafter INSTALLAFTER= _installafter

View File

@@ -1,3 +1,3 @@
NAME= openrc NAME= openrc
VERSION= 0.43.4 VERSION= 0.38.3
PKG= ${NAME}-${VERSION} PKG= ${NAME}-${VERSION}

75
NEWS.md
View File

@@ -4,81 +4,6 @@ OpenRC NEWS
This file will contain a list of notable changes for each release. Note This file will contain a list of notable changes for each release. Note
the information in this file is in reverse order. the information in this file is in reverse order.
## OpenRC 0.43
This version changes the behavior of the checkpath helper to address
CVE-2018-21269. on Linux systems, We require non-terminal symbolic links
to be owned by root. Since we can't do this on non-linux xystems, we do
not dereference non-terminal symbolic links by default. If you need them
dereferenced, you should add the "-s" switch to the appropriate
checkpath calls.
For more information, see http://github.com/openrc/openrc/issues/201.
The SHLIBDIR variable has been removed from the makefiles to make them
more consistent with most common makefiles. All libraries are now in
LIBDIR, so if you need to put them in /, override the LIBDIR variable
when you run make.
## OpenRC 0.42
openrc-shutdown now has the ability to shut down sysvinit-based systems.
A guide has been added for migrating systems using another init system
to openrc-init.
## 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 ## OpenRC 0.37
start-stop-daemon now supports logging stdout and stderr of daemons to start-stop-daemon now supports logging stdout and stderr of daemons to

View File

@@ -2,7 +2,8 @@ OpenRC README
============= =============
OpenRC is a dependency-based init system that works with the OpenRC is a dependency-based init system that works with the
system-provided init program, normally `/sbin/init`. system-provided init program, normally `/sbin/init`. Currently, it does
not have an init program of its own.
## Installation ## Installation
@@ -11,7 +12,7 @@ OpenRC requires GNU make.
Once you have GNU Make installed, the default OpenRC installation can be Once you have GNU Make installed, the default OpenRC installation can be
executed using this command: executed using this command:
`make install` make install
## Configuration ## Configuration
@@ -37,7 +38,6 @@ PKG_PREFIX=/usr/pkg
LOCAL_PREFIX=/usr/local LOCAL_PREFIX=/usr/local
PREFIX=/usr/local PREFIX=/usr/local
BRANDING=\"Gentoo/$(uname -s)\" BRANDING=\"Gentoo/$(uname -s)\"
SH=/bin/sh
``` ```
## Notes ## Notes
@@ -50,7 +50,7 @@ If you are building OpenRC for a Gentoo Prefix installation, add `MKPREFIX=yes`.
`PKG_PREFIX` should be set to where packages install to by default. `PKG_PREFIX` should be set to where packages install to by default.
`LOCAL_PREFIX` should be set to where user maintained packages are. `LOCAL_PREFIX` should be set when to where user maintained packages are.
Only set `LOCAL_PREFIX` if different from `PKG_PREFIX`. Only set `LOCAL_PREFIX` if different from `PKG_PREFIX`.
`PREFIX` should be set when OpenRC is not installed to /. `PREFIX` should be set when OpenRC is not installed to /.
@@ -78,14 +78,18 @@ remove them and then install so that the OS hooks into OpenRC.
## Reporting Bugs ## Reporting Bugs
Please report bugs on our [bug tracker](http://github.com/OpenRC/openrc/issues). If you are using Gentoo Linux, bugs can be filed on their bugzilla under
the `gentoo hosted projects` product and the `openrc` component [1].
Otherwise, you can report issues on our github [2].
If you can contribute code , please feel free to do so by opening Better yet, if you can contribute code, please feel free to submit pull
[pull requests](https://github.com/OpenRC/openrc/pulls). requests [3].
## IRC Channel ## IRC Channel
We have an official irc channel, #openrc on the libera network. We have an official irc channel, #openrc on freenode, feel free to join
Please connect your irc client to irc.libera.chat and join #openrc on us there.
that network.
[1] https://bugs.gentoo.org/
[2] https://github.com/openrc/openrc/issues
[3] https://github.com/openrc/openrc/pulls

View File

@@ -91,14 +91,11 @@ _rc_service()
done)) done))
return 0 return 0
elif [[ ${COMP_CWORD} -eq 2 ]] && [[ ${prev} != -* ]]; then # if second word typed and we didn't type in a function elif [[ ${COMP_CWORD} -eq 2 ]] && [[ ${prev} != -* ]]; then # if second word typed and we didn't type in a function
rc-service --exists "$prev" || return filename=$(rc-service --resolve ${prev})
shopt -s extglob opts=$(cat ${filename} | grep "^\w*()" | sed "s/().*$//") # Greps the functions included in the init script
while read -r _ line; do if [[ "x${opts}" == "x" ]] ; then # if no options found loosen the grep algorhythm
if [[ $line == +([[:alnum:]_]):* ]]; then opts=$(cat ${filename} | grep "\w*()" | sed "s/().*$//")
opts+="${line%%:*} " fi
fi
done < <(rc-service "$prev" describe 2>&1)
shopt -u extglob
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0 return 0
fi 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,40 +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.
# Run shellcheck, but don't fail (yet):
shellcheck --version
for shellscript in $(git ls-files); do
case $shellscript in
init.d/*.in) ;;
sh/*.in) ;;
sh/*.sh) ;;
support/init.d.examples/*.in) ;;
support/openvpn/*.sh) ;;
support/sysvinit/halt.sh) ;;
test/*.sh) ;;
*) continue ;;
esac
echo "Checking ${shellscript} with shellcheck:"
shellcheck -s sh "${shellscript}" || true
done
cpus=$(getconf _NPROCESSORS_CONF || echo 1)
# make on TravisCI doesn't support -O yet
make -j"${cpus}"
make test

View File

@@ -1,2 +1,2 @@
# Hostname fallback if /etc/hostname does not exist # Set to the hostname of this machine
hostname="localhost" hostname="localhost"

View File

@@ -8,6 +8,11 @@
#modules_2="ipv6" #modules_2="ipv6"
#modules="ohci1394" #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 # Linux users can give the modules some arguments if needed, per version
# if necessary. # if necessary.
# Again, the most specific versioned variable will take precedence. # Again, the most specific versioned variable will take precedence.

View File

@@ -198,9 +198,10 @@ rc_tty_number=12
# "unified" mounts cgroups version 2 on /sys/fs/cgroup # "unified" mounts cgroups version 2 on /sys/fs/cgroup
#rc_cgroup_mode="hybrid" #rc_cgroup_mode="hybrid"
# This is a list of controllers which should be enabled for cgroups version 2 # This is a list of controllers which should be enabled for cgroups version 2.
# when hybrid mode is being used. # If hybrid mode is being used, controllers listed here will not be
# Controllers listed here will not be available for cgroups version 1. # available for cgroups version 1.
# This is a global setting.
#rc_cgroup_controllers="" #rc_cgroup_controllers=""
# This variable contains the cgroups version 2 settings for your services. # This variable contains the cgroups version 2 settings for your services.
@@ -229,7 +230,7 @@ rc_tty_number=12
# The following setting turns on the memory.use_hierarchy setting in the # The following setting turns on the memory.use_hierarchy setting in the
# root memory cgroup for cgroups v1. # root memory cgroup for cgroups v1.
# It must be set to yes in this file if you want this functionality. # 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 # The following settings allow you to set up values for the cgroups version 1
# controllers for your services. # controllers for your services.

View File

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

View File

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

View File

@@ -1,47 +0,0 @@
# OpenRC init process guide
OpenRC now includes an init process which can be used on Linux systems
in place of sysvinit.
## migrating a live system to openrc-init
Configuring a live system to use this init process is very
straight-forward, but the steps must be completed in this order.
* have your boot loader add "init=/sbin/openrc-init" to the kernel command line
The details of how to do this will vary from distro to distro, so they are
out of scope for this document.
* Install gettys into the runlevels where you need them.
If you are using the provided /etc/init.d/agetty script,, you should
first create symlinks in /etc/init.d to it for the ports where you
want gettys to run, e.g. the following will work if you want gettys on
tty1-tty6.
```
# cd /etc/init.d
# for x in tty1 tty2 tty3 tty4 tty5 tty6; do
ln -snf agetty agetty.$x
done
```
Once this is done, use ```rc-update``` as normal to install the agetty
services in the appropriate runlevels.
* Reboot your system.
At this point you are running under openrc-init, and you should use
openrc-shutdown to handle shutting down, powering off, rebooting etc.
## optional sysvinit compatibility
If you build and install OpenRC with MKSYSVINIT=yes, you will build and install
wrappers that make openrc-init compatible with sysvinit -- you will have
commands like "halt" "shutdown" "reboot" and "poweroff".
If you want this functionality on a live system, you should first
migrate the system to openrc-init, remove sysvinit, then rebuild and
install this package with MKSYSVINIT=yes.

2
init.d/.gitignore vendored
View File

@@ -41,8 +41,6 @@ rc-enabled
rpcbind rpcbind
runsvdir runsvdir
savecore savecore
save-keymaps
save-termencoding
swap-blk swap-blk
swclock swclock
syslogd 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 \ SRCS-Linux= agetty.in binfmt.in devfs.in cgroups.in dmesg.in hwclock.in \
consolefont.in keymaps.in killprocs.in modules.in \ consolefont.in keymaps.in killprocs.in modules.in \
mount-ro.in mtab.in numlock.in procfs.in net-online.in save-keymaps.in \ mount-ro.in mtab.in numlock.in procfs.in net-online.in sysfs.in \
save-termencoding.in sysfs.in termencoding.in termencoding.in
# Generic BSD scripts # Generic BSD scripts
SRCS-NetBSD= hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \ 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" description="start agetty on a terminal line"
supervisor=supervise-daemon supervisor=supervise-daemon
port="${RC_SVCNAME#*.}" port="${RC_SVCNAME#*.}"
respawn_period="${respawn_period:-60}"
term_type="${term_type:-linux}" term_type="${term_type:-linux}"
command=/sbin/agetty command=/sbin/agetty
command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}" command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}"
@@ -21,7 +20,6 @@ pidfile="/run/${RC_SVCNAME}.pid"
depend() { depend() {
after local after local
keyword -prefix keyword -prefix
provide getty
} }
start_pre() { start_pre() {

View File

@@ -241,13 +241,7 @@ stop()
{ {
# Write a halt record if we're shutting down # Write a halt record if we're shutting down
if [ "$RC_RUNLEVEL" = shutdown ]; then if [ "$RC_RUNLEVEL" = shutdown ]; then
if [ "$RC_UNAME" = Linux ]; then [ "$RC_UNAME" = Linux ] && openrc-shutdown -w
if [ -x /sbin/halt ]; then
halt -w
else
openrc-shutdown -w
fi
fi
if [ "$RC_SYS" = OPENVZ ]; then if [ "$RC_SYS" = OPENVZ ]; then
yesno $RC_REBOOT && printf "" >/reboot yesno $RC_REBOOT && printf "" >/reboot
fi fi

View File

@@ -83,22 +83,14 @@ cgroup2_controllers()
local active cgroup_path x y local active cgroup_path x y
cgroup_path="$(cgroup2_find_path)" cgroup_path="$(cgroup2_find_path)"
[ -z "${cgroup_path}" ] && return 0 [ -z "${cgroup_path}" ] && return 0
[ ! -e "${cgroup_path}/cgroup.controllers" ] && return 0 [ -e "${cgroup_path}/cgroup.controllers" ] &&
[ ! -e "${cgroup_path}/cgroup.subtree_control" ]&& return 0
read -r active < "${cgroup_path}/cgroup.controllers" read -r active < "${cgroup_path}/cgroup.controllers"
for x in ${active}; do for x in ${rc_cgroup_controllers}; do
case "$rc_cgroup_mode" in for y in ${active}; do
unified) [ "$x" = "$y" ] &&
[ -e "${cgroup_path}/cgroup.subtree_control" ]&&
echo "+${x}" > "${cgroup_path}/cgroup.subtree_control" echo "+${x}" > "${cgroup_path}/cgroup.subtree_control"
;; done
hybrid)
for y in ${rc_cgroup_controllers}; do
if [ "$x" = "$y" ]; then
echo "+${x}" > "${cgroup_path}/cgroup.subtree_control"
fi
done
;;
esac
done done
return 0 return 0
} }

View File

@@ -15,7 +15,7 @@ depend()
{ {
provide dev-mount provide dev-mount
before dev before dev
keyword -docker -prefix -systemd-nspawn -vserver keyword -docker -lxc -prefix -systemd-nspawn -vserver
} }
mount_dev() mount_dev()
@@ -66,20 +66,18 @@ seed_dev()
{ {
# Seed /dev with some things that we know we need # Seed /dev with some things that we know we need
if [ "${RC_SYS}" != LXC ]; then # creating /dev/console, /dev/tty and /dev/tty1 to be able to write
# creating /dev/console, /dev/tty and /dev/tty1 to be able to write # to $CONSOLE with/without bootsplash before udevd creates it
# to $CONSOLE with/without bootsplash before udevd creates it [ -c /dev/console ] || mknod -m 600 /dev/console c 5 1
[ -c /dev/console ] || mknod -m 600 /dev/console c 5 1 [ -c /dev/tty1 ] || mknod -m 620 /dev/tty1 c 4 1
[ -c /dev/tty1 ] || mknod -m 620 /dev/tty1 c 4 1 [ -c /dev/tty ] || mknod -m 666 /dev/tty c 5 0
[ -c /dev/tty ] || mknod -m 666 /dev/tty c 5 0
# udevd will dup its stdin/stdout/stderr to /dev/null # udevd will dup its stdin/stdout/stderr to /dev/null
# and we do not want a file which gets buffered in ram # and we do not want a file which gets buffered in ram
[ -c /dev/null ] || mknod -m 666 /dev/null c 1 3 [ -c /dev/null ] || mknod -m 666 /dev/null c 1 3
# so udev can add its start-message to dmesg # so udev can add its start-message to dmesg
[ -c /dev/kmsg ] || mknod -m 660 /dev/kmsg c 1 11 [ -c /dev/kmsg ] || mknod -m 660 /dev/kmsg c 1 11
fi
# extra symbolic links not provided by default # extra symbolic links not provided by default
[ -e /dev/fd ] || ln -snf /proc/self/fd /dev/fd [ -e /dev/fd ] || ln -snf /proc/self/fd /dev/fd

View File

@@ -14,7 +14,7 @@ description="Applies a keymap for the consoles."
depend() depend()
{ {
need termencoding need termencoding
after devfs after bootmisc clock
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
} }
@@ -68,5 +68,10 @@ start()
echo "altgr keycode 18 = U+20AC" | loadkeys -q - echo "altgr keycode 18 = U+20AC" | loadkeys -q -
eend $? eend $?
fi 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

@@ -41,27 +41,26 @@ find_modfiles()
load_modules() load_modules()
{ {
local file m _modules rc x local file m modules rc x
file=$1 file=$1
[ -z "$file" ] && return 0 [ -z "$file" ] && return 0
while read m x; do while read m x; do
case $m in case $m in
\;*) continue ;; \;*) continue ;;
\#*) continue ;; \#*) continue ;;
*) _modules="$_modules $m" *) modules="$modules $m"
;; ;;
esac esac
done < $file done < $file
for x in $_modules; do for x in $modules; do
ebegin "Loading module $x" ebegin "Loading module $x"
case "$RC_UNAME" in case "$RC_UNAME" in
FreeBSD) kldload "$x"; rc=$? ;; FreeBSD) kldload "$x"; rc=$? ;;
Linux) modprobe --first-time -q --use-blacklist "$x"; rc=$? ;; Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
*) ;; *) ;;
esac esac
eend $rc "Failed to load $x" eend $rc "Failed to load $x"
done done
return 0
} }
modules_load_d() modules_load_d()
@@ -104,7 +103,7 @@ Linux_modules()
x=${x%.*} x=${x%.*}
done done
local list= x= xx= y= args= local list= x= xx= y= args= mpargs= a=
for x in $kv_variant_list ; do for x in $kv_variant_list ; do
eval list=\$modules_$(shell_var "$x") eval list=\$modules_$(shell_var "$x")
[ -n "$list" ] && break [ -n "$list" ] && break
@@ -113,13 +112,24 @@ Linux_modules()
[ -n "$list" ] && ebegin "Loading kernel modules" [ -n "$list" ] && ebegin "Loading kernel modules"
for x in $list; do 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") xx=$(shell_var "$x")
for y in $kv_variant_list ; do 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") eval args=\$module_${xx}_args_$(shell_var "$y")
[ -n "${args}" ] && break [ -n "${args}" ] && break
done done
[ -z "$args" ] && eval args=\$module_${aa}_args
[ -z "$args" ] && eval args=\$module_${xx}_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 done
[ -n "$list" ] && eend [ -n "$list" ] && eend
} }
@@ -127,7 +137,7 @@ Linux_modules()
start() start()
{ {
case "$RC_UNAME" in case "$RC_UNAME" in
FreeBSD|Linux) FreeBSD|Linux)
modules_load_d modules_load_d
${RC_UNAME}_modules ${RC_UNAME}_modules
;; ;;

View File

@@ -23,7 +23,7 @@ get_interfaces()
{ {
local ifname iftype local ifname iftype
for ifname in /sys/class/net/*; do for ifname in /sys/class/net/*; do
[ -h "${ifname}" ] || continue [ -h "${ifname}" ] && continue
read iftype < ${ifname}/type read iftype < ${ifname}/type
[ "$iftype" = "1" ] && printf "%s " ${ifname##*/} [ "$iftype" = "1" ] && printf "%s " ${ifname##*/}
done done

View File

@@ -42,8 +42,6 @@ start()
stop() stop()
{ {
yesno $RC_GOINGDOWN && return 0
ebegin "Disabling numlock on ttys" ebegin "Disabling numlock on ttys"
_setleds - _setleds -
eend $? "Failed to disable numlock" eend $? "Failed to disable numlock"

View File

@@ -17,15 +17,3 @@ depend()
{ {
provide clock provide clock
} }
start()
{
# This stub function is required to avoid OpenRC warning at boot:
#
# * The command variable is undefined.
# * There is nothing for osclock to start.
# * If this is what you intend, please write a start function.
# * This will become a failure in a future release.
#
return 0
}

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 ] && if [ -d /sys/firmware/efi/efivars ] &&
! mountinfo -q /sys/firmware/efi/efivars; then ! mountinfo -q /sys/firmware/efi/efivars; then
ebegin "Mounting efivarfs filesystem" 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 efivarfs /sys/firmware/efi/efivars 2> /dev/null
eend 0 eend 0
fi fi

View File

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

View File

@@ -332,7 +332,7 @@ section below.
.Sh _pre AND _post FUNCTIONS .Sh _pre AND _post FUNCTIONS
Any command defined in extra_commands, extra_started_commands or Any command defined in extra_commands, extra_started_commands or
extra_stopped_commands can have _pre and _post functions in the service extra_stopped_commands can have _pre and _post functions in the service
script. If the command function is called foo, the _pre and _post script. If the command function is called foo, the_pre and _post
functions for it should be called foo_pre and foo_post. functions for it should be called foo_pre and foo_post.
.Pp .Pp
These functions should be used to perform preparation before the These functions should be used to perform preparation before the
@@ -461,7 +461,6 @@ Mark the service as inactive.
.Op Fl p , -pipe .Op Fl p , -pipe
.Op Fl m , -mode Ar mode .Op Fl m , -mode Ar mode
.Op Fl o , -owner Ar owner .Op Fl o , -owner Ar owner
.Op Fl s , -symlinks
.Op Fl W , -writable .Op Fl W , -writable
.Op Fl q , -quiet .Op Fl q , -quiet
.Ar path ... .Ar path ...
@@ -482,11 +481,6 @@ or with names, and are separated by a colon.
The truncate options (-D and -F) cause the directory or file to be The truncate options (-D and -F) cause the directory or file to be
cleared of all contents. cleared of all contents.
.Pp .Pp
If -s is not specified on a non-linux platform, checkpath will refuse to
allow non-terminal symbolic links to exist in the path. This is for
security reasons so that a non-root user can't create a symbolic link to
a root-owned file and take ownership of that file.
.Pp
If -W is specified, checkpath checks to see if the first path given on If -W is specified, checkpath checks to see if the first path given on
the command line is writable. This is different from how the test the command line is writable. This is different from how the test
command in the shell works, because it also checks to make sure the file command in the shell works, because it also checks to make sure the file

View File

@@ -16,36 +16,15 @@
.Nd bring the system down .Nd bring the system down
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .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 , -no-write
.Op Fl D , -dry-run .Op Fl D , -dry-run
.Op Fl H , -halt .Op Fl H , -halt
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl k , -kexec .Op Fl k , -kexec
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl p , -poweroff .Op Fl p , -poweroff
time .Op Fl R , -reexec
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl r , -reboot .Op Fl r , -reboot
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl s , -single .Op Fl s , -single
time .Op Fl w , -write-only
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
is the utility that communicates with 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. to bring down the system or instruct openrc-init to re-execute itself.
It supports the following options: It supports the following options:
.Bl -tag -width "poweroff" .Bl -tag -width "poweroff"
.It Fl c , -cancel
Cancel a pending shutdown.
.It Fl d , -no-write .It Fl d , -no-write
Do not write the wtmp boot record. Do not write the wtmp boot record.
.It Fl D , -dry-run .It Fl D , -dry-run
@@ -76,7 +53,7 @@ Stop all services, kill all processes and reboot the system.
.It Fl s , -single .It Fl s , -single
Stop all services, kill all processes and move to single user mode. Stop all services, kill all processes and move to single user mode.
.It Fl w , -write-only .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 .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr openrc-init 8 , .Xr openrc-init 8 ,

View File

@@ -65,31 +65,7 @@ Instead you should use
and and
.Xr shutdown 8 .Xr shutdown 8
and let them call these special runlevels. and let them call these special runlevels.
.Sh OPTIONS
.Pp
.Bl -tag -width "-o , --override"
.It Fl n , -no-stop
Do not stop any services.
.It Fl o , -override
Override the next runlevel to change into when leaving single user or boot
runlevels
.It Fl s , -service
Run the service specified with the rest of the arguments.
.It Fl S , -sys
Output the RC system type, if any.
.It Fl h , -help
Display usage information and exit.
.It Fl C , -nocolor
Disable color output.
.It Fl V , -version
Display software version.
.It Fl v , -verbose
Run verbosely.
.It Fl q , -quiet
Run quietly (repeat to suppress errors).
.El
.Sh SEE ALSO .Sh SEE ALSO
.Xr openrc-run 8 ,
.Xr rc-status 8 , .Xr rc-status 8 ,
.Xr rc-update 8 , .Xr rc-update 8 ,
.Xr init 8 , .Xr init 8 ,

View File

@@ -17,7 +17,6 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl aclsuC .Op Fl aclsuC
.Op Fl f Ar ini
.Op Ar runlevel .Op Ar runlevel
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
@@ -38,17 +37,12 @@ The options are as follows:
Show all runlevels and their services. Show all runlevels and their services.
.It Fl c , -crashed .It Fl c , -crashed
List all services that have 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 .It Fl l , -list
List all defined runlevels. List all defined runlevels.
.It Fl m , -manual .It Fl m , -manual
Show all manually started services. Show all manually started services.
.It Fl r , -runlevel .It Fl r , -runlevel
Print the current runlevel name. Print the current runlevel name.
.It Fl S , -supervised
Show all supervised services.
.It Fl s , -servicelist .It Fl s , -servicelist
Show all services. Show all services.
.It Fl u , -unused .It Fl u , -unused

View File

@@ -120,7 +120,7 @@ Saves the pid of the daemon in the file specified by the
.Fl p , -pidfile .Fl p , -pidfile
option. Only useful when used with daemons that run in the foreground and option. Only useful when used with daemons that run in the foreground and
forced into the background with the forced into the background with the
.Fl b , -background .Fl -b , -background
option. option.
.It Fl I , -ionice Ar class Ns Op : Ns Ar data .It Fl I , -ionice Ar class Ns Op : Ns Ar data
Modifies the IO scheduling priority of the daemon. Modifies the IO scheduling priority of the daemon.

View File

@@ -9,18 +9,13 @@
.\" except according to the terms contained in the LICENSE file. .\" except according to the terms contained in the LICENSE file.
.\" .\"
.Dd April 27, 2016 .Dd April 27, 2016
.Dt SUPERVISE-DAEMON 8 SMM .Dt supervise-DAEMON 8 SMM
.Os OpenRC .Os OpenRC
.Sh NAME .Sh NAME
.Nm supervise-daemon .Nm supervise-daemon
.Nd starts a daemon and restarts it if it crashes .Nd starts a daemon and restarts it if it crashes
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
servicename
.Fl a , -healthcheck-timer
.Ar seconds
.Fl A , -healthcheck-delay
.Ar seconds
.Fl D , -respawn-delay .Fl D , -respawn-delay
.Ar seconds .Ar seconds
.Fl d , -chdir .Fl d , -chdir
@@ -38,7 +33,7 @@ servicename
.Fl N , -nicelevel .Fl N , -nicelevel
.Ar level .Ar level
.Fl p , -pidfile .Fl p , -pidfile
.Ar supervisorpidfile .Ar pidfile
.Fl P , -respawn-period .Fl P , -respawn-period
.Ar seconds .Ar seconds
.Fl R , -retry .Fl R , -retry
@@ -56,15 +51,10 @@ servicename
.Op Fl - .Op Fl -
.Op Ar arguments .Op Ar arguments
.Nm .Nm
servicename
.Fl K , -stop .Fl K , -stop
.Ar daemon .Ar daemon
.Fl r , -chroot .Fl p , -pidfile
.Ar chrootpath .Ar pidfile
.Nm
servicename
.Fl s , -signal
.Ar signal
.Fl r , -chroot .Fl r , -chroot
.Ar chrootpath .Ar chrootpath
.Sh DESCRIPTION .Sh DESCRIPTION
@@ -72,15 +62,22 @@ servicename
provides a consistent method of starting, stopping and restarting provides a consistent method of starting, stopping and restarting
daemons. If daemons. If
.Fl K , -stop .Fl K , -stop
or
.Fl s , -signal
is not provided, then we assume we are starting the daemon. is not provided, then we assume we are starting the daemon.
.Nm .Nm
only works with daemons which do not fork. If your daemon has options to only works with daemons which do not fork. Also, it uses its own pid
tell it not to fork, it should be configured to not fork. 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 .Pp
Here are the options to specify the daemon and how it should start or stop: Here are the options to specify the daemon and how it should start or stop:
.Bl -tag -width indent .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 .It Fl u , -user Ar user Ns Op : Ns Ar group
Start the daemon as the Start the daemon as the
.Ar user .Ar user
@@ -90,17 +87,11 @@ owned by the user. You can optionally append a
name here also. name here also.
.It Fl v , -verbose .It Fl v , -verbose
Print the action(s) that are taken just before doing them. Print the action(s) that are taken just before doing them.
.El
.Pp .Pp
The options are as follows: The options are as follows:
.Bl -tag -width indent .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 .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. The default is 0.
.It Fl d , -chdir Ar path .It Fl d , -chdir Ar path
chdir to this directory before starting the daemon. chdir to this directory before starting the daemon.
@@ -115,22 +106,16 @@ Data can be from 0 to 7 inclusive.
.It Fl k , -umask Ar mode .It Fl k , -umask Ar mode
Set the umask of the daemon. Set the umask of the daemon.
.It Fl m , -respawn-max Ar count .It Fl m , -respawn-max Ar count
Sets the maximum number of times a daemon will be respawned. If a daemon Sets the maximum number of times a daemon will be respawned during a
crashes more than this number of times, respawn period. If a daemon dies more than this number of times during a
respawn period,
.Nm .Nm
will give up and exit. The default is 10 and 0 means unlimited. will give up trying to respawn it and exit. The default is 10, and 0
.Pp means unlimited.
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.
.It Fl p , -pidfile Ar supervisorpidfile
Sets a path for the supervisor's pid file. Note that this is not the pid
file of the process that is being supervised.
.It Fl N , -nicelevel Ar level .It Fl N , -nicelevel Ar level
Modifies the scheduling priority of the daemon. Modifies the scheduling priority of the daemon.
.It Fl P , -respawn-period Ar seconds .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. description of --respawn-max for more information.
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout .It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
The retry specification can be either a timeout in seconds or multiple The retry specification can be either a timeout in seconds or multiple
@@ -138,11 +123,7 @@ signal/timeout pairs (like SIGTERM/5).
If this option is not given, the default is SIGTERM/5. If this option is not given, the default is SIGTERM/5.
.It Fl r , -chroot Ar path .It Fl r , -chroot Ar path
chroot to this directory before starting the daemon. All other paths, such 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. as the path to the daemon, chdir and pidfile, 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.
.It Fl u , -user Ar user .It Fl u , -user Ar user
Start the daemon as the specified user. Start the daemon as the specified user.
.It Fl 1 , -stdout Ar logfile .It Fl 1 , -stdout Ar logfile
@@ -155,6 +136,7 @@ The same thing as
.Fl 1 , -stdout .Fl 1 , -stdout
but with the standard error output. but with the standard error output.
.El .El
.El
.Sh ENVIRONMENT .Sh ENVIRONMENT
.Va SSD_NICELEVEL .Va SSD_NICELEVEL
can also set the scheduling priority of the daemon, but the command line can also set the scheduling priority of the daemon, but the command line
@@ -176,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 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 to infinite respawning since there can never be 10 respawns within 5
seconds. 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 .Sh SEE ALSO
.Xr chdir 2 , .Xr chdir 2 ,
.Xr chroot 2 , .Xr chroot 2 ,
.Xr getopt 3 , .Xr getopt 3 ,
.Xr nice 2 , .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 .Sh HISTORY
.Nm .Nm
first appeared in Debian. first appeared in Debian.

View File

@@ -52,12 +52,13 @@ ${SHLIB_NAME}: ${SOBJS}
${SOBJS} ${LDADD} ${SOBJS} ${LDADD}
install: all install: all
${INSTALL} -d ${DESTDIR}${LIBDIR}
ifeq (${MKSTATICLIBS},yes) ifeq (${MKSTATICLIBS},yes)
${INSTALL} -d ${DESTDIR}${LIBDIR}
${INSTALL} -m ${LIBMODE} lib${LIB}.a ${DESTDIR}${LIBDIR} ${INSTALL} -m ${LIBMODE} lib${LIB}.a ${DESTDIR}${LIBDIR}
endif endif
${INSTALL} -m ${LIBMODE} ${SHLIB_NAME} ${DESTDIR}${LIBDIR} ${INSTALL} -d ${DESTDIR}${SHLIBDIR}
ln -fs ${SHLIB_NAME} ${DESTDIR}${LIBDIR}/${SHLIB_LINK} ${INSTALL} -m ${LIBMODE} ${SHLIB_NAME} ${DESTDIR}${SHLIBDIR}
ln -fs ${SHLIB_NAME} ${DESTDIR}${SHLIBDIR}/${SHLIB_LINK}
${INSTALL} -d ${DESTDIR}${INCDIR} ${INSTALL} -d ${DESTDIR}${INCDIR}
for x in ${INCS}; do ${INSTALL} -m ${INCMODE} $$x ${DESTDIR}${INCDIR}; done for x in ${INCS}; do ${INSTALL} -m ${INCMODE} $$x ${DESTDIR}${INCDIR}; done

View File

@@ -11,7 +11,7 @@
SFX= .Linux.in SFX= .Linux.in
PKG_PREFIX?= /usr 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 LIBDL= -Wl,-Bdynamic -ldl
ifeq (${MKSELINUX},yes) 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_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}) _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 # Tweak our shell scripts
%.sh: %.sh.in %.sh: %.sh.in
@@ -53,6 +53,7 @@ realinstall: ${BIN} ${CONF} ${INC}
install: all realinstall ${INSTALLAFTER} install: all realinstall ${INSTALLAFTER}
check test:: check test::
@if test -e runtests.sh ; then ./runtests.sh || exit $$? ; fi
# A lot of scripts don't have anything to clean # A lot of scripts don't have anything to clean
# Also, some rm implentation require a file argument regardless of error # Also, some rm implentation require a file argument regardless of error

View File

@@ -52,9 +52,9 @@ _LIBNAME:= $(shell ${_LIBNAME_SH})
LIBNAME?= ${_LIBNAME} LIBNAME?= ${_LIBNAME}
LIBDIR?= ${UPREFIX}/${LIBNAME} LIBDIR?= ${UPREFIX}/${LIBNAME}
LIBMODE?= 0644 LIBMODE?= 0644
SHLIBDIR?= ${PREFIX}/${LIBNAME}
LIBEXECDIR?= ${PREFIX}/libexec/rc LIBEXECDIR?= ${PREFIX}/libexec/rc
PKGCONFIGDIR?= ${UPREFIX}/${LIBNAME}/pkgconfig
MANPREFIX?= ${UPREFIX}/share MANPREFIX?= ${UPREFIX}/share
MANDIR?= ${MANPREFIX}/man MANDIR?= ${MANPREFIX}/man

View File

@@ -1,4 +1,4 @@
DIR= ${PKGCONFIGDIR} DIR= ${LIBDIR}/pkgconfig
SRCS= einfo.pc.in openrc.pc.in SRCS= einfo.pc.in openrc.pc.in
INC= einfo.pc openrc.pc INC= einfo.pc openrc.pc

View File

@@ -36,8 +36,7 @@ BOOT-FreeBSD+= hostid modules newsyslog savecore syslogd
# FreeBSD specific stuff # FreeBSD specific stuff
BOOT-FreeBSD+= adjkerntz dumpon syscons BOOT-FreeBSD+= adjkerntz dumpon syscons
BOOT-Linux+= binfmt hwclock keymaps modules mtab procfs save-keymaps \ BOOT-Linux+= binfmt hwclock keymaps modules mtab procfs termencoding
save-termencoding termencoding
SHUTDOWN-Linux= killprocs mount-ro SHUTDOWN-Linux= killprocs mount-ro
SYSINIT-Linux= devfs cgroups dmesg sysfs SYSINIT-Linux= devfs cgroups dmesg sysfs
@@ -90,12 +89,6 @@ install:
fi; \ fi; \
ln -snf ${INITDIR}/"$$x" ${SHUTDOWNDIR}/"$$x" || exit $$?; done \ ln -snf ${INITDIR}/"$$x" ${SHUTDOWNDIR}/"$$x" || exit $$?; done \
fi fi
if test "${MKSYSVINIT}" = yes && test "${OS}" = Linux; then \
for x in tty1 tty2 tty3 tty4 tty5 tty6; do \
ln -snf ${INITDIR}/agetty ${DESTDIR}/${INITDIR}/"agetty.$$x" || exit $$?; \
ln -snf ${INITDIR}/agetty.$$x ${DEFAULTDIR}/"agetty.$$x" || exit $$?; \
done; \
fi
check test:: check test::

View File

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

View File

@@ -18,10 +18,9 @@ if [ -f /proc/acpi/ac_adapter/*/state ]; then
"state:"*"off-line") exit 128;; "state:"*"off-line") exit 128;;
esac esac
done done
elif [ -d /sys/class/power_supply ]; then elif [ -f /sys/class/power_supply/*/online ]; then
for dir in /sys/class/power_supply/*/; do cat /sys/class/power_supply/*/online | while read line; do
[ "$(cat "${dir}/type")" != "Mains" ] && continue [ "${line}" = 0 ] && exit 128
[ "$(cat "${dir}/online")" = 0 ] && exit 128
done done
elif [ -f /proc/pmu/info ]; then elif [ -f /proc/pmu/info ]; then
cat /proc/pmu/info | while read line; do cat /proc/pmu/info | while read line; do

View File

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

View File

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

View File

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

View File

@@ -1,31 +1,14 @@
#!/bin/sh #!@SHELL@
do_halt=false shutdown_arg=
while getopts :akrhPHfFnct: opt; do while getopts :akrhPHfFnct: opt; do
case "$opt" in case "$opt" in
a) ;; a) ;;
k) ;; k) ;;
r) r) shutdown_arg=--reboot ;;
shutdown_arg=--reboot h) shutdown_arg=--halt ;;
;; P) shutdown_arg=--poweroff ;;
h) H) shutdown_arg=--halt ;;
do_halt=true
shutdown_arg=--poweroff
;;
P)
if ! ${do_halt}; then
printf "%s\n" "The -P flag requires the -h flag" >&2
exit 1
fi
shutdown_arg=--poweroff
;;
H)
if ! ${do_halt}; then
printf "%s\n" "The -H flag requires the -h flag" >&2
exit 1
fi
shutdown_arg=--halt
;;
f) ;; f) ;;
F) ;; F) ;;
n) ;; n) ;;
@@ -42,5 +25,5 @@ if [ -z "${shutdown_arg}" ]; then
shutdown_arg=--single shutdown_arg=--single
fi fi
printf "%s %s\n" "@SBINDIR@/openrc-shutdown ${shutdown_arg}" "$@" echo @SBINDIR@/openrc-shutdown ${shutdown_arg} "$@"
exec @SBINDIR@/openrc-shutdown ${shutdown_arg} "$@" exec @SBINDIR@/openrc-shutdown ${shutdown_arg} "$@"

3
sh/.gitignore vendored
View File

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

View File

@@ -1,8 +1,8 @@
DIR= ${LIBEXECDIR}/sh DIR= ${LIBEXECDIR}/sh
SRCS= init.sh.in functions.sh.in gendepends.sh.in \ 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 \ 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}} BIN= gendepends.sh init.sh openrc-run.sh ${BIN-${OS}}
INSTALLAFTER= _installafter INSTALLAFTER= _installafter
@@ -13,9 +13,10 @@ include ${MK}/os.mk
SRCS-FreeBSD= SRCS-FreeBSD=
BIN-FreeBSD= BIN-FreeBSD=
SRCS-Linux= binfmt.sh.in cgroup-release-agent.sh.in init-early.sh.in 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 migrate-to-run.sh.in rc-cgroup.sh.in
INC-Linux= rc-cgroup.sh BIN-Linux= binfmt.sh cgroup-release-agent.sh init-early.sh migrate-to-run.sh \
rc-cgroup.sh
SRCS-NetBSD= SRCS-NetBSD=
BIN-NetBSD= BIN-NetBSD=
@@ -31,3 +32,4 @@ _installafter:
ln -snf ${LIBEXECDIR}/sh/functions.sh ${DESTDIR}/${INITDIR} || exit $$? ln -snf ${LIBEXECDIR}/sh/functions.sh ${DESTDIR}/${INITDIR} || exit $$?
check test:: 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 # This is a reimplementation of the systemd binfmt.d code to register
# misc binary formats with the kernel. # misc binary formats with the kernel.
# #
@@ -29,9 +29,6 @@ apply_file() {
\;*) continue ;; \;*) continue ;;
esac esac
local reg=${line#*:}
[ -e /proc/sys/fs/binfmt_misc/${reg%%:*} ] && echo -1 > /proc/sys/fs/binfmt_misc/${reg%%:*}
echo "${line}" > /proc/sys/fs/binfmt_misc/register echo "${line}" > /proc/sys/fs/binfmt_misc/register
rc=$? rc=$?
if [ $rc -ne 0 ]; then if [ $rc -ne 0 ]; then

View File

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

View File

@@ -46,7 +46,7 @@ yesno()
case "$value" in case "$value" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0;; [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;; [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 esac
} }

View File

@@ -1,4 +1,4 @@
#!/bin/sh #!@SHELL@
# Copyright (c) 2007-2015 The OpenRC Authors. # Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and # See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS # https://github.com/OpenRC/openrc/blob/master/AUTHORS
@@ -20,7 +20,7 @@ service_present()
# succeed if $RC_SYS empty, can't check further, assume script will run # succeed if $RC_SYS empty, can't check further, assume script will run
[ -z "$RC_SYS" ] && return 0 [ -z "$RC_SYS" ] && return 0
# fail if file contains "-$RC_SYS", because then it won't run # fail if file contains "-$RC_SYS", because then it won't run
grep -Eqi "^[[:space:]]*keyword[[:space:]].*-$RC_SYS([[:space:]]|$)" "$p" && return 1 egrep -qi "^[[:space:]]*keyword[[:space:]].*-$RC_SYS\>" "$p" && return 1
# succeed otherwise # succeed otherwise
return 0 return 0
} }

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
#!/bin/sh #!@SHELL@
# Copyright (c) 2007-2015 The OpenRC Authors. # Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and # See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS # 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) 1999-2007 Gentoo Foundation
# Copyright (c) 2007-2009 Roy Marples <roy@marples.name> # Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license. # Released under the 2-clause BSD license.
@@ -71,17 +71,20 @@ if [ "$sys" = VSERVER ]; then
rm -rf /run/* rm -rf /run/*
elif ! mountinfo -q /run; then elif ! mountinfo -q /run; then
ebegin "Mounting /run" ebegin "Mounting /run"
run_mount_opts="mode=0755,nosuid,nodev,nr_inodes=800k,size=20%,strictatime" rc=0
if ! fstabinfo --mount /run; then if ! fstabinfo --mount /run; then
if ! mount -t tmpfs -o ${run_mount_opts} tmpfs /run; then mount -t tmpfs -o mode=0755,nodev,size=10% tmpfs /run
eerror "Unable to mount tmpfs on /run." rc=$?
eerror "Can't continue." fi
exit 1 if [ $rc != 0 ]; then
fi eerror "Unable to mount tmpfs on /run."
eerror "Can't continue."
exit 1
fi fi
fi fi
checkpath -d "$RC_SVCDIR" [ -x /sbin/restorecon ] && /sbin/restorecon -rF /run
checkpath -d $RC_SVCDIR
checkpath -d -m 0775 -o root:uucp /run/lock checkpath -d -m 0775 -o root:uucp /run/lock
# Try to mount xenfs as early as possible, otherwise rc_sys() will always # Try to mount xenfs as early as possible, otherwise rc_sys() will always
@@ -99,5 +102,4 @@ if [ -e "$RC_LIBEXECDIR"/cache/softlevel ]; then
fi fi
echo sysinit >"$RC_SVCDIR"/softlevel echo sysinit >"$RC_SVCDIR"/softlevel
[ -x /sbin/restorecon ] && /sbin/restorecon -rF /run
exit 0 exit 0

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

@@ -254,11 +254,8 @@ fi
for _cmd; do for _cmd; do
if [ "$_cmd" != status -a "$_cmd" != describe ]; then if [ "$_cmd" != status -a "$_cmd" != describe ]; then
# Apply any ulimit defined # Apply any ulimit defined
if [ -n "${rc_ulimit:-$RC_ULIMIT}" ]; then [ -n "${rc_ulimit:-$RC_ULIMIT}" ] && \
if ! ulimit ${rc_ulimit:-$RC_ULIMIT}; then ulimit ${rc_ulimit:-$RC_ULIMIT}
eerror "${RC_SVCNAME}: unable to apply RC_ULIMIT settings"
fi
fi
# Apply cgroups settings if defined # Apply cgroups settings if defined
if [ "$(command -v cgroup_add_service)" = "cgroup_add_service" ] if [ "$(command -v cgroup_add_service)" = "cgroup_add_service" ]
then then

View File

@@ -1,3 +1,4 @@
#!@SHELL@
# Copyright (c) 2012-2015 The OpenRC Authors. # Copyright (c) 2012-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and # See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS # https://github.com/OpenRC/openrc/blob/master/AUTHORS
@@ -24,26 +25,18 @@ cgroup_find_path()
printf "%s" "${result}" printf "%s" "${result}"
} }
# This extracts all pids in a cgroup and puts them in the cgroup_pids
# variable.
# It is done this way to avoid subshells so we don't have to worry about
# locating the pid of the subshell in the cgroup.
# https://github.com/openrc/openrc/issues/396
cgroup_get_pids() cgroup_get_pids()
{ {
local cgroup_procs p local cgroup_procs p pids
cgroup_pids=
cgroup_procs="$(cgroup2_find_path)" cgroup_procs="$(cgroup2_find_path)"
if [ -n "${cgroup_procs}" ]; then [ -n "${cgroup_procs}" ] &&
cgroup_procs="${cgroup_procs}/${RC_SVCNAME}/cgroup.procs" cgroup_procs="${cgroup_procs}/${RC_SVCNAME}/cgroup.procs" ||
else
cgroup_procs="/sys/fs/cgroup/openrc/${RC_SVCNAME}/tasks" cgroup_procs="/sys/fs/cgroup/openrc/${RC_SVCNAME}/tasks"
fi
[ -f "${cgroup_procs}" ] || return 0 [ -f "${cgroup_procs}" ] || return 0
while read -r p; do while read -r p; do
[ "$p" -eq $$ ] && continue [ "$p" -eq $$ ] || pids="${pids} ${p}"
cgroup_pids="${cgroup_pids} ${p}"
done < "${cgroup_procs}" done < "${cgroup_procs}"
printf "%s" "${pids}"
return 0 return 0
} }
@@ -69,7 +62,7 @@ cgroup_set_values()
while [ -n "$1" ] && [ "$controller" != "cpuacct" ]; do while [ -n "$1" ] && [ "$controller" != "cpuacct" ]; do
case "$1" in case "$1" in
$controller.*) $controller.*)
if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] && if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] &&
[ -n "${val}" ]; then [ -n "${val}" ]; then
veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val" veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
printf "%s" "$val" > "$cgroup/$name" printf "%s" "$val" > "$cgroup/$name"
@@ -189,8 +182,7 @@ cgroup2_set_limits()
{ {
local cgroup_path local cgroup_path
cgroup_path="$(cgroup2_find_path)" cgroup_path="$(cgroup2_find_path)"
[ -z "${cgroup_path}" ] && return 0 [ -d "${cgroup_path}" ] || return 0
mountinfo -q "${cgroup_path}"|| return 0
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}" rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}" [ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
[ -f "${rc_cgroup_path}"/cgroup.procs ] && [ -f "${rc_cgroup_path}"/cgroup.procs ] &&
@@ -201,7 +193,7 @@ cgroup2_set_limits()
[ -z "${value}" ] && continue [ -z "${value}" ] && continue
[ ! -f "${rc_cgroup_path}/${key}" ] && continue [ ! -f "${rc_cgroup_path}/${key}" ] && continue
veinfo "${RC_SVCNAME}: cgroups: setting ${key} to ${value}" veinfo "${RC_SVCNAME}: cgroups: setting ${key} to ${value}"
printf "%s" "${value}" > "${rc_cgroup_path}/${key}" printf "%s\n" "${value}" > "${rc_cgroup_path}/${key}"
done done
return 0 return 0
} }
@@ -209,29 +201,26 @@ cgroup2_set_limits()
cgroup_cleanup() cgroup_cleanup()
{ {
cgroup_running || return 0 cgroup_running || return 0
ebegin "Starting cgroups cleanup" ebegin "starting cgroups cleanup"
local loops=0 local pids loops=0
cgroup_get_pids pids="$(cgroup_get_pids)"
if [ -n "${cgroup_pids}" ]; then if [ -n "${pids}" ]; then
kill -s CONT ${cgroup_pids} 2> /dev/null kill -s CONT ${pids} 2> /dev/null
kill -s "${stopsig:-TERM}" ${cgroup_pids} 2> /dev/null kill -s "${stopsig:-TERM}" ${pids} 2> /dev/null
yesno "${rc_send_sighup:-no}" && yesno "${rc_send_sighup:-no}" &&
kill -s HUP ${cgroup_pids} 2> /dev/null kill -s HUP ${pids} 2> /dev/null
kill -s "${stopsig:-TERM}" ${cgroup_pids} 2> /dev/null kill -s "${stopsig:-TERM}" ${pids} 2> /dev/null
cgroup_get_pids while [ -n "$(cgroup_get_pids)" ] &&
while [ -n "${cgroup_pids}" ] &&
[ "${loops}" -lt "${rc_timeout_stopsec:-90}" ]; do [ "${loops}" -lt "${rc_timeout_stopsec:-90}" ]; do
loops=$((loops+1)) loops=$((loops+1))
sleep 1 sleep 1
cgroup_get_pids
done done
if [ -n "${cgroup_pids}" ] && yesno "${rc_send_sigkill:-yes}"; then pids="$(cgroup_get_pids)"
kill -s KILL ${cgroup_pids} 2> /dev/null [ -n "${pids}" ] && yesno "${rc_send_sigkill:-yes}" &&
fi kill -s KILL ${pids} 2> /dev/null
fi fi
cgroup2_remove cgroup2_remove
cgroup_get_pids [ -z "$(cgroup_get_pids)" ]
[ -z "${cgroup_pids}" ]
eend $? "Unable to stop all processes" eend $? "Unable to stop all processes"
return 0 return 0
} }

View File

@@ -2,6 +2,42 @@
# Copyright (c) 2007-2009 Roy Marples <roy@marples.name> # Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license. # 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 net_fs_list="afs ceph cifs coda davfs fuse fuse.sshfs gfs glusterfs lustre
ncpfs nfs nfs4 ocfs2 shfs smbfs" ncpfs nfs nfs4 ocfs2 shfs smbfs"
is_net_fs() is_net_fs()

View File

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

View File

@@ -57,7 +57,7 @@ s6_stop()
ebegin "Stopping ${name:-$RC_SVCNAME}" ebegin "Stopping ${name:-$RC_SVCNAME}"
s6-svc -d -wD -T ${s6_service_timeout_stop:-60000} "${s6_service_link}" s6-svc -d -wD -T ${s6_service_timeout_stop:-60000} "${s6_service_link}"
set -- $(s6-svstat "${s6_service_link}") set -- $(s6-svstat "${s6_service_link}")
[ "$1" = "up" ] && [ "$1" = "up" ] &&
yesno "${s6_force_kill:-yes}" && yesno "${s6_force_kill:-yes}" &&
_s6_force_kill "$@" _s6_force_kill "$@"
set -- $(s6-svstat "${s6_service_link}") set -- $(s6-svstat "${s6_service_link}")

View File

@@ -38,9 +38,9 @@ ssd_start()
service_inactive && _inactive=true service_inactive && _inactive=true
mark_service_inactive mark_service_inactive
fi fi
[ -n "$output_logger" ] && [ -n "$output_logger" ] &&
output_logger_arg="--stdout-logger \"$output_logger\"" output_logger_arg="--stdout-logger \"$output_logger\""
[ -n "$error_logger" ] && [ -n "$error_logger" ] &&
error_logger_arg="--stderr-logger \"$error_logger\"" error_logger_arg="--stderr-logger \"$error_logger\""
#the eval call is necessary for cases like: #the eval call is necessary for cases like:
# command_args="this \"is a\" test" # command_args="this \"is a\" test"

View File

@@ -10,8 +10,6 @@
# This file may not be copied, modified, propagated, or distributed # This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file. # except according to the terms contained in the LICENSE file.
extra_commands="healthcheck unhealthy ${extra_commands}"
supervise_start() supervise_start()
{ {
if [ -z "$command" ]; then if [ -z "$command" ]; then
@@ -34,8 +32,6 @@ supervise_start()
${respawn_delay:+--respawn-delay} $respawn_delay \ ${respawn_delay:+--respawn-delay} $respawn_delay \
${respawn_max:+--respawn-max} $respawn_max \ ${respawn_max:+--respawn-max} $respawn_max \
${respawn_period:+--respawn-period} $respawn_period \ ${respawn_period:+--respawn-period} $respawn_period \
${healthcheck_delay:+--healthcheck-delay} $healthcheck_delay \
${healthcheck_timer:+--healthcheck-timer} $healthcheck_timer \
${command_user+--user} $command_user \ ${command_user+--user} $command_user \
${umask+--umask} $umask \ ${umask+--umask} $umask \
${supervise_daemon_args:-${start_stop_daemon_args}} \ ${supervise_daemon_args:-${start_stop_daemon_args}} \
@@ -55,9 +51,11 @@ supervise_stop()
local startpidfile="$(service_get_value "pidfile")" local startpidfile="$(service_get_value "pidfile")"
chroot="${startchroot:-$chroot}" chroot="${startchroot:-$chroot}"
pidfile="${startpidfile:-$pidfile}" pidfile="${startpidfile:-$pidfile}"
[ -n "$pidfile" ] || return 0
ebegin "Stopping ${name:-$RC_SVCNAME}" ebegin "Stopping ${name:-$RC_SVCNAME}"
supervise-daemon "${RC_SVCNAME}" --stop \ supervise-daemon "${RC_SVCNAME}" --stop \
${pidfile:+--pidfile} $chroot$pidfile ${pidfile:+--pidfile} $chroot$pidfile \
${stopsig:+--signal} $stopsig
eend $? "Failed to stop ${name:-$RC_SVCNAME}" eend $? "Failed to stop ${name:-$RC_SVCNAME}"
} }
@@ -100,13 +98,3 @@ supervise_status()
return 3 return 3
fi fi
} }
healthcheck()
{
return 0
}
unhealthy()
{
return 0
}

View File

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

View File

@@ -0,0 +1,26 @@
/*
* Written by Mike Frysinger
* Placed in the Public Domain
*/
#ifndef _HIDDEN_VISIBILITY_H_
#define _HIDDEN_VISIBILITY_H_
#if defined(__ELF__) && defined(__GNUC__)
# define __hidden_asmname(name) __hidden_asmname1 (__USER_LABEL_PREFIX__, name)
# define __hidden_asmname1(prefix, name) __hidden_asmname2(prefix, name)
# define __hidden_asmname2(prefix, name) #prefix name
# define __hidden_proto(name, internal) \
extern __typeof (name) name __asm__ (__hidden_asmname (#internal)) \
__attribute__ ((visibility ("hidden")));
# define __hidden_ver(local, internal, name) \
extern __typeof (name) __EI_##name __asm__(__hidden_asmname (#internal)); \
extern __typeof (name) __EI_##name __attribute__((alias (__hidden_asmname1 (,#local))))
# define hidden_proto(name) __hidden_proto(name, __RC_##name)
# define hidden_def(name) __hidden_ver(__RC_##name, name, name);
#else
# define hidden_proto(name)
# define hidden_def(name)
#endif
#endif

View File

@@ -15,7 +15,7 @@
* except according to the terms contained in the LICENSE file. * except according to the terms contained in the LICENSE file.
*/ */
static const char libeinfo_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; const char libeinfo_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@@ -39,6 +39,34 @@ static const char libeinfo_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include "einfo.h" #include "einfo.h"
#include "helpers.h" #include "helpers.h"
#include "hidden-visibility.h"
hidden_proto(ecolor)
hidden_proto(ebegin)
hidden_proto(ebeginv)
hidden_proto(ebracket)
hidden_proto(eend)
hidden_proto(eendv)
hidden_proto(eerror)
hidden_proto(eerrorn)
hidden_proto(eerrorx)
hidden_proto(eindent)
hidden_proto(eindentv)
hidden_proto(einfo)
hidden_proto(einfon)
hidden_proto(einfov)
hidden_proto(einfovn)
hidden_proto(elog)
hidden_proto(eoutdent)
hidden_proto(eoutdentv)
hidden_proto(eprefix)
hidden_proto(ewarn)
hidden_proto(ewarnn)
hidden_proto(ewarnv)
hidden_proto(ewarnvn)
hidden_proto(ewarnx)
hidden_proto(ewend)
hidden_proto(ewendv)
/* Incase we cannot work out how many columns from ioctl, supply a default */ /* Incase we cannot work out how many columns from ioctl, supply a default */
#define DEFAULT_COLS 80 #define DEFAULT_COLS 80
@@ -482,6 +510,7 @@ eprefix(const char *EINFO_RESTRICT prefix)
{ {
_eprefix = prefix; _eprefix = prefix;
} }
hidden_def(eprefix)
static void EINFO_PRINTF(2, 0) static void EINFO_PRINTF(2, 0)
elogv(int level, const char *EINFO_RESTRICT fmt, va_list ap) elogv(int level, const char *EINFO_RESTRICT fmt, va_list ap)
@@ -508,6 +537,7 @@ elog(int level, const char *EINFO_RESTRICT fmt, ...)
elogv(level, fmt, ap); elogv(level, fmt, ap);
va_end(ap); va_end(ap);
} }
hidden_def(elog)
static int static int
_eindent(FILE * EINFO_RESTRICT stream) _eindent(FILE * EINFO_RESTRICT stream)
@@ -546,6 +576,7 @@ _ecolor(FILE * EINFO_RESTRICT f, ECOLOR color)
return ecolors_str[i]; return ecolors_str[i];
return ""; return "";
} }
hidden_def(ecolor)
const char * const char *
ecolor(ECOLOR color) ecolor(ECOLOR color)
@@ -612,6 +643,7 @@ einfon(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("einfon"); LASTCMD("einfon");
return retval; return retval;
} }
hidden_def(einfon)
int int
ewarnn(const char *EINFO_RESTRICT fmt, ...) ewarnn(const char *EINFO_RESTRICT fmt, ...)
@@ -627,6 +659,7 @@ ewarnn(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewarnn"); LASTCMD("ewarnn");
return retval; return retval;
} }
hidden_def(ewarnn)
int int
eerrorn(const char *EINFO_RESTRICT fmt, ...) eerrorn(const char *EINFO_RESTRICT fmt, ...)
@@ -642,6 +675,7 @@ eerrorn(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("errorn"); LASTCMD("errorn");
return retval; return retval;
} }
hidden_def(eerrorn)
int int
einfo(const char *EINFO_RESTRICT fmt, ...) einfo(const char *EINFO_RESTRICT fmt, ...)
@@ -658,6 +692,7 @@ einfo(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("einfo"); LASTCMD("einfo");
return retval; return retval;
} }
hidden_def(einfo)
int int
ewarn(const char *EINFO_RESTRICT fmt, ...) ewarn(const char *EINFO_RESTRICT fmt, ...)
@@ -675,6 +710,7 @@ ewarn(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewarn"); LASTCMD("ewarn");
return retval; return retval;
} }
hidden_def(ewarn)
void void
ewarnx(const char *EINFO_RESTRICT fmt, ...) ewarnx(const char *EINFO_RESTRICT fmt, ...)
@@ -691,6 +727,7 @@ ewarnx(const char *EINFO_RESTRICT fmt, ...)
} }
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
hidden_def(ewarnx)
int int
eerror(const char *EINFO_RESTRICT fmt, ...) eerror(const char *EINFO_RESTRICT fmt, ...)
@@ -708,6 +745,7 @@ eerror(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("eerror"); LASTCMD("eerror");
return retval; return retval;
} }
hidden_def(eerror)
void void
eerrorx(const char *EINFO_RESTRICT fmt, ...) eerrorx(const char *EINFO_RESTRICT fmt, ...)
@@ -723,6 +761,7 @@ eerrorx(const char *EINFO_RESTRICT fmt, ...)
} }
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
hidden_def(eerrorx)
int int
ebegin(const char *EINFO_RESTRICT fmt, ...) ebegin(const char *EINFO_RESTRICT fmt, ...)
@@ -741,6 +780,7 @@ ebegin(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ebegin"); LASTCMD("ebegin");
return retval; return retval;
} }
hidden_def(ebegin)
static void static void
_eend(FILE * EINFO_RESTRICT fp, int col, ECOLOR color, const char *msg) _eend(FILE * EINFO_RESTRICT fp, int col, ECOLOR color, const char *msg)
@@ -814,6 +854,7 @@ eend(int retval, const char *EINFO_RESTRICT fmt, ...)
LASTCMD("eend"); LASTCMD("eend");
return retval; return retval;
} }
hidden_def(eend)
int int
ewend(int retval, const char *EINFO_RESTRICT fmt, ...) ewend(int retval, const char *EINFO_RESTRICT fmt, ...)
@@ -828,12 +869,14 @@ ewend(int retval, const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewend"); LASTCMD("ewend");
return retval; return retval;
} }
hidden_def(ewend)
void void
ebracket(int col, ECOLOR color, const char *msg) ebracket(int col, ECOLOR color, const char *msg)
{ {
_eend(stdout, col, color, msg); _eend(stdout, col, color, msg);
} }
hidden_def(ebracket)
void void
eindent(void) eindent(void)
@@ -855,6 +898,7 @@ eindent(void)
setenv("EINFO_INDENT", num, 1); setenv("EINFO_INDENT", num, 1);
free(num); free(num);
} }
hidden_def(eindent)
void eoutdent(void) void eoutdent(void)
{ {
@@ -880,6 +924,7 @@ void eoutdent(void)
} }
errno = serrno; errno = serrno;
} }
hidden_def(eoutdent)
int int
einfovn(const char *EINFO_RESTRICT fmt, ...) einfovn(const char *EINFO_RESTRICT fmt, ...)
@@ -895,6 +940,7 @@ einfovn(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("einfovn"); LASTCMD("einfovn");
return retval; return retval;
} }
hidden_def(einfovn)
int int
ewarnvn(const char *EINFO_RESTRICT fmt, ...) ewarnvn(const char *EINFO_RESTRICT fmt, ...)
@@ -910,6 +956,7 @@ ewarnvn(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewarnvn"); LASTCMD("ewarnvn");
return retval; return retval;
} }
hidden_def(ewarnvn)
int int
einfov(const char *EINFO_RESTRICT fmt, ...) einfov(const char *EINFO_RESTRICT fmt, ...)
@@ -926,6 +973,7 @@ einfov(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("einfov"); LASTCMD("einfov");
return retval; return retval;
} }
hidden_def(einfov)
int int
ewarnv(const char *EINFO_RESTRICT fmt, ...) ewarnv(const char *EINFO_RESTRICT fmt, ...)
@@ -942,6 +990,7 @@ ewarnv(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewarnv"); LASTCMD("ewarnv");
return retval; return retval;
} }
hidden_def(ewarnv)
int int
ebeginv(const char *EINFO_RESTRICT fmt, ...) ebeginv(const char *EINFO_RESTRICT fmt, ...)
@@ -961,6 +1010,7 @@ ebeginv(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ebeginv"); LASTCMD("ebeginv");
return retval; return retval;
} }
hidden_def(ebeginv)
int int
eendv(int retval, const char *EINFO_RESTRICT fmt, ...) eendv(int retval, const char *EINFO_RESTRICT fmt, ...)
@@ -975,6 +1025,7 @@ eendv(int retval, const char *EINFO_RESTRICT fmt, ...)
LASTCMD("eendv"); LASTCMD("eendv");
return retval; return retval;
} }
hidden_def(eendv)
int int
ewendv(int retval, const char *EINFO_RESTRICT fmt, ...) ewendv(int retval, const char *EINFO_RESTRICT fmt, ...)
@@ -989,6 +1040,7 @@ ewendv(int retval, const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewendv"); LASTCMD("ewendv");
return retval; return retval;
} }
hidden_def(ewendv)
void void
eindentv(void) eindentv(void)
@@ -996,6 +1048,7 @@ eindentv(void)
if (is_verbose()) if (is_verbose())
eindent(); eindent();
} }
hidden_def(eindentv)
void void
eoutdentv(void) eoutdentv(void)
@@ -1003,3 +1056,4 @@ eoutdentv(void)
if (is_verbose()) if (is_verbose())
eoutdent(); eoutdent();
} }
hidden_def(eoutdentv)

View File

@@ -59,7 +59,7 @@ pid_is_argv(pid_t pid, const char *const *argv)
free(cmdline); free(cmdline);
return false; return false;
} }
bytes = read(fd, buffer, sizeof(buffer) - 1); bytes = read(fd, buffer, sizeof(buffer));
close(fd); close(fd);
free(cmdline); free(cmdline);
if (bytes == -1) if (bytes == -1)
@@ -141,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(my_ns, 0, sizeof(my_ns));
memset(proc_ns, 0, sizeof(proc_ns)); memset(proc_ns, 0, sizeof(proc_ns));
if (exists("/proc/self/ns/pid")) { 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) if (rc <= 0)
my_ns[0] = '\0'; my_ns[0] = '\0';
} }
@@ -155,12 +155,12 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
continue; continue;
xasprintf(&buffer, "/proc/%d/ns/pid", p); xasprintf(&buffer, "/proc/%d/ns/pid", p);
if (exists(buffer)) { if (exists(buffer)) {
rc = readlink(buffer, proc_ns, sizeof(proc_ns)-1); rc = readlink(buffer, proc_ns, sizeof(proc_ns));
if (rc <= 0) if (rc <= 0)
proc_ns[0] = '\0'; proc_ns[0] = '\0';
} }
free(buffer); free(buffer);
if (pid == 0 && strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns)) if (strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns))
continue; continue;
if (uid) { if (uid) {
xasprintf(&buffer, "/proc/%d", p); xasprintf(&buffer, "/proc/%d", p);
@@ -208,6 +208,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
closedir(procdir); closedir(procdir);
return pids; return pids;
} }
librc_hidden_def(rc_find_pids)
#elif BSD #elif BSD
@@ -312,6 +313,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
return pids; return pids;
} }
librc_hidden_def(rc_find_pids)
#else #else
# error "Platform not supported!" # error "Platform not supported!"
@@ -453,6 +455,7 @@ rc_service_daemon_set(const char *service, const char *exec,
free(dirpath); free(dirpath);
return retval; return retval;
} }
librc_hidden_def(rc_service_daemon_set)
bool bool
rc_service_started_daemon(const char *service, rc_service_started_daemon(const char *service,
@@ -492,6 +495,7 @@ rc_service_started_daemon(const char *service,
free(dirpath); free(dirpath);
return retval; return retval;
} }
librc_hidden_def(rc_service_started_daemon)
bool bool
rc_service_daemons_crashed(const char *service) rc_service_daemons_crashed(const char *service)
@@ -611,7 +615,7 @@ rc_service_daemons_crashed(const char *service)
i = 0; i = 0;
TAILQ_FOREACH(s, list, entries) TAILQ_FOREACH(s, list, entries)
argv[i++] = s->value; argv[i++] = s->value;
argv[i] = NULL; argv[i] = '\0';
} }
} }
@@ -649,3 +653,4 @@ rc_service_daemons_crashed(const char *service)
return retval; return retval;
} }
librc_hidden_def(rc_service_daemons_crashed)

View File

@@ -78,16 +78,16 @@ rc_deptree_free(RC_DEPTREE *deptree)
} }
free(deptree); free(deptree);
} }
librc_hidden_def(rc_deptree_free)
static RC_DEPINFO * static RC_DEPINFO *
get_depinfo(const RC_DEPTREE *deptree, const char *service) get_depinfo(const RC_DEPTREE *deptree, const char *service)
{ {
RC_DEPINFO *di; RC_DEPINFO *di;
if (deptree) {
TAILQ_FOREACH(di, deptree, entries) TAILQ_FOREACH(di, deptree, entries)
if (strcmp(di->service, service) == 0) if (strcmp(di->service, service) == 0)
return di; return di;
}
return NULL; return NULL;
} }
@@ -96,11 +96,9 @@ get_deptype(const RC_DEPINFO *depinfo, const char *type)
{ {
RC_DEPTYPE *dt; RC_DEPTYPE *dt;
if (depinfo) { TAILQ_FOREACH(dt, &depinfo->depends, entries)
TAILQ_FOREACH(dt, &depinfo->depends, entries) if (strcmp(dt->type, type) == 0)
if (strcmp(dt->type, type) == 0) return dt;
return dt;
}
return NULL; return NULL;
} }
@@ -108,6 +106,7 @@ RC_DEPTREE *
rc_deptree_load(void) { rc_deptree_load(void) {
return rc_deptree_load_file(RC_DEPTREE_CACHE); return rc_deptree_load_file(RC_DEPTREE_CACHE);
} }
librc_hidden_def(rc_deptree_load)
RC_DEPTREE * RC_DEPTREE *
rc_deptree_load_file(const char *deptree_file) rc_deptree_load_file(const char *deptree_file)
@@ -171,6 +170,7 @@ rc_deptree_load_file(const char *deptree_file)
return deptree; return deptree;
} }
librc_hidden_def(rc_deptree_load_file)
static bool static bool
valid_service(const char *runlevel, const char *service, const char *type) valid_service(const char *runlevel, const char *service, const char *type)
@@ -456,6 +456,7 @@ rc_deptree_depend(const RC_DEPTREE *deptree,
rc_stringlist_add(svcs, svc->value); rc_stringlist_add(svcs, svc->value);
return svcs; return svcs;
} }
librc_hidden_def(rc_deptree_depend)
RC_STRINGLIST * RC_STRINGLIST *
rc_deptree_depends(const RC_DEPTREE *deptree, rc_deptree_depends(const RC_DEPTREE *deptree,
@@ -483,6 +484,7 @@ rc_deptree_depends(const RC_DEPTREE *deptree,
rc_stringlist_free(visited); rc_stringlist_free(visited);
return sorted; return sorted;
} }
librc_hidden_def(rc_deptree_depends)
RC_STRINGLIST * RC_STRINGLIST *
rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options) rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
@@ -538,6 +540,7 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
rc_stringlist_free(types); rc_stringlist_free(types);
return services; return services;
} }
librc_hidden_def(rc_deptree_order)
/* Given a time, recurse the target path to find out if there are /* Given a time, recurse the target path to find out if there are
@@ -613,11 +616,11 @@ mtime_check(const char *source, const char *target, bool newer,
return false; return false;
mtime = buf.st_mtime; mtime = buf.st_mtime;
retval = deep_mtime_check(target,newer,&mtime,file); retval = deep_mtime_check(target,newer,&mtime,file);
if (rel) { if (rel) {
*rel = mtime; *rel = mtime;
} }
return retval; return retval;
} }
bool bool
@@ -627,6 +630,7 @@ rc_newer_than(const char *source, const char *target,
return mtime_check(source, target, true, newest, file); return mtime_check(source, target, true, newest, file);
} }
librc_hidden_def(rc_newer_than)
bool bool
rc_older_than(const char *source, const char *target, rc_older_than(const char *source, const char *target,
@@ -634,6 +638,7 @@ rc_older_than(const char *source, const char *target,
{ {
return mtime_check(source, target, false, oldest, file); return mtime_check(source, target, false, oldest, file);
} }
librc_hidden_def(rc_older_than)
typedef struct deppair typedef struct deppair
{ {
@@ -729,6 +734,7 @@ rc_deptree_update_needed(time_t *newest, char *file)
return newer; return newer;
} }
librc_hidden_def(rc_deptree_update_needed)
/* This is a 7 phase operation /* This is a 7 phase operation
Phase 1 is a shell script which loads each init script and config in turn Phase 1 is a shell script which loads each init script and config in turn
@@ -1075,3 +1081,4 @@ rc_deptree_update(void)
rc_deptree_free(deptree); rc_deptree_free(deptree);
return retval; return retval;
} }
librc_hidden_def(rc_deptree_update)

View File

@@ -43,6 +43,7 @@ rc_yesno(const char *value)
return false; return false;
} }
librc_hidden_def(rc_yesno)
/** /**
@@ -90,6 +91,7 @@ rc_getfile(const char *file, char **buffer, size_t *len)
fclose(fp); fclose(fp);
return ret; return ret;
} }
librc_hidden_def(rc_getfile)
ssize_t ssize_t
rc_getline(char **line, size_t *len, FILE *fp) rc_getline(char **line, size_t *len, FILE *fp)
@@ -114,6 +116,7 @@ rc_getline(char **line, size_t *len, FILE *fp)
} }
return last; return last;
} }
librc_hidden_def(rc_getline)
char * char *
rc_proc_getent(const char *ent _unused) rc_proc_getent(const char *ent _unused)
@@ -160,6 +163,7 @@ rc_proc_getent(const char *ent _unused)
return NULL; return NULL;
#endif #endif
} }
librc_hidden_def(rc_proc_getent)
RC_STRINGLIST * RC_STRINGLIST *
rc_config_list(const char *file) rc_config_list(const char *file)
@@ -198,6 +202,7 @@ rc_config_list(const char *file)
return list; return list;
} }
librc_hidden_def(rc_config_list)
static void rc_config_set_value(RC_STRINGLIST *config, char *value) static void rc_config_set_value(RC_STRINGLIST *config, char *value)
{ {
@@ -272,6 +277,7 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
char *tmp = NULL; char *tmp = NULL;
char *value = NULL; char *value = NULL;
size_t varlen = 0; size_t varlen = 0;
size_t len = 0;
overrides = rc_stringlist_new(); overrides = rc_stringlist_new();
@@ -289,6 +295,7 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
} }
if (value != NULL) { if (value != NULL) {
len = varlen + strlen(value) + 2;
xasprintf(&tmp, "%s=%s", override->value, value); xasprintf(&tmp, "%s=%s", override->value, value);
} }
@@ -368,6 +375,7 @@ rc_config_load(const char *file)
return config; return config;
} }
librc_hidden_def(rc_config_load)
char * char *
rc_config_value(RC_STRINGLIST *list, const char *entry) rc_config_value(RC_STRINGLIST *list, const char *entry)
@@ -386,6 +394,7 @@ rc_config_value(RC_STRINGLIST *list, const char *entry)
} }
return NULL; return NULL;
} }
librc_hidden_def(rc_config_value)
/* Global for caching the strings loaded from rc.conf to avoid reparsing for /* Global for caching the strings loaded from rc.conf to avoid reparsing for
* each rc_conf_value call */ * each rc_conf_value call */
@@ -416,7 +425,7 @@ rc_conf_value(const char *setting)
} }
rc_conf = rc_config_directory(rc_conf); 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 */ /* Convert old uppercase to lowercase */
TAILQ_FOREACH(s, rc_conf, entries) { TAILQ_FOREACH(s, rc_conf, entries) {
@@ -431,3 +440,4 @@ rc_conf_value(const char *setting)
return rc_config_value(rc_conf, setting); return rc_config_value(rc_conf, setting);
} }
librc_hidden_def(rc_conf_value)

View File

@@ -25,6 +25,7 @@ rc_stringlist_new(void)
TAILQ_INIT(l); TAILQ_INIT(l);
return l; return l;
} }
librc_hidden_def(rc_stringlist_new)
RC_STRING * RC_STRING *
rc_stringlist_add(RC_STRINGLIST *list, const char *value) rc_stringlist_add(RC_STRINGLIST *list, const char *value)
@@ -35,6 +36,7 @@ rc_stringlist_add(RC_STRINGLIST *list, const char *value)
TAILQ_INSERT_TAIL(list, s, entries); TAILQ_INSERT_TAIL(list, s, entries);
return s; return s;
} }
librc_hidden_def(rc_stringlist_add)
RC_STRING * RC_STRING *
rc_stringlist_addu(RC_STRINGLIST *list, const char *value) rc_stringlist_addu(RC_STRINGLIST *list, const char *value)
@@ -49,6 +51,7 @@ rc_stringlist_addu(RC_STRINGLIST *list, const char *value)
return rc_stringlist_add(list, value); return rc_stringlist_add(list, value);
} }
librc_hidden_def(rc_stringlist_addu)
bool bool
rc_stringlist_delete(RC_STRINGLIST *list, const char *value) rc_stringlist_delete(RC_STRINGLIST *list, const char *value)
@@ -66,6 +69,7 @@ rc_stringlist_delete(RC_STRINGLIST *list, const char *value)
errno = EEXIST; errno = EEXIST;
return false; return false;
} }
librc_hidden_def(rc_stringlist_delete)
RC_STRING * RC_STRING *
rc_stringlist_find(RC_STRINGLIST *list, const char *value) rc_stringlist_find(RC_STRINGLIST *list, const char *value)
@@ -79,6 +83,7 @@ rc_stringlist_find(RC_STRINGLIST *list, const char *value)
} }
return NULL; return NULL;
} }
librc_hidden_def(rc_stringlist_find)
RC_STRINGLIST * RC_STRINGLIST *
rc_stringlist_split(const char *value, const char *sep) rc_stringlist_split(const char *value, const char *sep)
@@ -93,6 +98,7 @@ rc_stringlist_split(const char *value, const char *sep)
return list; return list;
} }
librc_hidden_def(rc_stringlist_split)
void void
rc_stringlist_sort(RC_STRINGLIST **list) rc_stringlist_sort(RC_STRINGLIST **list)
@@ -122,6 +128,7 @@ rc_stringlist_sort(RC_STRINGLIST **list)
free(l); free(l);
*list = new; *list = new;
} }
librc_hidden_def(rc_stringlist_sort)
void void
rc_stringlist_free(RC_STRINGLIST *list) rc_stringlist_free(RC_STRINGLIST *list)
@@ -141,3 +148,4 @@ rc_stringlist_free(RC_STRINGLIST *list)
} }
free(list); free(list);
} }
librc_hidden_def(rc_stringlist_free)

View File

@@ -15,7 +15,7 @@
* except according to the terms contained in the LICENSE file. * except according to the terms contained in the LICENSE file.
*/ */
static const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include "queue.h" #include "queue.h"
#include "librc.h" #include "librc.h"
@@ -351,6 +351,7 @@ rc_sys(void)
return sys; return sys;
} }
librc_hidden_def(rc_sys)
static const char * static const char *
rc_parse_service_state(RC_SERVICE state) rc_parse_service_state(RC_SERVICE state)
@@ -425,17 +426,20 @@ rc_runlevel_starting(void)
{ {
return exists(RC_STARTING); return exists(RC_STARTING);
} }
librc_hidden_def(rc_runlevel_starting)
bool bool
rc_runlevel_stopping(void) rc_runlevel_stopping(void)
{ {
return exists(RC_STOPPING); return exists(RC_STOPPING);
} }
librc_hidden_def(rc_runlevel_stopping)
RC_STRINGLIST *rc_runlevel_list(void) RC_STRINGLIST *rc_runlevel_list(void)
{ {
return ls_dir(RC_RUNLEVELDIR, LS_DIR); return ls_dir(RC_RUNLEVELDIR, LS_DIR);
} }
librc_hidden_def(rc_runlevel_list)
char * char *
rc_runlevel_get(void) rc_runlevel_get(void)
@@ -462,6 +466,7 @@ rc_runlevel_get(void)
return runlevel; return runlevel;
} }
librc_hidden_def(rc_runlevel_get)
bool bool
rc_runlevel_set(const char *runlevel) rc_runlevel_set(const char *runlevel)
@@ -474,6 +479,7 @@ rc_runlevel_set(const char *runlevel)
fclose(fp); fclose(fp);
return true; return true;
} }
librc_hidden_def(rc_runlevel_set)
bool bool
rc_runlevel_exists(const char *runlevel) rc_runlevel_exists(const char *runlevel)
@@ -481,14 +487,14 @@ rc_runlevel_exists(const char *runlevel)
char path[PATH_MAX]; char path[PATH_MAX];
struct stat buf; struct stat buf;
if (!runlevel || strcmp(runlevel, "") == 0 || strcmp(runlevel, ".") == 0 || if (!runlevel || strcmp(runlevel, ".") == 0 || strcmp(runlevel, "..") == 0)
strcmp(runlevel, "..") == 0)
return false; return false;
snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel); snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
if (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode)) if (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode))
return true; return true;
return false; return false;
} }
librc_hidden_def(rc_runlevel_exists)
bool bool
rc_runlevel_stack(const char *dst, const char *src) rc_runlevel_stack(const char *dst, const char *src)
@@ -501,6 +507,7 @@ rc_runlevel_stack(const char *dst, const char *src)
snprintf(d, sizeof(s), "%s/%s/%s", RC_RUNLEVELDIR, dst, src); snprintf(d, sizeof(s), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
return (symlink(s, d) == 0 ? true : false); return (symlink(s, d) == 0 ? true : false);
} }
librc_hidden_def(rc_runlevel_stack)
bool bool
rc_runlevel_unstack(const char *dst, const char *src) rc_runlevel_unstack(const char *dst, const char *src)
@@ -510,6 +517,7 @@ rc_runlevel_unstack(const char *dst, const char *src)
snprintf(path, sizeof(path), "%s/%s/%s", RC_RUNLEVELDIR, dst, src); snprintf(path, sizeof(path), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
return (unlink(path) == 0 ? true : false); return (unlink(path) == 0 ? true : false);
} }
librc_hidden_def(rc_runlevel_unstack)
RC_STRINGLIST * RC_STRINGLIST *
rc_runlevel_stacks(const char *runlevel) rc_runlevel_stacks(const char *runlevel)
@@ -522,6 +530,7 @@ rc_runlevel_stacks(const char *runlevel)
rc_stringlist_free(ancestor_list); rc_stringlist_free(ancestor_list);
return stack; return stack;
} }
librc_hidden_def(rc_runlevel_stacks)
/* Resolve a service name to its full path */ /* Resolve a service name to its full path */
char * char *
@@ -549,7 +558,7 @@ rc_service_resolve(const char *service)
if (*file) { if (*file) {
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
r = readlink(file, buffer, sizeof(buffer)-1); r = readlink(file, buffer, sizeof(buffer));
if (r > 0) if (r > 0)
return xstrdup(buffer); return xstrdup(buffer);
} }
@@ -575,6 +584,7 @@ rc_service_resolve(const char *service)
return NULL; return NULL;
} }
librc_hidden_def(rc_service_resolve)
bool bool
rc_service_exists(const char *service) rc_service_exists(const char *service)
@@ -613,6 +623,7 @@ rc_service_exists(const char *service)
free(file); free(file);
return retval; return retval;
} }
librc_hidden_def(rc_service_exists)
#define OPTSTR \ #define OPTSTR \
". '%s'; echo $extra_commands $extra_started_commands $extra_stopped_commands" ". '%s'; echo $extra_commands $extra_started_commands $extra_stopped_commands"
@@ -654,6 +665,7 @@ rc_service_extra_commands(const char *service)
free(cmd); free(cmd);
return commands; return commands;
} }
librc_hidden_def(rc_service_extra_commands)
#define DESCSTR ". '%s'; echo \"${description%s%s}\"" #define DESCSTR ". '%s'; echo \"${description%s%s}\""
char * char *
@@ -683,6 +695,7 @@ rc_service_description(const char *service, const char *option)
free(cmd); free(cmd);
return desc; return desc;
} }
librc_hidden_def(rc_service_description)
bool bool
rc_service_in_runlevel(const char *service, const char *runlevel) rc_service_in_runlevel(const char *service, const char *runlevel)
@@ -693,6 +706,7 @@ rc_service_in_runlevel(const char *service, const char *runlevel)
runlevel, basename_c(service)); runlevel, basename_c(service));
return exists(file); return exists(file);
} }
librc_hidden_def(rc_service_in_runlevel)
bool bool
rc_service_mark(const char *service, const RC_SERVICE state) rc_service_mark(const char *service, const RC_SERVICE state)
@@ -812,6 +826,7 @@ rc_service_mark(const char *service, const RC_SERVICE state)
free(init); free(init);
return true; return true;
} }
librc_hidden_def(rc_service_mark)
RC_SERVICE RC_SERVICE
rc_service_state(const char *service) rc_service_state(const char *service)
@@ -854,6 +869,7 @@ rc_service_state(const char *service)
return state; return state;
} }
librc_hidden_def(rc_service_state)
char * char *
rc_service_value_get(const char *service, const char *option) rc_service_value_get(const char *service, const char *option)
@@ -868,6 +884,7 @@ rc_service_value_get(const char *service, const char *option)
return buffer; return buffer;
} }
librc_hidden_def(rc_service_value_get)
bool bool
rc_service_value_set(const char *service, const char *option, rc_service_value_set(const char *service, const char *option,
@@ -892,6 +909,7 @@ rc_service_value_set(const char *service, const char *option,
} }
return true; return true;
} }
librc_hidden_def(rc_service_value_set)
bool bool
@@ -918,6 +936,7 @@ rc_service_schedule_start(const char *service, const char *service_to_start)
free(init); free(init);
return retval; return retval;
} }
librc_hidden_def(rc_service_schedule_start)
bool bool
rc_service_schedule_clear(const char *service) rc_service_schedule_clear(const char *service)
@@ -930,6 +949,7 @@ rc_service_schedule_clear(const char *service)
return true; return true;
return false; return false;
} }
librc_hidden_def(rc_service_schedule_clear)
RC_STRINGLIST * RC_STRINGLIST *
rc_services_in_runlevel(const char *runlevel) rc_services_in_runlevel(const char *runlevel)
@@ -967,6 +987,7 @@ rc_services_in_runlevel(const char *runlevel)
list = rc_stringlist_new(); list = rc_stringlist_new();
return list; return list;
} }
librc_hidden_def(rc_services_in_runlevel)
RC_STRINGLIST * RC_STRINGLIST *
rc_services_in_runlevel_stacked(const char *runlevel) rc_services_in_runlevel_stacked(const char *runlevel)
@@ -983,6 +1004,7 @@ rc_services_in_runlevel_stacked(const char *runlevel)
} }
return list; return list;
} }
librc_hidden_def(rc_services_in_runlevel_stacked)
RC_STRINGLIST * RC_STRINGLIST *
rc_services_in_state(RC_SERVICE state) rc_services_in_state(RC_SERVICE state)
@@ -1016,6 +1038,7 @@ rc_services_in_state(RC_SERVICE state)
rc_stringlist_free(dirs); rc_stringlist_free(dirs);
return list; return list;
} }
librc_hidden_def(rc_services_in_state)
bool bool
rc_service_add(const char *runlevel, const char *service) rc_service_add(const char *runlevel, const char *service)
@@ -1024,6 +1047,7 @@ rc_service_add(const char *runlevel, const char *service)
char *init; char *init;
char file[PATH_MAX]; char file[PATH_MAX];
char path[MAXPATHLEN] = { '\0' }; char path[MAXPATHLEN] = { '\0' };
char *p = NULL;
char binit[PATH_MAX]; char binit[PATH_MAX];
char *i; char *i;
@@ -1044,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 /* We need to ensure that only things in /etc/init.d are added
* to the boot runlevel */ * to the boot runlevel */
if (strcmp(runlevel, RC_LEVEL_BOOT) == 0) { if (strcmp(runlevel, RC_LEVEL_BOOT) == 0) {
if (realpath(dirname(init), path) == NULL) { p = realpath(dirname(init), path);
if (!*p) {
free(init); free(init);
return false; return false;
} }
@@ -1061,6 +1086,7 @@ rc_service_add(const char *runlevel, const char *service)
free(init); free(init);
return retval; return retval;
} }
librc_hidden_def(rc_service_add)
bool bool
rc_service_delete(const char *runlevel, const char *service) rc_service_delete(const char *runlevel, const char *service)
@@ -1073,6 +1099,7 @@ rc_service_delete(const char *runlevel, const char *service)
return true; return true;
return false; return false;
} }
librc_hidden_def(rc_service_delete)
RC_STRINGLIST * RC_STRINGLIST *
rc_services_scheduled_by(const char *service) rc_services_scheduled_by(const char *service)
@@ -1091,6 +1118,7 @@ rc_services_scheduled_by(const char *service)
rc_stringlist_free(dirs); rc_stringlist_free(dirs);
return list; return list;
} }
librc_hidden_def(rc_services_scheduled_by)
RC_STRINGLIST * RC_STRINGLIST *
rc_services_scheduled(const char *service) rc_services_scheduled(const char *service)
@@ -1101,3 +1129,4 @@ rc_services_scheduled(const char *service)
basename_c(service)); basename_c(service));
return ls_dir(dir, LS_INITD); return ls_dir(dir, LS_INITD);
} }
librc_hidden_def(rc_services_scheduled)

View File

@@ -56,4 +56,67 @@
#include "rc.h" #include "rc.h"
#include "rc-misc.h" #include "rc-misc.h"
#include "hidden-visibility.h"
#define librc_hidden_proto(x) hidden_proto(x)
#define librc_hidden_def(x) hidden_def(x)
librc_hidden_proto(rc_conf_value)
librc_hidden_proto(rc_config_list)
librc_hidden_proto(rc_config_load)
librc_hidden_proto(rc_config_value)
librc_hidden_proto(rc_deptree_depend)
librc_hidden_proto(rc_deptree_depends)
librc_hidden_proto(rc_deptree_free)
librc_hidden_proto(rc_deptree_load)
librc_hidden_proto(rc_deptree_load_file)
librc_hidden_proto(rc_deptree_order)
librc_hidden_proto(rc_deptree_update)
librc_hidden_proto(rc_deptree_update_needed)
librc_hidden_proto(rc_find_pids)
librc_hidden_proto(rc_getfile)
librc_hidden_proto(rc_getline)
librc_hidden_proto(rc_newer_than)
librc_hidden_proto(rc_proc_getent)
librc_hidden_proto(rc_older_than)
librc_hidden_proto(rc_runlevel_exists)
librc_hidden_proto(rc_runlevel_get)
librc_hidden_proto(rc_runlevel_list)
librc_hidden_proto(rc_runlevel_set)
librc_hidden_proto(rc_runlevel_stack)
librc_hidden_proto(rc_runlevel_stacks)
librc_hidden_proto(rc_runlevel_starting)
librc_hidden_proto(rc_runlevel_stopping)
librc_hidden_proto(rc_runlevel_unstack)
librc_hidden_proto(rc_service_add)
librc_hidden_proto(rc_service_daemons_crashed)
librc_hidden_proto(rc_service_daemon_set)
librc_hidden_proto(rc_service_delete)
librc_hidden_proto(rc_service_description)
librc_hidden_proto(rc_service_exists)
librc_hidden_proto(rc_service_extra_commands)
librc_hidden_proto(rc_service_in_runlevel)
librc_hidden_proto(rc_service_mark)
librc_hidden_proto(rc_service_resolve)
librc_hidden_proto(rc_service_schedule_clear)
librc_hidden_proto(rc_service_schedule_start)
librc_hidden_proto(rc_services_in_runlevel)
librc_hidden_proto(rc_services_in_runlevel_stacked)
librc_hidden_proto(rc_services_in_state)
librc_hidden_proto(rc_services_scheduled)
librc_hidden_proto(rc_services_scheduled_by)
librc_hidden_proto(rc_service_started_daemon)
librc_hidden_proto(rc_service_state)
librc_hidden_proto(rc_service_value_get)
librc_hidden_proto(rc_service_value_set)
librc_hidden_proto(rc_stringlist_add)
librc_hidden_proto(rc_stringlist_addu)
librc_hidden_proto(rc_stringlist_delete)
librc_hidden_proto(rc_stringlist_find)
librc_hidden_proto(rc_stringlist_free)
librc_hidden_proto(rc_stringlist_new)
librc_hidden_proto(rc_stringlist_split)
librc_hidden_proto(rc_stringlist_sort)
librc_hidden_proto(rc_sys)
librc_hidden_proto(rc_yesno)
#endif #endif

View File

@@ -14,8 +14,7 @@ SRCS+= rc-selinux.c
endif endif
ifeq (${OS},Linux) ifeq (${OS},Linux)
SRCS+= kill_all.c openrc-init.c openrc-shutdown.c rc-sysvinit.c broadcast.c \ SRCS+= kill_all.c openrc-init.c openrc-shutdown.c rc-wtmp.c
rc-wtmp.c
endif endif
CLEANFILES= version.h rc-selinux.o CLEANFILES= version.h rc-selinux.o
@@ -113,7 +112,7 @@ veinfo vewarn vebegin veend vewend veindent veoutdent: do_e.o rc-misc.o
fstabinfo: fstabinfo.o _usage.o rc-misc.o fstabinfo: fstabinfo.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-init: openrc-init.o rc-plugin.o rc-wtmp.o openrc-init: openrc-init.o rc-wtmp.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
is_newer_than: is_newer_than.o rc-misc.o is_newer_than: is_newer_than.o rc-misc.o
@@ -135,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 openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-shutdown: openrc-shutdown.o rc-misc.o _usage.o broadcast.o rc-wtmp.o rc-sysvinit.o openrc-shutdown: openrc-shutdown.o _usage.o rc-wtmp.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
@@ -162,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 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} ${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} ${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 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

@@ -16,7 +16,6 @@
* except according to the terms contained in the LICENSE file. * except according to the terms contained in the LICENSE file.
*/ */
#define _GNU_SOURCE
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -24,7 +23,6 @@
#include <fcntl.h> #include <fcntl.h>
#include <getopt.h> #include <getopt.h>
#include <grp.h> #include <grp.h>
#include <libgen.h>
#include <pwd.h> #include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -46,7 +44,7 @@ typedef enum {
const char *applet = NULL; const char *applet = NULL;
const char *extraopts ="path1 [path2] [...]"; const char *extraopts ="path1 [path2] [...]";
const char *getoptstring = "dDfFpm:o:sW" getoptstring_COMMON; const char *getoptstring = "dDfFpm:o:W" getoptstring_COMMON;
const struct option longopts[] = { const struct option longopts[] = {
{ "directory", 0, NULL, 'd'}, { "directory", 0, NULL, 'd'},
{ "directory-truncate", 0, NULL, 'D'}, { "directory-truncate", 0, NULL, 'D'},
@@ -55,7 +53,6 @@ const struct option longopts[] = {
{ "pipe", 0, NULL, 'p'}, { "pipe", 0, NULL, 'p'},
{ "mode", 1, NULL, 'm'}, { "mode", 1, NULL, 'm'},
{ "owner", 1, NULL, 'o'}, { "owner", 1, NULL, 'o'},
{ "symlinks", 0, NULL, 's'},
{ "writable", 0, NULL, 'W'}, { "writable", 0, NULL, 'W'},
longopts_COMMON longopts_COMMON
}; };
@@ -67,119 +64,15 @@ const char * const longopts_help[] = {
"Create a named pipe (FIFO) if not exists", "Create a named pipe (FIFO) if not exists",
"Mode to check", "Mode to check",
"Owner to check (user:group)", "Owner to check (user:group)",
"follow symbolic links (irrelivent on linux)",
"Check whether the path is writable or not", "Check whether the path is writable or not",
longopts_help_COMMON longopts_help_COMMON
}; };
const char *usagestring = NULL; const char *usagestring = NULL;
static int get_dirfd(char *path, bool symlinks) {
char *ch;
char *item;
char *linkpath = NULL;
char *path_dupe;
char *str;
int components = 0;
int dirfd;
int flags = 0;
int new_dirfd;
struct stat st;
ssize_t linksize;
if (!path || *path != '/')
eerrorx("%s: empty or relative path", applet);
dirfd = openat(dirfd, "/", O_RDONLY);
if (dirfd == -1)
eerrorx("%s: unable to open the root directory: %s",
applet, strerror(errno));
ch = path;
while (*ch) {
if (*ch == '/')
components++;
ch++;
}
path_dupe = xstrdup(path);
item = strtok(path_dupe, "/");
#ifdef O_PATH
flags |= O_PATH;
#endif
if (!symlinks)
flags |= O_NOFOLLOW;
flags |= O_RDONLY;
while (dirfd > 0 && item && components > 1) {
str = xstrdup(linkpath ? linkpath : item);
new_dirfd = openat(dirfd, str, flags);
if (new_dirfd == -1)
eerrorx("%s: %s: could not open %s: %s", applet, path, str,
strerror(errno));
if (fstat(new_dirfd, &st) == -1)
eerrorx("%s: %s: unable to stat %s: %s", applet, path, item,
strerror(errno));
if (S_ISLNK(st.st_mode) ) {
if (st.st_uid != 0)
eerrorx("%s: %s: symbolic link %s not owned by root",
applet, path, str);
linksize = st.st_size+1;
if (linkpath)
free(linkpath);
linkpath = xmalloc(linksize);
memset(linkpath, 0, linksize);
if (readlinkat(new_dirfd, "", linkpath, linksize) != st.st_size)
eerrorx("%s: symbolic link destination changed", applet);
/*
* now follow the symlink.
*/
close(new_dirfd);
} else {
/* now walk down the directory path */
close(dirfd);
dirfd = new_dirfd;
free(linkpath);
linkpath = NULL;
item = strtok(NULL, "/");
components--;
}
}
free(path_dupe);
free(linkpath);
return dirfd;
}
static char *clean_path(char *path)
{
char *ch;
char *ch2;
char *str;
str = xmalloc(strlen(path));
ch = path;
ch2 = str;
while (true) {
*ch2 = *ch;
ch++;
ch2++;
if (!*(ch-1))
break;
while (*(ch - 1) == '/' && *ch == '/')
ch++;
}
/* get rid of trailing / characters */
while ((ch = strrchr(str, '/'))) {
if (ch == str)
break;
if (!*(ch+1))
*ch = 0;
else
break;
}
return str;
}
static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
inode_t type, bool trunc, bool chowner, bool symlinks, bool selinux_on) inode_t type, bool trunc, bool chowner, bool selinux_on)
{ {
struct stat st; struct stat st;
char *name = NULL;
int dirfd;
int fd; int fd;
int flags; int flags;
int r; int r;
@@ -200,16 +93,14 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
#endif #endif
if (trunc) if (trunc)
flags |= O_TRUNC; flags |= O_TRUNC;
xasprintf(&name, "%s", basename_c(path)); readfd = open(path, readflags);
dirfd = get_dirfd(path, symlinks);
readfd = openat(dirfd, name, readflags);
if (readfd == -1 || (type == inode_file && trunc)) { if (readfd == -1 || (type == inode_file && trunc)) {
if (type == inode_file) { if (type == inode_file) {
einfo("%s: creating file", path); einfo("%s: creating file", path);
if (!mode) /* 664 */ if (!mode) /* 664 */
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
u = umask(0); u = umask(0);
fd = openat(dirfd, name, flags, mode); fd = open(path, flags, mode);
umask(u); umask(u);
if (fd == -1) { if (fd == -1) {
eerror("%s: open: %s", applet, strerror(errno)); eerror("%s: open: %s", applet, strerror(errno));
@@ -224,14 +115,14 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
u = umask(0); u = umask(0);
/* We do not recursively create parents */ /* We do not recursively create parents */
r = mkdirat(dirfd, name, mode); r = mkdir(path, mode);
umask(u); umask(u);
if (r == -1 && errno != EEXIST) { if (r == -1 && errno != EEXIST) {
eerror("%s: mkdirat: %s", applet, eerror("%s: mkdir: %s", applet,
strerror (errno)); strerror (errno));
return -1; return -1;
} }
readfd = openat(dirfd, name, readflags); readfd = open(path, readflags);
if (readfd == -1) { if (readfd == -1) {
eerror("%s: unable to open directory: %s", applet, eerror("%s: unable to open directory: %s", applet,
strerror(errno)); strerror(errno));
@@ -249,7 +140,7 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode,
strerror (errno)); strerror (errno));
return -1; return -1;
} }
readfd = openat(dirfd, name, readflags); readfd = open(path, readflags);
if (readfd == -1) { if (readfd == -1) {
eerror("%s: unable to open fifo: %s", applet, eerror("%s: unable to open fifo: %s", applet,
strerror(errno)); strerror(errno));
@@ -368,10 +259,8 @@ int main(int argc, char **argv)
int retval = EXIT_SUCCESS; int retval = EXIT_SUCCESS;
bool trunc = false; bool trunc = false;
bool chowner = false; bool chowner = false;
bool symlinks = false;
bool writable = false; bool writable = false;
bool selinux_on = false; bool selinux_on = false;
char *path = NULL;
applet = basename_c(argv[0]); applet = basename_c(argv[0]);
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
@@ -404,11 +293,6 @@ int main(int argc, char **argv)
eerrorx("%s: owner `%s' not found", eerrorx("%s: owner `%s' not found",
applet, optarg); applet, optarg);
break; break;
case 's':
#ifndef O_PATH
symlinks = true;
#endif
break;
case 'W': case 'W':
writable = true; writable = true;
break; break;
@@ -434,14 +318,11 @@ int main(int argc, char **argv)
selinux_on = true; selinux_on = true;
while (optind < argc) { while (optind < argc) {
path = clean_path(argv[optind]);
if (writable) if (writable)
exit(!is_writable(path)); exit(!is_writable(argv[optind]));
if (do_check(path, uid, gid, mode, type, trunc, chowner, if (do_check(argv[optind], uid, gid, mode, type, trunc, chowner, selinux_on))
symlinks, selinux_on))
retval = EXIT_FAILURE; retval = EXIT_FAILURE;
optind++; optind++;
free(path);
} }
if (selinux_on) if (selinux_on)

View File

@@ -35,9 +35,9 @@
const char *applet = NULL; const char *applet = NULL;
static int syslog_decode(char *name, const CODE *codetab) static int syslog_decode(char *name, CODE *codetab)
{ {
const CODE *c; CODE *c;
if (isdigit((unsigned char)*name)) if (isdigit((unsigned char)*name))
return atoi(name); return atoi(name);

View File

@@ -58,7 +58,7 @@ static int mount_proc(void)
if (exists("/proc/version")) if (exists("/proc/version"))
return 0; return 0;
pid = fork(); pid = fork();
switch (pid) { switch(pid) {
case -1: case -1:
syslog(LOG_ERR, "Unable to fork"); syslog(LOG_ERR, "Unable to fork");
return -1; return -1;
@@ -248,7 +248,7 @@ int main(int argc, char **argv)
usage(EXIT_FAILURE); usage(EXIT_FAILURE);
} }
} }
openlog(applet, LOG_CONS|LOG_PID, LOG_DAEMON); openlog(applet, LOG_CONS|LOG_PID, LOG_DAEMON);
if (mount_proc() != 0) { if (mount_proc() != 0) {
rc_stringlist_free(omits); rc_stringlist_free(omits);

View File

@@ -19,71 +19,59 @@
*/ */
#include <errno.h> #include <errno.h>
#include <pwd.h>
#include <signal.h> #include <signal.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/reboot.h> #include <sys/reboot.h>
#include <sys/wait.h> #include <sys/wait.h>
#ifdef HAVE_SELINUX
# include <selinux/selinux.h>
#endif
#include "helpers.h" #include "helpers.h"
#include "rc.h" #include "rc.h"
#include "rc-plugin.h"
#include "rc-wtmp.h" #include "rc-wtmp.h"
#include "version.h" #include "version.h"
static const char *path_default = "/sbin:/usr/sbin:/bin:/usr/bin"; static const char *path_default = "/sbin:/usr/sbin:/bin:/usr/bin";
static const char *rc_default_runlevel = "default"; static const char *rc_default_runlevel = "default";
static void do_openrc(const char *runlevel) static pid_t do_openrc(const char *runlevel)
{ {
pid_t pid; pid_t pid;
sigset_t all_signals; sigset_t signals;
sigset_t our_signals;
sigfillset(&all_signals);
/* block all signals */
sigprocmask(SIG_BLOCK, &all_signals, &our_signals);
pid = fork(); pid = fork();
switch (pid) { switch(pid) {
case -1: case -1:
perror("fork"); perror("fork");
exit(1);
break; break;
case 0: case 0:
setsid(); setsid();
/* unblock all signals */ /* unblock all signals */
sigprocmask(SIG_UNBLOCK, &all_signals, NULL); sigemptyset(&signals);
sigprocmask(SIG_SETMASK, &signals, NULL);
printf("Starting %s runlevel\n", runlevel); printf("Starting %s runlevel\n", runlevel);
execlp("openrc", "openrc", runlevel, NULL); execlp("openrc", "openrc", runlevel, NULL);
perror("exec"); perror("exec");
exit(1);
break; break;
default: default:
/* restore our signal mask */
sigprocmask(SIG_SETMASK, &our_signals, NULL);
while (waitpid(pid, NULL, 0) != pid)
if (errno == ECHILD)
break;
break; break;
} }
return pid;
} }
static void init(const char *default_runlevel) static void init(const char *default_runlevel)
{ {
const char *runlevel = NULL; const char *runlevel = NULL;
do_openrc("sysinit"); pid_t pid;
do_openrc("boot");
pid = do_openrc("sysinit");
waitpid(pid, NULL, 0);
pid = do_openrc("boot");
waitpid(pid, NULL, 0);
if (default_runlevel) if (default_runlevel)
runlevel = default_runlevel; runlevel = default_runlevel;
else else
@@ -94,7 +82,8 @@ static void init(const char *default_runlevel)
printf("%s is an invalid runlevel\n", runlevel); printf("%s is an invalid runlevel\n", runlevel);
runlevel = rc_default_runlevel; runlevel = rc_default_runlevel;
} }
do_openrc(runlevel); pid = do_openrc(runlevel);
waitpid(pid, NULL, 0);
log_wtmp("reboot", "~~", 0, RUN_LVL, "~~"); log_wtmp("reboot", "~~", 0, RUN_LVL, "~~");
} }
@@ -106,82 +95,25 @@ static void handle_reexec(char *my_name)
static void handle_shutdown(const char *runlevel, int cmd) static void handle_shutdown(const char *runlevel, int cmd)
{ {
struct timespec ts; pid_t pid;
do_openrc(runlevel); pid = do_openrc(runlevel);
while (waitpid(pid, NULL, 0) != pid);
printf("Sending the final term signal\n"); printf("Sending the final term signal\n");
kill(-1, SIGTERM); kill(-1, SIGTERM);
ts.tv_sec = 3; sleep(3);
ts.tv_nsec = 0;
nanosleep(&ts, NULL);
printf("Sending the final kill signal\n"); printf("Sending the final kill signal\n");
kill(-1, SIGKILL); kill(-1, SIGKILL);
sync(); sync();
reboot(cmd); reboot(cmd);
} }
static void run_program(const char *prog)
{
sigset_t full;
sigset_t old;
pid_t pid;
/* We need to block signals until we have forked */
sigfillset(&full);
sigprocmask(SIG_SETMASK, &full, &old);
pid = fork();
if (pid == -1) {
perror("init");
return;
}
if (pid == 0) {
/* Unmask signals */
sigprocmask(SIG_SETMASK, &old, NULL);
execl(prog, prog, (char *)NULL);
perror("init");
exit(1);
}
/* Unmask signals and wait for child */
sigprocmask(SIG_SETMASK, &old, NULL);
if (rc_waitpid(pid) == -1)
perror("init");
}
static void open_shell(void)
{
const char *shell;
struct passwd *pw;
#ifdef __linux__
const char *sys = rc_sys();
/* VSERVER systems cannot really drop to shells */
if (sys && strcmp(sys, RC_SYS_VSERVER) == 0)
{
execlp("halt", "halt", "-f", (char *) NULL);
perror("init");
return;
}
#endif
shell = rc_conf_value("rc_shell");
/* No shell set, so obey env, then passwd, then default to /bin/sh */
if (!shell) {
shell = getenv("SHELL");
if (!shell) {
pw = getpwuid(getuid());
if (pw)
shell = pw->pw_shell;
if (!shell)
shell = "/bin/sh";
}
}
run_program(shell);
}
static void handle_single(void) static void handle_single(void)
{ {
do_openrc("single"); pid_t pid;
pid = do_openrc("single");
while (waitpid(pid, NULL, 0) != pid);
} }
static void reap_zombies(void) static void reap_zombies(void)
@@ -203,16 +135,10 @@ static void reap_zombies(void)
static void signal_handler(int sig) static void signal_handler(int sig)
{ {
switch (sig) { switch(sig) {
case SIGINT: case SIGINT:
handle_shutdown("reboot", RB_AUTOBOOT); handle_shutdown("reboot", RB_AUTOBOOT);
break; break;
case SIGTERM:
#ifdef SIGPWR
case SIGPWR:
#endif
handle_shutdown("shutdown", RB_HALT_SYSTEM);
break;
case SIGCHLD: case SIGCHLD:
reap_zombies(); reap_zombies();
break; break;
@@ -231,36 +157,10 @@ int main(int argc, char **argv)
bool reexec = false; bool reexec = false;
sigset_t signals; sigset_t signals;
struct sigaction sa; struct sigaction sa;
#ifdef HAVE_SELINUX
int enforce = 0;
#endif
if (getpid() != 1) if (getpid() != 1)
return 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); printf("OpenRC init version %s starting\n", VERSION);
if (argc > 1) if (argc > 1)
@@ -275,10 +175,6 @@ int main(int argc, char **argv)
sigfillset(&signals); sigfillset(&signals);
sigdelset(&signals, SIGCHLD); sigdelset(&signals, SIGCHLD);
sigdelset(&signals, SIGINT); sigdelset(&signals, SIGINT);
sigdelset(&signals, SIGTERM);
#ifdef SIGPWR
sigdelset(&signals, SIGPWR);
#endif
sigprocmask(SIG_SETMASK, &signals, NULL); sigprocmask(SIG_SETMASK, &signals, NULL);
/* install signal handler */ /* install signal handler */
@@ -286,10 +182,6 @@ int main(int argc, char **argv)
sa.sa_handler = signal_handler; sa.sa_handler = signal_handler;
sigaction(SIGCHLD, &sa, NULL); sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGINT, &sa, NULL); sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
#ifdef SIGPWR
sigaction(SIGPWR, &sa, NULL);
#endif
reboot(RB_DISABLE_CAD); reboot(RB_DISABLE_CAD);
/* set default path */ /* set default path */
@@ -323,11 +215,8 @@ int main(int argc, char **argv)
handle_shutdown("reboot", RB_AUTOBOOT); handle_shutdown("reboot", RB_AUTOBOOT);
else if (strcmp(buf, "reexec") == 0) else if (strcmp(buf, "reexec") == 0)
handle_reexec(argv[0]); handle_reexec(argv[0]);
else if (strcmp(buf, "single") == 0) { else if (strcmp(buf, "single") == 0)
handle_single(); handle_single();
open_shell();
init(default_runlevel);
}
} }
return 0; return 0;
} }

View File

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

View File

@@ -25,25 +25,20 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <syslog.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include "broadcast.h"
#include "einfo.h" #include "einfo.h"
#include "rc.h" #include "rc.h"
#include "helpers.h" #include "helpers.h"
#include "rc-misc.h"
#include "rc-sysvinit.h"
#include "rc-wtmp.h"
#include "_usage.h" #include "_usage.h"
#include "rc-wtmp.h"
const char *applet = NULL; const char *applet = NULL;
const char *extraopts = NULL; const char *extraopts = NULL;
const char *getoptstring = "cdDfFHKpRrsw" getoptstring_COMMON; const char *getoptstring = "dDHKpRrsw" getoptstring_COMMON;
const struct option longopts[] = { const struct option longopts[] = {
{ "cancel", no_argument, NULL, 'c'},
{ "no-write", no_argument, NULL, 'd'}, { "no-write", no_argument, NULL, 'd'},
{ "dry-run", no_argument, NULL, 'D'}, { "dry-run", no_argument, NULL, 'D'},
{ "halt", no_argument, NULL, 'H'}, { "halt", no_argument, NULL, 'H'},
@@ -56,7 +51,6 @@ const struct option longopts[] = {
longopts_COMMON longopts_COMMON
}; };
const char * const longopts_help[] = { const char * const longopts_help[] = {
"cancel a pending shutdown",
"do not write wtmp record", "do not write wtmp record",
"print actions instead of executing them", "print actions instead of executing them",
"halt the system", "halt the system",
@@ -68,22 +62,10 @@ const char * const longopts_help[] = {
"write wtmp boot record and exit", "write wtmp boot record and exit",
longopts_help_COMMON longopts_help_COMMON
}; };
const char *usagestring = "" \ const char *usagestring = NULL;
"Usage: openrc-shutdown -c | --cancel\n" \
" or: openrc-shutdown -R | --reexec\n" \
" or: openrc-shutdown -w | --write-only\n" \
" or: openrc-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 *exclusive = "Select one of " const char *exclusive = "Select one of "
"--cancel, --halt, --kexec, --poweroff, --reexec, --reboot, --single or \n" "--halt, --kexec, --poweroff, --reexec, --reboot, --single or --write-only";
"--write-only";
const char *nologin_file = RC_SYSCONFDIR"/nologin";
const char *shutdown_pid = "/run/openrc-shutdown.pid";
static bool do_cancel = false;
static bool do_dryrun = false; static bool do_dryrun = false;
static bool do_halt = false; static bool do_halt = false;
static bool do_kexec = false; static bool do_kexec = false;
@@ -94,44 +76,10 @@ static bool do_single = false;
static bool do_wtmp = true; static bool do_wtmp = true;
static bool do_wtmp_only = false; 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) static void send_cmd(const char *cmd)
{ {
FILE *fifo; FILE *fifo;
size_t ignored; size_t ignored;
if (do_dryrun) { if (do_dryrun) {
einfo("Would send %s to init", cmd); einfo("Would send %s to init", cmd);
@@ -151,57 +99,16 @@ static void send_cmd(const char *cmd)
fclose(fifo); 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) int main(int argc, char **argv)
{ {
char *ch = NULL;
int opt; int opt;
int cmd_count = 0; 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]); applet = basename_c(argv[0]);
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1) longopts, (int *) 0)) != -1)
{ {
switch (opt) { switch (opt) {
case 'c':
do_cancel = true;
cmd_count++;
break;
case 'd': case 'd':
do_wtmp = false; do_wtmp = false;
break; break;
@@ -210,17 +117,14 @@ int main(int argc, char **argv)
break; break;
case 'H': case 'H':
do_halt = true; do_halt = true;
xasprintf(&state, "%s", "halt");
cmd_count++; cmd_count++;
break; break;
case 'K': case 'K':
do_kexec = true; do_kexec = true;
xasprintf(&state, "%s", "reboot");
cmd_count++; cmd_count++;
break; break;
case 'p': case 'p':
do_poweroff = true; do_poweroff = true;
xasprintf(&state, "%s", "power off");
cmd_count++; cmd_count++;
break; break;
case 'R': case 'R':
@@ -229,12 +133,10 @@ int main(int argc, char **argv)
break; break;
case 'r': case 'r':
do_reboot = true; do_reboot = true;
xasprintf(&state, "%s", "reboot");
cmd_count++; cmd_count++;
break; break;
case 's': case 's':
do_single = true; do_single = true;
xasprintf(&state, "%s", "go down for maintenance");
cmd_count++; cmd_count++;
break; break;
case 'w': case 'w':
@@ -244,115 +146,25 @@ int main(int argc, char **argv)
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
} }
if (geteuid() != 0) if (geteuid() != 0 && ! do_dryrun)
eerrorx("%s: you must be root\n", applet); eerrorx("%s: you must be root\n", applet);
if (cmd_count != 1) { if (cmd_count != 1) {
eerror("%s: %s\n", applet, exclusive); eerror("%s: %s\n", applet, exclusive);
usage(EXIT_FAILURE); usage(EXIT_FAILURE);
} }
if (do_halt)
if (do_cancel) { send_cmd("halt");
cancel_shutdown(); else if (do_kexec)
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) {
if (exists("/run/initctl")) {
sysvinit_setenv("INIT_HALT", "HALT");
sysvinit_runlevel('0');
} else
send_cmd("halt");
} else if (do_kexec)
send_cmd("kexec"); send_cmd("kexec");
else if (do_poweroff) { else if (do_poweroff)
if (exists("/run/initctl")) { send_cmd("poweroff");
sysvinit_setenv("INIT_HALT", "POWEROFF"); else if (do_reboot)
sysvinit_runlevel('0'); send_cmd("reboot");
} else else if (do_reexec)
send_cmd("poweroff"); send_cmd("reexec");
} else if (do_reboot) { else if (do_wtmp_only)
if (exists("/run/initctl")) log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
sysvinit_runlevel('6'); else if (do_single)
else send_cmd("single");
send_cmd("reboot");
} else if (do_single) {
if (exists("/run/initctl"))
sysvinit_runlevel('S');
else
send_cmd("single");
}
return 0; return 0;
} }

View File

@@ -13,8 +13,8 @@
#ifndef RC_LOGGER_H #ifndef RC_LOGGER_H
#define RC_LOGGER_H #define RC_LOGGER_H
extern pid_t rc_logger_pid; pid_t rc_logger_pid;
extern int rc_logger_tty; int rc_logger_tty;
extern bool rc_in_logger; extern bool rc_in_logger;
void rc_logger_open(const char *runlevel); void rc_logger_open(const char *runlevel);

View File

@@ -28,7 +28,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <syslog.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.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); einfo("Would send signal %d to PID %d", sig, pi->pid);
nkilled++; nkilled++;
} else { } else {
if (sig) { if (!quiet)
syslog(LOG_DEBUG, "Sending signal %d to PID %d", sig, pi->pid); ebeginv("Sending signal %d to PID %d", sig, pi->pid);
if (!quiet)
ebeginv("Sending signal %d to PID %d", sig, pi->pid);
}
errno = 0; errno = 0;
killed = (kill(pi->pid, sig) == 0 || killed = (kill(pi->pid, sig) == 0 ||
errno == ESRCH ? true : false); 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, eendv(killed ? 0 : 1,
"%s: failed to send signal %d to PID %d: %s", "%s: failed to send signal %d to PID %d: %s",
applet, sig, pi->pid, strerror(errno)); 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) { if (!killed) {
nkilled = -1; nkilled = -1;
} else { } else {
@@ -317,18 +310,12 @@ int run_stop_schedule(const char *applet,
if (!(pid > 0 || exec || uid || (argv && *argv))) if (!(pid > 0 || exec || uid || (argv && *argv)))
return 0; return 0;
if (exec) { if (exec)
einfov("Will stop %s", 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); 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); einfov("Will stop processes owned by UID %d", uid);
syslog(LOG_DEBUG, "Will stop processes owned by UID %d", uid);
}
if (argv && *argv) { if (argv && *argv) {
einfovn("Will stop processes of `"); einfovn("Will stop processes of `");
if (rc_yesno(getenv("EINFO_VERBOSE"))) { if (rc_yesno(getenv("EINFO_VERBOSE"))) {
@@ -364,9 +351,8 @@ int run_stop_schedule(const char *applet,
tkilled += nkilled; tkilled += nkilled;
break; break;
case SC_FOREVER:
case SC_TIMEOUT: case SC_TIMEOUT:
if (item->type == SC_TIMEOUT && item->value < 1) { if (item->value < 1) {
item = NULL; item = NULL;
break; break;
} }
@@ -374,7 +360,7 @@ int run_stop_schedule(const char *applet,
ts.tv_sec = 0; ts.tv_sec = 0;
ts.tv_nsec = POLL_INTERVAL; 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; for (nloops = 0;
nloops < ONE_SECOND / POLL_INTERVAL; nloops < ONE_SECOND / POLL_INTERVAL;
nloops++) nloops++)
@@ -389,7 +375,10 @@ int run_stop_schedule(const char *applet,
printf("\n"); printf("\n");
progressed = false; progressed = false;
} }
if (errno != EINTR) { if (errno == EINTR)
eerror("%s: caught an"
" interrupt", applet);
else {
eerror("%s: nanosleep: %s", eerror("%s: nanosleep: %s",
applet, strerror(errno)); applet, strerror(errno));
return 0; return 0;

View File

@@ -49,12 +49,10 @@ const char * const longopts_help[] = {
"set xtrace when running the command", "set xtrace when running the command",
"ignore dependencies", "ignore dependencies",
"tests if the service exists or not", "tests if the service exists or not",
"if the service is crashed run the command", "if the service is crashed then run the command",
"if the service exists run the command", "if the service exists then run the command",
"if the service is inactive run the command", "if the service is inactive then run the command",
"if the service is not started run the command", "if the service is not started then run the command",
"if the service is started run the command",
"if the service is stopped run the command",
"list all available services", "list all available services",
"resolve the service name to an init script", "resolve the service name to an init script",
"dry run (show what would happen)", "dry run (show what would happen)",

View File

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

View File

@@ -1,102 +0,0 @@
/*
* rc-sysvinit.c
* Helper to send a runlevel change to sysvinit
*/
/*
* Copyright (c) 2019 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 <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "einfo.h"
#include "rc-sysvinit.h"
static void sysvinit_send_cmd(struct init_request *request)
{
int fd;
char *p;
size_t bytes;
ssize_t r;
fd = open("/run/initctl", O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
if (fd < 0) {
if (errno != ENOENT)
eerror("Failed to open initctl fifo: %s", strerror(errno));
return;
}
p = (char *) request;
bytes = sizeof(*request);
do {
r = write(fd, p, bytes);
if (r < 0) {
if ((errno == EAGAIN) || (errno == EINTR))
continue;
eerror("Failed to write to /run/initctl: %s", strerror(errno));
return;
}
p += r;
bytes -= r;
} while (bytes > 0);
}
void sysvinit_runlevel(char rl)
{
struct init_request request;
if (!rl)
return;
request = (struct init_request) {
.magic = INIT_MAGIC,
.sleeptime = 0,
.cmd = INIT_CMD_RUNLVL,
.runlevel = rl,
};
sysvinit_send_cmd(&request);
return;
}
/*
* Set environment variables in the init process.
*/
void sysvinit_setenv(const char *name, const char *value)
{
struct init_request request;
size_t nl;
size_t vl;
memset(&request, 0, sizeof(request));
request.magic = INIT_MAGIC;
request.cmd = INIT_CMD_SETENV;
nl = strlen(name);
if (value)
vl = strlen(value);
else
vl = 0;
if (nl + vl + 3 >= (int)sizeof(request.i.data))
return;
memcpy(request.i.data, name, nl);
if (value) {
request.i.data[nl] = '=';
memcpy(request.i.data + nl + 1, value, vl);
}
sysvinit_send_cmd(&request);
return;
}

View File

@@ -1,72 +0,0 @@
/*
* rc-sysvinit.h - Interface to communicate with sysvinit via /run/initctl.
*/
/*
* Copyright (c) 2019 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_SYSVINIT_H
#define _RC_SYSVINIT_H
/*
* The #defines and structures below are taken from initreq.h in
* sysvinit and must be used by any program wishing to communicate with
* it.
*/
#define INIT_MAGIC 0x03091969
#define INIT_CMD_START 0
#define INIT_CMD_RUNLVL 1
#define INIT_CMD_POWERFAIL 2
#define INIT_CMD_POWERFAILNOW 3
#define INIT_CMD_POWEROK 4
#define INIT_CMD_BSD 5
#define INIT_CMD_SETENV 6
#define INIT_CMD_UNSETENV 7
/*
* This is what BSD 4.4 uses when talking to init.
* Linux doesn't use this right now.
*/
struct init_request_bsd {
char gen_id[8]; /* Beats me.. telnetd uses "fe" */
char tty_id[16]; /* Tty name minus /dev/tty */
char host[64]; /* Hostname */
char term_type[16]; /* Terminal type */
int signal; /* Signal to send */
int pid; /* Process to send to */
char exec_name[128]; /* Program to execute */
char reserved[128]; /* For future expansion. */
};
/*
* Because of legacy interfaces, "runlevel" and "sleeptime"
* aren't in a seperate struct in the union.
*
* The weird sizes are because init expects the whole
* struct to be 384 bytes.
*/
struct init_request {
int magic; /* Magic number */
int cmd; /* What kind of request */
int runlevel; /* Runlevel to change to */
int sleeptime; /* Time between TERM and KILL */
union {
struct init_request_bsd bsd;
char data[368];
} i;
};
void sysvinit_runlevel(char rl);
void sysvinit_setenv(const char *name, const char *value);
#endif

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_name, user, sizeof(utmp.ut_name));
strncpy(utmp.ut_id , id , sizeof(utmp.ut_id )); strncpy(utmp.ut_id , id , sizeof(utmp.ut_id ));
strncpy(utmp.ut_line, line, sizeof(utmp.ut_line)); strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
/* Put the OS version in place of the hostname */ /* Put the OS version in place of the hostname */
if (uname(&uname_buf) == 0) if (uname(&uname_buf) == 0)
strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host)); strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host));
updwtmp(WTMP_FILE, &utmp); updwtmp(WTMP_FILE, &utmp);

View File

@@ -20,7 +20,7 @@
* except according to the terms contained in the LICENSE file. * except according to the terms contained in the LICENSE file.
*/ */
static const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>

View File

@@ -389,11 +389,10 @@ int main(int argc, char **argv)
/* falls through */ /* falls through */
case 'u': /* --user <username>|<uid> */ case 'u': /* --user <username>|<uid> */
{ {
char dummy[2];
p = optarg; p = optarg;
tmp = strsep(&p, ":"); tmp = strsep(&p, ":");
changeuser = xstrdup(tmp); changeuser = xstrdup(tmp);
if (sscanf(tmp, "%d%1s", &tid, dummy) != 1) if (sscanf(tmp, "%d", &tid) != 1)
pw = getpwnam(tmp); pw = getpwnam(tmp);
else else
pw = getpwuid((uid_t)tid); pw = getpwuid((uid_t)tid);
@@ -414,7 +413,7 @@ int main(int argc, char **argv)
if (p) { if (p) {
tmp = strsep (&p, ":"); tmp = strsep (&p, ":");
if (sscanf(tmp, "%d%1s", &tid, dummy) != 1) if (sscanf(tmp, "%d", &tid) != 1)
gr = getgrnam(tmp); gr = getgrnam(tmp);
else else
gr = getgrgid((gid_t) tid); gr = getgrgid((gid_t) tid);
@@ -493,7 +492,7 @@ int main(int argc, char **argv)
startas = optarg; startas = optarg;
break; break;
case 'w': case 'w':
if (sscanf(optarg, "%u", &start_wait) != 1) if (sscanf(optarg, "%d", &start_wait) != 1)
eerrorx("%s: `%s' not a number", eerrorx("%s: `%s' not a number",
applet, optarg); applet, optarg);
break; break;
@@ -548,7 +547,7 @@ int main(int argc, char **argv)
} else if (name) { } else if (name) {
*--argv = name; *--argv = name;
++argc; ++argc;
} else if (exec) { } else if (exec) {
*--argv = exec; *--argv = exec;
++argc; ++argc;
}; };
@@ -629,7 +628,7 @@ int main(int argc, char **argv)
} }
if (start && !exists(exec_file)) { if (start && !exists(exec_file)) {
eerror("%s: %s does not exist", applet, eerror("%s: %s does not exist", applet,
exec_file ? exec_file : exec); *exec_file ? exec_file : exec);
free(exec_file); free(exec_file);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -670,7 +669,7 @@ int main(int argc, char **argv)
nav[len++] = p; nav[len++] = p;
for (i = 0; i < opt; i++) for (i = 0; i < opt; i++)
nav[i + len] = argv[i]; nav[i + len] = argv[i];
nav[i + len] = NULL; nav[i + len] = '\0';
} }
} }
} }
@@ -864,8 +863,8 @@ int main(int argc, char **argv)
TAILQ_FOREACH(env, env_list, entries) { TAILQ_FOREACH(env, env_list, entries) {
if ((strncmp(env->value, "RC_", 3) == 0 && if ((strncmp(env->value, "RC_", 3) == 0 &&
strncmp(env->value, "RC_SERVICE=", 11) != 0 && strncmp(env->value, "RC_SERVICE=", 10) != 0 &&
strncmp(env->value, "RC_SVCNAME=", 11) != 0) || strncmp(env->value, "RC_SVCNAME=", 10) != 0) ||
strncmp(env->value, "SSD_NICELEVEL=", 14) == 0 || strncmp(env->value, "SSD_NICELEVEL=", 14) == 0 ||
strncmp(env->value, "SSD_IONICELEVEL=", 16) == 0) strncmp(env->value, "SSD_IONICELEVEL=", 16) == 0)
{ {
@@ -997,7 +996,9 @@ int main(int argc, char **argv)
ts.tv_sec = start_wait / 1000; ts.tv_sec = start_wait / 1000;
ts.tv_nsec = (start_wait % 1000) * ONE_MS; ts.tv_nsec = (start_wait % 1000) * ONE_MS;
if (nanosleep(&ts, NULL) == -1) { if (nanosleep(&ts, NULL) == -1) {
if (errno != EINTR) { if (errno == EINTR)
eerror("%s: caught an interrupt", applet);
else {
eerror("%s: nanosleep: %s", eerror("%s: nanosleep: %s",
applet, strerror(errno)); applet, strerror(errno));
return 0; return 0;

View File

@@ -61,18 +61,15 @@ static struct pam_conv conv = { NULL, NULL};
#include "queue.h" #include "queue.h"
#include "rc.h" #include "rc.h"
#include "rc-misc.h" #include "rc-misc.h"
#include "rc-plugin.h"
#include "rc-schedules.h" #include "rc-schedules.h"
#include "_usage.h" #include "_usage.h"
#include "helpers.h" #include "helpers.h"
const char *applet = NULL; const char *applet = NULL;
const char *extraopts = 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; getoptstring_COMMON;
const struct option longopts[] = { const struct option longopts[] = {
{ "healthcheck-timer", 1, NULL, 'a'},
{ "healthcheck-delay", 1, NULL, 'A'},
{ "respawn-delay", 1, NULL, 'D'}, { "respawn-delay", 1, NULL, 'D'},
{ "chdir", 1, NULL, 'd'}, { "chdir", 1, NULL, 'd'},
{ "env", 1, NULL, 'e'}, { "env", 1, NULL, 'e'},
@@ -86,7 +83,6 @@ const struct option longopts[] = {
{ "respawn-period", 1, NULL, 'P'}, { "respawn-period", 1, NULL, 'P'},
{ "retry", 1, NULL, 'R'}, { "retry", 1, NULL, 'R'},
{ "chroot", 1, NULL, 'r'}, { "chroot", 1, NULL, 'r'},
{ "signal", 1, NULL, 's'},
{ "start", 0, NULL, 'S'}, { "start", 0, NULL, 'S'},
{ "user", 1, NULL, 'u'}, { "user", 1, NULL, 'u'},
{ "stdout", 1, NULL, '1'}, { "stdout", 1, NULL, '1'},
@@ -95,8 +91,6 @@ const struct option longopts[] = {
longopts_COMMON longopts_COMMON
}; };
const char * const longopts_help[] = { const char * const longopts_help[] = {
"set an initial health check delay",
"set a health check timer",
"Set a respawn delay", "Set a respawn delay",
"Change the PWD", "Change the PWD",
"Set an environment string", "Set an environment string",
@@ -110,7 +104,6 @@ const char * const longopts_help[] = {
"Set respawn time period", "Set respawn time period",
"Retry schedule to use when stopping", "Retry schedule to use when stopping",
"Chroot to this directory", "Chroot to this directory",
"Send a signal to the daemon",
"Start daemon", "Start daemon",
"Change the process user", "Change the process user",
"Redirect stdout to file", "Redirect stdout to file",
@@ -120,10 +113,6 @@ const char * const longopts_help[] = {
}; };
const char *usagestring = NULL; 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 nicelevel = 0;
static int ionicec = -1; static int ionicec = -1;
static int ioniced = 0; static int ioniced = 0;
@@ -136,6 +125,7 @@ static int stdout_fd;
static int stderr_fd; static int stderr_fd;
static char *redirect_stderr = NULL; static char *redirect_stderr = NULL;
static char *redirect_stdout = NULL; static char *redirect_stdout = NULL;
static bool exiting = false;
#ifdef TIOCNOTTY #ifdef TIOCNOTTY
static int tty_fd = -1; static int tty_fd = -1;
#endif #endif
@@ -143,12 +133,9 @@ static pid_t child_pid;
static int respawn_count = 0; static int respawn_count = 0;
static int respawn_delay = 0; static int respawn_delay = 0;
static int respawn_max = 10; static int respawn_max = 10;
static int respawn_period = 0; static int respawn_period = 5;
static char *fifopath = NULL;
static int fifo_fd = 0;
static char *pidfile = NULL; static char *pidfile = NULL;
static char *svcname = NULL; static char *svcname = NULL;
static bool verbose = false;
extern char **environ; extern char **environ;
@@ -185,32 +172,15 @@ static void re_exec_supervisor(void)
static void handle_signal(int sig) static void handle_signal(int sig)
{ {
int serrno = errno; int serrno = errno;
pid_t pid;
switch (sig) { syslog(LOG_WARNING, "caught signal %d", sig);
case SIGALRM:
do_healthcheck = 1; if (sig == SIGTERM)
break; exiting = true;
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();
}
/* Restore errno */ /* Restore errno */
errno = serrno; errno = serrno;
if (! exiting)
re_exec_supervisor();
} }
static char * expand_home(const char *home, const char *path) static char * expand_home(const char *home, const char *path)
@@ -238,7 +208,7 @@ static char * expand_home(const char *home, const char *path)
ppath++; ppath++;
if (!home) { if (!home) {
free(opath); free(opath);
return xstrdup(path); return xstrdup(path);
} }
if (!ppath) { if (!ppath) {
@@ -268,56 +238,6 @@ static char *make_cmdline(char **argv)
return cmdline; 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) static void child_process(char *exec, char **argv)
{ {
RC_STRINGLIST *env_list; RC_STRINGLIST *env_list;
@@ -421,8 +341,8 @@ static void child_process(char *exec, char **argv)
TAILQ_FOREACH(env, env_list, entries) { TAILQ_FOREACH(env, env_list, entries) {
if ((strncmp(env->value, "RC_", 3) == 0 && if ((strncmp(env->value, "RC_", 3) == 0 &&
strncmp(env->value, "RC_SERVICE=", 11) != 0 && strncmp(env->value, "RC_SERVICE=", 10) != 0 &&
strncmp(env->value, "RC_SVCNAME=", 11) != 0) || strncmp(env->value, "RC_SVCNAME=", 10) != 0) ||
strncmp(env->value, "SSD_NICELEVEL=", 14) == 0) strncmp(env->value, "SSD_NICELEVEL=", 14) == 0)
{ {
p = strchr(env->value, '='); p = strchr(env->value, '=');
@@ -503,40 +423,52 @@ static void child_process(char *exec, char **argv)
static void supervisor(char *exec, char **argv) static void supervisor(char *exec, char **argv)
{ {
FILE *fp; FILE *fp;
char buf[2048];
char cmd[2048];
int count;
int failing;
int health_status;
int healthcheck_respawn;
int i; int i;
int nkilled; 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 respawn_now= 0;
time_t first_spawn= 0; time_t first_spawn= 0;
/* block all signals we do not handle */ #ifndef RC_DEBUG
sigfillset(&signals); signal_setup_restart(SIGHUP, handle_signal);
sigdelset(&signals, SIGALRM); signal_setup_restart(SIGINT, handle_signal);
sigdelset(&signals, SIGCHLD); signal_setup_restart(SIGQUIT, handle_signal);
sigdelset(&signals, SIGTERM); signal_setup_restart(SIGILL, handle_signal);
sigprocmask(SIG_SETMASK, &signals, &old_signals); signal_setup_restart(SIGABRT, handle_signal);
signal_setup_restart(SIGFPE, handle_signal);
/* install signal handler */ signal_setup_restart(SIGSEGV, handle_signal);
memset(&sa, 0, sizeof(sa)); signal_setup_restart(SIGPIPE, handle_signal);
sa.sa_handler = handle_signal; signal_setup_restart(SIGALRM, handle_signal);
sigaction(SIGALRM, &sa, NULL); signal_setup(SIGTERM, handle_signal);
sigaction(SIGCHLD, &sa, NULL); signal_setup_restart(SIGUSR1, handle_signal);
sigaction(SIGTERM, &sa, NULL); 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"); fp = fopen(pidfile, "w");
if (!fp) if (! fp)
eerrorx("%s: fopen `%s': %s", applet, pidfile, strerror(errno)); eerrorx("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
fprintf(fp, "%d\n", getpid()); fprintf(fp, "%d\n", getpid());
fclose(fp); fclose(fp);
@@ -554,135 +486,56 @@ static void supervisor(char *exec, char **argv)
/* /*
* Supervisor main loop * Supervisor main loop
*/ */
if (healthcheckdelay) i = 0;
alarm(healthcheckdelay);
else if (healthchecktimer)
alarm(healthchecktimer);
failing = 0;
while (!exiting) { while (!exiting) {
healthcheck_respawn = 0; wait(&i);
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;
if (verbose)
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);
if (verbose)
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;
}
}
if (exiting) { if (exiting) {
alarm(0); signal_setup(SIGCHLD, SIG_IGN);
syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid); 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); false, false, true);
if (nkilled > 0) if (nkilled > 0)
syslog(LOG_INFO, "killed %d processes", nkilled); syslog(LOG_INFO, "killed %d processes", nkilled);
continue; } else {
} sleep(respawn_delay);
wait_pid = waitpid(child_pid, &i, WNOHANG); if (respawn_max > 0 && respawn_period > 0) {
if (wait_pid == child_pid) { 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)) if (WIFEXITED(i))
syslog(LOG_WARNING, "%s, pid %d, exited with return code %d", syslog(LOG_WARNING, "%s, pid %d, exited with return code %d",
exec, child_pid, WEXITSTATUS(i)); exec, child_pid, WEXITSTATUS(i));
else if (WIFSIGNALED(i)) else if (WIFSIGNALED(i))
syslog(LOG_WARNING, "%s, pid %d, terminated by signal %d", syslog(LOG_WARNING, "%s, pid %d, terminated by signal %d",
exec, child_pid, WTERMSIG(i)); 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);
if (exiting)
continue;
child_pid = fork(); child_pid = fork();
if (child_pid == -1) { if (child_pid == -1)
syslog(LOG_ERR, "%s: fork: %s", applet, strerror(errno)); eerrorx("%s: fork: %s", applet, strerror(errno));
exit(EXIT_FAILURE); if (child_pid == 0)
}
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);
child_process(exec, argv); child_process(exec, argv);
}
if (healthcheckdelay)
alarm(healthcheckdelay);
else if (healthchecktimer)
alarm(healthchecktimer);
} }
} }
if (pidfile && exists(pidfile))
unlink(pidfile);
if (svcname) { if (svcname) {
rc_service_daemon_set(svcname, exec, (const char *const *)argv, rc_service_daemon_set(svcname, exec, (const char *const *)argv,
pidfile, false); pidfile, false);
rc_service_value_set(svcname, "child_pid", NULL);
rc_service_mark(svcname, RC_SERVICE_STOPPED); rc_service_mark(svcname, RC_SERVICE_STOPPED);
if (failing) rc_service_value_set(svcname, "child_pid", NULL);
rc_service_mark(svcname, RC_SERVICE_FAILED);
} }
if (pidfile && exists(pidfile))
unlink(pidfile);
if (fifopath && exists(fifopath))
unlink(fifopath);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@@ -694,7 +547,6 @@ int main(int argc, char **argv)
bool start = false; bool start = false;
bool stop = false; bool stop = false;
bool reexec = false; bool reexec = false;
bool sendsig = false;
char *exec = NULL; char *exec = NULL;
char *retry = NULL; char *retry = NULL;
int sig = SIGTERM; int sig = SIGTERM;
@@ -725,7 +577,7 @@ int main(int argc, char **argv)
eerrorx("%s: The RC_SVCNAME environment variable is not set", applet); eerrorx("%s: The RC_SVCNAME environment variable is not set", applet);
openlog(applet, LOG_PID, LOG_DAEMON); 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", eerrorx("%s: the first argument is %s and must be %s",
applet, argv[1], svcname); applet, argv[1], svcname);
@@ -757,16 +609,6 @@ int main(int argc, char **argv)
while ((opt = getopt_long(argc, argv, getoptstring, longopts, while ((opt = getopt_long(argc, argv, getoptstring, longopts,
(int *) 0)) != -1) (int *) 0)) != -1)
switch (opt) { 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 */ case 'D': /* --respawn-delay time */
n = sscanf(optarg, "%d", &respawn_delay); n = sscanf(optarg, "%d", &respawn_delay);
if (n != 1 || respawn_delay < 1) if (n != 1 || respawn_delay < 1)
@@ -800,10 +642,6 @@ int main(int argc, char **argv)
eerrorx("Invalid respawn-period value '%s'", optarg); eerrorx("Invalid respawn-period value '%s'", optarg);
break; break;
case 's': /* --signal */
sig = parse_signal(applet, optarg);
sendsig = true;
break;
case 'S': /* --start */ case 'S': /* --start */
start = true; start = true;
break; break;
@@ -827,11 +665,6 @@ int main(int argc, char **argv)
gid = gr->gr_gid; gid = gr->gr_gid;
break; 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': case 'k':
if (parse_mode(&numask, optarg)) if (parse_mode(&numask, optarg))
eerrorx("%s: invalid mode `%s'", eerrorx("%s: invalid mode `%s'",
@@ -840,7 +673,7 @@ int main(int argc, char **argv)
case 'm': /* --respawn-max count */ case 'm': /* --respawn-max count */
n = sscanf(optarg, "%d", &respawn_max); n = sscanf(optarg, "%d", &respawn_max);
if (n != 1 || respawn_max < 0) if (n != 1 || respawn_max < 1)
eerrorx("Invalid respawn-max value '%s'", optarg); eerrorx("Invalid respawn-max value '%s'", optarg);
break; break;
@@ -857,11 +690,10 @@ int main(int argc, char **argv)
case 'u': /* --user <username>|<uid> */ case 'u': /* --user <username>|<uid> */
{ {
char dummy[2];
p = optarg; p = optarg;
tmp = strsep(&p, ":"); tmp = strsep(&p, ":");
changeuser = xstrdup(tmp); changeuser = xstrdup(tmp);
if (sscanf(tmp, "%d%1s", &tid, dummy) != 1) if (sscanf(tmp, "%d", &tid) != 1)
pw = getpwnam(tmp); pw = getpwnam(tmp);
else else
pw = getpwuid((uid_t)tid); pw = getpwuid((uid_t)tid);
@@ -882,7 +714,7 @@ int main(int argc, char **argv)
if (p) { if (p) {
tmp = strsep (&p, ":"); tmp = strsep (&p, ":");
if (sscanf(tmp, "%d%1s", &tid, dummy) != 1) if (sscanf(tmp, "%d", &tid) != 1)
gr = getgrnam(tmp); gr = getgrnam(tmp);
else else
gr = getgrgid((gid_t) tid); gr = getgrgid((gid_t) tid);
@@ -910,7 +742,8 @@ int main(int argc, char **argv)
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
verbose = rc_yesno(getenv ("EINFO_VERBOSE")); if (!pidfile && !reexec)
eerrorx("%s: --pidfile must be specified", applet);
endpwent(); endpwent();
argc -= optind; argc -= optind;
argv += optind; argv += optind;
@@ -923,12 +756,6 @@ int main(int argc, char **argv)
ch_root = expand_home(home, ch_root); ch_root = expand_home(home, ch_root);
umask(numask); 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) { if (reexec) {
str = rc_service_value_get(svcname, "argc"); str = rc_service_value_get(svcname, "argc");
@@ -990,7 +817,7 @@ int main(int argc, char **argv)
} }
if (!exists(exec_file)) { if (!exists(exec_file)) {
eerror("%s: %s does not exist", applet, eerror("%s: %s does not exist", applet,
exec_file ? exec_file : exec); *exec_file ? exec_file : exec);
free(exec_file); free(exec_file);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -1003,9 +830,9 @@ int main(int argc, char **argv)
0, false, true) > 0) 0, false, true) > 0)
eerrorx("%s: %s is already running", applet, exec); 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 " 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); respawn_delay * respawn_max);
if (retry) { if (retry) {
@@ -1050,9 +877,6 @@ int main(int argc, char **argv)
tty_fd = open("/dev/tty", O_RDWR); tty_fd = open("/dev/tty", O_RDWR);
#endif #endif
devnull_fd = open("/dev/null", O_RDWR); 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(); child_pid = fork();
if (child_pid == -1) if (child_pid == -1)
eerrorx("%s: fork: %s", applet, strerror(errno)); eerrorx("%s: fork: %s", applet, strerror(errno));
@@ -1069,8 +893,8 @@ int main(int argc, char **argv)
c++; c++;
} }
xasprintf(&varbuf, "%d", x); xasprintf(&varbuf, "%d", x);
rc_service_value_set(svcname, "argc", varbuf); rc_service_value_set(svcname, "argc", varbuf);
free(varbuf); free(varbuf);
rc_service_value_set(svcname, "exec", exec); rc_service_value_set(svcname, "exec", exec);
supervisor(exec, argv); supervisor(exec, argv);
} else } else
@@ -1105,18 +929,5 @@ int main(int argc, char **argv)
rc_service_mark(svcname, RC_SERVICE_STOPPED); rc_service_mark(svcname, RC_SERVICE_STOPPED);
} }
exit(EXIT_SUCCESS); 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

Some files were not shown because too many files have changed in this diff Show More