sysinit is now a real runlevel that handles things like udev, dmesg and
mounting various bits in /dev and /sys. init.sh JUST mounts /lib/rc/init.d (and /proc for Linux systems) To make development of this easier we now return an empty RC_STRINGLIST instead of a NULL for empty things. If you don't have a udev init script installed, don't reboot your box OR roll back to an older OpenRC version.
This commit is contained in:
parent
247766695c
commit
d6da8e8c48
@ -1 +1 @@
|
|||||||
CONF+= consolefont hwclock keymaps modules
|
CONF+= consolefont dmesg hwclock keymaps modules
|
||||||
|
3
conf.d/dmesg
Normal file
3
conf.d/dmesg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Sets the level at which logging of messages is done to the
|
||||||
|
# console. See dmesg(8) for more info.
|
||||||
|
dmesg_level="1"
|
@ -6,20 +6,3 @@
|
|||||||
# consolefont, numlock, etc ...)
|
# consolefont, numlock, etc ...)
|
||||||
rc_tty_number=12
|
rc_tty_number=12
|
||||||
|
|
||||||
# Use this variable to control the /dev management behavior.
|
|
||||||
# devfs - use devfs (requires sys-fs/devfsd)
|
|
||||||
# mdev - use mdev (requires sys-apps/busybox)
|
|
||||||
# udev - use udev (requires sys-fs/udev)
|
|
||||||
# static - let the user manage /dev (YOU need to create ALL device nodes)
|
|
||||||
# Leave it blank to let rc work it out (udev, mdev, devfs, static)
|
|
||||||
#rc_devices=""
|
|
||||||
|
|
||||||
# UDEV OPTION:
|
|
||||||
# Set to "yes" if you want to save /dev to a tarball on shutdown
|
|
||||||
# and restore it on startup. This is useful if you have a lot of
|
|
||||||
# custom device nodes that udev does not handle/know about.
|
|
||||||
rc_device_tarball="NO"
|
|
||||||
|
|
||||||
# Sets the level at which logging of messages is done to the
|
|
||||||
# console. See dmesg(8) for more info.
|
|
||||||
dmesg_level="1"
|
|
||||||
|
@ -27,25 +27,17 @@ rc_depend_strict="YES"
|
|||||||
# starting/stopping of the init.d service triggered by it.
|
# starting/stopping of the init.d service triggered by it.
|
||||||
rc_hotplug="YES"
|
rc_hotplug="YES"
|
||||||
|
|
||||||
# Dynamic /dev managers can trigger coldplug events which cause services to
|
# Some people want a finer grain over hotplug. rc_plug_services is a
|
||||||
# start before we are ready for them. If this happens, we can defer these
|
|
||||||
# services to start in the boot runlevel. Set rc_coldplug="NO" if you don't
|
|
||||||
# want this.
|
|
||||||
# NOTE: This also affects module coldplugging in udev-096 and higher
|
|
||||||
# If you want module coldplugging but not coldplugging of services then you
|
|
||||||
# can set rc_coldplug="YES" and rc_plug_services="!*"
|
|
||||||
rc_coldplug="YES"
|
|
||||||
|
|
||||||
# Some people want a finer grain over hotplug/coldplug. rc_plug_services is a
|
|
||||||
# list of services that are matched in order, either allowing or not. By
|
# list of services that are matched in order, either allowing or not. By
|
||||||
# default we allow services through as rc_coldplug/rc_hotplug has to be YES
|
# default we allow services through as rc_hotplug has to be YES anyway.
|
||||||
# anyway.
|
|
||||||
# Example - rc_plug_services="net.wlan !net.*"
|
# Example - rc_plug_services="net.wlan !net.*"
|
||||||
# This allows net.wlan and any service not matching net.* to be plugged.
|
# This allows net.wlan and any service not matching net.* to be plugged.
|
||||||
rc_plug_services=""
|
rc_plug_services=""
|
||||||
|
|
||||||
# rc_logger launches a logging daemon to log the entire rc process to
|
# rc_logger launches a logging daemon to log the entire rc process to
|
||||||
# /var/log/rc.log
|
# /var/log/rc.log
|
||||||
|
# NOTE: Linux systems require the devfs service to be started before
|
||||||
|
# logging can take place.
|
||||||
rc_logger="NO"
|
rc_logger="NO"
|
||||||
|
|
||||||
# By default we filter the environment for our running scripts. To allow other
|
# By default we filter the environment for our running scripts. To allow other
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
NET_LO= net.lo
|
NET_LO= net.lo
|
||||||
|
|
||||||
SRCS+= hwclock.in consolefont.in keymaps.in modules.in mtab.in numlock.in \
|
SRCS+= devfs.in dmesg.in hwclock.in consolefont.in keymaps.in modules.in \
|
||||||
procfs.in termencoding.in
|
mtab.in numlock.in procfs.in sysfs.in termencoding.in
|
||||||
|
|
||||||
.SUFFIXES: .Linux.in
|
.SUFFIXES: .Linux.in
|
||||||
.Linux.in:
|
.Linux.in:
|
||||||
|
36
init.d/devfs.in
Normal file
36
init.d/devfs.in
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!@PREFIX@/sbin/runscript
|
||||||
|
# Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||||
|
# All rights reserved. Released under the 2-clause BSD license.
|
||||||
|
|
||||||
|
description="Mount system critical filesystems in /dev."
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
use dev
|
||||||
|
keyword noprefix
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
# Mount required stuff as user may not have then in /etc/fstab
|
||||||
|
for x in \
|
||||||
|
"devpts /dev/pts 0755 ,gid=5,mode=0620 devpts" \
|
||||||
|
"tmpfs /dev/shm 1777 ,nodev shm" \
|
||||||
|
; do
|
||||||
|
set -- ${x}
|
||||||
|
grep -Eq "[[:space:]]+$1$" /proc/filesystems || continue
|
||||||
|
mountinfo -q "$2" && continue
|
||||||
|
|
||||||
|
if [ ! -d "$2" ]; then
|
||||||
|
mkdir -m "$3" -p "$2" >/dev/null 2>&1 || \
|
||||||
|
ewarn "Could not create $2!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$2" ]; then
|
||||||
|
ebegin "Mounting $2"
|
||||||
|
if ! fstabinfo --mount "$2"; then
|
||||||
|
mount -n -t "$1" -o noexec,nosuid"$4" "$5" "$2"
|
||||||
|
fi
|
||||||
|
eend $?
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
}
|
17
init.d/dmesg.in
Normal file
17
init.d/dmesg.in
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!@PREFIX@/sbin/runscript
|
||||||
|
# Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||||
|
# All rights reserved. Released under the 2-clause BSD license.
|
||||||
|
|
||||||
|
description="Set the dmesg level for a cleaner boot"
|
||||||
|
|
||||||
|
depend()
|
||||||
|
{
|
||||||
|
before dev modules
|
||||||
|
}
|
||||||
|
|
||||||
|
start()
|
||||||
|
{
|
||||||
|
if [ -n "${dmesg_level}" ]; then
|
||||||
|
dmesg -n"${dmesg_level}"
|
||||||
|
fi
|
||||||
|
}
|
@ -8,7 +8,7 @@ _IFS="
|
|||||||
|
|
||||||
depend()
|
depend()
|
||||||
{
|
{
|
||||||
after clock modules
|
use dev clock modules
|
||||||
keyword nojail noopenvz noprefix notimeout novserver
|
keyword nojail noopenvz noprefix notimeout novserver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ description="Mounts misc filesystems in /proc."
|
|||||||
|
|
||||||
depend()
|
depend()
|
||||||
{
|
{
|
||||||
|
use devfs
|
||||||
need localmount
|
need localmount
|
||||||
keyword noopenvz noprefix novserver
|
keyword noopenvz noprefix novserver
|
||||||
}
|
}
|
||||||
@ -39,7 +40,7 @@ start()
|
|||||||
# Setup Kernel Support for the NFS daemon status
|
# Setup Kernel Support for the NFS daemon status
|
||||||
if [ -d /proc/fs/nfsd ] && ! mountinfo -q /proc/fs/nfsd; then
|
if [ -d /proc/fs/nfsd ] && ! mountinfo -q /proc/fs/nfsd; then
|
||||||
if grep -qs nfsd /proc/filesystems; then
|
if grep -qs nfsd /proc/filesystems; then
|
||||||
ebegin "Mounting nfsd filesystem"
|
ebegin "Mounting NFS filesystem"
|
||||||
mount -t nfsd -o nodev,noexec,nosuid \
|
mount -t nfsd -o nodev,noexec,nosuid \
|
||||||
nfsd /proc/fs/nfsd
|
nfsd /proc/fs/nfsd
|
||||||
eend $?
|
eend $?
|
||||||
@ -56,26 +57,6 @@ start()
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Setup Kernel Support for securityfs
|
|
||||||
if [ -d /sys/kernel/security ] && ! mountinfo -q /sys/kernel/security; then
|
|
||||||
if grep -qs securityfs /proc/filesystems; then
|
|
||||||
ebegin "Mounting security filesystem"
|
|
||||||
mount -t securityfs -o nodev,noexec,nosuid \
|
|
||||||
securityfs /sys/kernel/security
|
|
||||||
eend $?
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Setup Kernel Support for debugfs
|
|
||||||
if [ -d /sys/kernel/debug ] && ! mountinfo -q /sys/kernel/debug; then
|
|
||||||
if grep -qs debugfs /proc/filesystems; then
|
|
||||||
ebegin "Mounting debug filesystem"
|
|
||||||
mount -t debugfs -o nodev,noexec,nosuid \
|
|
||||||
debugfs /sys/kernel/debug
|
|
||||||
eend $?
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Setup Kernel Support for SELinux
|
# Setup Kernel Support for SELinux
|
||||||
if [ -d /selinux ] && ! mountinfo -q /selinux; then
|
if [ -d /selinux ] && ! mountinfo -q /selinux; then
|
||||||
if grep -qs selinuxfs /proc/filesystems; then
|
if grep -qs selinuxfs /proc/filesystems; then
|
||||||
|
63
init.d/sysfs.in
Normal file
63
init.d/sysfs.in
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#!@PREFIX@/sbin/runscript
|
||||||
|
# Copyright 2007-2008 Roy Marples <roy@marples.name>
|
||||||
|
# All rights reserved. Released under the 2-clause BSD license.
|
||||||
|
|
||||||
|
description="Mount the sys filesystem."
|
||||||
|
|
||||||
|
depend()
|
||||||
|
{
|
||||||
|
keyword noprefix
|
||||||
|
}
|
||||||
|
|
||||||
|
mount_sys()
|
||||||
|
{
|
||||||
|
grep -Eq "[[:space:]]+sysfs$" /proc/filesystems || return 1
|
||||||
|
mountinfo -q /sys && return 0
|
||||||
|
|
||||||
|
if [ ! -d /sys ]; then
|
||||||
|
if ! mkdir -m 0755 /sys; then
|
||||||
|
ewarn "Could not create /sys!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
ebegin "Mounting /sys"
|
||||||
|
if ! fstabinfo --mount /sys; then
|
||||||
|
mount -n -t sysfs -o noexec,nosuid,nodev sysfs /sys
|
||||||
|
fi
|
||||||
|
eend $?
|
||||||
|
}
|
||||||
|
|
||||||
|
mount_misc()
|
||||||
|
{
|
||||||
|
# Setup Kernel Support for securityfs
|
||||||
|
if [ -d /sys/kernel/security ] && ! mountinfo -q /sys/kernel/security; then
|
||||||
|
if grep -qs securityfs /proc/filesystems; then
|
||||||
|
ebegin "Mounting security filesystem"
|
||||||
|
mount -t securityfs -o nodev,noexec,nosuid \
|
||||||
|
securityfs /sys/kernel/security
|
||||||
|
eend $?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Setup Kernel Support for debugfs
|
||||||
|
if [ -d /sys/kernel/debug ] && ! mountinfo -q /sys/kernel/debug; then
|
||||||
|
if grep -qs debugfs /proc/filesystems; then
|
||||||
|
ebegin "Mounting debug filesystem"
|
||||||
|
mount -t debugfs -o nodev,noexec,nosuid \
|
||||||
|
debugfs /sys/kernel/debug
|
||||||
|
eend $?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
start()
|
||||||
|
{
|
||||||
|
local retval
|
||||||
|
mount_sys
|
||||||
|
retval=$?
|
||||||
|
if [ ${retval} -eq 0 ]; then
|
||||||
|
mount_misc
|
||||||
|
fi
|
||||||
|
return ${retval}
|
||||||
|
}
|
@ -3,6 +3,7 @@ BOOT= bootmisc fsck hostname localmount \
|
|||||||
DEFAULT= local netmount
|
DEFAULT= local netmount
|
||||||
|
|
||||||
LEVELDIR= ${DESTDIR}/${SYSCONFDIR}/runlevels
|
LEVELDIR= ${DESTDIR}/${SYSCONFDIR}/runlevels
|
||||||
|
SYSINITDIR= ${LEVELDIR}/sysinit
|
||||||
BOOTDIR= ${LEVELDIR}/boot
|
BOOTDIR= ${LEVELDIR}/boot
|
||||||
DEFAULTDIR= ${LEVELDIR}/default
|
DEFAULTDIR= ${LEVELDIR}/default
|
||||||
|
|
||||||
@ -17,6 +18,14 @@ include Makefile.${OS}
|
|||||||
all:
|
all:
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
if ! test -d "${SYSINITDIR}"; then \
|
||||||
|
${INSTALL} -d ${SYSINITDIR} || exit $$?; \
|
||||||
|
for x in ${SYSINIT}; do \
|
||||||
|
if test -n "${PREFIX}"; then \
|
||||||
|
grep -q "keyword .*noprefix" ${INITDIR}/"$$x" && continue; \
|
||||||
|
fi; \
|
||||||
|
ln -snf ${PREFIX}/etc/init.d/"$$x" ${SYSINITDIR}/"$$x" || exit $$?; done \
|
||||||
|
fi
|
||||||
if ! test -d "${BOOTDIR}"; then \
|
if ! test -d "${BOOTDIR}"; then \
|
||||||
${INSTALL} -d ${BOOTDIR} || exit $$?; \
|
${INSTALL} -d ${BOOTDIR} || exit $$?; \
|
||||||
for x in ${BOOT}; do \
|
for x in ${BOOT}; do \
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
BOOT+= hwclock consolefont keymaps modules mtab net.lo procfs \
|
SYSINIT+= devfs dmesg
|
||||||
termencoding
|
BOOT+= hwclock keymaps modules mtab net.lo procfs termencoding
|
||||||
|
@ -22,8 +22,4 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "sysinit" > "${RC_SVCDIR}/softlevel"
|
echo "sysinit" > "${RC_SVCDIR}/softlevel"
|
||||||
|
|
||||||
# sysinit is now done, so allow init scripts to run normally
|
|
||||||
[ -e /dev/.rcsysinit ] && rm -f /dev/.rcsysinit
|
|
||||||
|
|
||||||
exit ${retval}
|
exit ${retval}
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
# tmpfs and ramfs are easy, so force one or the other.
|
# tmpfs and ramfs are easy, so force one or the other.
|
||||||
mount_svcdir()
|
mount_svcdir()
|
||||||
{
|
{
|
||||||
local fs= fsopts="-o rw,noexec,nodev,nosuid" devdir="rc-svcdir" devtmp="none" x=
|
local fs= fsopts="-o rw,noexec,nodev,nosuid"
|
||||||
|
local devdir="rc-svcdir" devtmp="none" x=
|
||||||
local svcsize=${rc_svcsize:-1024}
|
local svcsize=${rc_svcsize:-1024}
|
||||||
|
|
||||||
if grep -Eq "[[:space:]]+tmpfs$" /proc/filesystems; then
|
if grep -Eq "[[:space:]]+tmpfs$" /proc/filesystems; then
|
||||||
@ -56,17 +57,8 @@ mount_svcdir()
|
|||||||
}
|
}
|
||||||
|
|
||||||
. /etc/init.d/functions.sh
|
. /etc/init.d/functions.sh
|
||||||
. "${RC_LIBDIR}"/sh/rc-functions.sh
|
|
||||||
[ -r /etc/conf.d/rc ] && . /etc/conf.d/rc
|
|
||||||
[ -r /etc/rc.conf ] && . /etc/rc.conf
|
[ -r /etc/rc.conf ] && . /etc/rc.conf
|
||||||
|
|
||||||
# Set the console loglevel to 1 for a cleaner boot
|
|
||||||
# the logger should anyhow dump the ring-0 buffer at start to the
|
|
||||||
# logs, and that with dmesg can be used to check for problems
|
|
||||||
if [ -n "${dmesg_level}" -a "${RC_SYS}" != "VSERVER" ]; then
|
|
||||||
dmesg -n "${dmesg_level}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# By default VServer already has /proc mounted, but OpenVZ does not!
|
# By default VServer already has /proc mounted, but OpenVZ does not!
|
||||||
# However, some of our users have an old proc image in /proc
|
# However, some of our users have an old proc image in /proc
|
||||||
# NFC how they managed that, but the end result means we have to test if
|
# NFC how they managed that, but the end result means we have to test if
|
||||||
@ -82,7 +74,6 @@ if [ -e /proc/uptime ]; then
|
|||||||
einfo "/proc is already mounted, skipping"
|
einfo "/proc is already mounted, skipping"
|
||||||
mountproc=false
|
mountproc=false
|
||||||
fi
|
fi
|
||||||
unset up
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ${mountproc}; then
|
if ${mountproc}; then
|
||||||
@ -94,98 +85,5 @@ if ${mountproc}; then
|
|||||||
fi
|
fi
|
||||||
eend $?
|
eend $?
|
||||||
fi
|
fi
|
||||||
unset mountproc
|
|
||||||
|
|
||||||
# Re-load RC_SYS if empty now we have /proc mounted
|
|
||||||
[ -z "${RC_SYS}" ] && export RC_SYS="$(rc --sys)"
|
|
||||||
|
|
||||||
# Read off the kernel commandline to see if there's any special settings
|
|
||||||
# especially check to see if we need to set the CDBOOT environment variable
|
|
||||||
# Note: /proc MUST be mounted
|
|
||||||
if [ -r /sbin/livecd-functions.sh ]; then
|
|
||||||
. /sbin/livecd-functions.sh
|
|
||||||
livecd_read_commandline
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${RC_UNAME}" != "GNU/kFreeBSD" \
|
|
||||||
-a "${RC_SYS}" != "VSERVER" ];
|
|
||||||
then
|
|
||||||
if grep -Eq "[[:space:]]+sysfs$" /proc/filesystems; then
|
|
||||||
if [ -d /sys ]; then
|
|
||||||
if ! mountinfo --quiet /sys; then
|
|
||||||
ebegin "Mounting /sys"
|
|
||||||
if ! fstabinfo --mount /sys; then
|
|
||||||
mount -n -t sysfs -o noexec,nosuid,nodev sysfs /sys
|
|
||||||
fi
|
|
||||||
eend $?
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
ewarn "No /sys to mount sysfs needed in 2.6 and later kernels!"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Default OpenVZ to static devices
|
|
||||||
if [ "${RC_SYS}" = "OPENVZ" ]; then
|
|
||||||
rc_devices=${rc_devices:-static}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Try to figure out how the user wants /dev handled
|
|
||||||
if [ "${rc_devices}" = "static" \
|
|
||||||
-o "${RC_SYS}" = "VSERVER" \
|
|
||||||
-o "${RC_UNAME}" = "GNU/kFreeBSD" ]
|
|
||||||
then
|
|
||||||
ebegin "Using existing device nodes in /dev"
|
|
||||||
eend 0
|
|
||||||
else
|
|
||||||
case ${rc_devices} in
|
|
||||||
devfs) managers="devfs udev mdev";;
|
|
||||||
udev) managers="udev devfs mdev";;
|
|
||||||
mdev) managers="mdev udev devfs";;
|
|
||||||
*) managers="udev devfs mdev";;
|
|
||||||
esac
|
|
||||||
|
|
||||||
for m in ${managers}; do
|
|
||||||
# Check kernel params
|
|
||||||
if get_bootparam "no${m}" || ! has_addon ${m}-start; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
# Let's see if we can get this puppy rolling
|
|
||||||
start_addon ${m} && break
|
|
||||||
|
|
||||||
# Clean up
|
|
||||||
mountinfo -q /dev && umount -n /dev
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Mount required stuff as user may not have then in /etc/fstab
|
|
||||||
for x in "devpts /dev/pts 0755 ,gid=5,mode=0620 devpts" "tmpfs /dev/shm 1777 ,nodev shm"
|
|
||||||
do
|
|
||||||
set -- ${x}
|
|
||||||
grep -Eq "[[:space:]]+$1$" /proc/filesystems || continue
|
|
||||||
mountinfo -q "$2" && continue
|
|
||||||
|
|
||||||
if [ ! -d "$2" ] && \
|
|
||||||
[ "${m}" = "devfs" -o "${m}" = "udev" ]; then
|
|
||||||
mkdir -m "$3" -p "$2" >/dev/null 2>&1 || \
|
|
||||||
ewarn "Could not create $2!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "$2" ]; then
|
|
||||||
ebegin "Mounting $2"
|
|
||||||
if ! fstabinfo --mount "$2"; then
|
|
||||||
mount -n -t "$1" -o noexec,nosuid"$4" "$5" "$2"
|
|
||||||
fi
|
|
||||||
eend $?
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# If booting off CD, we want to update inittab before setting the runlevel
|
|
||||||
if [ -f /sbin/livecd-functions.sh -a -n "${CDBOOT}" ]; then
|
|
||||||
ebegin "Updating inittab"
|
|
||||||
livecd_fix_inittab
|
|
||||||
eend $?
|
|
||||||
telinit q &>/dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
. "${RC_LIBDIR}"/sh/init-common-post.sh
|
. "${RC_LIBDIR}"/sh/init-common-post.sh
|
||||||
|
@ -143,7 +143,6 @@ char *rc_conf_value(const char *var);
|
|||||||
bool rc_conf_yesno(const char *var);
|
bool rc_conf_yesno(const char *var);
|
||||||
void env_filter(void);
|
void env_filter(void);
|
||||||
void env_config(void);
|
void env_config(void);
|
||||||
bool service_plugable(const char *service);
|
|
||||||
int signal_setup(int sig, void (*handler)(int));
|
int signal_setup(int sig, void (*handler)(int));
|
||||||
pid_t exec_service(const char *, const char *);
|
pid_t exec_service(const char *, const char *);
|
||||||
|
|
||||||
|
@ -187,12 +187,21 @@ valid_service(const char *runlevel, const char *service, const char *type)
|
|||||||
strcmp(type, "needsme") == 0)
|
strcmp(type, "needsme") == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (rc_service_in_runlevel(service, runlevel))
|
||||||
|
return true;
|
||||||
|
if (strcmp(runlevel, RC_LEVEL_SYSINIT) != 0 &&
|
||||||
|
strcmp(runlevel, bootlevel) != 0)
|
||||||
|
{
|
||||||
|
if (rc_service_in_runlevel(service, bootlevel))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
state = rc_service_state(service);
|
state = rc_service_state(service);
|
||||||
return ((strcmp(runlevel, bootlevel) != 0 &&
|
if (state & RC_SERVICE_COLDPLUGGED ||
|
||||||
rc_service_in_runlevel(service, bootlevel)) ||
|
state & RC_SERVICE_STARTED)
|
||||||
rc_service_in_runlevel(service, runlevel) ||
|
return true;
|
||||||
state & RC_SERVICE_COLDPLUGGED ||
|
|
||||||
state & RC_SERVICE_STARTED);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -344,7 +353,7 @@ get_provided(const RC_DEPINFO *depinfo, const char *runlevel, int options)
|
|||||||
static void
|
static void
|
||||||
visit_service(const RC_DEPTREE *deptree,
|
visit_service(const RC_DEPTREE *deptree,
|
||||||
const RC_STRINGLIST *types,
|
const RC_STRINGLIST *types,
|
||||||
RC_STRINGLIST **sorted,
|
RC_STRINGLIST *sorted,
|
||||||
RC_STRINGLIST *visited,
|
RC_STRINGLIST *visited,
|
||||||
const RC_DEPINFO *depinfo,
|
const RC_DEPINFO *depinfo,
|
||||||
const char *runlevel, int options)
|
const char *runlevel, int options)
|
||||||
@ -373,9 +382,7 @@ visit_service(const RC_DEPTREE *deptree,
|
|||||||
if (!(options & RC_DEP_TRACE) ||
|
if (!(options & RC_DEP_TRACE) ||
|
||||||
strcmp(type->value, "iprovide") == 0)
|
strcmp(type->value, "iprovide") == 0)
|
||||||
{
|
{
|
||||||
if (!*sorted)
|
rc_stringlist_add(sorted, service->value);
|
||||||
*sorted = rc_stringlist_new();
|
|
||||||
rc_stringlist_add(*sorted, service->value);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,11 +427,9 @@ visit_service(const RC_DEPTREE *deptree,
|
|||||||
/* We've visited everything we need, so add ourselves unless we
|
/* We've visited everything we need, so add ourselves unless we
|
||||||
are also the service calling us or we are provided by something */
|
are also the service calling us or we are provided by something */
|
||||||
svcname = getenv("RC_SVCNAME");
|
svcname = getenv("RC_SVCNAME");
|
||||||
if (!svcname || strcmp(svcname, depinfo->service) != 0)
|
if (!svcname || strcmp(svcname, depinfo->service) != 0) {
|
||||||
if (!get_deptype(depinfo, "providedby")) {
|
if (!get_deptype(depinfo, "providedby"))
|
||||||
if (!*sorted)
|
rc_stringlist_add(sorted, depinfo->service);
|
||||||
*sorted = rc_stringlist_new();
|
|
||||||
rc_stringlist_add(*sorted, depinfo->service);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,15 +442,15 @@ rc_deptree_depend(const RC_DEPTREE *deptree,
|
|||||||
RC_STRINGLIST *svcs;
|
RC_STRINGLIST *svcs;
|
||||||
RC_STRING *svc;
|
RC_STRING *svc;
|
||||||
|
|
||||||
|
svcs = rc_stringlist_new();
|
||||||
if (!(di = get_depinfo(deptree, service)) ||
|
if (!(di = get_depinfo(deptree, service)) ||
|
||||||
!(dt = get_deptype(di, type)))
|
!(dt = get_deptype(di, type)))
|
||||||
{
|
{
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return NULL;
|
return svcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For consistency, we copy the array */
|
/* For consistency, we copy the array */
|
||||||
svcs = rc_stringlist_new();
|
|
||||||
TAILQ_FOREACH(svc, dt->services, entries)
|
TAILQ_FOREACH(svc, dt->services, entries)
|
||||||
rc_stringlist_add(svcs, svc->value);
|
rc_stringlist_add(svcs, svc->value);
|
||||||
return svcs;
|
return svcs;
|
||||||
@ -458,7 +463,7 @@ rc_deptree_depends(const RC_DEPTREE *deptree,
|
|||||||
const RC_STRINGLIST *services,
|
const RC_STRINGLIST *services,
|
||||||
const char *runlevel, int options)
|
const char *runlevel, int options)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *sorted = NULL;
|
RC_STRINGLIST *sorted = rc_stringlist_new();
|
||||||
RC_STRINGLIST *visited = rc_stringlist_new();
|
RC_STRINGLIST *visited = rc_stringlist_new();
|
||||||
RC_DEPINFO *di;
|
RC_DEPINFO *di;
|
||||||
const RC_STRING *service;
|
const RC_STRING *service;
|
||||||
@ -472,7 +477,7 @@ rc_deptree_depends(const RC_DEPTREE *deptree,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (types)
|
if (types)
|
||||||
visit_service(deptree, types, &sorted, visited,
|
visit_service(deptree, types, sorted, visited,
|
||||||
di, runlevel, options);
|
di, runlevel, options);
|
||||||
}
|
}
|
||||||
rc_stringlist_free(visited);
|
rc_stringlist_free(visited);
|
||||||
@ -499,42 +504,25 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
|
|||||||
{
|
{
|
||||||
list = rc_services_in_state(RC_SERVICE_STARTED);
|
list = rc_services_in_state(RC_SERVICE_STARTED);
|
||||||
list2 = rc_services_in_state(RC_SERVICE_INACTIVE);
|
list2 = rc_services_in_state(RC_SERVICE_INACTIVE);
|
||||||
if (list2) {
|
|
||||||
if (list) {
|
|
||||||
TAILQ_CONCAT(list, list2, entries);
|
TAILQ_CONCAT(list, list2, entries);
|
||||||
free(list2);
|
free(list2);
|
||||||
} else
|
|
||||||
list = list2;
|
|
||||||
}
|
|
||||||
list2 = rc_services_in_state(RC_SERVICE_STARTING);
|
list2 = rc_services_in_state(RC_SERVICE_STARTING);
|
||||||
if (list2) {
|
|
||||||
if (list) {
|
|
||||||
TAILQ_CONCAT(list, list2, entries);
|
TAILQ_CONCAT(list, list2, entries);
|
||||||
free(list2);
|
free(list2);
|
||||||
} else
|
|
||||||
list = list2;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
list = rc_services_in_runlevel(runlevel);
|
list = rc_services_in_runlevel(RC_LEVEL_SYSINIT);
|
||||||
/* Add coldplugged services */
|
if (strcmp(runlevel, RC_LEVEL_SYSINIT) != 0) {
|
||||||
list2 = rc_services_in_state(RC_SERVICE_COLDPLUGGED);
|
list2 = rc_services_in_runlevel(runlevel);
|
||||||
if (list2) {
|
TAILQ_CONCAT(list, list2, entries);
|
||||||
if (list) {
|
free(list2);
|
||||||
|
list2 = rc_services_in_state(RC_SERVICE_COLDPLUGGED);
|
||||||
TAILQ_CONCAT(list, list2, entries);
|
TAILQ_CONCAT(list, list2, entries);
|
||||||
free(list2);
|
free(list2);
|
||||||
} else
|
|
||||||
list = list2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we're not the boot runlevel then add that too */
|
/* If we're not the boot runlevel then add that too */
|
||||||
if (strcmp(runlevel, bootlevel) != 0) {
|
if (strcmp(runlevel, bootlevel) != 0) {
|
||||||
list2 = rc_services_in_runlevel(bootlevel);
|
list2 = rc_services_in_runlevel(bootlevel);
|
||||||
if (list2) {
|
|
||||||
if (list) {
|
|
||||||
TAILQ_CONCAT(list, list2, entries);
|
TAILQ_CONCAT(list, list2, entries);
|
||||||
free(list2);
|
free(list2);
|
||||||
} else
|
|
||||||
list = list2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -683,7 +671,6 @@ rc_deptree_update_needed(void)
|
|||||||
/* Some init scripts dependencies change depending on config files
|
/* Some init scripts dependencies change depending on config files
|
||||||
* outside of baselayout, like syslog-ng, so we check those too. */
|
* outside of baselayout, like syslog-ng, so we check those too. */
|
||||||
config = rc_config_list(RC_DEPCONFIG);
|
config = rc_config_list(RC_DEPCONFIG);
|
||||||
if (config) {
|
|
||||||
TAILQ_FOREACH(s, config, entries) {
|
TAILQ_FOREACH(s, config, entries) {
|
||||||
if (!rc_newer_than(RC_DEPTREE_CACHE, s->value)) {
|
if (!rc_newer_than(RC_DEPTREE_CACHE, s->value)) {
|
||||||
newer = true;
|
newer = true;
|
||||||
@ -691,7 +678,6 @@ rc_deptree_update_needed(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc_stringlist_free(config);
|
rc_stringlist_free(config);
|
||||||
}
|
|
||||||
return newer;
|
return newer;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_deptree_update_needed)
|
librc_hidden_def(rc_deptree_update_needed)
|
||||||
@ -907,13 +893,11 @@ rc_deptree_update(void)
|
|||||||
deptype = get_deptype(depinfo, "ibefore");
|
deptype = get_deptype(depinfo, "ibefore");
|
||||||
if (!deptype)
|
if (!deptype)
|
||||||
continue;
|
continue;
|
||||||
sorted = NULL;
|
sorted = rc_stringlist_new();
|
||||||
visited = rc_stringlist_new();
|
visited = rc_stringlist_new();
|
||||||
visit_service(deptree, types, &sorted, visited, depinfo,
|
visit_service(deptree, types, sorted, visited, depinfo,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
rc_stringlist_free(visited);
|
rc_stringlist_free(visited);
|
||||||
if (!sorted)
|
|
||||||
continue;
|
|
||||||
TAILQ_FOREACH_SAFE(s2, deptype->services, entries, s2_np) {
|
TAILQ_FOREACH_SAFE(s2, deptype->services, entries, s2_np) {
|
||||||
TAILQ_FOREACH(s3, sorted, entries) {
|
TAILQ_FOREACH(s3, sorted, entries) {
|
||||||
di = get_depinfo(deptree, s3->value);
|
di = get_depinfo(deptree, s3->value);
|
||||||
|
@ -84,10 +84,10 @@ RC_STRINGLIST *rc_config_list(const char *file)
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char *p;
|
char *p;
|
||||||
char *token;
|
char *token;
|
||||||
RC_STRINGLIST *list = NULL;
|
RC_STRINGLIST *list = rc_stringlist_new();
|
||||||
|
|
||||||
if (!(fp = fopen(file, "r")))
|
if (!(fp = fopen(file, "r")))
|
||||||
return NULL;
|
return list;
|
||||||
|
|
||||||
while ((rc_getline(&buffer, &len, fp))) {
|
while ((rc_getline(&buffer, &len, fp))) {
|
||||||
p = buffer;
|
p = buffer;
|
||||||
@ -104,8 +104,6 @@ RC_STRINGLIST *rc_config_list(const char *file)
|
|||||||
if (token[strlen(token) - 1] == '\n')
|
if (token[strlen(token) - 1] == '\n')
|
||||||
token[strlen(token) - 1] = 0;
|
token[strlen(token) - 1] = 0;
|
||||||
|
|
||||||
if (!list)
|
|
||||||
list = rc_stringlist_new();
|
|
||||||
rc_stringlist_add(list, token);
|
rc_stringlist_add(list, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,9 +129,6 @@ RC_STRINGLIST *rc_config_load(const char *file)
|
|||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
list = rc_config_list(file);
|
list = rc_config_list(file);
|
||||||
if (!list)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
config = rc_stringlist_new();
|
config = rc_stringlist_new();
|
||||||
TAILQ_FOREACH(line, list, entries) {
|
TAILQ_FOREACH(line, list, entries) {
|
||||||
/* Get entry */
|
/* Get entry */
|
||||||
@ -203,9 +198,6 @@ char *rc_config_value(RC_STRINGLIST *list, const char *entry)
|
|||||||
RC_STRING *line;
|
RC_STRING *line;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (!list)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(line, list, entries) {
|
TAILQ_FOREACH(line, list, entries) {
|
||||||
p = strchr(line->value, '=');
|
p = strchr(line->value, '=');
|
||||||
if (p &&
|
if (p &&
|
||||||
|
@ -67,7 +67,8 @@ static const rc_service_state_name_t rc_service_state_names[] = {
|
|||||||
|
|
||||||
#define LS_INITD 0x01
|
#define LS_INITD 0x01
|
||||||
#define LS_DIR 0x02
|
#define LS_DIR 0x02
|
||||||
static RC_STRINGLIST *ls_dir(const char *dir, int options)
|
static RC_STRINGLIST *
|
||||||
|
ls_dir(const char *dir, int options)
|
||||||
{
|
{
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
@ -77,15 +78,15 @@ static RC_STRINGLIST *ls_dir(const char *dir, int options)
|
|||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
list = rc_stringlist_new();
|
||||||
if ((dp = opendir(dir)) == NULL)
|
if ((dp = opendir(dir)) == NULL)
|
||||||
return NULL;
|
return list;
|
||||||
|
|
||||||
while (((d = readdir(dp)) != NULL)) {
|
while (((d = readdir(dp)) != NULL)) {
|
||||||
if (d->d_name[0] != '.') {
|
if (d->d_name[0] != '.') {
|
||||||
if (options & LS_INITD) {
|
if (options & LS_INITD) {
|
||||||
/* Check that our file really exists.
|
/* Check that our file really exists.
|
||||||
* This is important as a service maybe in a runlevel, but
|
* This is important as a service maybe in a
|
||||||
* could also have been removed. */
|
* runlevel, but could have been removed. */
|
||||||
snprintf(file, sizeof(file), "%s/%s",
|
snprintf(file, sizeof(file), "%s/%s",
|
||||||
dir, d->d_name);
|
dir, d->d_name);
|
||||||
r = stat(file, &buf);
|
r = stat(file, &buf);
|
||||||
@ -104,17 +105,15 @@ static RC_STRINGLIST *ls_dir(const char *dir, int options)
|
|||||||
! S_ISDIR(buf.st_mode))
|
! S_ISDIR(buf.st_mode))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (! list)
|
|
||||||
list = rc_stringlist_new();
|
|
||||||
rc_stringlist_add(list, d->d_name);
|
rc_stringlist_add(list, d->d_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rm_dir(const char *pathname, bool top)
|
static bool
|
||||||
|
rm_dir(const char *pathname, bool top)
|
||||||
{
|
{
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
@ -127,14 +126,15 @@ static bool rm_dir(const char *pathname, bool top)
|
|||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
while (((d = readdir(dp)) != NULL) && errno == 0) {
|
while (((d = readdir(dp)) != NULL) && errno == 0) {
|
||||||
if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) {
|
if (strcmp(d->d_name, ".") != 0 &&
|
||||||
snprintf(file, sizeof(file), "%s/%s", pathname, d->d_name);
|
strcmp(d->d_name, "..") != 0)
|
||||||
|
{
|
||||||
|
snprintf(file, sizeof(file),
|
||||||
|
"%s/%s", pathname, d->d_name);
|
||||||
if (stat(file, &s) != 0) {
|
if (stat(file, &s) != 0) {
|
||||||
retval = false;
|
retval = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (S_ISDIR(s.st_mode)) {
|
if (S_ISDIR(s.st_mode)) {
|
||||||
if (!rm_dir(file, true))
|
if (!rm_dir(file, true))
|
||||||
{
|
{
|
||||||
@ -162,7 +162,8 @@ static bool rm_dir(const char *pathname, bool top)
|
|||||||
|
|
||||||
/* Other systems may need this at some point, but for now it's Linux only */
|
/* Other systems may need this at some point, but for now it's Linux only */
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
static bool file_regex(const char *file, const char *regex)
|
static bool
|
||||||
|
file_regex(const char *file, const char *regex)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
@ -197,8 +198,8 @@ static bool file_regex(const char *file, const char *regex)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const char *
|
||||||
const char *rc_sys(void)
|
rc_sys(void)
|
||||||
{
|
{
|
||||||
#ifdef PREFIX
|
#ifdef PREFIX
|
||||||
return RC_SYS_PREFIX;
|
return RC_SYS_PREFIX;
|
||||||
@ -242,7 +243,8 @@ const char *rc_sys(void)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_sys)
|
librc_hidden_def(rc_sys)
|
||||||
|
|
||||||
static const char *rc_parse_service_state(RC_SERVICE state)
|
static const char *
|
||||||
|
rc_parse_service_state(RC_SERVICE state)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -250,17 +252,18 @@ static const char *rc_parse_service_state(RC_SERVICE state)
|
|||||||
if (rc_service_state_names[i].state == state)
|
if (rc_service_state_names[i].state == state)
|
||||||
return rc_service_state_names[i].name;
|
return rc_service_state_names[i].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rc_runlevel_starting(void)
|
bool
|
||||||
|
rc_runlevel_starting(void)
|
||||||
{
|
{
|
||||||
return exists(RC_STARTING);
|
return exists(RC_STARTING);
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_runlevel_starting)
|
librc_hidden_def(rc_runlevel_starting)
|
||||||
|
|
||||||
bool rc_runlevel_stopping(void)
|
bool
|
||||||
|
rc_runlevel_stopping(void)
|
||||||
{
|
{
|
||||||
return exists(RC_STOPPING);
|
return exists(RC_STOPPING);
|
||||||
}
|
}
|
||||||
@ -272,15 +275,17 @@ RC_STRINGLIST *rc_runlevel_list(void)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_runlevel_list)
|
librc_hidden_def(rc_runlevel_list)
|
||||||
|
|
||||||
char *rc_runlevel_get(void)
|
char *
|
||||||
|
rc_runlevel_get(void)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *runlevel = NULL;
|
char *runlevel = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if ((fp = fopen(RC_RUNLEVEL, "r"))) {
|
if ((fp = fopen(RC_RUNLEVEL, "r"))) {
|
||||||
runlevel = xmalloc(sizeof(char) * PATH_MAX);
|
runlevel = xmalloc(sizeof(char) * PATH_MAX);
|
||||||
if (fgets(runlevel, PATH_MAX, fp)) {
|
if (fgets(runlevel, PATH_MAX, fp)) {
|
||||||
int i = strlen(runlevel) - 1;
|
i = strlen(runlevel) - 1;
|
||||||
if (runlevel[i] == '\n')
|
if (runlevel[i] == '\n')
|
||||||
runlevel[i] = 0;
|
runlevel[i] = 0;
|
||||||
} else
|
} else
|
||||||
@ -297,7 +302,8 @@ char *rc_runlevel_get(void)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_runlevel_get)
|
librc_hidden_def(rc_runlevel_get)
|
||||||
|
|
||||||
bool rc_runlevel_set(const char *runlevel)
|
bool
|
||||||
|
rc_runlevel_set(const char *runlevel)
|
||||||
{
|
{
|
||||||
FILE *fp = fopen(RC_RUNLEVEL, "w");
|
FILE *fp = fopen(RC_RUNLEVEL, "w");
|
||||||
|
|
||||||
@ -309,14 +315,14 @@ bool rc_runlevel_set(const char *runlevel)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_runlevel_set)
|
librc_hidden_def(rc_runlevel_set)
|
||||||
|
|
||||||
bool rc_runlevel_exists(const char *runlevel)
|
bool
|
||||||
|
rc_runlevel_exists(const char *runlevel)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
if (!runlevel)
|
if (!runlevel)
|
||||||
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;
|
||||||
@ -325,7 +331,8 @@ bool rc_runlevel_exists(const char *runlevel)
|
|||||||
librc_hidden_def(rc_runlevel_exists)
|
librc_hidden_def(rc_runlevel_exists)
|
||||||
|
|
||||||
/* Resolve a service name to it's full path */
|
/* Resolve a service name to it's full path */
|
||||||
char *rc_service_resolve(const char *service)
|
char *
|
||||||
|
rc_service_resolve(const char *service)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
@ -377,7 +384,8 @@ char *rc_service_resolve(const char *service)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_resolve)
|
librc_hidden_def(rc_service_resolve)
|
||||||
|
|
||||||
bool rc_service_exists(const char *service)
|
bool
|
||||||
|
rc_service_exists(const char *service)
|
||||||
{
|
{
|
||||||
char *file;
|
char *file;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
@ -406,7 +414,8 @@ bool rc_service_exists(const char *service)
|
|||||||
librc_hidden_def(rc_service_exists)
|
librc_hidden_def(rc_service_exists)
|
||||||
|
|
||||||
#define OPTSTR ". '%s'; echo \"${opts}\""
|
#define OPTSTR ". '%s'; echo \"${opts}\""
|
||||||
RC_STRINGLIST *rc_service_extra_commands(const char *service)
|
RC_STRINGLIST *
|
||||||
|
rc_service_extra_commands(const char *service)
|
||||||
{
|
{
|
||||||
char *svc;
|
char *svc;
|
||||||
char *cmd = NULL;
|
char *cmd = NULL;
|
||||||
@ -421,7 +430,6 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)
|
|||||||
if (!(svc = rc_service_resolve(service)))
|
if (!(svc = rc_service_resolve(service)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
l = strlen(OPTSTR) + strlen(svc) + 1;
|
l = strlen(OPTSTR) + strlen(svc) + 1;
|
||||||
cmd = xmalloc(sizeof(char) * l);
|
cmd = xmalloc(sizeof(char) * l);
|
||||||
snprintf(cmd, l, OPTSTR, svc);
|
snprintf(cmd, l, OPTSTR, svc);
|
||||||
@ -444,7 +452,8 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)
|
|||||||
librc_hidden_def(rc_service_extra_commands)
|
librc_hidden_def(rc_service_extra_commands)
|
||||||
|
|
||||||
#define DESCSTR ". '%s'; echo \"${description%s%s}\""
|
#define DESCSTR ". '%s'; echo \"${description%s%s}\""
|
||||||
char *rc_service_description(const char *service, const char *option)
|
char *
|
||||||
|
rc_service_description(const char *service, const char *option)
|
||||||
{
|
{
|
||||||
char *svc;
|
char *svc;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
@ -472,7 +481,8 @@ char *rc_service_description(const char *service, const char *option)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_description)
|
librc_hidden_def(rc_service_description)
|
||||||
|
|
||||||
bool rc_service_in_runlevel(const char *service, const char *runlevel)
|
bool
|
||||||
|
rc_service_in_runlevel(const char *service, const char *runlevel)
|
||||||
{
|
{
|
||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
|
|
||||||
@ -482,7 +492,8 @@ bool rc_service_in_runlevel(const char *service, const char *runlevel)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_in_runlevel)
|
librc_hidden_def(rc_service_in_runlevel)
|
||||||
|
|
||||||
bool rc_service_mark(const char *service, const RC_SERVICE state)
|
bool
|
||||||
|
rc_service_mark(const char *service, const RC_SERVICE state)
|
||||||
{
|
{
|
||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -500,7 +511,6 @@ bool rc_service_mark(const char *service, const RC_SERVICE state)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
base = basename_c(service);
|
base = basename_c(service);
|
||||||
|
|
||||||
if (state != RC_SERVICE_STOPPED) {
|
if (state != RC_SERVICE_STOPPED) {
|
||||||
if (!exists(init)) {
|
if (!exists(init)) {
|
||||||
free(init);
|
free(init);
|
||||||
@ -583,29 +593,26 @@ bool rc_service_mark(const char *service, const RC_SERVICE state)
|
|||||||
if (state == RC_SERVICE_STARTED || state == RC_SERVICE_STOPPED) {
|
if (state == RC_SERVICE_STARTED || state == RC_SERVICE_STOPPED) {
|
||||||
snprintf(file, sizeof(file), RC_SVCDIR "/%s", "scheduled");
|
snprintf(file, sizeof(file), RC_SVCDIR "/%s", "scheduled");
|
||||||
dirs = ls_dir(file, 0);
|
dirs = ls_dir(file, 0);
|
||||||
if (dirs) {
|
|
||||||
TAILQ_FOREACH(dir, dirs, entries) {
|
TAILQ_FOREACH(dir, dirs, entries) {
|
||||||
snprintf(was, sizeof(was), "%s/%s/%s",
|
snprintf(was, sizeof(was), "%s/%s/%s",
|
||||||
file, dir->value, base);
|
file, dir->value, base);
|
||||||
unlink(was);
|
unlink(was);
|
||||||
|
|
||||||
/* Try and remove the dir - we don't care about errors */
|
/* Try and remove the dir; we don't care about errors */
|
||||||
snprintf(was, sizeof(was), "%s/%s",
|
snprintf(was, sizeof(was), "%s/%s", file, dir->value);
|
||||||
file, dir->value);
|
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
rmdir(was);
|
rmdir(was);
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
}
|
}
|
||||||
rc_stringlist_free(dirs);
|
rc_stringlist_free(dirs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
free(init);
|
free(init);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_mark)
|
librc_hidden_def(rc_service_mark)
|
||||||
|
|
||||||
RC_SERVICE rc_service_state(const char *service)
|
RC_SERVICE
|
||||||
|
rc_service_state(const char *service)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int state = RC_SERVICE_STOPPED;
|
int state = RC_SERVICE_STOPPED;
|
||||||
@ -627,7 +634,6 @@ RC_SERVICE rc_service_state(const char *service)
|
|||||||
|
|
||||||
if (state & RC_SERVICE_STOPPED) {
|
if (state & RC_SERVICE_STOPPED) {
|
||||||
dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
|
dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
|
||||||
if (dirs) {
|
|
||||||
TAILQ_FOREACH (dir, dirs, entries) {
|
TAILQ_FOREACH (dir, dirs, entries) {
|
||||||
snprintf(file, sizeof(file),
|
snprintf(file, sizeof(file),
|
||||||
RC_SVCDIR "/scheduled/%s/%s",
|
RC_SVCDIR "/scheduled/%s/%s",
|
||||||
@ -639,13 +645,13 @@ RC_SERVICE rc_service_state(const char *service)
|
|||||||
}
|
}
|
||||||
rc_stringlist_free(dirs);
|
rc_stringlist_free(dirs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_state)
|
librc_hidden_def(rc_service_state)
|
||||||
|
|
||||||
char *rc_service_value_get(const char *service, const char *option)
|
char *
|
||||||
|
rc_service_value_get(const char *service, const char *option)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
@ -663,7 +669,8 @@ char *rc_service_value_get(const char *service, const char *option)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_value_get)
|
librc_hidden_def(rc_service_value_get)
|
||||||
|
|
||||||
bool rc_service_value_set(const char *service, const char *option,
|
bool
|
||||||
|
rc_service_value_set(const char *service, const char *option,
|
||||||
const char *value)
|
const char *value)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
@ -685,8 +692,8 @@ bool rc_service_value_set(const char *service, const char *option,
|
|||||||
librc_hidden_def(rc_service_value_set)
|
librc_hidden_def(rc_service_value_set)
|
||||||
|
|
||||||
|
|
||||||
bool rc_service_schedule_start(const char *service,
|
bool
|
||||||
const char *service_to_start)
|
rc_service_schedule_start(const char *service, const char *service_to_start)
|
||||||
{
|
{
|
||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
char *p = file;
|
char *p = file;
|
||||||
@ -703,15 +710,16 @@ bool rc_service_schedule_start(const char *service,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
init = rc_service_resolve(service_to_start);
|
init = rc_service_resolve(service_to_start);
|
||||||
snprintf(p, sizeof(file) - (p - file), "/%s", basename_c(service_to_start));
|
snprintf(p, sizeof(file) - (p - file),
|
||||||
|
"/%s", basename_c(service_to_start));
|
||||||
retval = (exists(file) || symlink(init, file) == 0);
|
retval = (exists(file) || symlink(init, file) == 0);
|
||||||
free(init);
|
free(init);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_schedule_start)
|
librc_hidden_def(rc_service_schedule_start)
|
||||||
|
|
||||||
bool rc_service_schedule_clear(const char *service)
|
bool
|
||||||
|
rc_service_schedule_clear(const char *service)
|
||||||
{
|
{
|
||||||
char dir[PATH_MAX];
|
char dir[PATH_MAX];
|
||||||
|
|
||||||
@ -723,10 +731,11 @@ bool rc_service_schedule_clear(const char *service)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_schedule_clear)
|
librc_hidden_def(rc_service_schedule_clear)
|
||||||
|
|
||||||
RC_STRINGLIST *rc_services_in_runlevel(const char *runlevel)
|
RC_STRINGLIST *
|
||||||
|
rc_services_in_runlevel(const char *runlevel)
|
||||||
{
|
{
|
||||||
char dir[PATH_MAX];
|
char dir[PATH_MAX];
|
||||||
RC_STRINGLIST *list;
|
RC_STRINGLIST *list = NULL;
|
||||||
|
|
||||||
if (!runlevel) {
|
if (!runlevel) {
|
||||||
#ifdef RC_PKG_INITDIR
|
#ifdef RC_PKG_INITDIR
|
||||||
@ -739,36 +748,32 @@ RC_STRINGLIST *rc_services_in_runlevel(const char *runlevel)
|
|||||||
list = ls_dir(RC_INITDIR, LS_INITD);
|
list = ls_dir(RC_INITDIR, LS_INITD);
|
||||||
|
|
||||||
#ifdef RC_PKG_INITDIR
|
#ifdef RC_PKG_INITDIR
|
||||||
if (pkg) {
|
|
||||||
TAILQ_CONCAT(list, pkg, entries);
|
TAILQ_CONCAT(list, pkg, entries);
|
||||||
free(pkg);
|
free(pkg);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef RC_LOCAL_INITDIR
|
#ifdef RC_LOCAL_INITDIR
|
||||||
if (local) {
|
|
||||||
TAILQ_CONCAT(list, local, entries);
|
TAILQ_CONCAT(list, local, entries);
|
||||||
free(local);
|
free(local);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These special levels never contain any services */
|
/* These special levels never contain any services */
|
||||||
if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0 ||
|
if (strcmp(runlevel, RC_LEVEL_SINGLE) != 0) {
|
||||||
strcmp(runlevel, RC_LEVEL_SINGLE) == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(dir, sizeof(dir), RC_RUNLEVELDIR "/%s", runlevel);
|
snprintf(dir, sizeof(dir), RC_RUNLEVELDIR "/%s", runlevel);
|
||||||
list = ls_dir(dir, LS_INITD);
|
list = ls_dir(dir, LS_INITD);
|
||||||
|
}
|
||||||
|
if (!list)
|
||||||
|
list = rc_stringlist_new();
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_services_in_runlevel)
|
librc_hidden_def(rc_services_in_runlevel)
|
||||||
|
|
||||||
RC_STRINGLIST *rc_services_in_state(RC_SERVICE state)
|
RC_STRINGLIST *
|
||||||
|
rc_services_in_state(RC_SERVICE state)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *services;
|
RC_STRINGLIST *services;
|
||||||
RC_STRINGLIST *list = NULL;
|
RC_STRINGLIST *list;
|
||||||
RC_STRINGLIST *dirs;
|
RC_STRINGLIST *dirs;
|
||||||
RC_STRING *d;
|
RC_STRING *d;
|
||||||
char dir[PATH_MAX];
|
char dir[PATH_MAX];
|
||||||
@ -780,28 +785,26 @@ RC_STRINGLIST *rc_services_in_state(RC_SERVICE state)
|
|||||||
if (state != RC_SERVICE_SCHEDULED)
|
if (state != RC_SERVICE_SCHEDULED)
|
||||||
return ls_dir(dir, LS_INITD);
|
return ls_dir(dir, LS_INITD);
|
||||||
|
|
||||||
|
|
||||||
dirs = ls_dir(dir, 0);
|
dirs = ls_dir(dir, 0);
|
||||||
|
list = rc_stringlist_new();
|
||||||
if (! dirs)
|
if (! dirs)
|
||||||
return NULL;
|
return list;
|
||||||
|
|
||||||
TAILQ_FOREACH(d, dirs, entries) {
|
TAILQ_FOREACH(d, dirs, entries) {
|
||||||
snprintf(p, sizeof(dir) - (p - dir), "/%s", d->value);
|
snprintf(p, sizeof(dir) - (p - dir), "/%s", d->value);
|
||||||
services = ls_dir(dir, LS_INITD);
|
services = ls_dir(dir, LS_INITD);
|
||||||
if (! list)
|
if (services) {
|
||||||
services = list;
|
|
||||||
else if (services) {
|
|
||||||
TAILQ_CONCAT(list, services, entries);
|
TAILQ_CONCAT(list, services, entries);
|
||||||
free(services);
|
free(services);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc_stringlist_free(dirs);
|
rc_stringlist_free(dirs);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_services_in_state)
|
librc_hidden_def(rc_services_in_state)
|
||||||
|
|
||||||
bool rc_service_add(const char *runlevel, const char *service)
|
bool
|
||||||
|
rc_service_add(const char *runlevel, const char *service)
|
||||||
{
|
{
|
||||||
bool retval;
|
bool retval;
|
||||||
char *init;
|
char *init;
|
||||||
@ -832,7 +835,6 @@ bool rc_service_add(const char *runlevel, const char *service)
|
|||||||
if (!*p) {
|
if (!*p) {
|
||||||
free(init);
|
free(init);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (strcmp(path, RC_INITDIR) != 0) {
|
if (strcmp(path, RC_INITDIR) != 0) {
|
||||||
free(init);
|
free(init);
|
||||||
@ -849,7 +851,8 @@ bool rc_service_add(const char *runlevel, const char *service)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_add)
|
librc_hidden_def(rc_service_add)
|
||||||
|
|
||||||
bool rc_service_delete (const char *runlevel, const char *service)
|
bool
|
||||||
|
rc_service_delete(const char *runlevel, const char *service)
|
||||||
{
|
{
|
||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
|
|
||||||
@ -861,32 +864,27 @@ bool rc_service_delete (const char *runlevel, const char *service)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_delete)
|
librc_hidden_def(rc_service_delete)
|
||||||
|
|
||||||
RC_STRINGLIST *rc_services_scheduled_by(const char *service)
|
RC_STRINGLIST *
|
||||||
|
rc_services_scheduled_by(const char *service)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
|
RC_STRINGLIST *dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
|
||||||
RC_STRINGLIST *list = NULL;
|
RC_STRINGLIST *list = rc_stringlist_new();
|
||||||
RC_STRING *dir;
|
RC_STRING *dir;
|
||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
|
|
||||||
if (! dirs)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
TAILQ_FOREACH (dir, dirs, entries) {
|
TAILQ_FOREACH (dir, dirs, entries) {
|
||||||
snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s/%s",
|
snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s/%s",
|
||||||
dir->value, service);
|
dir->value, service);
|
||||||
if (exists(file)) {
|
if (exists(file))
|
||||||
if (! list)
|
|
||||||
list = rc_stringlist_new();
|
|
||||||
rc_stringlist_add(list, file);
|
rc_stringlist_add(list, file);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
rc_stringlist_free(dirs);
|
rc_stringlist_free(dirs);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_services_scheduled_by)
|
librc_hidden_def(rc_services_scheduled_by)
|
||||||
|
|
||||||
RC_STRINGLIST *rc_services_scheduled(const char *service)
|
RC_STRINGLIST *
|
||||||
|
rc_services_scheduled(const char *service)
|
||||||
{
|
{
|
||||||
char dir[PATH_MAX];
|
char dir[PATH_MAX];
|
||||||
|
|
||||||
|
@ -48,7 +48,8 @@
|
|||||||
|
|
||||||
extern const char *applet;
|
extern const char *applet;
|
||||||
|
|
||||||
RC_DEPTREE *_rc_deptree_load(int *regen) {
|
RC_DEPTREE *
|
||||||
|
_rc_deptree_load(int *regen) {
|
||||||
int fd;
|
int fd;
|
||||||
int retval;
|
int retval;
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
@ -65,12 +66,10 @@ RC_DEPTREE *_rc_deptree_load(int *regen) {
|
|||||||
|
|
||||||
if (regen)
|
if (regen)
|
||||||
*regen = 1;
|
*regen = 1;
|
||||||
|
|
||||||
ebegin("Caching service dependencies");
|
ebegin("Caching service dependencies");
|
||||||
retval = rc_deptree_update();
|
retval = rc_deptree_update();
|
||||||
eend (retval ? 0 : -1, "Failed to update the dependency tree");
|
eend (retval ? 0 : -1, "Failed to update the dependency tree");
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc_deptree_load();
|
return rc_deptree_load();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +95,8 @@ static const char * const longopts_help[] = {
|
|||||||
};
|
};
|
||||||
#include "_usage.c"
|
#include "_usage.c"
|
||||||
|
|
||||||
int rc_depend(int argc, char **argv)
|
int
|
||||||
|
rc_depend(int argc, char **argv)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *list;
|
RC_STRINGLIST *list;
|
||||||
RC_STRINGLIST *types;
|
RC_STRINGLIST *types;
|
||||||
@ -112,7 +112,6 @@ int rc_depend(int argc, char **argv)
|
|||||||
char *token;
|
char *token;
|
||||||
|
|
||||||
types = rc_stringlist_new();
|
types = rc_stringlist_new();
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
{
|
||||||
@ -162,7 +161,8 @@ int rc_depend(int argc, char **argv)
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
depends = rc_deptree_depends(deptree, NULL, list, runlevel, 0);
|
depends = rc_deptree_depends(deptree, NULL, list, runlevel, 0);
|
||||||
if (!depends && errno == ENOENT)
|
if (!depends && errno == ENOENT)
|
||||||
eerror("no dependency info for service `%s'", argv[optind]);
|
eerror("no dependency info for service `%s'",
|
||||||
|
argv[optind]);
|
||||||
else
|
else
|
||||||
rc_stringlist_add(services, argv[optind]);
|
rc_stringlist_add(services, argv[optind]);
|
||||||
|
|
||||||
@ -186,7 +186,8 @@ int rc_depend(int argc, char **argv)
|
|||||||
rc_stringlist_add(types, "iuse");
|
rc_stringlist_add(types, "iuse");
|
||||||
}
|
}
|
||||||
|
|
||||||
depends = rc_deptree_depends(deptree, types, services, runlevel, options);
|
depends = rc_deptree_depends(deptree, types, services,
|
||||||
|
runlevel, options);
|
||||||
|
|
||||||
if (TAILQ_FIRST(depends)) {
|
if (TAILQ_FIRST(depends)) {
|
||||||
TAILQ_FOREACH(s, depends, entries) {
|
TAILQ_FOREACH(s, depends, entries) {
|
||||||
|
@ -62,13 +62,15 @@ static RC_STRINGLIST *rc_conf = NULL;
|
|||||||
extern char** environ;
|
extern char** environ;
|
||||||
|
|
||||||
#ifdef DEBUG_MEMORY
|
#ifdef DEBUG_MEMORY
|
||||||
static void _free_rc_conf(void)
|
static void
|
||||||
|
_free_rc_conf(void)
|
||||||
{
|
{
|
||||||
rc_stringlist_free(rc_conf);
|
rc_stringlist_free(rc_conf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *rc_conf_value(const char *setting)
|
char *
|
||||||
|
rc_conf_value(const char *setting)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *old;
|
RC_STRINGLIST *old;
|
||||||
RC_STRING *s;
|
RC_STRING *s;
|
||||||
@ -83,17 +85,13 @@ char *rc_conf_value(const char *setting)
|
|||||||
/* Support old configs */
|
/* Support old configs */
|
||||||
if (exists(RC_CONF_OLD)) {
|
if (exists(RC_CONF_OLD)) {
|
||||||
old = rc_config_load(RC_CONF_OLD);
|
old = rc_config_load(RC_CONF_OLD);
|
||||||
if (old) {
|
|
||||||
if (rc_conf) {
|
|
||||||
TAILQ_CONCAT(rc_conf, old, entries);
|
TAILQ_CONCAT(rc_conf, old, entries);
|
||||||
|
#ifdef DEBUG_MEMORY
|
||||||
free(old);
|
free(old);
|
||||||
} else
|
#endif
|
||||||
rc_conf = old;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert old uppercase to lowercase */
|
/* Convert old uppercase to lowercase */
|
||||||
if (rc_conf)
|
|
||||||
TAILQ_FOREACH(s, rc_conf, entries) {
|
TAILQ_FOREACH(s, rc_conf, entries) {
|
||||||
p = s->value;
|
p = s->value;
|
||||||
while (p && *p && *p != '=') {
|
while (p && *p && *p != '=') {
|
||||||
@ -107,7 +105,8 @@ char *rc_conf_value(const char *setting)
|
|||||||
return rc_config_value(rc_conf, setting);
|
return rc_config_value(rc_conf, setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rc_conf_yesno(const char *setting)
|
bool
|
||||||
|
rc_conf_yesno(const char *setting)
|
||||||
{
|
{
|
||||||
return rc_yesno(rc_conf_value (setting));
|
return rc_yesno(rc_conf_value (setting));
|
||||||
}
|
}
|
||||||
@ -122,10 +121,11 @@ static const char *const env_whitelist[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
void env_filter(void)
|
void
|
||||||
|
env_filter(void)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *env_allow;
|
RC_STRINGLIST *env_allow;
|
||||||
RC_STRINGLIST *profile = NULL;
|
RC_STRINGLIST *profile;
|
||||||
RC_STRINGLIST *env_list;
|
RC_STRINGLIST *env_list;
|
||||||
RC_STRING *env;
|
RC_STRING *env;
|
||||||
char *e;
|
char *e;
|
||||||
@ -133,7 +133,6 @@ void env_filter(void)
|
|||||||
|
|
||||||
/* Add the user defined list of vars */
|
/* Add the user defined list of vars */
|
||||||
env_allow = rc_stringlist_split(rc_conf_value("rc_env_allow"), " ");
|
env_allow = rc_stringlist_split(rc_conf_value("rc_env_allow"), " ");
|
||||||
if (exists(PROFILE_ENV))
|
|
||||||
profile = rc_config_load(PROFILE_ENV);
|
profile = rc_config_load(PROFILE_ENV);
|
||||||
|
|
||||||
/* Copy the env and work from this so we can manipulate it safely */
|
/* Copy the env and work from this so we can manipulate it safely */
|
||||||
@ -163,21 +162,22 @@ void env_filter(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Now add anything missing from the profile */
|
/* Now add anything missing from the profile */
|
||||||
if (profile) {
|
|
||||||
TAILQ_FOREACH(env, profile, entries) {
|
TAILQ_FOREACH(env, profile, entries) {
|
||||||
e = strchr(env->value, '=');
|
e = strchr(env->value, '=');
|
||||||
*e = '\0';
|
*e = '\0';
|
||||||
if (!getenv(env->value))
|
if (!getenv(env->value))
|
||||||
setenv(env->value, e + 1, 1);
|
setenv(env->value, e + 1, 1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_MEMORY
|
||||||
rc_stringlist_free(env_list);
|
rc_stringlist_free(env_list);
|
||||||
rc_stringlist_free(env_allow);
|
rc_stringlist_free(env_allow);
|
||||||
rc_stringlist_free(profile);
|
rc_stringlist_free(profile);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void env_config(void)
|
void
|
||||||
|
env_config(void)
|
||||||
{
|
{
|
||||||
size_t pplen = strlen(PATH_PREFIX);
|
size_t pplen = strlen(PATH_PREFIX);
|
||||||
char *path;
|
char *path;
|
||||||
@ -203,7 +203,8 @@ void env_config(void)
|
|||||||
e = p = xmalloc(sizeof(char) * l);
|
e = p = xmalloc(sizeof(char) * l);
|
||||||
p += snprintf(p, l, "%s", PATH_PREFIX);
|
p += snprintf(p, l, "%s", PATH_PREFIX);
|
||||||
|
|
||||||
/* Now go through the env var and only add bits not in our PREFIX */
|
/* Now go through the env var and only add bits not in our
|
||||||
|
* PREFIX */
|
||||||
while ((token = strsep(&path, ":"))) {
|
while ((token = strsep(&path, ":"))) {
|
||||||
np = npp = xstrdup(PATH_PREFIX);
|
np = npp = xstrdup(PATH_PREFIX);
|
||||||
while ((tok = strsep(&npp, ":")))
|
while ((tok = strsep(&npp, ":")))
|
||||||
@ -259,48 +260,8 @@ void env_config(void)
|
|||||||
setenv("EINFO_COLOR", "NO", 1);
|
setenv("EINFO_COLOR", "NO", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool service_plugable(const char *service)
|
int
|
||||||
{
|
signal_setup(int sig, void (*handler)(int))
|
||||||
char *list;
|
|
||||||
char *p;
|
|
||||||
char *star;
|
|
||||||
char *token;
|
|
||||||
bool allow = true;
|
|
||||||
char *match = rc_conf_value("rc_plug_services");
|
|
||||||
bool truefalse;
|
|
||||||
|
|
||||||
if (! match)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
list = xstrdup(match);
|
|
||||||
p = list;
|
|
||||||
while ((token = strsep(&p, " "))) {
|
|
||||||
if (token[0] == '!') {
|
|
||||||
truefalse = false;
|
|
||||||
token++;
|
|
||||||
} else
|
|
||||||
truefalse = true;
|
|
||||||
|
|
||||||
star = strchr(token, '*');
|
|
||||||
if (star) {
|
|
||||||
if (strncmp(service, token, (size_t)(star - token)) == 0)
|
|
||||||
{
|
|
||||||
allow = truefalse;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (strcmp(service, token) == 0) {
|
|
||||||
allow = truefalse;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(list);
|
|
||||||
return allow;
|
|
||||||
}
|
|
||||||
|
|
||||||
int signal_setup(int sig, void (*handler)(int))
|
|
||||||
{
|
{
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
@ -310,7 +271,8 @@ int signal_setup(int sig, void (*handler)(int))
|
|||||||
return sigaction(sig, &sa, NULL);
|
return sigaction(sig, &sa, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t exec_service(const char *service, const char *arg)
|
pid_t
|
||||||
|
exec_service(const char *service, const char *arg)
|
||||||
{
|
{
|
||||||
char *file;
|
char *file;
|
||||||
char fifo[PATH_MAX];
|
char fifo[PATH_MAX];
|
||||||
@ -368,7 +330,6 @@ pid_t exec_service(const char *service, const char *arg)
|
|||||||
sigprocmask(SIG_SETMASK, &old, NULL);
|
sigprocmask(SIG_SETMASK, &old, NULL);
|
||||||
|
|
||||||
free(file);
|
free(file);
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,8 @@ static const char * const longopts_help[] = {
|
|||||||
};
|
};
|
||||||
#include "_usage.c"
|
#include "_usage.c"
|
||||||
|
|
||||||
int rc_service(int argc, char **argv)
|
int
|
||||||
|
rc_service(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
char *service;
|
char *service;
|
||||||
@ -75,17 +76,21 @@ int rc_service(int argc, char **argv)
|
|||||||
case 'e':
|
case 'e':
|
||||||
service = rc_service_resolve(optarg);
|
service = rc_service_resolve(optarg);
|
||||||
opt = service ? EXIT_SUCCESS : EXIT_FAILURE;
|
opt = service ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
#ifdef DEBUG_MEMORY
|
||||||
free(service);
|
free(service);
|
||||||
|
#endif
|
||||||
return opt;
|
return opt;
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
case 'l':
|
case 'l':
|
||||||
list = rc_services_in_runlevel(NULL);
|
list = rc_services_in_runlevel(NULL);
|
||||||
if (! list)
|
if (!TAILQ_FIRST(list))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
rc_stringlist_sort(&list);
|
rc_stringlist_sort(&list);
|
||||||
TAILQ_FOREACH(s, list, entries)
|
TAILQ_FOREACH(s, list, entries)
|
||||||
printf("%s\n", s->value);
|
printf("%s\n", s->value);
|
||||||
|
#ifdef DEBUG_MEMORY
|
||||||
rc_stringlist_free(list);
|
rc_stringlist_free(list);
|
||||||
|
#endif
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
case 'r':
|
case 'r':
|
||||||
@ -93,7 +98,9 @@ int rc_service(int argc, char **argv)
|
|||||||
if (!service)
|
if (!service)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
printf("%s\n", service);
|
printf("%s\n", service);
|
||||||
|
#ifdef DEBUG_MEMORY
|
||||||
free(service);
|
free(service);
|
||||||
|
#endif
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
|
||||||
@ -103,13 +110,10 @@ int rc_service(int argc, char **argv)
|
|||||||
|
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
if (!*argv)
|
if (!*argv)
|
||||||
eerrorx("%s: you need to specify a service", applet);
|
eerrorx("%s: you need to specify a service", applet);
|
||||||
|
|
||||||
if (!(service = rc_service_resolve(*argv)))
|
if (!(service = rc_service_resolve(*argv)))
|
||||||
eerrorx("%s: service `%s' does not exist", applet, *argv);
|
eerrorx("%s: service `%s' does not exist", applet, *argv);
|
||||||
|
|
||||||
*argv = service;
|
*argv = service;
|
||||||
execv(*argv, argv);
|
execv(*argv, argv);
|
||||||
eerrorx("%s: %s", applet, strerror(errno));
|
eerrorx("%s: %s", applet, strerror(errno));
|
||||||
|
193
src/rc/rc.c
193
src/rc/rc.c
@ -43,12 +43,6 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
|
|||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
/* So we can coldplug net devices */
|
|
||||||
#ifdef BSD
|
|
||||||
# include <sys/socket.h>
|
|
||||||
# include <ifaddrs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
# include <asm/setup.h> /* for COMMAND_LINE_SIZE */
|
# include <asm/setup.h> /* for COMMAND_LINE_SIZE */
|
||||||
#endif
|
#endif
|
||||||
@ -519,115 +513,10 @@ static void handle_signal(int sig)
|
|||||||
errno = serrno;
|
errno = serrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_coldplug(void)
|
|
||||||
{
|
|
||||||
size_t l;
|
|
||||||
DIR *dp;
|
|
||||||
struct dirent *d;
|
|
||||||
char *service;
|
|
||||||
RC_STRING *s;
|
|
||||||
#ifdef BSD
|
|
||||||
struct ifaddrs *ifap;
|
|
||||||
struct ifaddrs *ifa;
|
|
||||||
char *p;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
if (!rc_conf_yesno("rc_coldplug") && errno != ENOENT)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* We need to ensure our state dirs exist.
|
|
||||||
* We should have a better call than this, but oh well. */
|
|
||||||
rc_deptree_update_needed();
|
|
||||||
|
|
||||||
#ifdef BSD
|
|
||||||
if (getifaddrs(&ifap) == 0) {
|
|
||||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
|
|
||||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
l = strlen("net.") + strlen(ifa->ifa_name) + 1;
|
|
||||||
service = xmalloc(sizeof (char) * l);
|
|
||||||
snprintf(service, l, "net.%s", ifa->ifa_name);
|
|
||||||
if (rc_service_exists(service) &&
|
|
||||||
service_plugable(service))
|
|
||||||
rc_service_mark(service, RC_SERVICE_COLDPLUGGED);
|
|
||||||
free(service);
|
|
||||||
}
|
|
||||||
freeifaddrs (ifap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The mice are a little more tricky.
|
|
||||||
* If we coldplug anything else, we'll probably do it here. */
|
|
||||||
if ((dp = opendir("/dev"))) {
|
|
||||||
while ((d = readdir(dp))) {
|
|
||||||
if (strncmp(d->d_name, "psm", 3) == 0 ||
|
|
||||||
strncmp(d->d_name, "ums", 3) == 0)
|
|
||||||
{
|
|
||||||
p = d->d_name + 3;
|
|
||||||
if (p && isdigit((unsigned char)*p)) {
|
|
||||||
l = strlen("moused.") + strlen(d->d_name) + 1;
|
|
||||||
service = xmalloc(sizeof(char) * l);
|
|
||||||
snprintf (service, l, "moused.%s", d->d_name);
|
|
||||||
if (rc_service_exists (service) &&
|
|
||||||
service_plugable (service))
|
|
||||||
rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
|
|
||||||
free(service);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir (dp);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* udev likes to start services before we're ready when it does
|
|
||||||
* its coldplugging thing. runscript knows when we're not ready so it
|
|
||||||
* stores a list of coldplugged services in DEVBOOT for us to pick up
|
|
||||||
* here when we are ready for them */
|
|
||||||
if ((dp = opendir(DEVBOOT))) {
|
|
||||||
while ((d = readdir(dp))) {
|
|
||||||
if (d->d_name[0] == '.' &&
|
|
||||||
(d->d_name[1] == '\0' ||
|
|
||||||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rc_service_exists(d->d_name) &&
|
|
||||||
service_plugable(d->d_name))
|
|
||||||
rc_service_mark(d->d_name, RC_SERVICE_COLDPLUGGED);
|
|
||||||
|
|
||||||
l = strlen(DEVBOOT "/") + strlen(d->d_name) + 1;
|
|
||||||
service = xmalloc(sizeof (char) * l);
|
|
||||||
snprintf(service, l, DEVBOOT "/%s", d->d_name);
|
|
||||||
if (unlink(service))
|
|
||||||
eerror("%s: unlink `%s': %s", applet, service,
|
|
||||||
strerror(errno));
|
|
||||||
free(service);
|
|
||||||
}
|
|
||||||
closedir(dp);
|
|
||||||
rmdir(DEVBOOT);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (rc_yesno(getenv("EINFO_QUIET")))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Load our list of coldplugged services and display them */
|
|
||||||
einfon("Device initiated services:%s", ecolor(ECOLOR_HILITE));
|
|
||||||
coldplugged_services = rc_services_in_state(RC_SERVICE_COLDPLUGGED);
|
|
||||||
if (coldplugged_services)
|
|
||||||
TAILQ_FOREACH(s, coldplugged_services, entries)
|
|
||||||
printf(" %s", s->value);
|
|
||||||
printf("%s\n", ecolor(ECOLOR_NORMAL));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_newlevel(const char *newlevel)
|
static void do_newlevel(const char *newlevel)
|
||||||
{
|
{
|
||||||
struct utsname uts;
|
struct utsname uts;
|
||||||
const char *sys;
|
const char *sys;
|
||||||
#ifdef __linux__
|
|
||||||
char *cmd;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (strcmp(newlevel, RC_LEVEL_SYSINIT) == 0
|
if (strcmp(newlevel, RC_LEVEL_SYSINIT) == 0
|
||||||
#ifndef PREFIX
|
#ifndef PREFIX
|
||||||
@ -669,39 +558,13 @@ static void do_newlevel(const char *newlevel)
|
|||||||
ecolor(ECOLOR_GOOD), ecolor(ECOLOR_NORMAL));
|
ecolor(ECOLOR_GOOD), ecolor(ECOLOR_NORMAL));
|
||||||
|
|
||||||
setenv("RC_RUNLEVEL", newlevel, 1);
|
setenv("RC_RUNLEVEL", newlevel, 1);
|
||||||
rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, newlevel);
|
|
||||||
hook_out = RC_HOOK_RUNLEVEL_START_OUT;
|
|
||||||
run_program(INITSH);
|
run_program(INITSH);
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
/* If we requested a runlevel, save it now */
|
|
||||||
if ((cmd = proc_getent("rc_runlevel"))) {
|
|
||||||
set_krunlevel(cmd);
|
|
||||||
free(cmd);
|
|
||||||
} else if ((cmd = proc_getent("softlevel"))) {
|
|
||||||
set_krunlevel(cmd);
|
|
||||||
free(cmd);
|
|
||||||
} else
|
|
||||||
set_krunlevel(NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Setup our coldplugged services now */
|
|
||||||
do_coldplug();
|
|
||||||
|
|
||||||
rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, newlevel);
|
|
||||||
hook_out = 0;
|
|
||||||
|
|
||||||
if (want_interactive())
|
|
||||||
mark_interactive();
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
} else if (strcmp(newlevel, RC_LEVEL_SINGLE) == 0) {
|
} else if (strcmp(newlevel, RC_LEVEL_SINGLE) == 0) {
|
||||||
#ifndef PREFIX
|
#ifndef PREFIX
|
||||||
if (! RUNLEVEL ||
|
if (! RUNLEVEL ||
|
||||||
(strcmp(RUNLEVEL, "S") != 0 &&
|
(strcmp(RUNLEVEL, "S") != 0 &&
|
||||||
strcmp(RUNLEVEL, "1") != 0))
|
strcmp(RUNLEVEL, "1") != 0))
|
||||||
{
|
{
|
||||||
/* Remember the current runlevel for when we come back */
|
|
||||||
set_krunlevel(runlevel);
|
set_krunlevel(runlevel);
|
||||||
single_user();
|
single_user();
|
||||||
}
|
}
|
||||||
@ -883,7 +746,12 @@ interactive_option:
|
|||||||
if (! parallel) {
|
if (! parallel) {
|
||||||
rc_waitpid(pid);
|
rc_waitpid(pid);
|
||||||
remove_pid(pid);
|
remove_pid(pid);
|
||||||
|
/* Attempt to open the logger as a service may
|
||||||
|
* mount the needed /dev/pts for this to work */
|
||||||
|
if (rc_logger_tty == -1)
|
||||||
|
rc_logger_open(runlevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1076,7 +944,8 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
/* Try not to join boot and krunlevels together */
|
/* Try not to join boot and krunlevels together */
|
||||||
if (! newlevel ||
|
if (! newlevel ||
|
||||||
strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0)
|
(strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0 &&
|
||||||
|
strcmp(newlevel, RC_LEVEL_SYSINIT) != 0))
|
||||||
if (get_krunlevel(krunlevel, sizeof(krunlevel)))
|
if (get_krunlevel(krunlevel, sizeof(krunlevel)))
|
||||||
newlevel = krunlevel;
|
newlevel = krunlevel;
|
||||||
} else if (! RUNLEVEL ||
|
} else if (! RUNLEVEL ||
|
||||||
@ -1135,21 +1004,11 @@ int main(int argc, char **argv)
|
|||||||
* correct order for stopping them */
|
* correct order for stopping them */
|
||||||
stop_services = rc_services_in_state(RC_SERVICE_STARTED);
|
stop_services = rc_services_in_state(RC_SERVICE_STARTED);
|
||||||
tmplist = rc_services_in_state(RC_SERVICE_INACTIVE);
|
tmplist = rc_services_in_state(RC_SERVICE_INACTIVE);
|
||||||
if (tmplist) {
|
|
||||||
if (stop_services) {
|
|
||||||
TAILQ_CONCAT(stop_services, tmplist, entries);
|
TAILQ_CONCAT(stop_services, tmplist, entries);
|
||||||
free(tmplist);
|
free(tmplist);
|
||||||
} else
|
|
||||||
stop_services = tmplist;
|
|
||||||
}
|
|
||||||
tmplist = rc_services_in_state(RC_SERVICE_STARTING);
|
tmplist = rc_services_in_state(RC_SERVICE_STARTING);
|
||||||
if (tmplist) {
|
|
||||||
if (stop_services) {
|
|
||||||
TAILQ_CONCAT(stop_services, tmplist, entries);
|
TAILQ_CONCAT(stop_services, tmplist, entries);
|
||||||
free(tmplist);
|
free(tmplist);
|
||||||
} else
|
|
||||||
stop_services = tmplist;
|
|
||||||
}
|
|
||||||
if (stop_services)
|
if (stop_services)
|
||||||
rc_stringlist_sort(&stop_services);
|
rc_stringlist_sort(&stop_services);
|
||||||
|
|
||||||
@ -1171,17 +1030,22 @@ int main(int argc, char **argv)
|
|||||||
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
|
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
|
||||||
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
|
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
|
||||||
{
|
{
|
||||||
/* We need to include the boot runlevel services if we're not in it */
|
start_services = rc_services_in_runlevel(RC_LEVEL_SYSINIT);
|
||||||
start_services = rc_services_in_runlevel(bootlevel);
|
if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT)
|
||||||
if (strcmp (newlevel ? newlevel : runlevel, bootlevel) != 0) {
|
!= 0)
|
||||||
tmplist = rc_services_in_runlevel(newlevel ? newlevel : runlevel);
|
{
|
||||||
if (tmplist) {
|
/* We need to include the boot runlevel services */
|
||||||
if (start_services) {
|
tmplist = rc_services_in_runlevel(bootlevel);
|
||||||
|
TAILQ_CONCAT(start_services, tmplist, entries);
|
||||||
|
free(tmplist);
|
||||||
|
if (strcmp (newlevel ? newlevel : runlevel, bootlevel)
|
||||||
|
!= 0)
|
||||||
|
{
|
||||||
|
tmplist = rc_services_in_runlevel(newlevel ?
|
||||||
|
newlevel :
|
||||||
|
runlevel);
|
||||||
TAILQ_CONCAT(start_services, tmplist, entries);
|
TAILQ_CONCAT(start_services, tmplist, entries);
|
||||||
free(tmplist);
|
free(tmplist);
|
||||||
} else
|
|
||||||
start_services = tmplist;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coldplugged_services) {
|
if (coldplugged_services) {
|
||||||
@ -1191,6 +1055,7 @@ int main(int argc, char **argv)
|
|||||||
rc_stringlist_addu(start_services, service->value);
|
rc_stringlist_addu(start_services, service->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parallel = rc_conf_yesno("rc_parallel");
|
parallel = rc_conf_yesno("rc_parallel");
|
||||||
|
|
||||||
@ -1265,14 +1130,15 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (start_services) {
|
if (start_services) {
|
||||||
do_start_services(parallel);
|
do_start_services(parallel);
|
||||||
|
/* FIXME: If we skip the boot runlevel and go straight
|
||||||
|
* to default from sysinit, we should now re-evaluate our
|
||||||
|
* start services + coldplugged services and call
|
||||||
|
* do_start_services a second time. */
|
||||||
|
|
||||||
/* Wait for our services to finish */
|
/* Wait for our services to finish */
|
||||||
wait_for_services();
|
wait_for_services();
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel);
|
|
||||||
hook_out = 0;
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
/* mark any services skipped as stopped */
|
/* mark any services skipped as stopped */
|
||||||
if (PREVLEVEL && strcmp(PREVLEVEL, "N") == 0) {
|
if (PREVLEVEL && strcmp(PREVLEVEL, "N") == 0) {
|
||||||
@ -1285,12 +1151,15 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel);
|
||||||
|
hook_out = 0;
|
||||||
|
|
||||||
/* If we're in the boot runlevel and we regenerated our dependencies
|
/* If we're in the boot runlevel and we regenerated our dependencies
|
||||||
* we need to delete them so that they are regenerated again in the
|
* we need to delete them so that they are regenerated again in the
|
||||||
* default runlevel as they may depend on things that are now available */
|
* default runlevel as they may depend on things that are now
|
||||||
|
* available */
|
||||||
if (regen && strcmp(runlevel, bootlevel) == 0)
|
if (regen && strcmp(runlevel, bootlevel) == 0)
|
||||||
unlink(RC_DEPTREE_CACHE);
|
unlink(RC_DEPTREE_CACHE);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,9 +108,8 @@ static RC_STRINGLIST *types_mua = NULL;
|
|||||||
static void (*selinux_run_init_old)(void);
|
static void (*selinux_run_init_old)(void);
|
||||||
static void (*selinux_run_init_new)(int argc, char **argv);
|
static void (*selinux_run_init_new)(int argc, char **argv);
|
||||||
|
|
||||||
static void setup_selinux(int argc, char **argv);
|
static void
|
||||||
|
setup_selinux(int argc, char **argv)
|
||||||
static void setup_selinux(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
void *lib_handle = NULL;
|
void *lib_handle = NULL;
|
||||||
|
|
||||||
@ -141,7 +140,8 @@ static void setup_selinux(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void handle_signal(int sig)
|
static void
|
||||||
|
handle_signal(int sig)
|
||||||
{
|
{
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
char signame[10] = { '\0' };
|
char signame[10] = { '\0' };
|
||||||
@ -155,7 +155,8 @@ static void handle_signal(int sig)
|
|||||||
case SIGCHLD:
|
case SIGCHLD:
|
||||||
if (signal_pipe[1] > -1) {
|
if (signal_pipe[1] > -1) {
|
||||||
if (write(signal_pipe[1], &sig, sizeof(sig)) == -1)
|
if (write(signal_pipe[1], &sig, sizeof(sig)) == -1)
|
||||||
eerror("%s: send: %s", service, strerror(errno));
|
eerror("%s: send: %s",
|
||||||
|
service, strerror(errno));
|
||||||
} else
|
} else
|
||||||
rc_waitpid(-1);
|
rc_waitpid(-1);
|
||||||
break;
|
break;
|
||||||
@ -192,18 +193,17 @@ static void handle_signal(int sig)
|
|||||||
errno = serrno;
|
errno = serrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
static time_t get_mtime(const char *pathname, bool follow_link)
|
static time_t
|
||||||
|
get_mtime(const char *pathname, bool follow_link)
|
||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (!pathname)
|
if (!pathname)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
retval = follow_link ? stat(pathname, &buf) : lstat(pathname, &buf);
|
retval = follow_link ? stat(pathname, &buf) : lstat(pathname, &buf);
|
||||||
if (!retval)
|
if (!retval)
|
||||||
return buf.st_mtime;
|
return buf.st_mtime;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -211,7 +211,8 @@ static time_t get_mtime(const char *pathname, bool follow_link)
|
|||||||
static const char *const tests[] = {
|
static const char *const tests[] = {
|
||||||
"starting", "started", "stopping", "inactive", "wasinactive", NULL
|
"starting", "started", "stopping", "inactive", "wasinactive", NULL
|
||||||
};
|
};
|
||||||
static bool in_control()
|
static bool
|
||||||
|
in_control()
|
||||||
{
|
{
|
||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
time_t m;
|
time_t m;
|
||||||
@ -231,7 +232,8 @@ static bool in_control()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (tests[i]) {
|
while (tests[i]) {
|
||||||
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", tests[i], applet);
|
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
|
||||||
|
tests[i], applet);
|
||||||
if (exists(file)) {
|
if (exists(file)) {
|
||||||
m = get_mtime(file, false);
|
m = get_mtime(file, false);
|
||||||
if (mtime < m && m != 0)
|
if (mtime < m && m != 0)
|
||||||
@ -243,7 +245,8 @@ static bool in_control()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uncoldplug()
|
static void
|
||||||
|
uncoldplug()
|
||||||
{
|
{
|
||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
|
|
||||||
@ -252,7 +255,9 @@ static void uncoldplug()
|
|||||||
eerror("%s: unlink `%s': %s", applet, file, strerror(errno));
|
eerror("%s: unlink `%s': %s", applet, file, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void start_services(RC_STRINGLIST *list) {
|
static void
|
||||||
|
start_services(RC_STRINGLIST *list)
|
||||||
|
{
|
||||||
RC_STRING *svc;
|
RC_STRING *svc;
|
||||||
RC_SERVICE state = rc_service_state (service);
|
RC_SERVICE state = rc_service_state (service);
|
||||||
|
|
||||||
@ -265,11 +270,14 @@ static void start_services(RC_STRINGLIST *list) {
|
|||||||
state & RC_SERVICE_STARTED)
|
state & RC_SERVICE_STARTED)
|
||||||
{
|
{
|
||||||
TAILQ_FOREACH(svc, list, entries) {
|
TAILQ_FOREACH(svc, list, entries) {
|
||||||
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) {
|
if (!(rc_service_state(svc->value) &
|
||||||
|
RC_SERVICE_STOPPED))
|
||||||
|
continue;
|
||||||
if (state & RC_SERVICE_INACTIVE ||
|
if (state & RC_SERVICE_INACTIVE ||
|
||||||
state & RC_SERVICE_WASINACTIVE)
|
state & RC_SERVICE_WASINACTIVE)
|
||||||
{
|
{
|
||||||
rc_service_schedule_start(service, svc->value);
|
rc_service_schedule_start(service,
|
||||||
|
svc->value);
|
||||||
ewarn("WARNING: %s is scheduled to started"
|
ewarn("WARNING: %s is scheduled to started"
|
||||||
" when %s has started",
|
" when %s has started",
|
||||||
svc->value, applet);
|
svc->value, applet);
|
||||||
@ -278,15 +286,14 @@ static void start_services(RC_STRINGLIST *list) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void restore_state(void)
|
static void
|
||||||
|
restore_state(void)
|
||||||
{
|
{
|
||||||
RC_SERVICE state;
|
RC_SERVICE state;
|
||||||
|
|
||||||
if (rc_in_plugin || !in_control())
|
if (rc_in_plugin || !in_control())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
state = rc_service_state(applet);
|
state = rc_service_state(applet);
|
||||||
if (state & RC_SERVICE_STOPPING) {
|
if (state & RC_SERVICE_STOPPING) {
|
||||||
if (state & RC_SERVICE_WASINACTIVE)
|
if (state & RC_SERVICE_WASINACTIVE)
|
||||||
@ -310,7 +317,8 @@ static void restore_state(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup(void)
|
static void
|
||||||
|
cleanup(void)
|
||||||
{
|
{
|
||||||
restore_state();
|
restore_state();
|
||||||
|
|
||||||
@ -318,9 +326,11 @@ static void cleanup(void)
|
|||||||
if (hook_out) {
|
if (hook_out) {
|
||||||
rc_plugin_run(hook_out, applet);
|
rc_plugin_run(hook_out, applet);
|
||||||
if (hook_out == RC_HOOK_SERVICE_START_DONE)
|
if (hook_out == RC_HOOK_SERVICE_START_DONE)
|
||||||
rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet);
|
rc_plugin_run(RC_HOOK_SERVICE_START_OUT,
|
||||||
|
applet);
|
||||||
else if (hook_out == RC_HOOK_SERVICE_STOP_DONE)
|
else if (hook_out == RC_HOOK_SERVICE_STOP_DONE)
|
||||||
rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet);
|
rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT,
|
||||||
|
applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restart_services)
|
if (restart_services)
|
||||||
@ -353,7 +363,9 @@ static void cleanup(void)
|
|||||||
unlink(mtime_test);
|
unlink(mtime_test);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) {
|
static int
|
||||||
|
write_prefix(const char *buffer, size_t bytes, bool *prefixed)
|
||||||
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
const char *ec = ecolor(ECOLOR_HILITE);
|
const char *ec = ecolor(ECOLOR_HILITE);
|
||||||
const char *ec_normal = ecolor(ECOLOR_NORMAL);
|
const char *ec_normal = ecolor(ECOLOR_NORMAL);
|
||||||
@ -389,11 +401,11 @@ static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) {
|
|||||||
|
|
||||||
/* Release the lock */
|
/* Release the lock */
|
||||||
close(lock_fd);
|
close(lock_fd);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool svc_exec(const char *arg1, const char *arg2)
|
static bool
|
||||||
|
svc_exec(const char *arg1, const char *arg2)
|
||||||
{
|
{
|
||||||
bool execok;
|
bool execok;
|
||||||
int fdout = fileno(stdout);
|
int fdout = fileno(stdout);
|
||||||
@ -430,7 +442,6 @@ static bool svc_exec(const char *arg1, const char *arg2)
|
|||||||
/* If the below call fails due to not enough ptys then we don't
|
/* If the below call fails due to not enough ptys then we don't
|
||||||
* prefix the output, but we still work */
|
* prefix the output, but we still work */
|
||||||
openpty(&master_tty, &slave_tty, NULL, &tt, &ws);
|
openpty(&master_tty, &slave_tty, NULL, &tt, &ws);
|
||||||
|
|
||||||
if (master_tty >= 0 &&
|
if (master_tty >= 0 &&
|
||||||
(flags = fcntl(master_tty, F_GETFD, 0)) == 0)
|
(flags = fcntl(master_tty, F_GETFD, 0)) == 0)
|
||||||
fcntl(master_tty, F_SETFD, flags | FD_CLOEXEC);
|
fcntl(master_tty, F_SETFD, flags | FD_CLOEXEC);
|
||||||
@ -450,13 +461,15 @@ static bool svc_exec(const char *arg1, const char *arg2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (exists(RC_SVCDIR "/runscript.sh")) {
|
if (exists(RC_SVCDIR "/runscript.sh")) {
|
||||||
execl(RC_SVCDIR "/runscript.sh", RC_SVCDIR "/runscript.sh",
|
execl(RC_SVCDIR "/runscript.sh",
|
||||||
|
RC_SVCDIR "/runscript.sh",
|
||||||
service, arg1, arg2, (char *) NULL);
|
service, arg1, arg2, (char *) NULL);
|
||||||
eerror("%s: exec `" RC_SVCDIR "/runscript.sh': %s",
|
eerror("%s: exec `" RC_SVCDIR "/runscript.sh': %s",
|
||||||
service, strerror(errno));
|
service, strerror(errno));
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
} else {
|
} else {
|
||||||
execl(RC_LIBDIR "/sh/runscript.sh", RC_LIBDIR "/sh/runscript.sh",
|
execl(RC_LIBDIR "/sh/runscript.sh",
|
||||||
|
RC_LIBDIR "/sh/runscript.sh",
|
||||||
service, arg1, arg2, (char *) NULL);
|
service, arg1, arg2, (char *) NULL);
|
||||||
eerror("%s: exec `" RC_LIBDIR "/sh/runscript.sh': %s",
|
eerror("%s: exec `" RC_LIBDIR "/sh/runscript.sh': %s",
|
||||||
service, strerror(errno));
|
service, strerror(errno));
|
||||||
@ -474,7 +487,8 @@ static bool svc_exec(const char *arg1, const char *arg2)
|
|||||||
|
|
||||||
if ((s = select(selfd, &rset, NULL, NULL, NULL)) == -1) {
|
if ((s = select(selfd, &rset, NULL, NULL, NULL)) == -1) {
|
||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
eerror("%s: select: %s", service, strerror(errno));
|
eerror("%s: select: %s", service,
|
||||||
|
strerror(errno));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -509,7 +523,8 @@ static bool svc_exec(const char *arg1, const char *arg2)
|
|||||||
return execok;
|
return execok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool svc_wait(const char *svc)
|
static bool
|
||||||
|
svc_wait(const char *svc)
|
||||||
{
|
{
|
||||||
char fifo[PATH_MAX];
|
char fifo[PATH_MAX];
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
@ -525,7 +540,8 @@ static bool svc_wait(const char *svc)
|
|||||||
forever = true;
|
forever = true;
|
||||||
rc_stringlist_free(keywords);
|
rc_stringlist_free(keywords);
|
||||||
|
|
||||||
snprintf(fifo, sizeof(fifo), RC_SVCDIR "/exclusive/%s", basename_c(svc));
|
snprintf(fifo, sizeof(fifo), RC_SVCDIR "/exclusive/%s",
|
||||||
|
basename_c(svc));
|
||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = WAIT_INTERVAL;
|
ts.tv_nsec = WAIT_INTERVAL;
|
||||||
|
|
||||||
@ -554,7 +570,8 @@ static bool svc_wait(const char *svc)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RC_SERVICE svc_status(void)
|
static RC_SERVICE
|
||||||
|
svc_status(void)
|
||||||
{
|
{
|
||||||
char status[10];
|
char status[10];
|
||||||
int (*e) (const char *fmt, ...) EINFO_PRINTF(1, 2) = einfo;
|
int (*e) (const char *fmt, ...) EINFO_PRINTF(1, 2) = einfo;
|
||||||
@ -586,19 +603,21 @@ static RC_SERVICE svc_status(void)
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void make_exclusive(void)
|
static void
|
||||||
|
make_exclusive(void)
|
||||||
{
|
{
|
||||||
/* We create a fifo so that other services can wait until we complete */
|
/* We create a fifo so that other services can wait until we complete */
|
||||||
if (!*exclusive)
|
if (!*exclusive)
|
||||||
snprintf(exclusive, sizeof(exclusive), RC_SVCDIR "/exclusive/%s",
|
snprintf(exclusive, sizeof(exclusive),
|
||||||
applet);
|
RC_SVCDIR "/exclusive/%s", applet);
|
||||||
|
|
||||||
if (mkfifo(exclusive, 0600) != 0 && errno != EEXIST &&
|
if (mkfifo(exclusive, 0600) != 0 && errno != EEXIST &&
|
||||||
(errno != EACCES || geteuid () == 0))
|
(errno != EACCES || geteuid () == 0))
|
||||||
eerrorx ("%s: unable to create fifo `%s': %s",
|
eerrorx ("%s: unable to create fifo `%s': %s",
|
||||||
applet, exclusive, strerror(errno));
|
applet, exclusive, strerror(errno));
|
||||||
|
|
||||||
snprintf(mtime_test, sizeof(mtime_test), RC_SVCDIR "/exclusive/%s.%d", applet, getpid());
|
snprintf(mtime_test, sizeof(mtime_test),
|
||||||
|
RC_SVCDIR "/exclusive/%s.%d", applet, getpid());
|
||||||
|
|
||||||
if (exists(mtime_test) && unlink(mtime_test) != 0) {
|
if (exists(mtime_test) && unlink(mtime_test) != 0) {
|
||||||
eerror("%s: unlink `%s': %s",
|
eerror("%s: unlink `%s': %s",
|
||||||
@ -614,28 +633,28 @@ static void make_exclusive(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unlink_mtime_test(void)
|
static void
|
||||||
|
unlink_mtime_test(void)
|
||||||
{
|
{
|
||||||
if (unlink(mtime_test) != 0)
|
if (unlink(mtime_test) != 0)
|
||||||
eerror("%s: unlink `%s': %s", applet, mtime_test, strerror(errno));
|
eerror("%s: unlink `%s': %s",
|
||||||
|
applet, mtime_test, strerror(errno));
|
||||||
*mtime_test = '\0';
|
*mtime_test = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_started_services(void)
|
static void
|
||||||
|
get_started_services(void)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *tmp = rc_services_in_state(RC_SERVICE_INACTIVE);
|
RC_STRINGLIST *tmp = rc_services_in_state(RC_SERVICE_INACTIVE);
|
||||||
|
|
||||||
rc_stringlist_free(restart_services);
|
rc_stringlist_free(restart_services);
|
||||||
restart_services = rc_services_in_state(RC_SERVICE_STARTED);
|
restart_services = rc_services_in_state(RC_SERVICE_STARTED);
|
||||||
if (tmp) {
|
|
||||||
if (restart_services) {
|
|
||||||
TAILQ_CONCAT(restart_services, tmp, entries);
|
TAILQ_CONCAT(restart_services, tmp, entries);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
} else
|
|
||||||
restart_services = tmp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_types(void)
|
static void
|
||||||
|
setup_types(void)
|
||||||
{
|
{
|
||||||
types_b = rc_stringlist_new();
|
types_b = rc_stringlist_new();
|
||||||
rc_stringlist_add(types_b, "broken");
|
rc_stringlist_add(types_b, "broken");
|
||||||
@ -661,7 +680,8 @@ static void setup_types(void)
|
|||||||
rc_stringlist_add(types_mua, "beforeme");
|
rc_stringlist_add(types_mua, "beforeme");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void svc_start(bool deps)
|
static void
|
||||||
|
svc_start(bool deps)
|
||||||
{
|
{
|
||||||
bool started;
|
bool started;
|
||||||
bool background = false;
|
bool background = false;
|
||||||
@ -682,6 +702,10 @@ static void svc_start(bool deps)
|
|||||||
! state & RC_SERVICE_STOPPED)
|
! state & RC_SERVICE_STOPPED)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
background = true;
|
background = true;
|
||||||
|
rc_service_mark(service, RC_SERVICE_COLDPLUGGED);
|
||||||
|
if (rc_runlevel_starting())
|
||||||
|
ewarnx("WARNING: %s will be started when the runlevel"
|
||||||
|
" has finished.", applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state & RC_SERVICE_STARTED) {
|
if (state & RC_SERVICE_STARTED) {
|
||||||
@ -692,7 +716,8 @@ static void svc_start(bool deps)
|
|||||||
else if (state & RC_SERVICE_STOPPING)
|
else if (state & RC_SERVICE_STOPPING)
|
||||||
ewarnx("WARNING: %s is stopping", applet);
|
ewarnx("WARNING: %s is stopping", applet);
|
||||||
else if (state & RC_SERVICE_INACTIVE && ! background)
|
else if (state & RC_SERVICE_INACTIVE && ! background)
|
||||||
ewarnx("WARNING: %s has already started, but is inactive", applet);
|
ewarnx("WARNING: %s has already started, but is inactive",
|
||||||
|
applet);
|
||||||
|
|
||||||
if (!rc_service_mark(service, RC_SERVICE_STARTING)) {
|
if (!rc_service_mark(service, RC_SERVICE_STARTING)) {
|
||||||
if (errno == EACCES)
|
if (errno == EACCES)
|
||||||
@ -701,7 +726,6 @@ static void svc_start(bool deps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
make_exclusive();
|
make_exclusive();
|
||||||
|
|
||||||
hook_out = RC_HOOK_SERVICE_START_OUT;
|
hook_out = RC_HOOK_SERVICE_START_OUT;
|
||||||
rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet);
|
rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet);
|
||||||
|
|
||||||
@ -712,13 +736,12 @@ static void svc_start(bool deps)
|
|||||||
if (deps) {
|
if (deps) {
|
||||||
if (!deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))
|
if (!deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))
|
||||||
eerrorx("failed to load deptree");
|
eerrorx("failed to load deptree");
|
||||||
|
|
||||||
if (!types_b)
|
if (!types_b)
|
||||||
setup_types();
|
setup_types();
|
||||||
|
|
||||||
services = rc_deptree_depends(deptree, types_b, applet_list,
|
services = rc_deptree_depends(deptree, types_b, applet_list,
|
||||||
runlevel, 0);
|
runlevel, 0);
|
||||||
if (services && TAILQ_FIRST(services)) {
|
if (TAILQ_FIRST(services)) {
|
||||||
eerrorn("ERROR: `%s' needs ", applet);
|
eerrorn("ERROR: `%s' needs ", applet);
|
||||||
first = true;
|
first = true;
|
||||||
TAILQ_FOREACH(svc, services, entries) {
|
TAILQ_FOREACH(svc, services, entries) {
|
||||||
@ -733,12 +756,14 @@ static void svc_start(bool deps)
|
|||||||
rc_stringlist_free(services);
|
rc_stringlist_free(services);
|
||||||
services = NULL;
|
services = NULL;
|
||||||
|
|
||||||
need_services = rc_deptree_depends(deptree, types_n, applet_list,
|
need_services = rc_deptree_depends(deptree, types_n,
|
||||||
runlevel, depoptions);
|
applet_list, runlevel,
|
||||||
use_services = rc_deptree_depends(deptree, types_nu, applet_list,
|
depoptions);
|
||||||
runlevel, depoptions);
|
use_services = rc_deptree_depends(deptree, types_nu,
|
||||||
|
applet_list, runlevel,
|
||||||
|
depoptions);
|
||||||
|
|
||||||
if (! rc_runlevel_starting() && use_services)
|
if (!rc_runlevel_starting()) {
|
||||||
TAILQ_FOREACH(svc, use_services, entries) {
|
TAILQ_FOREACH(svc, use_services, entries) {
|
||||||
state = rc_service_state(svc->value);
|
state = rc_service_state(svc->value);
|
||||||
/* Don't stop failed services again.
|
/* Don't stop failed services again.
|
||||||
@ -753,26 +778,27 @@ static void svc_start(bool deps)
|
|||||||
rc_waitpid(pid);
|
rc_waitpid(pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Now wait for them to start */
|
/* Now wait for them to start */
|
||||||
services = rc_deptree_depends(deptree, types_nua, applet_list,
|
services = rc_deptree_depends(deptree, types_nua, applet_list,
|
||||||
runlevel, depoptions);
|
runlevel, depoptions);
|
||||||
|
|
||||||
if (services) {
|
|
||||||
/* We use tmplist to hold our scheduled by list */
|
/* We use tmplist to hold our scheduled by list */
|
||||||
tmplist = NULL;
|
tmplist = rc_stringlist_new();
|
||||||
TAILQ_FOREACH(svc, services, entries) {
|
TAILQ_FOREACH(svc, services, entries) {
|
||||||
state = rc_service_state(svc->value);
|
state = rc_service_state(svc->value);
|
||||||
if (state & RC_SERVICE_STARTED)
|
if (state & RC_SERVICE_STARTED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Don't wait for services which went inactive but are now in
|
/* Don't wait for services which went inactive but are
|
||||||
* starting state which we are after */
|
* now in starting state which we are after */
|
||||||
if (state & RC_SERVICE_STARTING &&
|
if (state & RC_SERVICE_STARTING &&
|
||||||
state & RC_SERVICE_WASINACTIVE)
|
state & RC_SERVICE_WASINACTIVE)
|
||||||
{
|
{
|
||||||
if (!rc_stringlist_find(need_services, svc->value) &&
|
if (!rc_stringlist_find(need_services,
|
||||||
!rc_stringlist_find(use_services, svc->value))
|
svc->value) &&
|
||||||
|
!rc_stringlist_find(use_services,
|
||||||
|
svc->value))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,17 +812,15 @@ static void svc_start(bool deps)
|
|||||||
if (state & RC_SERVICE_INACTIVE ||
|
if (state & RC_SERVICE_INACTIVE ||
|
||||||
state & RC_SERVICE_WASINACTIVE)
|
state & RC_SERVICE_WASINACTIVE)
|
||||||
{
|
{
|
||||||
if (! tmplist)
|
|
||||||
tmplist = rc_stringlist_new();
|
|
||||||
rc_stringlist_add(tmplist, svc->value);
|
rc_stringlist_add(tmplist, svc->value);
|
||||||
} else if (!tmplist)
|
} else if (!TAILQ_FIRST(tmplist))
|
||||||
eerrorx("ERROR: cannot start %s as"
|
eerrorx("ERROR: cannot start %s as"
|
||||||
" %s would not start",
|
" %s would not start",
|
||||||
applet, svc->value);
|
applet, svc->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmplist && TAILQ_FIRST(tmplist)) {
|
if (TAILQ_FIRST(tmplist)) {
|
||||||
/* Set the state now, then unlink our exclusive so that
|
/* Set the state now, then unlink our exclusive so that
|
||||||
our scheduled list is preserved */
|
our scheduled list is preserved */
|
||||||
rc_service_mark(service, RC_SERVICE_STOPPED);
|
rc_service_mark(service, RC_SERVICE_STOPPED);
|
||||||
@ -808,14 +832,14 @@ static void svc_start(bool deps)
|
|||||||
n = 0;
|
n = 0;
|
||||||
TAILQ_FOREACH(svc, tmplist, entries) {
|
TAILQ_FOREACH(svc, tmplist, entries) {
|
||||||
rc_service_schedule_start(svc->value, service);
|
rc_service_schedule_start(svc->value, service);
|
||||||
use_services = rc_deptree_depend(deptree, "iprovide",
|
use_services = rc_deptree_depend(deptree,
|
||||||
|
"iprovide",
|
||||||
svc->value);
|
svc->value);
|
||||||
if (use_services) {
|
|
||||||
TAILQ_FOREACH(svc2, use_services, entries)
|
TAILQ_FOREACH(svc2, use_services, entries)
|
||||||
rc_service_schedule_start(svc2->value, service);
|
rc_service_schedule_start(svc2->value,
|
||||||
|
service);
|
||||||
rc_stringlist_free(use_services);
|
rc_stringlist_free(use_services);
|
||||||
use_services = NULL;
|
use_services = NULL;
|
||||||
}
|
|
||||||
len += strlen(svc->value) + 2;
|
len += strlen(svc->value) + 2;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
@ -825,19 +849,19 @@ static void svc_start(bool deps)
|
|||||||
TAILQ_FOREACH(svc, tmplist, entries) {
|
TAILQ_FOREACH(svc, tmplist, entries) {
|
||||||
if (p != tmp)
|
if (p != tmp)
|
||||||
p += snprintf(p, len, ", ");
|
p += snprintf(p, len, ", ");
|
||||||
p += snprintf(p, len - (p - tmp), "%s", svc->value);
|
p += snprintf(p, len - (p - tmp),
|
||||||
|
"%s", svc->value);
|
||||||
}
|
}
|
||||||
rc_stringlist_free(tmplist);
|
rc_stringlist_free(tmplist);
|
||||||
tmplist = NULL;
|
tmplist = NULL;
|
||||||
ewarnx("WARNING: %s is scheduled to start when %s has started",
|
ewarnx("WARNING: %s is scheduled to start when "
|
||||||
applet, tmp);
|
"%s has started", applet, tmp);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_stringlist_free(services);
|
rc_stringlist_free(services);
|
||||||
services = NULL;
|
services = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (ibsave)
|
if (ibsave)
|
||||||
setenv("IN_BACKGROUND", ibsave, 1);
|
setenv("IN_BACKGROUND", ibsave, 1);
|
||||||
@ -852,9 +876,11 @@ static void svc_start(bool deps)
|
|||||||
eerrorx("ERROR: %s failed to start", applet);
|
eerrorx("ERROR: %s failed to start", applet);
|
||||||
} else {
|
} else {
|
||||||
if (rc_service_state(service) & RC_SERVICE_INACTIVE)
|
if (rc_service_state(service) & RC_SERVICE_INACTIVE)
|
||||||
ewarnx("WARNING: %s has started, but is inactive", applet);
|
ewarnx("WARNING: %s has started, but is inactive",
|
||||||
|
applet);
|
||||||
else
|
else
|
||||||
ewarnx("WARNING: %s not under our control, aborting", applet);
|
ewarnx("WARNING: %s not under our control, aborting",
|
||||||
|
applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_service_mark(service, RC_SERVICE_STARTED);
|
rc_service_mark(service, RC_SERVICE_STARTED);
|
||||||
@ -865,29 +891,24 @@ static void svc_start(bool deps)
|
|||||||
|
|
||||||
/* Now start any scheduled services */
|
/* Now start any scheduled services */
|
||||||
services = rc_services_scheduled(service);
|
services = rc_services_scheduled(service);
|
||||||
if (services) {
|
|
||||||
TAILQ_FOREACH(svc, services, entries)
|
TAILQ_FOREACH(svc, services, entries)
|
||||||
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
|
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
|
||||||
service_start(svc->value);
|
service_start(svc->value);
|
||||||
rc_stringlist_free(services);
|
rc_stringlist_free(services);
|
||||||
services = NULL;
|
services = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/* Do the same for any services we provide */
|
/* Do the same for any services we provide */
|
||||||
if (deptree) {
|
if (deptree) {
|
||||||
tmplist = rc_deptree_depend(deptree, "iprovide", applet);
|
tmplist = rc_deptree_depend(deptree, "iprovide", applet);
|
||||||
if (tmplist) {
|
|
||||||
TAILQ_FOREACH(svc, tmplist, entries) {
|
TAILQ_FOREACH(svc, tmplist, entries) {
|
||||||
services = rc_services_scheduled(svc->value);
|
services = rc_services_scheduled(svc->value);
|
||||||
if (! services)
|
|
||||||
continue;
|
|
||||||
TAILQ_FOREACH(svc2, services, entries)
|
TAILQ_FOREACH(svc2, services, entries)
|
||||||
if (rc_service_state(svc2->value) & RC_SERVICE_STOPPED)
|
if (rc_service_state(svc2->value) &
|
||||||
|
RC_SERVICE_STOPPED)
|
||||||
service_start(svc2->value);
|
service_start(svc2->value);
|
||||||
rc_stringlist_free(services);
|
rc_stringlist_free(services);
|
||||||
services = NULL;
|
services = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
rc_stringlist_free(tmplist);
|
rc_stringlist_free(tmplist);
|
||||||
tmplist = NULL;
|
tmplist = NULL;
|
||||||
}
|
}
|
||||||
@ -896,15 +917,16 @@ static void svc_start(bool deps)
|
|||||||
rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet);
|
rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void svc_stop(bool deps)
|
static void
|
||||||
|
svc_stop(bool deps)
|
||||||
{
|
{
|
||||||
bool stopped;
|
bool stopped;
|
||||||
RC_SERVICE state = rc_service_state(service);
|
RC_SERVICE state = rc_service_state(service);
|
||||||
int depoptions = RC_DEP_TRACE;
|
int depoptions = RC_DEP_TRACE;
|
||||||
RC_STRING *svc;
|
RC_STRING *svc;
|
||||||
|
|
||||||
if (rc_runlevel_stopping() &&
|
|
||||||
state & RC_SERVICE_FAILED)
|
if (rc_runlevel_stopping() && state & RC_SERVICE_FAILED)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (rc_yesno(getenv("IN_HOTPLUG")) || in_background)
|
if (rc_yesno(getenv("IN_HOTPLUG")) || in_background)
|
||||||
@ -946,7 +968,7 @@ static void svc_stop(bool deps)
|
|||||||
|
|
||||||
services = rc_deptree_depends(deptree, types_m, applet_list,
|
services = rc_deptree_depends(deptree, types_m, applet_list,
|
||||||
runlevel, depoptions);
|
runlevel, depoptions);
|
||||||
if (services) {
|
tmplist = rc_stringlist_new();
|
||||||
TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) {
|
TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) {
|
||||||
state = rc_service_state(svc->value);
|
state = rc_service_state(svc->value);
|
||||||
/* Don't stop failed services again.
|
/* Don't stop failed services again.
|
||||||
@ -966,45 +988,43 @@ static void svc_stop(bool deps)
|
|||||||
pid_t pid = service_stop(svc->value);
|
pid_t pid = service_stop(svc->value);
|
||||||
if (!rc_conf_yesno("rc_parallel"))
|
if (!rc_conf_yesno("rc_parallel"))
|
||||||
rc_waitpid(pid);
|
rc_waitpid(pid);
|
||||||
if (! tmplist)
|
|
||||||
tmplist = rc_stringlist_new();
|
|
||||||
rc_stringlist_add(tmplist, svc->value);
|
rc_stringlist_add(tmplist, svc->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc_stringlist_free(services);
|
rc_stringlist_free(services);
|
||||||
services = NULL;
|
services = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (tmplist) {
|
|
||||||
TAILQ_FOREACH(svc, tmplist, entries) {
|
TAILQ_FOREACH(svc, tmplist, entries) {
|
||||||
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
|
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
|
||||||
continue;
|
continue;
|
||||||
svc_wait(svc->value);
|
svc_wait(svc->value);
|
||||||
if (! (rc_service_state(svc->value) & RC_SERVICE_STOPPED)) {
|
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
|
||||||
|
continue;
|
||||||
if (rc_runlevel_stopping()) {
|
if (rc_runlevel_stopping()) {
|
||||||
/* If shutting down, we should stop even
|
/* If shutting down, we should stop even
|
||||||
* if a dependant failed */
|
* if a dependant failed */
|
||||||
if (runlevel &&
|
if (runlevel &&
|
||||||
(strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
|
(strcmp(runlevel,
|
||||||
strcmp(runlevel, RC_LEVEL_REBOOT) == 0 ||
|
RC_LEVEL_SHUTDOWN) == 0 ||
|
||||||
strcmp(runlevel, RC_LEVEL_SINGLE) == 0))
|
strcmp(runlevel,
|
||||||
|
RC_LEVEL_REBOOT) == 0 ||
|
||||||
|
strcmp(runlevel,
|
||||||
|
RC_LEVEL_SINGLE) == 0))
|
||||||
continue;
|
continue;
|
||||||
rc_service_mark(service, RC_SERVICE_FAILED);
|
rc_service_mark(service, RC_SERVICE_FAILED);
|
||||||
}
|
}
|
||||||
eerrorx("ERROR: cannot stop %s as %s is still up",
|
eerrorx("ERROR: cannot stop %s as %s "
|
||||||
applet, svc->value);
|
"is still up", applet, svc->value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
rc_stringlist_free(tmplist);
|
rc_stringlist_free(tmplist);
|
||||||
tmplist = NULL;
|
tmplist = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/* We now wait for other services that may use us and are stopping
|
|
||||||
This is important when a runlevel stops */
|
/* We now wait for other services that may use us and are
|
||||||
|
* stopping. This is important when a runlevel stops */
|
||||||
services = rc_deptree_depends(deptree, types_mua, applet_list,
|
services = rc_deptree_depends(deptree, types_mua, applet_list,
|
||||||
runlevel, depoptions);
|
runlevel, depoptions);
|
||||||
if (services) {
|
|
||||||
TAILQ_FOREACH(svc, services, entries) {
|
TAILQ_FOREACH(svc, services, entries) {
|
||||||
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
|
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
|
||||||
continue;
|
continue;
|
||||||
@ -1013,7 +1033,6 @@ static void svc_stop(bool deps)
|
|||||||
rc_stringlist_free(services);
|
rc_stringlist_free(services);
|
||||||
services = NULL;
|
services = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* If we're stopping localmount, set LC_ALL=C so that
|
/* If we're stopping localmount, set LC_ALL=C so that
|
||||||
* bash doesn't load anything blocking the unmounting of /usr */
|
* bash doesn't load anything blocking the unmounting of /usr */
|
||||||
@ -1047,16 +1066,20 @@ static void svc_stop(bool deps)
|
|||||||
rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet);
|
rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void svc_restart(bool deps)
|
static void
|
||||||
|
svc_restart(bool deps)
|
||||||
{
|
{
|
||||||
/* This is hairly and a better way needs to be found I think!
|
/* This is hairly and a better way needs to be found I think!
|
||||||
The issue is this - openvpn need net and dns. net can restart
|
* The issue is this - openvpn need net and dns. net can restart
|
||||||
dns via resolvconf, so you could have openvpn trying to restart dnsmasq
|
* dns via resolvconf, so you could have openvpn trying to restart
|
||||||
which in turn is waiting on net which in turn is waiting on dnsmasq.
|
* dnsmasq which in turn is waiting on net which in turn is waiting
|
||||||
The work around is for resolvconf to restart it's services with --nodeps
|
* on dnsmasq.
|
||||||
which means just that. The downside is that there is a small window when
|
* The work around is for resolvconf to restart it's services with
|
||||||
our status is invalid.
|
* --nodeps which means just that.
|
||||||
One workaround would be to introduce a new status, or status locking. */
|
* The downside is that there is a small window when our status is
|
||||||
|
* invalid.
|
||||||
|
* One workaround would be to introduce a new status,
|
||||||
|
* or status locking. */
|
||||||
if (!deps) {
|
if (!deps) {
|
||||||
RC_SERVICE state = rc_service_state(service);
|
RC_SERVICE state = rc_service_state(service);
|
||||||
if (state & RC_SERVICE_STARTED || state & RC_SERVICE_INACTIVE)
|
if (state & RC_SERVICE_STARTED || state & RC_SERVICE_INACTIVE)
|
||||||
@ -1077,6 +1100,51 @@ static void svc_restart(bool deps)
|
|||||||
restart_services = NULL;
|
restart_services = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
service_plugable(void)
|
||||||
|
{
|
||||||
|
char *list;
|
||||||
|
char *p;
|
||||||
|
char *star;
|
||||||
|
char *token;
|
||||||
|
bool allow = true;
|
||||||
|
char *match = rc_conf_value("rc_plug_services");
|
||||||
|
bool truefalse;
|
||||||
|
|
||||||
|
if (! match)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
list = xstrdup(match);
|
||||||
|
p = list;
|
||||||
|
while ((token = strsep(&p, " "))) {
|
||||||
|
if (token[0] == '!') {
|
||||||
|
truefalse = false;
|
||||||
|
token++;
|
||||||
|
} else
|
||||||
|
truefalse = true;
|
||||||
|
|
||||||
|
star = strchr(token, '*');
|
||||||
|
if (star) {
|
||||||
|
if (strncmp(applet, token,
|
||||||
|
(size_t)(star - token)) == 0)
|
||||||
|
{
|
||||||
|
allow = truefalse;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (strcmp(applet, token) == 0) {
|
||||||
|
allow = truefalse;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_MEMORY
|
||||||
|
free(list);
|
||||||
|
#endif
|
||||||
|
return allow;
|
||||||
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
#define getoptstring "dDsv" getoptstring_COMMON
|
#define getoptstring "dDsv" getoptstring_COMMON
|
||||||
#define extraopts "stop | start | restart | describe | zap"
|
#define extraopts "stop | start | restart | describe | zap"
|
||||||
@ -1094,7 +1162,8 @@ static const char * const longopts_help[] = {
|
|||||||
};
|
};
|
||||||
#include "_usage.c"
|
#include "_usage.c"
|
||||||
|
|
||||||
int runscript(int argc, char **argv)
|
int
|
||||||
|
runscript(int argc, char **argv)
|
||||||
{
|
{
|
||||||
bool deps = true;
|
bool deps = true;
|
||||||
bool doneone = false;
|
bool doneone = false;
|
||||||
@ -1165,20 +1234,6 @@ int runscript(int argc, char **argv)
|
|||||||
/* Change dir to / to ensure all init scripts don't use stuff in pwd */
|
/* Change dir to / to ensure all init scripts don't use stuff in pwd */
|
||||||
chdir("/");
|
chdir("/");
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
/* coldplug events can trigger init scripts, but we don't want to run
|
|
||||||
* them until after rc sysinit has completed so we punt them to the
|
|
||||||
* boot runlevel */
|
|
||||||
if (exists("/dev/.rcsysinit")) {
|
|
||||||
eerror("%s: cannot run until sysvinit completes", applet);
|
|
||||||
if (mkdir("/dev/.rcboot", 0755) != 0 && errno != EEXIST)
|
|
||||||
eerrorx("%s: mkdir `/dev/.rcboot': %s", applet, strerror(errno));
|
|
||||||
snprintf(exclusive, sizeof(exclusive), "/dev/.rcboot/%s", applet);
|
|
||||||
symlink(service, exclusive);
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((runlevel = xstrdup (getenv ("RC_RUNLEVEL"))) == NULL) {
|
if ((runlevel = xstrdup (getenv ("RC_RUNLEVEL"))) == NULL) {
|
||||||
env_filter();
|
env_filter();
|
||||||
env_config();
|
env_config();
|
||||||
@ -1198,7 +1253,6 @@ int runscript(int argc, char **argv)
|
|||||||
if (rc_conf_yesno("rc_parallel")) {
|
if (rc_conf_yesno("rc_parallel")) {
|
||||||
/* Get the longest service name */
|
/* Get the longest service name */
|
||||||
services = rc_services_in_runlevel(NULL);
|
services = rc_services_in_runlevel(NULL);
|
||||||
if (services) {
|
|
||||||
TAILQ_FOREACH(svc, services, entries) {
|
TAILQ_FOREACH(svc, services, entries) {
|
||||||
ll = strlen(svc->value);
|
ll = strlen(svc->value);
|
||||||
if (ll > l)
|
if (ll > l)
|
||||||
@ -1206,7 +1260,9 @@ int runscript(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
rc_stringlist_free(services);
|
rc_stringlist_free(services);
|
||||||
services = NULL;
|
services = NULL;
|
||||||
} else l = strlen(applet);
|
ll = strlen(applet);
|
||||||
|
if (ll > l)
|
||||||
|
l = ll;
|
||||||
|
|
||||||
/* Make our prefix string */
|
/* Make our prefix string */
|
||||||
prefix = xmalloc(sizeof(char) * l + 1);
|
prefix = xmalloc(sizeof(char) * l + 1);
|
||||||
@ -1227,7 +1283,8 @@ int runscript(int argc, char **argv)
|
|||||||
argv++;
|
argv++;
|
||||||
|
|
||||||
/* Right then, parse any options there may be */
|
/* Right then, parse any options there may be */
|
||||||
while ((opt = getopt_long(argc, argv, getoptstring, longopts, (int *) 0)) != -1)
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
|
longopts, (int *)0)) != -1)
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'd':
|
case 'd':
|
||||||
setenv("RC_DEBUG", "yes", 1);
|
setenv("RC_DEBUG", "yes", 1);
|
||||||
@ -1251,7 +1308,7 @@ int runscript(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rc_yesno(getenv("IN_HOTPLUG"))) {
|
if (rc_yesno(getenv("IN_HOTPLUG"))) {
|
||||||
if (! rc_conf_yesno("rc_hotplug") || ! service_plugable(applet))
|
if (!rc_conf_yesno("rc_hotplug") || !service_plugable())
|
||||||
eerrorx("%s: not allowed to be hotplugged", applet);
|
eerrorx("%s: not allowed to be hotplugged", applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1304,25 +1361,25 @@ int runscript(int argc, char **argv)
|
|||||||
strcmp(optarg, "iprovide") == 0)
|
strcmp(optarg, "iprovide") == 0)
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT)
|
if (rc_conf_yesno("rc_depend_strict") ||
|
||||||
|
errno == ENOENT)
|
||||||
depoptions |= RC_DEP_STRICT;
|
depoptions |= RC_DEP_STRICT;
|
||||||
|
|
||||||
if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))
|
if (!deptree &&
|
||||||
|
((deptree = _rc_deptree_load(NULL)) == NULL))
|
||||||
eerrorx("failed to load deptree");
|
eerrorx("failed to load deptree");
|
||||||
|
|
||||||
tmplist = rc_stringlist_new();
|
tmplist = rc_stringlist_new();
|
||||||
rc_stringlist_add(tmplist, optarg);
|
rc_stringlist_add(tmplist, optarg);
|
||||||
services = rc_deptree_depends(deptree, tmplist, applet_list,
|
services = rc_deptree_depends(deptree, tmplist,
|
||||||
|
applet_list,
|
||||||
runlevel, depoptions);
|
runlevel, depoptions);
|
||||||
rc_stringlist_free(tmplist);
|
rc_stringlist_free(tmplist);
|
||||||
tmplist = NULL;
|
|
||||||
if (services) {
|
|
||||||
TAILQ_FOREACH(svc, services, entries)
|
TAILQ_FOREACH(svc, services, entries)
|
||||||
printf("%s ", svc->value);
|
printf("%s ", svc->value);
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
rc_stringlist_free(services);
|
rc_stringlist_free(services);
|
||||||
services = NULL;
|
services = NULL;
|
||||||
}
|
|
||||||
} else if (strcmp (optarg, "status") == 0) {
|
} else if (strcmp (optarg, "status") == 0) {
|
||||||
RC_SERVICE r = svc_status();
|
RC_SERVICE r = svc_status();
|
||||||
retval = (int) r;
|
retval = (int) r;
|
||||||
@ -1332,7 +1389,8 @@ int runscript(int argc, char **argv)
|
|||||||
if (strcmp(optarg, "conditionalrestart") == 0 ||
|
if (strcmp(optarg, "conditionalrestart") == 0 ||
|
||||||
strcmp(optarg, "condrestart") == 0)
|
strcmp(optarg, "condrestart") == 0)
|
||||||
{
|
{
|
||||||
if (rc_service_state(service) & RC_SERVICE_STARTED)
|
if (rc_service_state(service) &
|
||||||
|
RC_SERVICE_STARTED)
|
||||||
svc_restart(deps);
|
svc_restart(deps);
|
||||||
} else if (strcmp(optarg, "restart") == 0) {
|
} else if (strcmp(optarg, "restart") == 0) {
|
||||||
svc_restart (deps);
|
svc_restart (deps);
|
||||||
@ -1341,32 +1399,39 @@ int runscript(int argc, char **argv)
|
|||||||
} else if (strcmp(optarg, "stop") == 0) {
|
} else if (strcmp(optarg, "stop") == 0) {
|
||||||
if (deps && in_background)
|
if (deps && in_background)
|
||||||
get_started_services();
|
get_started_services();
|
||||||
|
|
||||||
svc_stop(deps);
|
svc_stop(deps);
|
||||||
|
|
||||||
if (deps) {
|
if (deps) {
|
||||||
if (! in_background &&
|
if (! in_background &&
|
||||||
! rc_runlevel_stopping() &&
|
! rc_runlevel_stopping() &&
|
||||||
rc_service_state(service) & RC_SERVICE_STOPPED)
|
rc_service_state(service) &
|
||||||
|
RC_SERVICE_STOPPED)
|
||||||
uncoldplug();
|
uncoldplug();
|
||||||
|
|
||||||
if (in_background &&
|
if (in_background &&
|
||||||
rc_service_state(service) & RC_SERVICE_INACTIVE)
|
rc_service_state(service) &
|
||||||
|
RC_SERVICE_INACTIVE)
|
||||||
{
|
{
|
||||||
TAILQ_FOREACH(svc, restart_services, entries)
|
TAILQ_FOREACH(svc,
|
||||||
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
|
restart_services,
|
||||||
|
entries)
|
||||||
|
if (rc_service_state(svc->value) &
|
||||||
|
RC_SERVICE_STOPPED)
|
||||||
rc_service_schedule_start(service, svc->value);
|
rc_service_schedule_start(service, svc->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (strcmp(optarg, "zap") == 0) {
|
} else if (strcmp(optarg, "zap") == 0) {
|
||||||
einfo("Manually resetting %s to stopped state", applet);
|
einfo("Manually resetting %s to stopped state",
|
||||||
if (!rc_service_mark(applet, RC_SERVICE_STOPPED))
|
applet);
|
||||||
eerrorx("rc_service_mark: %s", strerror(errno));
|
if (!rc_service_mark(applet,
|
||||||
|
RC_SERVICE_STOPPED))
|
||||||
|
eerrorx("rc_service_mark: %s",
|
||||||
|
strerror(errno));
|
||||||
uncoldplug();
|
uncoldplug();
|
||||||
} else
|
} else
|
||||||
svc_exec(optarg, NULL);
|
svc_exec(optarg, NULL);
|
||||||
|
|
||||||
/* We should ensure this list is empty after an action is done */
|
/* We should ensure this list is empty after
|
||||||
|
* an action is done */
|
||||||
rc_stringlist_free(restart_services);
|
rc_stringlist_free(restart_services);
|
||||||
restart_services = NULL;
|
restart_services = NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user