Compare commits
139 Commits
openrc-0.2
...
openrc-0.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84f6bf4bff | ||
|
|
5f76c1121a | ||
|
|
41c1e170d6 | ||
|
|
f53197818b | ||
|
|
bb41d2cc80 | ||
|
|
4291b9140e | ||
|
|
28d7fb9430 | ||
|
|
abe94bec6f | ||
|
|
c3e192a834 | ||
|
|
13d88731b7 | ||
|
|
ffc79a50c2 | ||
|
|
6748c0e04e | ||
|
|
27805de20a | ||
|
|
53693367df | ||
|
|
554d2fea19 | ||
|
|
a63303971a | ||
|
|
5610c8560c | ||
|
|
2c62d095c8 | ||
|
|
a72dc1194a | ||
|
|
dcc4aa131c | ||
|
|
6b3d8cf598 | ||
|
|
600d1f62fb | ||
|
|
2de401bca1 | ||
|
|
e368a4b4f8 | ||
|
|
354fb96ee9 | ||
|
|
312d6f3e57 | ||
|
|
39ea0cb84d | ||
|
|
17bf78a539 | ||
|
|
072328ff60 | ||
|
|
e0dfa472d1 | ||
|
|
ccc24d1086 | ||
|
|
c4c024fc9d | ||
|
|
223015920c | ||
|
|
aa02a5516a | ||
|
|
80a17eb596 | ||
|
|
39304745d4 | ||
|
|
93a3b2dd02 | ||
|
|
00d010fbe0 | ||
|
|
01de348ede | ||
|
|
fabee4dc2d | ||
|
|
1ab1e9328a | ||
|
|
a9f7d2d5e5 | ||
|
|
a3c8706618 | ||
|
|
1f227d62bf | ||
|
|
cdace75539 | ||
|
|
15678263d5 | ||
|
|
cea206014d | ||
|
|
46a74f244e | ||
|
|
c67233f15c | ||
|
|
b15c4758f8 | ||
|
|
289889ebf0 | ||
|
|
7183cb1b18 | ||
|
|
b83108cd2e | ||
|
|
1ca63447c9 | ||
|
|
c2781c209e | ||
|
|
5983add0f2 | ||
|
|
a566493eb8 | ||
|
|
bdd8b150cd | ||
|
|
53401cd35f | ||
|
|
7a6112d3b0 | ||
|
|
157db50df7 | ||
|
|
a88a177f99 | ||
|
|
d61f831896 | ||
|
|
28a65393ca | ||
|
|
aa57dd1ff6 | ||
|
|
e0968a1c2e | ||
|
|
2f5d2855ba | ||
|
|
db9bf18587 | ||
|
|
feac5ea1d5 | ||
|
|
64dbae7f61 | ||
|
|
11e4059b05 | ||
|
|
5510451bac | ||
|
|
11acce3c7d | ||
|
|
4f2bb5ceaf | ||
|
|
bf8f0da921 | ||
|
|
9b1cb4e246 | ||
|
|
2adc99a8f5 | ||
|
|
fc747f9894 | ||
|
|
76063daee5 | ||
|
|
dc891b0647 | ||
|
|
3525e602d6 | ||
|
|
79ebd89d19 | ||
|
|
ba8008fb05 | ||
|
|
5e2c3fb5fe | ||
|
|
e6aed12328 | ||
|
|
83ade5b701 | ||
|
|
587051ec67 | ||
|
|
f2ea7ca514 | ||
|
|
b41c864fc3 | ||
|
|
c409dd0570 | ||
|
|
aaaa0b50d8 | ||
|
|
ca6f289c80 | ||
|
|
f640ecaebb | ||
|
|
75eff5a86b | ||
|
|
eeadc618fb | ||
|
|
bb069e1618 | ||
|
|
3a592fa31b | ||
|
|
6b77cc624f | ||
|
|
328215e841 | ||
|
|
b03282b901 | ||
|
|
08081f7ef4 | ||
|
|
8ca8e00a89 | ||
|
|
1df3ab05b5 | ||
|
|
775df18a70 | ||
|
|
148caecc7e | ||
|
|
d0f7a63487 | ||
|
|
b7e598ad91 | ||
|
|
5c114d9430 | ||
|
|
f13ea77491 | ||
|
|
a89171ee9b | ||
|
|
6d5d655b52 | ||
|
|
0f51f3e863 | ||
|
|
be8f8d0ac0 | ||
|
|
d667da8e5c | ||
|
|
9894669742 | ||
|
|
b732df31ef | ||
|
|
762dc3d197 | ||
|
|
30fe99dead | ||
|
|
2d75eb7976 | ||
|
|
3663cf1e2a | ||
|
|
766ec96e3d | ||
|
|
a854fe6d61 | ||
|
|
619b0b4f37 | ||
|
|
c8248d05a0 | ||
|
|
5ae702339e | ||
|
|
d384502e57 | ||
|
|
bdaca0baf5 | ||
|
|
5188fd2592 | ||
|
|
5b800030f1 | ||
|
|
208443fa0e | ||
|
|
a818eebf7b | ||
|
|
10910876d1 | ||
|
|
35b4978152 | ||
|
|
cedd81801a | ||
|
|
e273b4e08e | ||
|
|
50cff8ebc8 | ||
|
|
aec83494d6 | ||
|
|
5ba6f0a628 | ||
|
|
5a59542629 |
2
Makefile
2
Makefile
@@ -3,7 +3,7 @@
|
|||||||
# All rights reserved. Released under the 2-clause BSD license.
|
# All rights reserved. Released under the 2-clause BSD license.
|
||||||
|
|
||||||
NAME= openrc
|
NAME= openrc
|
||||||
VERSION= 0.2.3
|
VERSION= 0.3.0
|
||||||
PKG= ${NAME}-${VERSION}
|
PKG= ${NAME}-${VERSION}
|
||||||
|
|
||||||
SUBDIR= conf.d doc etc init.d man net sh src
|
SUBDIR= conf.d doc etc init.d man net sh src
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
DIR= ${CONFDIR}
|
DIR= ${CONFDIR}
|
||||||
CONF= bootmisc fsck hostname local net urandom
|
CONF= bootmisc fsck hostname local localmount net urandom
|
||||||
|
|
||||||
MK= ../mk
|
MK= ../mk
|
||||||
include ${MK}/os.mk
|
include ${MK}/os.mk
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
CONF+= moused powerd rarpd savecore syscons
|
CONF+= ipfw moused powerd rarpd savecore syscons
|
||||||
|
|||||||
14
conf.d/ipfw
Normal file
14
conf.d/ipfw
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# ipfw provides a stateful firewall.
|
||||||
|
# This means we allow everything out, and if we have a connection we allow it
|
||||||
|
# back in. This is very flexable and quite secure.
|
||||||
|
|
||||||
|
# For ease of use, we allow auth and ssh ports through as well.
|
||||||
|
# To override the list of allowed ports
|
||||||
|
#ipfw_ports_in="auth ssh"
|
||||||
|
|
||||||
|
# You may want to enable logging of denied connections
|
||||||
|
#ipfw_log_deny="YES"
|
||||||
|
|
||||||
|
# This ports not logged
|
||||||
|
#ipfw_ports_nolog="135-139,445 1026,1027 1433,1434"
|
||||||
|
|
||||||
3
conf.d/localmount
Normal file
3
conf.d/localmount
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Stop the unmounting of certain points.
|
||||||
|
# This could be useful for some NFS related work.
|
||||||
|
#no_umounts="/dir1:/var/dir2"
|
||||||
@@ -5,6 +5,10 @@
|
|||||||
#modules_2_6="tun"
|
#modules_2_6="tun"
|
||||||
#modules="ohci1394"
|
#modules="ohci1394"
|
||||||
|
|
||||||
|
# You can give modules a different name when they load - the new name
|
||||||
|
# will also be used to pick arguments below.
|
||||||
|
#modules="dummy:dummy1"
|
||||||
|
|
||||||
# Give the modules some arguments if needed, per version if necessary.
|
# Give the modules some arguments if needed, per version if necessary.
|
||||||
#module_ieee1394_args="debug"
|
#module_ieee1394_args="debug"
|
||||||
#module_ieee1394_args_2_6_23_gentoo_r5="ieee1394 ohci1394"
|
#module_ieee1394_args_2_6_23_gentoo_r5="ieee1394 ohci1394"
|
||||||
|
|||||||
@@ -87,6 +87,10 @@
|
|||||||
# is how long we wait for carrier. The current default is 3 seconds
|
# is how long we wait for carrier. The current default is 3 seconds
|
||||||
#carrier_timeout_eth0=-1
|
#carrier_timeout_eth0=-1
|
||||||
|
|
||||||
|
# You may wish to disable the interface being brought down when stopping.
|
||||||
|
# This is only of use for WakeOnLan.
|
||||||
|
#ifdown_eth0="NO"
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# OPTIONAL MODULES
|
# OPTIONAL MODULES
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,10 @@
|
|||||||
# tables you may have to set a global metric as the due to a simple read of
|
# tables you may have to set a global metric as the due to a simple read of
|
||||||
# the routing table taking over a minute at a time.
|
# the routing table taking over a minute at a time.
|
||||||
|
|
||||||
|
# You may wish to disable the interface being brought down when stopping.
|
||||||
|
# This is only of use for WakeOnLan.
|
||||||
|
#ifdown_eth0="NO"
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# OPTIONAL MODULES
|
# OPTIONAL MODULES
|
||||||
|
|
||||||
@@ -565,12 +569,18 @@
|
|||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# Bonding
|
# Bonding
|
||||||
# For link bonding/trunking emerge net-misc/ifenslave
|
# For link bonding/trunking on 2.4 kernels, or kernels without sysfs
|
||||||
|
# emerge net-misc/ifenslave
|
||||||
|
|
||||||
# To bond interfaces together
|
# To bond interfaces together
|
||||||
#slaves_bond0="eth0 eth1 eth2"
|
#slaves_bond0="eth0 eth1 eth2"
|
||||||
#config_bond0="null" # You may not want to assign an IP the the bond
|
#config_bond0="null" # You may not want to assign an IP the the bond
|
||||||
|
|
||||||
|
# You can also configure the bond here, which must be done via sysfs on 2.6
|
||||||
|
# kernels or newer. See the kernel bonding documention for a description of
|
||||||
|
# these options.
|
||||||
|
#arp_ip_target_bond0="+26.0.0.0"
|
||||||
|
|
||||||
# If any of the slaves require extra configuration - for example wireless or
|
# If any of the slaves require extra configuration - for example wireless or
|
||||||
# ppp devices - we need to depend function on the bonded interfaces
|
# ppp devices - we need to depend function on the bonded interfaces
|
||||||
#rc_need_bond0="net.eth0 net.eth1"
|
#rc_need_bond0="net.eth0 net.eth1"
|
||||||
@@ -1006,7 +1016,7 @@
|
|||||||
|
|
||||||
#postdown() {
|
#postdown() {
|
||||||
# # Enable Wake-On-LAN for every interface except for lo
|
# # Enable Wake-On-LAN for every interface except for lo
|
||||||
# # Probably a good idea to set RC_DOWN_INTERFACE="no" in /etc/conf.d/rc
|
# # Probably a good idea to set ifdown="no" in /etc/conf.d/net
|
||||||
# # as well ;)
|
# # as well ;)
|
||||||
# [ "${IFACE}" != "lo" ] && ethtool -s "${IFACE}" wol g
|
# [ "${IFACE}" != "lo" ] && ethtool -s "${IFACE}" wol g
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
# in parallel for a slight speed improvement. When running in parallel we
|
# in parallel for a slight speed improvement. When running in parallel we
|
||||||
# prefix the service output with it's name as the output will get
|
# prefix the service output with it's name as the output will get
|
||||||
# jumbled up.
|
# jumbled up.
|
||||||
|
# WARNING: whilst we have improved parallel, it can still potentially lock
|
||||||
|
# the boot process. Don't file bugs about this unless you can supply
|
||||||
|
# patches that fix it without breaking other things!
|
||||||
rc_parallel="NO"
|
rc_parallel="NO"
|
||||||
|
|
||||||
# Set rc_interactive to "YES" and you'll be able to press the I key during
|
# Set rc_interactive to "YES" and you'll be able to press the I key during
|
||||||
@@ -49,6 +52,14 @@ rc_logger="NO"
|
|||||||
# variables through, add them here. Use a * to allow all variables through.
|
# variables through, add them here. Use a * to allow all variables through.
|
||||||
# rc_env_allow="VAR1 VAR2"
|
# rc_env_allow="VAR1 VAR2"
|
||||||
|
|
||||||
|
# By default we assume that all daemons will start correctly.
|
||||||
|
# However, some do not - a classic example is that they fork and return 0 AND
|
||||||
|
# then child barfs on a configuration error. Or the daemon has a bug and the
|
||||||
|
# child crashes. You can set the number of milliseconds start-stop-daemon
|
||||||
|
# waits to check that the daemon is still running after starting here.
|
||||||
|
# The default is 0 - no checking.
|
||||||
|
# rc_start_wait=100
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# MISC CONFIGURATION VARIABLES
|
# MISC CONFIGURATION VARIABLES
|
||||||
# There variables are shared between many init scripts
|
# There variables are shared between many init scripts
|
||||||
|
|||||||
13
init.d/.gitignore
vendored
13
init.d/.gitignore
vendored
@@ -26,3 +26,16 @@ mixer
|
|||||||
nscd
|
nscd
|
||||||
powerd
|
powerd
|
||||||
syscons
|
syscons
|
||||||
|
net.lo
|
||||||
|
ttys
|
||||||
|
swap-blk
|
||||||
|
wscons
|
||||||
|
consolefont
|
||||||
|
hwclock
|
||||||
|
keymaps
|
||||||
|
modules
|
||||||
|
mtab
|
||||||
|
numlock
|
||||||
|
procfs
|
||||||
|
termencoding
|
||||||
|
devdb
|
||||||
|
|||||||
@@ -3,7 +3,14 @@ SRCS= bootmisc.in fsck.in halt.sh.in hostname.in local.in localmount.in \
|
|||||||
netmount.in root.in swap.in sysctl.in urandom.in
|
netmount.in root.in swap.in sysctl.in urandom.in
|
||||||
BIN= ${OBJS}
|
BIN= ${OBJS}
|
||||||
|
|
||||||
|
INSTALLAFTER= _installafter
|
||||||
|
CLEANFILES+= net.lo
|
||||||
|
TARGETS+= net.lo
|
||||||
|
|
||||||
MK= ../mk
|
MK= ../mk
|
||||||
include ${MK}/os.mk
|
include ${MK}/os.mk
|
||||||
include Makefile.${OS}
|
include Makefile.${OS}
|
||||||
include ${MK}/scripts.mk
|
include ${MK}/scripts.mk
|
||||||
|
|
||||||
|
_installafter: realinstall
|
||||||
|
${INSTALL} -m ${BINMODE} net.lo ${DESTDIR}/${INITDIR}/${NET_LO}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
NET_LO= net.lo0
|
||||||
|
|
||||||
# Generic BSD scripts
|
# Generic BSD scripts
|
||||||
SRCS+= hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
|
SRCS+= hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
|
||||||
rpcbind.in savecore.in syslogd.in
|
rpcbind.in savecore.in syslogd.in
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
NET_LO= net.lo
|
||||||
|
|
||||||
SRCS+= hwclock.in consolefont.in keymaps.in modules.in mtab.in numlock.in \
|
SRCS+= hwclock.in consolefont.in keymaps.in modules.in mtab.in numlock.in \
|
||||||
procfs.in termencoding.in
|
procfs.in termencoding.in
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
NET_LO= net.lo0
|
||||||
|
|
||||||
# Generic BSD scripts
|
# Generic BSD scripts
|
||||||
SRCS+= hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
|
SRCS+= hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \
|
||||||
rpcbind.in savecore.in syslogd.in
|
rpcbind.in savecore.in syslogd.in
|
||||||
|
|
||||||
# These are NetBSD specific
|
# These are NetBSD specific
|
||||||
SRCS+= swap-blk.in ttys.in wscons.in
|
SRCS+= devdb.in swap-blk.in ttys.in wscons.in
|
||||||
|
|
||||||
.SUFFIXES: .BSD.in
|
.SUFFIXES: .BSD.in
|
||||||
.BSD.in:
|
.BSD.in:
|
||||||
|
|||||||
@@ -28,13 +28,8 @@ cleanup_tmp_dir()
|
|||||||
cd "${dir}"
|
cd "${dir}"
|
||||||
if yesno ${wipe_tmp:-${WIPE_TMP:-yes}}; then
|
if yesno ${wipe_tmp:-${WIPE_TMP:-yes}}; then
|
||||||
ebegin "Wiping ${dir} directory"
|
ebegin "Wiping ${dir} directory"
|
||||||
local startopts="-x . -depth" delete="-exec rm -rf -- {} ;"
|
local startopts="-x . -depth"
|
||||||
|
[ "${RC_UNAME}" = "Linux" ] && startopts=". -xdev -depth"
|
||||||
if [ "${RC_UNAME}" = "Linux" ]; then
|
|
||||||
startopts=". -xdev -depth"
|
|
||||||
# busybox find / rm cannot handle --
|
|
||||||
delete="-delete"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Faster than find
|
# Faster than find
|
||||||
rm -rf -- [b-ikm-pr-zA-Z0-9\.]*
|
rm -rf -- [b-ikm-pr-zA-Z0-9\.]*
|
||||||
@@ -54,8 +49,7 @@ cleanup_tmp_dir()
|
|||||||
! -path "./journal/*" \
|
! -path "./journal/*" \
|
||||||
! -path "./.private" \
|
! -path "./.private" \
|
||||||
! -path "./.private/*" \
|
! -path "./.private/*" \
|
||||||
${delete} \
|
-exec rm -rf {} \;
|
||||||
-type d -prune
|
|
||||||
eend 0
|
eend 0
|
||||||
else
|
else
|
||||||
ebegin "Cleaning ${dir} directory"
|
ebegin "Cleaning ${dir} directory"
|
||||||
@@ -92,9 +86,13 @@ start()
|
|||||||
|
|
||||||
ebegin "Cleaning /var/run"
|
ebegin "Cleaning /var/run"
|
||||||
for x in $(find /var/run ! -type d ! -name utmp \
|
for x in $(find /var/run ! -type d ! -name utmp \
|
||||||
! -name random-seed \
|
! -name random-seed ! -name dev.db \
|
||||||
! -name ld-elf.so.hints ! -name ld.so.hints);
|
! -name ld-elf.so.hints ! -name ld.so.hints);
|
||||||
do
|
do
|
||||||
|
# Clean stale sockets
|
||||||
|
if [ -S "${x}" ] && type fuser >/dev/null 2>&1; then
|
||||||
|
fuser -s "${x}" || rm "${x}"
|
||||||
|
fi
|
||||||
[ ! -f "${x}" ] && continue
|
[ ! -f "${x}" ] && continue
|
||||||
# Do not remove pidfiles of already running daemons
|
# Do not remove pidfiles of already running daemons
|
||||||
case "${x}" in
|
case "${x}" in
|
||||||
|
|||||||
21
init.d/devdb.in
Normal file
21
init.d/devdb.in
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#!@PREFIX@/sbin/runscript
|
||||||
|
# Copyright 2008 Roy Marples <roy@marples.name>
|
||||||
|
# All rights reserved. Released under the 2-clause BSD license.
|
||||||
|
|
||||||
|
description="Creates the dev database"
|
||||||
|
|
||||||
|
depend()
|
||||||
|
{
|
||||||
|
need localmount
|
||||||
|
}
|
||||||
|
|
||||||
|
start()
|
||||||
|
{
|
||||||
|
ebegin "Bulding the dev database"
|
||||||
|
if [ /var/run/dev.db -nt /dev ]; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
dev_mkdb
|
||||||
|
fi
|
||||||
|
eend $?
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
# All rights reserved. Released under the 2-clause BSD license.
|
# All rights reserved. Released under the 2-clause BSD license.
|
||||||
|
|
||||||
description="Check and repair filesystems according to /etc/fstab"
|
description="Check and repair filesystems according to /etc/fstab"
|
||||||
_ISF="
|
_IFS="
|
||||||
"
|
"
|
||||||
|
|
||||||
depend()
|
depend()
|
||||||
@@ -33,7 +33,7 @@ start()
|
|||||||
ewarn "Skipping fsck due to /fastboot"
|
ewarn "Skipping fsck due to /fastboot"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
if [ -e /forcefsck ]; then
|
if [ -e /forcefsck ] || get_bootparam forcefsck; then
|
||||||
fsck_opts="${fsck_opts} -f"
|
fsck_opts="${fsck_opts} -f"
|
||||||
check_extra="(check forced)"
|
check_extra="(check forced)"
|
||||||
fi
|
fi
|
||||||
@@ -47,7 +47,7 @@ start()
|
|||||||
case "${p}" in
|
case "${p}" in
|
||||||
[0-9]*) p="=${p}";;
|
[0-9]*) p="=${p}";;
|
||||||
esac
|
esac
|
||||||
set -- "$@" "$(fstabinfo --passno "${p}")"
|
set -- "$@" $(fstabinfo --passno "${p}")
|
||||||
unset IFS
|
unset IFS
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ start()
|
|||||||
reboot_opts="-f"
|
reboot_opts="-f"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
trap : QUIT
|
trap : INT QUIT
|
||||||
fsck ${fsck_args--p} ${fsck_opts} "$@"
|
fsck ${fsck_args--p} ${fsck_opts} "$@"
|
||||||
case $? in
|
case $? in
|
||||||
0) eend 0; return 0;;
|
0) eend 0; return 0;;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
. @SYSCONFDIR@/init.d/functions.sh
|
. @SYSCONFDIR@/init.d/functions.sh
|
||||||
. "${RC_LIBDIR}"/sh/rc-functions.sh
|
. "${RC_LIBDIR}"/sh/rc-functions.sh
|
||||||
|
[ -r @SYSCONFDIR@/conf.d/localmount ] && . @SYSCONFDIR@/conf.d/localmount
|
||||||
[ -r @SYSCONFDIR@/rc.conf ] && . @SYSCONFDIR@/rc.conf
|
[ -r @SYSCONFDIR@/rc.conf ] && . @SYSCONFDIR@/rc.conf
|
||||||
|
|
||||||
# Support LiveCD foo
|
# Support LiveCD foo
|
||||||
@@ -38,7 +39,11 @@ fi
|
|||||||
|
|
||||||
# If $svcdir is still mounted, preserve it if we can
|
# If $svcdir is still mounted, preserve it if we can
|
||||||
mnt=$(mountinfo --node "${RC_SVCDIR}")
|
mnt=$(mountinfo --node "${RC_SVCDIR}")
|
||||||
if [ -n "${mnt}" -a -w "${RC_LIBDIR}" ]; then
|
if [ -n "${mnt}" ] && \
|
||||||
|
rm -rf "${RC_LIBDIR}/tmp.$$" && \
|
||||||
|
mkdir -p "${RC_LIBDIR}/tmp.$$" 2>/dev/null \
|
||||||
|
; then
|
||||||
|
rmdir "${RC_LIBDIR}/tmp.$$"
|
||||||
f_opts="-m -c"
|
f_opts="-m -c"
|
||||||
[ "${RC_UNAME}" = "Linux" ] && f_opts="-c"
|
[ "${RC_UNAME}" = "Linux" ] && f_opts="-c"
|
||||||
if type fuser >/dev/null 2>&1; then
|
if type fuser >/dev/null 2>&1; then
|
||||||
@@ -75,13 +80,27 @@ if [ "${RC_UNAME}" = "Linux" ]; then
|
|||||||
# We need the do_unmount function
|
# We need the do_unmount function
|
||||||
. "${RC_LIBDIR}"/sh/rc-mount.sh
|
. "${RC_LIBDIR}"/sh/rc-mount.sh
|
||||||
eindent
|
eindent
|
||||||
|
no_umounts_r="/dev|/dev/.*|${RC_SVCDIR}"
|
||||||
|
# RC_NO_UMOUNTS is an env var that can be set by plugins
|
||||||
|
OIFS=${IFS} SIFS=${IFS-y}
|
||||||
|
IFS=$IFS:
|
||||||
|
for x in ${no_umounts} ${RC_NO_UMOUNTS}; do
|
||||||
|
no_umounts_r="${no_umounts_r}|${x}"
|
||||||
|
done
|
||||||
|
if [ "${SIFS}" = "y" ]; then
|
||||||
|
IFS=$OIFS
|
||||||
|
else
|
||||||
|
unset IFS
|
||||||
|
fi
|
||||||
|
no_umounts_r="${no_umounts_r}|/proc|/proc/.*|/sys|/sys/.*"
|
||||||
|
no_umounts_r="^(${no_umounts_r})$"
|
||||||
fs=
|
fs=
|
||||||
for x in ${net_fs_list}; do
|
for x in ${net_fs_list}; do
|
||||||
fs="${fs}${fs:+|}${x}"
|
fs="${fs}${fs:+|}${x}"
|
||||||
done
|
done
|
||||||
[ -n "${fs}" ] && fs="^(${fs})$"
|
[ -n "${fs}" ] && fs="^(${fs})$"
|
||||||
do_unmount "mount -n -o remount,ro" \
|
do_unmount "mount -n -o remount,ro" \
|
||||||
--skip-point-regex "^(/dev|/dev/.*|/proc|/proc/.*|/sys|/sys/.*)$" \
|
--skip-point-regex "${no_umounts_r}" \
|
||||||
${fs:+--skip-fstype-regex} ${fs} --nonetdev
|
${fs:+--skip-fstype-regex} ${fs} --nonetdev
|
||||||
eoutdent
|
eoutdent
|
||||||
eend $?
|
eend $?
|
||||||
|
|||||||
@@ -74,8 +74,12 @@ start()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
ebegin "Setting system clock using the hardware clock [${utc}]"
|
ebegin "Setting system clock using the hardware clock [${utc}]"
|
||||||
if [ -e /proc/modules -a ! -e /dev/rtc ]; then
|
local rtc=
|
||||||
modprobe -q rtc || modprobe -q genrtc
|
for rtc in /dev/rtc /dev/rtc[0-9]*; do
|
||||||
|
[ -e "${rtc}" ] && break
|
||||||
|
done
|
||||||
|
if [ ! -e "${rtc}" -a -e /proc/modules ]; then
|
||||||
|
modprobe -q rtc-cmos || modprobe -q rtc || modprobe -q genrtc
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -e /etc/adjtime ] && yesno ${clock_adjfile}; then
|
if [ -e /etc/adjtime ] && yesno ${clock_adjfile}; then
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ ipfw() {
|
|||||||
/sbin/ipfw -f -q "$@"
|
/sbin/ipfw -f -q "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
have_ip6() {
|
||||||
|
sysctl net.ipv6 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
# Load the kernel module
|
# Load the kernel module
|
||||||
if ! sysctl net.inet.ip.fw.enable=1 >/dev/null 2>&1; then
|
if ! sysctl net.inet.ip.fw.enable=1 >/dev/null 2>&1; then
|
||||||
@@ -36,13 +40,15 @@ init() {
|
|||||||
ipfw add deny all from any to 127.0.0.0/8
|
ipfw add deny all from any to 127.0.0.0/8
|
||||||
ipfw add deny ip from 127.0.0.0/8 to any
|
ipfw add deny ip from 127.0.0.0/8 to any
|
||||||
|
|
||||||
ipfw add pass ip6 from any to any via lo0
|
if have_ip6; then
|
||||||
ipfw add deny ip6 from any to ::1
|
ipfw add pass ip6 from any to any via lo0
|
||||||
ipfw add deny ip6 from ::1 to any
|
ipfw add deny ip6 from any to ::1
|
||||||
|
ipfw add deny ip6 from ::1 to any
|
||||||
|
|
||||||
ipfw add pass ip6 from :: to ff02::/16 proto ipv6-icmp
|
ipfw add pass ip6 from :: to ff02::/16 proto ipv6-icmp
|
||||||
ipfw add pass ip6 from fe80::/10 to fe80::/10 proto ipv6-icmp
|
ipfw add pass ip6 from fe80::/10 to fe80::/10 proto ipv6-icmp
|
||||||
ipfw add pass ip6 from fe80::/10 to ff02::/16 proto ipv6-icmp
|
ipfw add pass ip6 from fe80::/10 to ff02::/16 proto ipv6-icmp
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
@@ -62,9 +68,11 @@ start() {
|
|||||||
ipfw add pass udp from me to any keep-state
|
ipfw add pass udp from me to any keep-state
|
||||||
ipfw add pass icmp from me to any keep-state
|
ipfw add pass icmp from me to any keep-state
|
||||||
|
|
||||||
ipfw add pass tcp from me6 to any setup keep-state
|
if have_ip6; then
|
||||||
ipfw add pass udp from me6 to any keep-state
|
ipfw add pass tcp from me6 to any setup keep-state
|
||||||
ipfw add pass icmp from me6 to any keep-state
|
ipfw add pass udp from me6 to any keep-state
|
||||||
|
ipfw add pass icmp from me6 to any keep-state
|
||||||
|
fi
|
||||||
|
|
||||||
# Allow DHCP.
|
# Allow DHCP.
|
||||||
ipfw add pass udp from 0.0.0.0 68 to 255.255.255.255 67 out
|
ipfw add pass udp from 0.0.0.0 68 to 255.255.255.255 67 out
|
||||||
@@ -77,11 +85,13 @@ start() {
|
|||||||
# Allow "mandatory" ICMP in.
|
# Allow "mandatory" ICMP in.
|
||||||
ipfw add pass icmp from any to any icmptype 3,4,11
|
ipfw add pass icmp from any to any icmptype 3,4,11
|
||||||
|
|
||||||
# Allow ICMPv6 destination unreach
|
if have_ip6; then
|
||||||
ipfw add pass ip6 from any to any icmp6types 1 proto ipv6-icmp
|
# Allow ICMPv6 destination unreach
|
||||||
|
ipfw add pass ip6 from any to any icmp6types 1 proto ipv6-icmp
|
||||||
|
|
||||||
# Allow NS/NA/toobig (don't filter it out)
|
# Allow NS/NA/toobig (don't filter it out)
|
||||||
ipfw add pass ip6 from any to any icmp6types 2,135,136 proto ipv6-icmp
|
ipfw add pass ip6 from any to any icmp6types 2,135,136 proto ipv6-icmp
|
||||||
|
fi
|
||||||
|
|
||||||
# Add permits for this workstations published services below
|
# Add permits for this workstations published services below
|
||||||
# Only IPs and nets in firewall_allowservices is allowed in.
|
# Only IPs and nets in firewall_allowservices is allowed in.
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ start()
|
|||||||
stop()
|
stop()
|
||||||
{
|
{
|
||||||
# We never unmount / or /dev or $RC_SVCDIR
|
# We never unmount / or /dev or $RC_SVCDIR
|
||||||
local x= no_umounts="/|/dev|/dev/.*|${RC_SVCDIR}"
|
local x= no_umounts_r="/|/dev|/dev/.*|${RC_SVCDIR}"
|
||||||
|
|
||||||
# RC_NO_UMOUNTS is an env var that can be set by plugins
|
# RC_NO_UMOUNTS is an env var that can be set by plugins
|
||||||
OIFS=${IFS} SIFS=${IFS-y}
|
OIFS=${IFS} SIFS=${IFS-y}
|
||||||
IFS=$IFS:
|
IFS=$IFS:
|
||||||
for x in ${no_umounts} ${RC_NO_UMOUNTS}; do
|
for x in ${no_umounts} ${RC_NO_UMOUNTS}; do
|
||||||
no_umounts="${no_umounts}|${x}"
|
no_umounts_r="${no_umounts_r}|${x}"
|
||||||
done
|
done
|
||||||
if [ "${SIFS}" = "y" ]; then
|
if [ "${SIFS}" = "y" ]; then
|
||||||
IFS=$OIFS
|
IFS=$OIFS
|
||||||
@@ -45,9 +45,9 @@ stop()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${RC_UNAME}" = "Linux" ]; then
|
if [ "${RC_UNAME}" = "Linux" ]; then
|
||||||
no_umounts="${no_umounts}|/proc|/proc/.*|/sys|/sys/.*"
|
no_umounts_r="${no_umounts_r}|/proc|/proc/.*|/sys|/sys/.*"
|
||||||
fi
|
fi
|
||||||
no_umounts="^(${no_umounts})$"
|
no_umounts_r="^(${no_umounts_r})$"
|
||||||
|
|
||||||
# Flush all pending disk writes now
|
# Flush all pending disk writes now
|
||||||
sync; sync
|
sync; sync
|
||||||
@@ -63,7 +63,7 @@ stop()
|
|||||||
# Umount loopback devices
|
# Umount loopback devices
|
||||||
einfo "Unmounting loopback devices"
|
einfo "Unmounting loopback devices"
|
||||||
eindent
|
eindent
|
||||||
do_unmount "umount -d" --skip-point-regex "${no_umounts}" \
|
do_unmount "umount -d" --skip-point-regex "${no_umounts_r}" \
|
||||||
--node-regex "^/dev/loop"
|
--node-regex "^/dev/loop"
|
||||||
eoutdent
|
eoutdent
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ stop()
|
|||||||
fs="${fs}${fs:+|}${x}"
|
fs="${fs}${fs:+|}${x}"
|
||||||
done
|
done
|
||||||
[ -n "${fs}" ] && fs="^(${fs})$"
|
[ -n "${fs}" ] && fs="^(${fs})$"
|
||||||
do_unmount "umount" --skip-point-regex "${no_umounts}" \
|
do_unmount "umount" --skip-point-regex "${no_umounts_r}" \
|
||||||
${fs:+--skip-fstype-regex} ${fs} --nonetdev
|
${fs:+--skip-fstype-regex} ${fs} --nonetdev
|
||||||
eoutdent
|
eoutdent
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ start()
|
|||||||
x=${KV#*.*.}
|
x=${KV#*.*.}
|
||||||
local KV_MICRO=${x%%-*}
|
local KV_MICRO=${x%%-*}
|
||||||
|
|
||||||
local list= x= xx= y= args= cnt=0
|
local list= x= xx= y= args= mpargs= cnt=0 a=
|
||||||
for x in "${KV}" \
|
for x in "${KV}" \
|
||||||
${KV_MAJOR}.${KV_MINOR}.${KV_MICRO} \
|
${KV_MAJOR}.${KV_MINOR}.${KV_MICRO} \
|
||||||
${KV_MAJOR}.${KV_MINOR} \
|
${KV_MAJOR}.${KV_MINOR} \
|
||||||
@@ -34,17 +34,29 @@ start()
|
|||||||
[ -z "${list}" ] && list=${modules}
|
[ -z "${list}" ] && list=${modules}
|
||||||
|
|
||||||
for x in ${list}; do
|
for x in ${list}; do
|
||||||
ebegin "Loading module ${x}"
|
a=${x#*:}
|
||||||
|
if [ "${a}" = "${x}" ]; then
|
||||||
|
unset mpargs
|
||||||
|
ebegin "Loading module ${x}"
|
||||||
|
else
|
||||||
|
x=${x%%:*}
|
||||||
|
mpargs="-o ${a}"
|
||||||
|
ebegin "Loading module ${x} as ${a}"
|
||||||
|
fi
|
||||||
|
aa=$(shell_var "${a}")
|
||||||
xx=$(shell_var "${x}")
|
xx=$(shell_var "${x}")
|
||||||
for y in "${KV}" \
|
for y in "${KV}" \
|
||||||
${KV_MAJOR}.${KV_MINOR}.${KV_MICRO} \
|
${KV_MAJOR}.${KV_MINOR}.${KV_MICRO} \
|
||||||
${KV_MAJOR}.${KV_MINOR} \
|
${KV_MAJOR}.${KV_MINOR} \
|
||||||
; do
|
; do
|
||||||
|
eval args=\$module_${aa}_args_$(shell_var "${y}")
|
||||||
|
[ -n "${args}" ] && break
|
||||||
eval args=\$module_${xx}_args_$(shell_var "${y}")
|
eval args=\$module_${xx}_args_$(shell_var "${y}")
|
||||||
[ -n "${args}" ] && break
|
[ -n "${args}" ] && break
|
||||||
done
|
done
|
||||||
|
[ -z "${args}" ] && eval args=\$module_${aa}_args
|
||||||
[ -z "${args}" ] && eval args=\$module_${xx}_args
|
[ -z "${args}" ] && eval args=\$module_${xx}_args
|
||||||
eval modprobe -q "${x}" "${args}"
|
eval modprobe -q "${mpargs}" "${x}" "${args}"
|
||||||
eend $? "Failed to load ${x}" && cnt=$((${cnt} + 1))
|
eend $? "Failed to load ${x}" && cnt=$((${cnt} + 1))
|
||||||
done
|
done
|
||||||
einfo "Autoloaded ${cnt} module(s)"
|
einfo "Autoloaded ${cnt} module(s)"
|
||||||
|
|||||||
@@ -663,9 +663,14 @@ stop()
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
! yesno ${IN_BACKGROUND} && \
|
# If not in background, and not loopback then bring the interface down
|
||||||
[ "${IFACE}" != "lo" -a "${IFACE}" != "lo0" ] && \
|
# unless overridden.
|
||||||
_down 2>/dev/null
|
if ! yesno ${IN_BACKGROUND} && \
|
||||||
|
[ "${IFACE}" != "lo" -a "${IFACE}" != "lo0" ]; then
|
||||||
|
eval module=\$ifdown_${IFVAR}
|
||||||
|
module=${module:-${ifdown:-YES}}
|
||||||
|
yesno ${module} && _down 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
type resolvconf >/dev/null 2>&1 && resolvconf -d "${IFACE}" 2>/dev/null
|
type resolvconf >/dev/null 2>&1 && resolvconf -d "${IFACE}" 2>/dev/null
|
||||||
|
|
||||||
@@ -33,8 +33,9 @@ depend()
|
|||||||
|
|
||||||
config /etc/fstab
|
config /etc/fstab
|
||||||
need net ${pmap}
|
need net ${pmap}
|
||||||
use afc-client amd autofs dns nfs nfsmount portmap rpcbind rpc.statd
|
use afc-client amd autofs openvpn
|
||||||
keyword nojail noopenvz noprefix novserver
|
use dns nfs nfsmount portmap rpcbind rpc.statd rpc.lockd
|
||||||
|
keyword nojail noprefix novserver
|
||||||
}
|
}
|
||||||
|
|
||||||
start()
|
start()
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ start() {
|
|||||||
|
|
||||||
local v= f=
|
local v= f=
|
||||||
for v in font8x16 font8x14 font8x8; do
|
for v in font8x16 font8x14 font8x8; do
|
||||||
f=$(eval \$"${v}")
|
eval f=\$${v}
|
||||||
if [ -n "${f}" ]; then
|
if [ -n "${f}" ]; then
|
||||||
ebegin "Setting font ${f}"
|
ebegin "Setting font ${f}"
|
||||||
vidcontrol -f ${v##FONT} ${f}
|
vidcontrol -f ${v##font} ${f}
|
||||||
eend $?
|
eend $?
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -202,4 +202,4 @@ Rinse and repeat for the other verbose functions.
|
|||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr printf 3 ,
|
.Xr printf 3 ,
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples <roy@marples.name>
|
||||||
|
|||||||
@@ -61,4 +61,4 @@ does the same and also prints the full path of the service to stdout.
|
|||||||
.Xr rc 8 ,
|
.Xr rc 8 ,
|
||||||
.Xr stdout 3
|
.Xr stdout 3
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
@@ -61,4 +61,4 @@ Show information only for the named
|
|||||||
.Xr rc 8 ,
|
.Xr rc 8 ,
|
||||||
.Xr rc-update 8
|
.Xr rc-update 8
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
@@ -77,4 +77,4 @@ Show all services.
|
|||||||
.Xr rc 8 ,
|
.Xr rc 8 ,
|
||||||
.Xr rc-status 8
|
.Xr rc-status 8
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
2
man/rc.8
2
man/rc.8
@@ -74,4 +74,4 @@ Changes to the single runlevel and then halts the host.
|
|||||||
.Xr rc-status 8 ,
|
.Xr rc-status 8 ,
|
||||||
.Xr rc-update 8
|
.Xr rc-update 8
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples <roy@marples.name>
|
||||||
|
|||||||
@@ -70,4 +70,4 @@ is set to
|
|||||||
.Xr rc_stringlist_free 3 ,
|
.Xr rc_stringlist_free 3 ,
|
||||||
.Xr sh 1
|
.Xr sh 1
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
@@ -110,4 +110,4 @@ when done.
|
|||||||
.Xr rc_stringlist_free 3 ,
|
.Xr rc_stringlist_free 3 ,
|
||||||
.Xr runscript 8
|
.Xr runscript 8
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
@@ -67,4 +67,4 @@ Each RC_PID should be freed in the list as well as the list itself when done.
|
|||||||
.Xr free 3 ,
|
.Xr free 3 ,
|
||||||
.Xr queue 3
|
.Xr queue 3
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
@@ -48,4 +48,4 @@ Plugins can affect the parent environemnt by writing NULL separated strings to
|
|||||||
.Xr rc 8 ,
|
.Xr rc 8 ,
|
||||||
.Xr runscript 8
|
.Xr runscript 8
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
@@ -63,4 +63,4 @@ Rinse and repeat for the other verbose functions.
|
|||||||
.Xr free 3
|
.Xr free 3
|
||||||
.Xr rc_stringlist_free 3
|
.Xr rc_stringlist_free 3
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
@@ -227,4 +227,4 @@ normally holds the volatile state data for services on a RAM backed disk.
|
|||||||
.Xr rc_stringlist_free 3 ,
|
.Xr rc_stringlist_free 3 ,
|
||||||
.Xr start-stop-daemon 8
|
.Xr start-stop-daemon 8
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
@@ -85,4 +85,4 @@ itself.
|
|||||||
.Xr queue 3 ,
|
.Xr queue 3 ,
|
||||||
.Xr strcmp 3
|
.Xr strcmp 3
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd Mar 19, 2008
|
.Dd September 19, 2008
|
||||||
.Dt RUNSCRIPT 8 SMM
|
.Dt RUNSCRIPT 8 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -173,8 +173,9 @@ If
|
|||||||
does not equal 0 then output the string using
|
does not equal 0 then output the string using
|
||||||
.Ic eerror
|
.Ic eerror
|
||||||
and !! in square brackets
|
and !! in square brackets
|
||||||
at the end of the line. Otherwise output ok in square brackets at the end of
|
at the end of the line.
|
||||||
the line. The value of
|
Otherwise output ok in square brackets at the end of the line.
|
||||||
|
The value of
|
||||||
.Ar retval
|
.Ar retval
|
||||||
is returned.
|
is returned.
|
||||||
.It Ic ewend Ar retval Op Ar string
|
.It Ic ewend Ar retval Op Ar string
|
||||||
@@ -193,6 +194,14 @@ output when the environment variable
|
|||||||
.Va EINFO_VERBOSE
|
.Va EINFO_VERBOSE
|
||||||
is true.
|
is true.
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
|
.It Ic ewaitfile Ar timeout Ar file1 Ar file2 ...
|
||||||
|
Wait for
|
||||||
|
.Ar timeout
|
||||||
|
seconds until all files exist.
|
||||||
|
Returns 0 if all files exist, otherwise non zero.
|
||||||
|
If
|
||||||
|
.Ar timeout
|
||||||
|
is less then 1 then we wait indefinitely.
|
||||||
.It Ic is_newer_than Ar file1 Ar file2 ...
|
.It Ic is_newer_than Ar file1 Ar file2 ...
|
||||||
If
|
If
|
||||||
.Ar file1
|
.Ar file1
|
||||||
@@ -205,7 +214,7 @@ is a directory, then check all it's contents too.
|
|||||||
.It Ic is_older_than Ar file1 Ar file2 ...
|
.It Ic is_older_than Ar file1 Ar file2 ...
|
||||||
If
|
If
|
||||||
.Ar file1
|
.Ar file1
|
||||||
is older than
|
is newer than
|
||||||
.Ar file2
|
.Ar file2
|
||||||
return 0, otherwise 1.
|
return 0, otherwise 1.
|
||||||
If
|
If
|
||||||
@@ -432,6 +441,16 @@ show()
|
|||||||
}
|
}
|
||||||
|
|
||||||
.Ed
|
.Ed
|
||||||
|
.Sh BUGS
|
||||||
|
Because of the way we load our configuration files and the need to handle
|
||||||
|
more than one service directory, you can only use symlinks in service
|
||||||
|
directories to other services in the same directory.
|
||||||
|
You cannot symlink to a service in a different directory even if it is
|
||||||
|
another service directory.
|
||||||
|
.Pp
|
||||||
|
is_older_than should return 0 on success.
|
||||||
|
Instead we return 1 to be compliant with Gentoo baselayout.
|
||||||
|
Users are encouraged to use the is_newer_than function which returns correctly.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr einfo 3 ,
|
.Xr einfo 3 ,
|
||||||
.Xr rc 8 ,
|
.Xr rc 8 ,
|
||||||
@@ -442,4 +461,4 @@ show()
|
|||||||
.Xr start-stop-daemon 8 ,
|
.Xr start-stop-daemon 8 ,
|
||||||
.Xr uname 1
|
.Xr uname 1
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd Feb 24, 2008
|
.Dd September 27, 2008
|
||||||
.Dt START-STOP-DAEMON 8 SMM
|
.Dt START-STOP-DAEMON 8 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -44,6 +44,11 @@
|
|||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
provides a consistent method of starting, stopping and signalling daemons.
|
provides a consistent method of starting, stopping and signalling daemons.
|
||||||
|
If neither
|
||||||
|
.Fl K , -stop
|
||||||
|
nor
|
||||||
|
.Fl s , -signal
|
||||||
|
are provided, then we assume we are starting the daemon.
|
||||||
If a daemon cannot background by itself, nor create a pidfile,
|
If a daemon cannot background by itself, nor create a pidfile,
|
||||||
.Nm
|
.Nm
|
||||||
can do it for the daemon in a secure fashion.
|
can do it for the daemon in a secure fashion.
|
||||||
@@ -67,16 +72,8 @@ Here are the options to specify the daemon and how it should start or stop:
|
|||||||
The
|
The
|
||||||
.Ar daemon
|
.Ar daemon
|
||||||
we start or stop.
|
we start or stop.
|
||||||
If the
|
If this option is not specified, then the first non option argument
|
||||||
.Ar daemon
|
is used.
|
||||||
is a script and you are not using the pidfile or process name options,
|
|
||||||
then you should replace
|
|
||||||
.Ar daemon
|
|
||||||
with the interpreter and pass
|
|
||||||
.Ar daemon
|
|
||||||
as an argument. Below is an example:
|
|
||||||
.Pp
|
|
||||||
start-stop-daemon -Sx /usr/bin/perl -- /usr/bin/daemon.pl
|
|
||||||
.It Fl p , -pidfile Ar pidfile
|
.It Fl p , -pidfile Ar pidfile
|
||||||
When starting, we expect the daemon to create a valid
|
When starting, we expect the daemon to create a valid
|
||||||
.Ar pidfile
|
.Ar pidfile
|
||||||
@@ -97,10 +94,17 @@ name here also.
|
|||||||
.It Fl t , -test
|
.It Fl t , -test
|
||||||
Print the action(s) that would be taken, but don't actually do anything.
|
Print the action(s) that would be taken, but don't actually do anything.
|
||||||
The return value is set as if the command was taken and worked.
|
The return value is set as if the command was taken and worked.
|
||||||
|
.It Fl v , -verbose
|
||||||
|
P
|
||||||
|
Print the action(s) that are taken just before doing them.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
These options are only used for starting daemons:
|
These options are only used for starting daemons:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
|
.It Fl a , -startas Ar name
|
||||||
|
Change the process name of the daemon to
|
||||||
|
.Ar name .
|
||||||
|
This just changes the first argument passed to the daemon.
|
||||||
.It Fl b , -background
|
.It Fl b , -background
|
||||||
Force the daemon into the background. Some daemons don't create pidfiles, so a
|
Force the daemon into the background. Some daemons don't create pidfiles, so a
|
||||||
good trick is to get the daemon to run in the foreground, and use the this
|
good trick is to get the daemon to run in the foreground, and use the this
|
||||||
@@ -116,6 +120,8 @@ as the path to the daemon, chdir and pidfile, should be relative to the chroot.
|
|||||||
Set the environment variable VAR to VALUE.
|
Set the environment variable VAR to VALUE.
|
||||||
.It Fl g , -group Ar group
|
.It Fl g , -group Ar group
|
||||||
Start the daemon as in the group.
|
Start the daemon as in the group.
|
||||||
|
.It Fl k , -umask Ar mode
|
||||||
|
Set the umask of the daemon.
|
||||||
.It Fl m , -make-pidfile
|
.It Fl m , -make-pidfile
|
||||||
Saves the pid of the daemon in the file specified by the
|
Saves the pid of the daemon in the file specified by the
|
||||||
.Fl p , -pidfile
|
.Fl p , -pidfile
|
||||||
@@ -149,6 +155,12 @@ assumed.
|
|||||||
.Va SSD_NICELEVEL
|
.Va SSD_NICELEVEL
|
||||||
can also set the scheduling priority of the daemon, but the command line
|
can also set the scheduling priority of the daemon, but the command line
|
||||||
option takes precedence.
|
option takes precedence.
|
||||||
|
.Pp
|
||||||
|
.Va SSD_STARTWAIT
|
||||||
|
overrides the number of milliseconds set in
|
||||||
|
.Pa /etc/rc.conf
|
||||||
|
.Nm
|
||||||
|
waits for to check the daemon is still running.
|
||||||
.Sh NOTE
|
.Sh NOTE
|
||||||
.Nm
|
.Nm
|
||||||
uses
|
uses
|
||||||
@@ -163,6 +175,9 @@ to stop or signal.
|
|||||||
.Xr getopt 3 ,
|
.Xr getopt 3 ,
|
||||||
.Xr nice 2 ,
|
.Xr nice 2 ,
|
||||||
.Xr rc_find_pids 3
|
.Xr rc_find_pids 3
|
||||||
|
.Sh BUGS
|
||||||
|
.Nm
|
||||||
|
cannot stop an interperted daemon that no longer exists without a pidfile.
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
.Nm
|
.Nm
|
||||||
first appeared in Debian.
|
first appeared in Debian.
|
||||||
@@ -170,4 +185,4 @@ first appeared in Debian.
|
|||||||
This is a complete re-implementation with the process finding code in the
|
This is a complete re-implementation with the process finding code in the
|
||||||
OpenRC library (librc, -lrc) so other programs can make use of it.
|
OpenRC library (librc, -lrc) so other programs can make use of it.
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An Roy Marples" <roy@marples.name>
|
||||||
|
|||||||
31
mk/cc.mk
31
mk/cc.mk
@@ -1,5 +1,4 @@
|
|||||||
# Copyright 2008 Roy Marples <roy@marples.name>
|
# Copyright 2008 Roy Marples <roy@marples.name>
|
||||||
# All rights reserved. Released under the 2-clause BSD license.
|
|
||||||
|
|
||||||
# Setup some good default CFLAGS
|
# Setup some good default CFLAGS
|
||||||
CFLAGS?= -O2
|
CFLAGS?= -O2
|
||||||
@@ -10,15 +9,25 @@ _CSTD_SH= if test -n "${CSTD}"; then echo "-std=${CSTD}"; else echo ""; fi
|
|||||||
_CSTD!= ${_CSTD_SH}
|
_CSTD!= ${_CSTD_SH}
|
||||||
CFLAGS+= ${_CSTD}$(shell ${_CSTD_SH})
|
CFLAGS+= ${_CSTD}$(shell ${_CSTD_SH})
|
||||||
|
|
||||||
# Try and use some good cc flags
|
# Try and use some good cc flags if we're building from git
|
||||||
_CC_FLAGS= -pedantic -Wall -Wunused -Wimplicit -Wshadow -Wformat=2 \
|
# We don't use -pedantic as it will warn about our perfectly valid
|
||||||
-Wmissing-declarations -Wno-missing-prototypes -Wwrite-strings \
|
# use of %m in our logger.
|
||||||
-Wbad-function-cast -Wnested-externs -Wcomment -Winline \
|
_CCFLAGS= -Wall -Wextra -Wimplicit -Wshadow -Wformat=2 \
|
||||||
-Wchar-subscripts -Wcast-align -Wno-format-nonliteral \
|
-Wmissing-prototypes -Wmissing-declarations \
|
||||||
-Wdeclaration-after-statement -Wsequence-point -Wextra
|
-Wmissing-noreturn -Wmissing-format-attribute \
|
||||||
_CC_FLAGS_SH= for f in ${_CC_FLAGS}; do \
|
-Wnested-externs \
|
||||||
if ${CC} $$f -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \
|
-Winline -Wwrite-strings -Wcast-align -Wcast-qual \
|
||||||
|
-Wpointer-arith \
|
||||||
|
-Wdeclaration-after-statement -Wsequence-point
|
||||||
|
|
||||||
|
# We should be using -Wredundant-decls, but our library hidden proto stuff
|
||||||
|
# gives loads of warnings. I don't fully understand it (the hidden proto,
|
||||||
|
# not the warning) so we just silence the warning.
|
||||||
|
|
||||||
|
_CC_FLAGS_SH= for f in ${_CCFLAGS}; do \
|
||||||
|
if echo "int main(void) { return 0;} " | \
|
||||||
|
${CC} $$f -S -xc -o /dev/null - ; \
|
||||||
then printf "%s" "$$f "; fi \
|
then printf "%s" "$$f "; fi \
|
||||||
done
|
done;
|
||||||
_CC_FLAGS!= ${_CC_FLAGS_SH}
|
_CC_FLAGS!= ${_CC_FLAGS_SH}
|
||||||
CFLAGS+= ${_CC_FLAGS}$(shell ${CC_FLAGS_SH})
|
CFLAGS+= ${_CC_FLAGS}$(shell ${_CC_FLAGS_SH})
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
_RC_DEBUG_SH= case "${DEBUG}" in "") echo "";; *) echo "-DRC_DEBUG";; esac
|
_RC_DEBUG_SH= case "${DEBUG}" in "") echo "";; *) echo "-DRC_DEBUG";; esac
|
||||||
_RC_DEBUG!= ${_RC_DEBUG_SH}
|
_RC_DEBUG!= ${_RC_DEBUG_SH}
|
||||||
CFLAGS+= ${_RC_DEBUG}$(shell ${_RC_DEBUG_SH})
|
CPPFLAGS+= ${_RC_DEBUG}$(shell ${_RC_DEBUG_SH})
|
||||||
|
|
||||||
# Should we enable this with a different flag?
|
# Should we enable this with a different flag?
|
||||||
_LD_DEBUG_SH= case "${DEBUG}" in "") echo "";; *) echo "-Wl,--rpath=../librc -Wl,--rpath=../libeinfo";; esac
|
_LD_DEBUG_SH= case "${DEBUG}" in "") echo "";; *) echo "-Wl,--rpath=../librc -Wl,--rpath=../libeinfo";; esac
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ CLEANFILES+= .depend
|
|||||||
IGNOREFILES+= .depend
|
IGNOREFILES+= .depend
|
||||||
|
|
||||||
.depend: ${SRCS}
|
.depend: ${SRCS}
|
||||||
${CC} ${CFLAGS} -MM ${SRCS} > .depend
|
${CC} ${CPPFLAGS} -MM ${SRCS} > .depend
|
||||||
|
|
||||||
depend: .depend
|
depend: .depend
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ CLEANFILES+= ${OBJS} ${SOBJS} ${_LIBS} ${SHLIB_LINK}
|
|||||||
.SUFFIXES: .So
|
.SUFFIXES: .So
|
||||||
|
|
||||||
.c.So:
|
.c.So:
|
||||||
${CC} ${PICFLAG} -DPIC ${CFLAGS} -c $< -o $@
|
${CC} ${PICFLAG} -DPIC ${CPPFLAGS} ${CFLAGS} -c $< -o $@
|
||||||
|
|
||||||
all: depend ${_LIBS}
|
all: depend ${_LIBS}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
LIBTERMCAP?= -lncurses
|
LIBTERMCAP?= -lncurses
|
||||||
CFLAGS+= -DHAVE_TERMCAP
|
CPPFLAGS+= -DHAVE_TERMCAP
|
||||||
LDADD+= ${LIBTERMCAP}
|
LDADD+= ${LIBTERMCAP}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2008 Roy Marples <roy@marples.name>
|
# Copyright 2008 Roy Marples <roy@marples.name>
|
||||||
# All rights reserved. Released under the 2-clause BSD license.
|
# All rights reserved. Released under the 2-clause BSD license.
|
||||||
|
|
||||||
CFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=600
|
CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=600
|
||||||
LIBDL= -Wl,-Bdynamic -ldl
|
LIBDL= -Wl,-Bdynamic -ldl
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
LIBPAM?= -lpam
|
LIBPAM?= -lpam
|
||||||
CFLAGS+= -DHAVE_PAM
|
CPPFLAGS+= -DHAVE_PAM
|
||||||
LDADD+= ${LIBPAM}
|
LDADD+= ${LIBPAM}
|
||||||
|
|
||||||
PAMDIR?= /etc/pam.d
|
PAMDIR?= /etc/pam.d
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ CLEANFILES+= ${OBJS} ${PROG}
|
|||||||
|
|
||||||
all: depend ${PROG}
|
all: depend ${PROG}
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@
|
||||||
|
|
||||||
${PROG}: ${SCRIPTS} ${OBJS}
|
${PROG}: ${SCRIPTS} ${OBJS}
|
||||||
${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD}
|
${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD}
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ SED_REPLACE= -e 's:@SHELL@:${SH}:g' -e 's:@LIB@:${LIBNAME}:g' -e 's:@SYSCONFDIR
|
|||||||
.in:
|
.in:
|
||||||
${SED} ${SED_REPLACE} ${SED_EXTRA} $< > $@
|
${SED} ${SED_REPLACE} ${SED_EXTRA} $< > $@
|
||||||
|
|
||||||
all: ${OBJS}
|
all: ${OBJS} ${TARGETS}
|
||||||
|
|
||||||
realinstall: ${BIN} ${CONF} ${CONF_APPEND}
|
realinstall: ${BIN} ${CONF} ${INC}
|
||||||
@if test -n "${DIR}"; then \
|
@if test -n "${DIR}"; then \
|
||||||
${ECHO} ${INSTALL} -d ${DESTDIR}/${DIR}; \
|
${ECHO} ${INSTALL} -d ${DESTDIR}/${DIR}; \
|
||||||
${INSTALL} -d ${DESTDIR}/${DIR} || exit $$?; \
|
${INSTALL} -d ${DESTDIR}/${DIR} || exit $$?; \
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
LIBTERMCAP?= -ltermcap
|
LIBTERMCAP?= -ltermcap
|
||||||
CFLAGS+= -DHAVE_TERMCAP
|
CPPFLAGS+= -DHAVE_TERMCAP
|
||||||
LDADD+= ${LIBTERMCAP}
|
LDADD+= ${LIBTERMCAP}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
bonding_depend()
|
bonding_depend()
|
||||||
{
|
{
|
||||||
before interface macchanger
|
before interface macchanger
|
||||||
program /sbin/ifenslave
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_config_vars="$_config_vars slaves"
|
_config_vars="$_config_vars slaves"
|
||||||
@@ -16,7 +15,7 @@ _is_bond()
|
|||||||
|
|
||||||
bonding_pre_start()
|
bonding_pre_start()
|
||||||
{
|
{
|
||||||
local s= slaves="$(_get_array "slaves_${IFVAR}")"
|
local x= s= slaves="$(_get_array "slaves_${IFVAR}")"
|
||||||
|
|
||||||
[ -z "${slaves}" ] && return 0
|
[ -z "${slaves}" ] && return 0
|
||||||
|
|
||||||
@@ -40,6 +39,16 @@ bonding_pre_start()
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Configure the bond.
|
||||||
|
# Nice and dynamic :)
|
||||||
|
for x in /sys/class/net/"${IFACE}"/bonding/*; do
|
||||||
|
[ -f "${x}" ] || continue
|
||||||
|
eval s=\$${x##*/}_${IFVAR}
|
||||||
|
if [ -n "${s}" ]; then
|
||||||
|
echo "${s}" >"${x}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
ebegin "Adding slaves to ${IFACE}"
|
ebegin "Adding slaves to ${IFACE}"
|
||||||
eindent
|
eindent
|
||||||
einfo "${slaves}"
|
einfo "${slaves}"
|
||||||
@@ -53,7 +62,7 @@ bonding_pre_start()
|
|||||||
# Must force the slaves to a particular state before adding them
|
# Must force the slaves to a particular state before adding them
|
||||||
for IFACE in ${slaves}; do
|
for IFACE in ${slaves}; do
|
||||||
_delete_addresses
|
_delete_addresses
|
||||||
_up
|
_down
|
||||||
done
|
done
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -62,7 +71,13 @@ bonding_pre_start()
|
|||||||
|
|
||||||
# finally add in slaves
|
# finally add in slaves
|
||||||
eoutdent
|
eoutdent
|
||||||
/sbin/ifenslave "${IFACE}" ${slaves} >/dev/null
|
if [ -d /sys/class/net ]; then
|
||||||
|
for s in ${slaves}; do
|
||||||
|
echo "+${s}" >/sys/class/net/"${IFACE}"/bonding/slaves
|
||||||
|
done
|
||||||
|
else
|
||||||
|
/sbin/ifenslave "${IFACE}" ${slaves} >/dev/null
|
||||||
|
fi
|
||||||
eend $?
|
eend $?
|
||||||
|
|
||||||
return 0 #important
|
return 0 #important
|
||||||
@@ -84,7 +99,13 @@ bonding_stop()
|
|||||||
eindent
|
eindent
|
||||||
einfo "${slaves}"
|
einfo "${slaves}"
|
||||||
eoutdent
|
eoutdent
|
||||||
/sbin/ifenslave -d "${IFACE}" ${slaves}
|
if [ -d /sys/class/net ]; then
|
||||||
|
for s in ${slaves}; do
|
||||||
|
echo -"${s}" > /sys/class/net/"${IFACE}"/bonding/slaves
|
||||||
|
done
|
||||||
|
else
|
||||||
|
/sbin/ifenslave -d "${IFACE}" ${slaves}
|
||||||
|
fi
|
||||||
|
|
||||||
# reset all slaves
|
# reset all slaves
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -16,12 +16,15 @@ _is_bridge()
|
|||||||
|
|
||||||
bridge_pre_start()
|
bridge_pre_start()
|
||||||
{
|
{
|
||||||
local ports= brif= iface="${IFACE}" e= x=
|
local brif= iface="${IFACE}" e= x=
|
||||||
local ports="$(_get_array "bridge_${IFVAR}")"
|
local ports="$(_get_array "bridge_${IFVAR}")"
|
||||||
local opts="$(_get_array "brctl_${IFVAR}")"
|
local opts="$(_get_array "brctl_${IFVAR}")"
|
||||||
|
|
||||||
eval brif=\$bridge_add_${IFVAR}
|
eval brif=\$bridge_add_${IFVAR}
|
||||||
[ -z "${ports}" -a -z "${brif}" -a -z "${opts}" ] && return 0
|
eval x=\${bridge_${IFVAR}-y\}
|
||||||
|
if [ -z "${brif}" -a -z "${opts}" ]; then
|
||||||
|
[ -n "${ports}" -o "${x}" != "y" ] || return 0
|
||||||
|
fi
|
||||||
|
|
||||||
[ -n "${ports}" ] && bridge_post_stop
|
[ -n "${ports}" ] && bridge_post_stop
|
||||||
|
|
||||||
|
|||||||
@@ -15,20 +15,42 @@ _config_vars="$_config_vars dhcp dhcpcd"
|
|||||||
|
|
||||||
dhcpcd_start()
|
dhcpcd_start()
|
||||||
{
|
{
|
||||||
local args= opt= opts= pidfile="/var/run/dhcpcd-${IFACE}.pid"
|
local args= opt= opts= pidfile="/var/run/dhcpcd-${IFACE}.pid" new=true
|
||||||
|
|
||||||
eval args=\$dhcpcd_${IFVAR}
|
eval args=\$dhcpcd_${IFVAR}
|
||||||
|
[ -z "${args}" ] && args=${dhcpcd}
|
||||||
|
|
||||||
# Get our options
|
# Get our options
|
||||||
eval opts=\$dhcp_${IFVAR}
|
eval opts=\$dhcp_${IFVAR}
|
||||||
[ -z "${opts}" ] && opts=${dhcp}
|
[ -z "${opts}" ] && opts=${dhcp}
|
||||||
|
|
||||||
|
case "$(dhcpcd --version)" in
|
||||||
|
"dhcpcd "[123]*) new=false;;
|
||||||
|
esac
|
||||||
|
|
||||||
# Map some generic options to dhcpcd
|
# Map some generic options to dhcpcd
|
||||||
for opt in ${opts}; do
|
for opt in ${opts}; do
|
||||||
case "${opt}" in
|
case "${opt}" in
|
||||||
nodns) args="${args} -R";;
|
nodns)
|
||||||
nontp) args="${args} -N";;
|
if ${new}; then
|
||||||
nonis) args="${args} -Y";;
|
args="${args} -C resolv.conf"
|
||||||
|
else
|
||||||
|
args="${args} -R"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
nontp)
|
||||||
|
if ${new}; then
|
||||||
|
args="${args} -C ntp.conf"
|
||||||
|
else
|
||||||
|
args="${args} -N"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
nonis)
|
||||||
|
if ${new}; then
|
||||||
|
args="${args} -C yp.conf"
|
||||||
|
else
|
||||||
|
args="${args} -Y"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
nogateway) args="${args} -G";;
|
nogateway) args="${args} -G";;
|
||||||
nosendhost) args="${args} -h ''";
|
nosendhost) args="${args} -h ''";
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -235,7 +235,11 @@ _delete_addresses()
|
|||||||
local addr=
|
local addr=
|
||||||
for addr in $(LC_ALL=C ifconfig "${IFACE}" | \
|
for addr in $(LC_ALL=C ifconfig "${IFACE}" | \
|
||||||
sed -n -e 's/^.*\(inet6 addr:\|inet6\) \([^ ]*\) .*\(Scope:[^L]\|scopeid [^<]*<[^l]\).*/\2/p'); do
|
sed -n -e 's/^.*\(inet6 addr:\|inet6\) \([^ ]*\) .*\(Scope:[^L]\|scopeid [^<]*<[^l]\).*/\2/p'); do
|
||||||
[ "${addr}" = "::1/128" -a "${IFACE}" = "lo" ] && continue
|
if [ "${IFACE}" = "lo" ]; then
|
||||||
|
case "${addr}" in
|
||||||
|
"::1/128"|"/128") continue;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
einfo "${addr}"
|
einfo "${addr}"
|
||||||
ifconfig "${IFACE}" inet6 del "${addr}"
|
ifconfig "${IFACE}" inet6 del "${addr}"
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ ifwatchd_stop()
|
|||||||
ebegin "Stopping ifwatchd on" "${IFACE}"
|
ebegin "Stopping ifwatchd on" "${IFACE}"
|
||||||
start-stop-daemon --stop --exec /usr/sbin/ifwatchd \
|
start-stop-daemon --stop --exec /usr/sbin/ifwatchd \
|
||||||
-- -c "${RC_LIBDIR}/sh/ifwatchd-carrier.sh" \
|
-- -c "${RC_LIBDIR}/sh/ifwatchd-carrier.sh" \
|
||||||
-n "${RC_LIBDIR}/sh/ifwatchd-nocarrier.sh" "${IFACE}" \
|
-n "${RC_LIBDIR}/sh/ifwatchd-nocarrier.sh" "${IFACE}"
|
||||||
&& return 0
|
|
||||||
eend $?
|
eend $?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ iproute2_depend()
|
|||||||
|
|
||||||
_up()
|
_up()
|
||||||
{
|
{
|
||||||
ip link set up dev "${IFACE}"
|
ip link set "${IFACE}" up
|
||||||
}
|
}
|
||||||
|
|
||||||
_down()
|
_down()
|
||||||
{
|
{
|
||||||
ip link set down dev "${IFACE}"
|
ip link set "${IFACE}" down
|
||||||
}
|
}
|
||||||
|
|
||||||
_exists()
|
_exists()
|
||||||
@@ -78,7 +78,7 @@ _get_mac_address()
|
|||||||
|
|
||||||
_set_mac_address()
|
_set_mac_address()
|
||||||
{
|
{
|
||||||
ip link set address "$1" dev "${IFACE}"
|
ip link set "${IFACE}" address "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
_get_inet_addresses()
|
_get_inet_addresses()
|
||||||
@@ -126,7 +126,7 @@ _add_address()
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
ip addr add dev "${IFACE}" "$@"
|
ip addr add "$@" dev "${IFACE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
_add_route()
|
_add_route()
|
||||||
@@ -184,12 +184,12 @@ iproute2_pre_start()
|
|||||||
# MTU support
|
# MTU support
|
||||||
local mtu=
|
local mtu=
|
||||||
eval mtu=\$mtu_${IFVAR}
|
eval mtu=\$mtu_${IFVAR}
|
||||||
[ -n "${mtu}" ] && ip link set mtu "${mtu}" dev "${IFACE}"
|
[ -n "${mtu}" ] && ip link set "${IFACE}" mtu "${mtu}"
|
||||||
|
|
||||||
# TX Queue Length support
|
# TX Queue Length support
|
||||||
local len=
|
local len=
|
||||||
eval len=\$txqueuelen_${IFVAR}
|
eval len=\$txqueuelen_${IFVAR}
|
||||||
[ -n "${len}" ] && ip link set qlen "${len}" dev "${IFACE}"
|
[ -n "${len}" ] && ip link set "${IFACE}" txqueuelen "${len}"
|
||||||
|
|
||||||
local tunnel=
|
local tunnel=
|
||||||
eval tunnel=\$iptunnel_${IFVAR}
|
eval tunnel=\$iptunnel_${IFVAR}
|
||||||
@@ -208,6 +208,8 @@ iproute2_pre_start()
|
|||||||
|
|
||||||
_iproute2_ipv6_tentative()
|
_iproute2_ipv6_tentative()
|
||||||
{
|
{
|
||||||
|
# Only check tentative when we have a carrier.
|
||||||
|
LC_ALL=C ip link show dev "${IFACE}" | grep -q "NO-CARRIER" && return 1
|
||||||
LC_ALL=C ip addr show dev "${IFACE}" | \
|
LC_ALL=C ip addr show dev "${IFACE}" | \
|
||||||
grep -q "^[[:space:]]*inet6 .* tentative"
|
grep -q "^[[:space:]]*inet6 .* tentative"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,9 +206,13 @@ iwconfig_wait_for_association()
|
|||||||
# Use sysfs if we can
|
# Use sysfs if we can
|
||||||
if [ -e /sys/class/net/"${IFACE}"/carrier ]; then
|
if [ -e /sys/class/net/"${IFACE}"/carrier ]; then
|
||||||
if [ "$(cat /sys/class/net/"${IFACE}"/carrier)" = "1" ]; then
|
if [ "$(cat /sys/class/net/"${IFACE}"/carrier)" = "1" ]; then
|
||||||
# Double check we have an ssid. This is mainly for buggy
|
# Double check we have an ssid and a non-zero
|
||||||
# prism54 drivers that always set their carrier on :/
|
# mac address. This is mainly for buggy
|
||||||
[ -n "$(iwgetid --raw "${IFACE}")" ] && return 0
|
# prism54 drivers that always set their
|
||||||
|
# carrier on or buggy madwifi drivers that
|
||||||
|
# sometimes have carrier on and ssid set
|
||||||
|
# without being associated. :/
|
||||||
|
[ -n "$(iwgetid --raw "${IFACE}")" ] && [ "$(iwgetid --ap --raw "${IFACE}")" != "00:00:00:00:00:00" ] && return 0
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
local atest=
|
local atest=
|
||||||
@@ -429,7 +433,7 @@ iwconfig_scan()
|
|||||||
[ -z "${a}" ] && break
|
[ -z "${a}" ] && break
|
||||||
eval b=\$QUALITY_${k}
|
eval b=\$QUALITY_${k}
|
||||||
if [ -n "${b}" -a "${a}" -lt "${b}" ]; then
|
if [ -n "${b}" -a "${a}" -lt "${b}" ]; then
|
||||||
for x in MAC SSID CHAN QUALITY ENC; do
|
for x in MAC SSID MODE CHAN QUALITY ENC; do
|
||||||
eval t=\$${x}_${i}
|
eval t=\$${x}_${i}
|
||||||
eval ${x}_${i}=\$${x}_${k}
|
eval ${x}_${i}=\$${x}_${k}
|
||||||
eval ${x}_${k}=\$t
|
eval ${x}_${k}=\$t
|
||||||
@@ -453,7 +457,7 @@ iwconfig_scan()
|
|||||||
local u=${k}
|
local u=${k}
|
||||||
# We need to split this into two tests, otherwise bash errors
|
# We need to split this into two tests, otherwise bash errors
|
||||||
[ -n "${a}" -a -n "${b}" ] && [ "${a}" -lt "${b}" ] && u=${i}
|
[ -n "${a}" -a -n "${b}" ] && [ "${a}" -lt "${b}" ] && u=${i}
|
||||||
unset MAC_${u} SSID_${u} CHAN_${u} QUALITY_${u} ENC_${u}
|
unset MAC_${u} SSID_${u} MODE_${u} CHAN_${u} QUALITY_${u} ENC_${u}
|
||||||
fi
|
fi
|
||||||
k=$((${k} + 1))
|
k=$((${k} + 1))
|
||||||
done
|
done
|
||||||
@@ -499,7 +503,7 @@ iwconfig_scan()
|
|||||||
for x; do
|
for x; do
|
||||||
if [ "${x}" = "${s}" ]; then
|
if [ "${x}" = "${s}" ]; then
|
||||||
ewarn "${s} has been blacklisted - not connecting"
|
ewarn "${s} has been blacklisted - not connecting"
|
||||||
unset SSID_${i} MAC_${i} CHAN_${i} QUALITY_${i} ENC_${i}
|
unset SSID_${i} MAC_${i} ${MODE}_${i} CHAN_${i} QUALITY_${i} ENC_${i}
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
i=$((${i} + 1))
|
i=$((${i} + 1))
|
||||||
@@ -597,10 +601,8 @@ iwconfig_connect_not_preferred()
|
|||||||
|
|
||||||
iwconfig_defaults()
|
iwconfig_defaults()
|
||||||
{
|
{
|
||||||
local x=
|
# Turn on the radio
|
||||||
for x in txpower rate rts frag; do
|
iwconfig "${IFACE}" txpower on 2>/dev/null
|
||||||
iwconfig "${IFACE}" "${x}" auto 2>/dev/null
|
|
||||||
done
|
|
||||||
|
|
||||||
# Release the AP forced
|
# Release the AP forced
|
||||||
# Must do ap and then ssid otherwise scanning borks
|
# Must do ap and then ssid otherwise scanning borks
|
||||||
@@ -735,7 +737,7 @@ iwconfig_pre_start()
|
|||||||
# which reports NOT READY!
|
# which reports NOT READY!
|
||||||
x="$(iwconfig_get_type)"
|
x="$(iwconfig_get_type)"
|
||||||
if [ "${x}" = "NOT READY!" ]; then
|
if [ "${x}" = "NOT READY!" ]; then
|
||||||
eerror "Looks like there was a probem loading the firmware for ${IFACE}"
|
eerror "Looks like there was a problem loading the firmware for ${IFACE}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -78,11 +78,9 @@ wpa_supplicant_pre_start()
|
|||||||
service_set_value "SSID" ""
|
service_set_value "SSID" ""
|
||||||
ebegin "Starting wpa_supplicant on ${IFVAR}"
|
ebegin "Starting wpa_supplicant on ${IFVAR}"
|
||||||
|
|
||||||
if [ -x /sbin/iwconfig ]; then
|
if type iwconfig_defaults >/dev/null 2>&1; then
|
||||||
local x=
|
iwconfig_defaults
|
||||||
for x in txpower rate rts frag; do
|
iwconfig_user_config
|
||||||
iwconfig "${IFACE}" "${x}" auto 2>/dev/null
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cfgfile=${opts##* -c}
|
cfgfile=${opts##* -c}
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
BOOT+= hostid net.lo0 newsyslog savecore syslogd
|
BOOT+= hostid net.lo0 newsyslog savecore syslogd
|
||||||
|
|
||||||
# NetBSD specific stuff
|
# NetBSD specific stuff
|
||||||
BOOT+= swap-blk ttys wscons
|
BOOT+= devdb swap-blk ttys wscons
|
||||||
|
|||||||
4
sh/.gitignore
vendored
4
sh/.gitignore
vendored
@@ -3,4 +3,8 @@ gendepends.sh
|
|||||||
net.sh
|
net.sh
|
||||||
rc-functions.sh
|
rc-functions.sh
|
||||||
runscript.sh
|
runscript.sh
|
||||||
|
init-common-post.sh
|
||||||
|
init-early.sh
|
||||||
init.sh
|
init.sh
|
||||||
|
ifwatchd-carrier.sh
|
||||||
|
ifwatchd-nocarrier.sh
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
DIR= ${PREFIX}/${RC_LIB}/sh
|
DIR= ${PREFIX}/${RC_LIB}/sh
|
||||||
SRCS= functions.sh.in gendepends.sh.in net.sh.in \
|
SRCS= functions.sh.in gendepends.sh.in init-common-post.sh.in \
|
||||||
rc-functions.sh.in runscript.sh.in
|
rc-functions.sh.in runscript.sh.in
|
||||||
INC= init-common-post.sh rc-mount.sh functions.sh rc-functions.sh
|
INC= init-common-post.sh rc-mount.sh functions.sh rc-functions.sh
|
||||||
BIN= gendepends.sh init.sh net.sh runscript.sh
|
BIN= gendepends.sh init.sh runscript.sh
|
||||||
|
|
||||||
INSTALLAFTER= _installafter
|
INSTALLAFTER= _installafter
|
||||||
|
|
||||||
@@ -13,8 +13,6 @@ include ${MK}/scripts.mk
|
|||||||
|
|
||||||
_installafter:
|
_installafter:
|
||||||
${INSTALL} -d ${DESTDIR}/${INITDIR}
|
${INSTALL} -d ${DESTDIR}/${INITDIR}
|
||||||
@# Provide an init script for the loopback interface
|
|
||||||
ln -snf ${PREFIX}/${RC_LIB}/sh/net.sh ${DESTDIR}/${INITDIR}/${NET_LO} || exit $$?
|
|
||||||
@# Put functions.sh into the init.d dir so 3rd party apps don't have to
|
@# Put functions.sh into the init.d dir so 3rd party apps don't have to
|
||||||
@# be multilib aware
|
@# be multilib aware
|
||||||
ln -snf ${PREFIX}/${RC_LIB}/sh/functions.sh ${DESTDIR}/${INITDIR} || exit $$?
|
ln -snf ${PREFIX}/${RC_LIB}/sh/functions.sh ${DESTDIR}/${INITDIR} || exit $$?
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
SRCS+= init.sh.in
|
SRCS+= init.sh.in
|
||||||
|
|
||||||
NET_LO= net.lo0
|
|
||||||
|
|
||||||
.SUFFIXES: .sh.BSD.in
|
.SUFFIXES: .sh.BSD.in
|
||||||
.sh.BSD.in.sh:
|
.sh.BSD.in.sh:
|
||||||
${SED} ${SED_REPLACE} ${SED_EXTRA} $< > $@
|
${SED} ${SED_REPLACE} ${SED_EXTRA} $< > $@
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
NET_LO= net.lo
|
|
||||||
SRCS+= init.sh.in init-early.sh.in
|
SRCS+= init.sh.in init-early.sh.in
|
||||||
BIN+= init-early.sh
|
BIN+= init-early.sh
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
SRCS+= init.sh.in
|
SRCS+= init.sh.in
|
||||||
|
|
||||||
NET_LO= net.lo0
|
|
||||||
SRCS+= ifwatchd-carrier.sh.in ifwatchd-nocarrier.sh.in
|
SRCS+= ifwatchd-carrier.sh.in ifwatchd-nocarrier.sh.in
|
||||||
BIN+= ifwatchd-carrier.sh ifwatchd-nocarrier.sh
|
BIN+= ifwatchd-carrier.sh ifwatchd-nocarrier.sh
|
||||||
|
|
||||||
|
|||||||
@@ -51,9 +51,11 @@ do
|
|||||||
[ -x "${RC_SERVICE}" -a -f "${RC_SERVICE}" ] || continue
|
[ -x "${RC_SERVICE}" -a -f "${RC_SERVICE}" ] || continue
|
||||||
|
|
||||||
# Only generate dependencies for runscripts
|
# Only generate dependencies for runscripts
|
||||||
read one two < "${RC_SERVICE}"
|
read one two three < "${RC_SERVICE}"
|
||||||
[ "${one}" = "#!@PREFIX@/sbin/runscript" ] || continue
|
[ "${one}" = "#!@PREFIX@/sbin/runscript" ] || \
|
||||||
unset one two
|
[ "${one}" = "#!" -a "${two}" = "@PREFIX@/sbin/runscript" ] || \
|
||||||
|
continue
|
||||||
|
unset one two three
|
||||||
|
|
||||||
export RC_SVCNAME=${RC_SERVICE##*/}
|
export RC_SVCNAME=${RC_SERVICE##*/}
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ retval=0
|
|||||||
# mount $svcdir as something we can write to if it's not rw
|
# mount $svcdir as something we can write to if it's not rw
|
||||||
# On vservers, / is always rw at this point, so we need to clean out
|
# On vservers, / is always rw at this point, so we need to clean out
|
||||||
# the old service state data
|
# the old service state data
|
||||||
|
RC_SVCDIR=${RC_SVCDIR:-/@LIB@/rc/init.d}
|
||||||
if [ "${RC_SVCDIR}" != "/" ] && mkdir "${RC_SVCDIR}/.test.$$" 2>/dev/null; then
|
if [ "${RC_SVCDIR}" != "/" ] && mkdir "${RC_SVCDIR}/.test.$$" 2>/dev/null; then
|
||||||
rmdir "${RC_SVCDIR}/.test.$$"
|
rmdir "${RC_SVCDIR}/.test.$$"
|
||||||
for x in ${RC_SVCDIR:-/@LIB@/rc/init.d}/*; do
|
for x in ${RC_SVCDIR}/*; do
|
||||||
[ -e "${x}" ] || continue
|
[ -e "${x}" ] || continue
|
||||||
case ${x##*/} in
|
case ${x##*/} in
|
||||||
depconfig|deptree|ksoftlevel|rc.log);;
|
depconfig|deptree|ksoftlevel|rc.log);;
|
||||||
@@ -108,8 +108,7 @@ if [ -r /sbin/livecd-functions.sh ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${RC_UNAME}" != "GNU/kFreeBSD" \
|
if [ "${RC_UNAME}" != "GNU/kFreeBSD" \
|
||||||
-a "${RC_SYS}" != "VSERVER" \
|
-a "${RC_SYS}" != "VSERVER" ];
|
||||||
-a "${RC_SYS}" != "OPENVZ" ]
|
|
||||||
then
|
then
|
||||||
if grep -Eq "[[:space:]]+sysfs$" /proc/filesystems; then
|
if grep -Eq "[[:space:]]+sysfs$" /proc/filesystems; then
|
||||||
if [ -d /sys ]; then
|
if [ -d /sys ]; then
|
||||||
@@ -126,10 +125,14 @@ then
|
|||||||
fi
|
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
|
# Try to figure out how the user wants /dev handled
|
||||||
if [ "${rc_devices}" = "static" \
|
if [ "${rc_devices}" = "static" \
|
||||||
-o "${RC_SYS}" = "VSERVER" \
|
-o "${RC_SYS}" = "VSERVER" \
|
||||||
-o "${RC_SYS}" = "OPENVZ" \
|
|
||||||
-o "${RC_UNAME}" = "GNU/kFreeBSD" ]
|
-o "${RC_UNAME}" = "GNU/kFreeBSD" ]
|
||||||
then
|
then
|
||||||
ebegin "Using existing device nodes in /dev"
|
ebegin "Using existing device nodes in /dev"
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ get_bootparam()
|
|||||||
|
|
||||||
set -- $(cat /proc/cmdline)
|
set -- $(cat /proc/cmdline)
|
||||||
while [ -n "$1" ]; do
|
while [ -n "$1" ]; do
|
||||||
|
[ "$1" = "${match}" ] && return 0
|
||||||
case "$1" in
|
case "$1" in
|
||||||
gentoo=*)
|
gentoo=*)
|
||||||
local params="${1##*=}"
|
local params="${1##*=}"
|
||||||
|
|||||||
@@ -52,26 +52,20 @@
|
|||||||
|
|
||||||
#define ERRX fprintf (stderr, "out of memory\n"); exit (1)
|
#define ERRX fprintf (stderr, "out of memory\n"); exit (1)
|
||||||
|
|
||||||
|
#define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
|
||||||
|
|
||||||
#ifdef lint
|
#ifdef lint
|
||||||
# define _unused
|
# define _unused
|
||||||
#endif
|
#endif
|
||||||
#if __GNUC__ > 2 || defined(__INTEL_COMPILER)
|
#if __GNUC__ > 2 || defined(__INTEL_COMPILER)
|
||||||
|
# define _dead __attribute__((__noreturn__))
|
||||||
# define _unused __attribute__((__unused__))
|
# define _unused __attribute__((__unused__))
|
||||||
#else
|
#else
|
||||||
|
# define _dead
|
||||||
# define _unused
|
# define _unused
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Some libc implemntations don't have these */
|
/* Some libc implemntations don't have these */
|
||||||
#ifndef STAILQ_CONCAT
|
|
||||||
#define STAILQ_CONCAT(head1, head2) do { \
|
|
||||||
if (!STAILQ_EMPTY((head2))) { \
|
|
||||||
*(head1)->stqh_last = (head2)->stqh_first; \
|
|
||||||
(head1)->stqh_last = (head2)->stqh_last; \
|
|
||||||
STAILQ_INIT((head2)); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TAILQ_CONCAT
|
#ifndef TAILQ_CONCAT
|
||||||
#define TAILQ_CONCAT(head1, head2, field) do { \
|
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||||
if (!TAILQ_EMPTY(head2)) { \
|
if (!TAILQ_EMPTY(head2)) { \
|
||||||
@@ -83,13 +77,6 @@
|
|||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STAILQ_FOREACH_SAFE
|
|
||||||
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
|
||||||
for ((var) = STAILQ_FIRST((head)); \
|
|
||||||
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
|
||||||
(var) = (tvar))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TAILQ_FOREACH_SAFE
|
#ifndef TAILQ_FOREACH_SAFE
|
||||||
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||||
for ((var) = TAILQ_FIRST((head)); \
|
for ((var) = TAILQ_FIRST((head)); \
|
||||||
@@ -174,4 +161,5 @@ _unused static const char *basename_c(const char *path)
|
|||||||
return (path);
|
return (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int parse_mode(mode_t *, char *);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ SRCS= libeinfo.c
|
|||||||
INCS= einfo.h
|
INCS= einfo.h
|
||||||
VERSION_MAP= einfo.map
|
VERSION_MAP= einfo.map
|
||||||
|
|
||||||
CFLAGS+= -I../includes
|
CPPFLAGS+= -I../includes
|
||||||
|
|
||||||
MK= ../../mk
|
MK= ../../mk
|
||||||
include ${MK}/lib.mk
|
include ${MK}/lib.mk
|
||||||
|
|||||||
@@ -199,7 +199,8 @@ static const char *const color_terms[] = {
|
|||||||
/* strlcat and strlcpy are nice, shame glibc does not define them */
|
/* strlcat and strlcpy are nice, shame glibc does not define them */
|
||||||
#ifdef __GLIBC__
|
#ifdef __GLIBC__
|
||||||
# if ! defined (__UCLIBC__) && ! defined (__dietlibc__)
|
# if ! defined (__UCLIBC__) && ! defined (__dietlibc__)
|
||||||
static size_t strlcat(char *dst, const char *src, size_t size)
|
static size_t
|
||||||
|
strlcat(char *dst, const char *src, size_t size)
|
||||||
{
|
{
|
||||||
char *d = dst;
|
char *d = dst;
|
||||||
const char *s = src;
|
const char *s = src;
|
||||||
@@ -226,18 +227,19 @@ static size_t strlcat(char *dst, const char *src, size_t size)
|
|||||||
return dst_n + (s - src);
|
return dst_n + (s - src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t strlcpy(char *dst, const char *src, size_t size)
|
static size_t
|
||||||
|
strlcpy(char *dst, const char *src, size_t size)
|
||||||
{
|
{
|
||||||
const char *s = src;
|
const char *s = src;
|
||||||
size_t n = size;
|
size_t n = size;
|
||||||
|
|
||||||
if (n && --n)
|
if (n && --n)
|
||||||
do {
|
do {
|
||||||
if (! (*dst++ = *src++))
|
if (!(*dst++ = *src++))
|
||||||
break;
|
break;
|
||||||
} while (--n);
|
} while (--n);
|
||||||
|
|
||||||
if (! n) {
|
if (!n) {
|
||||||
if (size)
|
if (size)
|
||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
while (*src++);
|
while (*src++);
|
||||||
@@ -248,9 +250,10 @@ static size_t strlcpy(char *dst, const char *src, size_t size)
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool yesno(const char *value)
|
static bool
|
||||||
|
yesno(const char *value)
|
||||||
{
|
{
|
||||||
if (! value) {
|
if (!value) {
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -272,7 +275,8 @@ static bool yesno(const char *value)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool noyes(const char *value)
|
static bool
|
||||||
|
noyes(const char *value)
|
||||||
{
|
{
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
bool retval;
|
bool retval;
|
||||||
@@ -280,26 +284,29 @@ static bool noyes(const char *value)
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
retval = yesno(value);
|
retval = yesno(value);
|
||||||
if (errno == 0) {
|
if (errno == 0) {
|
||||||
retval = ! retval;
|
retval = !retval;
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_quiet(void)
|
static bool
|
||||||
|
is_quiet(void)
|
||||||
{
|
{
|
||||||
return yesno(getenv("EINFO_QUIET"));
|
return yesno(getenv("EINFO_QUIET"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_verbose(void)
|
static bool
|
||||||
|
is_verbose(void)
|
||||||
{
|
{
|
||||||
return yesno(getenv ("EINFO_VERBOSE"));
|
return yesno(getenv ("EINFO_VERBOSE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fake tgoto call - very crapy, but works for our needs */
|
/* Fake tgoto call - very crapy, but works for our needs */
|
||||||
#ifndef HAVE_TERMCAP
|
#ifndef HAVE_TERMCAP
|
||||||
static char *tgoto(const char *cap, int a, int b)
|
static char *
|
||||||
|
tgoto(const char *cap, int a, int b)
|
||||||
{
|
{
|
||||||
static char buf[20];
|
static char buf[20];
|
||||||
|
|
||||||
@@ -308,22 +315,22 @@ static char *tgoto(const char *cap, int a, int b)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool colour_terminal(FILE * __EINFO_RESTRICT f)
|
static bool
|
||||||
|
colour_terminal(FILE * __EINFO_RESTRICT f)
|
||||||
{
|
{
|
||||||
static int in_colour = -1;
|
static int in_colour = -1;
|
||||||
char *e;
|
char *e, *ee, *end, *d, *p;
|
||||||
int c;
|
int c;
|
||||||
const char *_af = NULL;
|
const char *_af = NULL, *_ce = NULL, *_ch = NULL;
|
||||||
const char *_ce = NULL;
|
const char *_md = NULL, *_me = NULL, *_up = NULL;
|
||||||
const char *_ch = NULL;
|
const char *bold;
|
||||||
const char *_md = NULL;
|
|
||||||
const char *_me = NULL;
|
|
||||||
const char *_up = NULL;
|
|
||||||
char tmp[100];
|
char tmp[100];
|
||||||
char *p;
|
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
|
#ifdef HAVE_TERMCAP
|
||||||
|
char *bp;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (f && ! isatty(fileno(f)))
|
if (f && !isatty(fileno(f)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (noyes(getenv("EINFO_COLOR")))
|
if (noyes(getenv("EINFO_COLOR")))
|
||||||
@@ -335,26 +342,23 @@ static bool colour_terminal(FILE * __EINFO_RESTRICT f)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
term_is_cons25 = false;
|
term_is_cons25 = false;
|
||||||
|
if (!term) {
|
||||||
if (! term) {
|
|
||||||
term = getenv("TERM");
|
term = getenv("TERM");
|
||||||
if (! term)
|
if (!term)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(term, "cons25") == 0)
|
if (strcmp(term, "cons25") == 0)
|
||||||
term_is_cons25 = true;
|
term_is_cons25 = true;
|
||||||
|
|
||||||
#ifdef HAVE_TERMCAP
|
#ifdef HAVE_TERMCAP
|
||||||
/* Check termcap to see if we can do colour or not */
|
/* Check termcap to see if we can do colour or not */
|
||||||
if (tgetent(termcapbuf, term) == 1) {
|
if (tgetent(termcapbuf, term) == 1) {
|
||||||
char *bp = tcapbuf;
|
bp = tcapbuf;
|
||||||
|
|
||||||
_af = tgetstr("AF", &bp);
|
_af = tgetstr("AF", &bp);
|
||||||
_ce = tgetstr("ce", &bp);
|
_ce = tgetstr("ce", &bp);
|
||||||
_ch = tgetstr("ch", &bp);
|
_ch = tgetstr("ch", &bp);
|
||||||
/* Our ch use also works with RI .... for now */
|
/* Our ch use also works with RI .... for now */
|
||||||
if (! _ch)
|
if (!_ch)
|
||||||
_ch = tgetstr("RI", &bp);
|
_ch = tgetstr("RI", &bp);
|
||||||
_md = tgetstr("md", &bp);
|
_md = tgetstr("md", &bp);
|
||||||
_me = tgetstr("me", &bp);
|
_me = tgetstr("me", &bp);
|
||||||
@@ -377,29 +381,29 @@ static bool colour_terminal(FILE * __EINFO_RESTRICT f)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (! _af)
|
if (!_af)
|
||||||
_af = AF;
|
_af = AF;
|
||||||
if (! _ce)
|
if (!_ce)
|
||||||
_ce = CE;
|
_ce = CE;
|
||||||
if (! _ch)
|
if (!_ch)
|
||||||
_ch = CH;
|
_ch = CH;
|
||||||
if (! _md)
|
if (!_md)
|
||||||
_md = MD;
|
_md = MD;
|
||||||
if (! _me)
|
if (!_me)
|
||||||
_me = ME;
|
_me = ME;
|
||||||
if (! _up)
|
if (!_up)
|
||||||
_up = UP;
|
_up = UP;
|
||||||
#ifdef HAVE_TERMCAP
|
#ifdef HAVE_TERMCAP
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! _af || ! _ce || ! _me || !_md || ! _up) {
|
if (!_af || !_ce || !_me || !_md || !_up) {
|
||||||
in_colour = 0;
|
in_colour = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Many termcap databases don't have ch or RI even though they
|
/* Many termcap databases don't have ch or RI even though they
|
||||||
* do work */
|
* do work */
|
||||||
if (! _ch)
|
if (!_ch)
|
||||||
_ch = CH;
|
_ch = CH;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -407,33 +411,28 @@ static bool colour_terminal(FILE * __EINFO_RESTRICT f)
|
|||||||
p = ebuffer;
|
p = ebuffer;
|
||||||
for (i = 0; i < sizeof(ecolors) / sizeof(ecolors[0]); i++) {
|
for (i = 0; i < sizeof(ecolors) / sizeof(ecolors[0]); i++) {
|
||||||
tmp[0] = '\0';
|
tmp[0] = '\0';
|
||||||
|
|
||||||
if (ecolors[i].name) {
|
if (ecolors[i].name) {
|
||||||
const char *bold = _md;
|
bold = _md;
|
||||||
c = ecolors[i].def;
|
c = ecolors[i].def;
|
||||||
|
|
||||||
/* See if the user wants to override the colour
|
/* See if the user wants to override the colour
|
||||||
* We use a :col;bold: format like 2;1: for bold green
|
* We use a :col;bold: format like 2;1: for bold green
|
||||||
* and 1;0: for a normal red */
|
* and 1;0: for a normal red */
|
||||||
if ((e = getenv("EINFO_COLOR"))) {
|
if ((e = getenv("EINFO_COLOR"))) {
|
||||||
char *ee = strstr(e, ecolors[i].name);
|
ee = strstr(e, ecolors[i].name);
|
||||||
|
|
||||||
if (ee)
|
if (ee)
|
||||||
ee += strlen(ecolors[i].name);
|
ee += strlen(ecolors[i].name);
|
||||||
|
|
||||||
if (ee && *ee == '=') {
|
if (ee && *ee == '=') {
|
||||||
char *d = strdup(ee + 1);
|
d = strdup(ee + 1);
|
||||||
if (d) {
|
if (d) {
|
||||||
char *end = strchr(d, ':');
|
end = strchr(d, ':');
|
||||||
if (end)
|
if (end)
|
||||||
*end = '\0';
|
*end = '\0';
|
||||||
|
|
||||||
c = atoi(d);
|
c = atoi(d);
|
||||||
|
|
||||||
end = strchr(d, ';');
|
end = strchr(d, ';');
|
||||||
if (end && *++end == '0')
|
if (end && *++end == '0')
|
||||||
bold = _me;
|
bold = _me;
|
||||||
|
|
||||||
free(d);
|
free(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -460,7 +459,8 @@ static bool colour_terminal(FILE * __EINFO_RESTRICT f)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_term_columns(FILE * __EINFO_RESTRICT stream)
|
static int
|
||||||
|
get_term_columns(FILE * __EINFO_RESTRICT stream)
|
||||||
{
|
{
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
char *env = getenv("COLUMNS");
|
char *env = getenv("COLUMNS");
|
||||||
@@ -469,7 +469,7 @@ static int get_term_columns(FILE * __EINFO_RESTRICT stream)
|
|||||||
|
|
||||||
if (env) {
|
if (env) {
|
||||||
i = strtoimax(env, &p, 10);
|
i = strtoimax(env, &p, 10);
|
||||||
if (! *p)
|
if (!*p)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,13 +479,15 @@ static int get_term_columns(FILE * __EINFO_RESTRICT stream)
|
|||||||
return DEFAULT_COLS;
|
return DEFAULT_COLS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void eprefix(const char *__EINFO_RESTRICT prefix)
|
void
|
||||||
|
eprefix(const char *__EINFO_RESTRICT prefix)
|
||||||
{
|
{
|
||||||
_eprefix = prefix;
|
_eprefix = prefix;
|
||||||
}
|
}
|
||||||
hidden_def(eprefix)
|
hidden_def(eprefix)
|
||||||
|
|
||||||
static void elogv(int level, const char *__EINFO_RESTRICT fmt, va_list ap)
|
static void
|
||||||
|
elogv(int level, const char *__EINFO_RESTRICT fmt, va_list ap)
|
||||||
{
|
{
|
||||||
char *e = getenv("EINFO_LOG");
|
char *e = getenv("EINFO_LOG");
|
||||||
va_list apc;
|
va_list apc;
|
||||||
@@ -500,7 +502,8 @@ static void elogv(int level, const char *__EINFO_RESTRICT fmt, va_list ap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void elog(int level, const char *__EINFO_RESTRICT fmt, ...)
|
void
|
||||||
|
elog(int level, const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
@@ -510,7 +513,8 @@ void elog(int level, const char *__EINFO_RESTRICT fmt, ...)
|
|||||||
}
|
}
|
||||||
hidden_def(elog)
|
hidden_def(elog)
|
||||||
|
|
||||||
static int _eindent(FILE * __EINFO_RESTRICT stream)
|
static int
|
||||||
|
_eindent(FILE * __EINFO_RESTRICT stream)
|
||||||
{
|
{
|
||||||
char *env = getenv("EINFO_INDENT");
|
char *env = getenv("EINFO_INDENT");
|
||||||
int amount = 0;
|
int amount = 0;
|
||||||
@@ -525,7 +529,7 @@ static int _eindent(FILE * __EINFO_RESTRICT stream)
|
|||||||
amount = INDENT_MAX;
|
amount = INDENT_MAX;
|
||||||
|
|
||||||
if (amount > 0)
|
if (amount > 0)
|
||||||
memset(indent, ' ', (size_t) amount);
|
memset(indent, ' ', (size_t)amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Terminate it */
|
/* Terminate it */
|
||||||
@@ -533,32 +537,32 @@ static int _eindent(FILE * __EINFO_RESTRICT stream)
|
|||||||
return fprintf(stream, "%s", indent);
|
return fprintf(stream, "%s", indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *_ecolor(FILE * __EINFO_RESTRICT f, ECOLOR color)
|
static const char *
|
||||||
|
_ecolor(FILE * __EINFO_RESTRICT f, ECOLOR color)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (! colour_terminal(f))
|
if (!colour_terminal(f))
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
for (i = 0; i < sizeof(ecolors) / sizeof(ecolors[0]); i++) {
|
for (i = 0; i < sizeof(ecolors) / sizeof(ecolors[0]); i++)
|
||||||
if (ecolors[i].color == color)
|
if (ecolors[i].color == color)
|
||||||
return ecolors_str[i];
|
return ecolors_str[i];
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
hidden_def(ecolor)
|
hidden_def(ecolor)
|
||||||
|
|
||||||
const char *ecolor(ECOLOR color)
|
const char *
|
||||||
|
ecolor(ECOLOR color)
|
||||||
{
|
{
|
||||||
FILE *f = stdout;
|
FILE *f = stdout;
|
||||||
|
|
||||||
/* Try and guess a valid tty */
|
/* Try and guess a valid tty */
|
||||||
if (! isatty(fileno(f))) {
|
if (!isatty(fileno(f))) {
|
||||||
f = stderr;
|
f = stderr;
|
||||||
if (! isatty(fileno(f))) {
|
if (!isatty(fileno(f))) {
|
||||||
f = stdin;
|
f = stdin;
|
||||||
if (! isatty(fileno(f)))
|
if (!isatty(fileno(f)))
|
||||||
f = NULL;
|
f = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -571,87 +575,69 @@ const char *ecolor(ECOLOR color)
|
|||||||
setenv("EINFO_LASTCMD", _cmd, 1); \
|
setenv("EINFO_LASTCMD", _cmd, 1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EINFOVN(_file, _color) \
|
static int
|
||||||
{ \
|
_einfo(FILE *f, ECOLOR color, const char *__EINFO_RESTRICT fmt, va_list va)
|
||||||
char *_e = getenv("EINFO_LASTCMD"); \
|
|
||||||
if (_e && ! colour_terminal(_file) && strcmp(_e, "ewarn") != 0 && \
|
|
||||||
_e[strlen (_e) - 1] == 'n') \
|
|
||||||
fprintf(_file, "\n"); \
|
|
||||||
if (_eprefix) \
|
|
||||||
fprintf(_file, "%s%s%s|", _ecolor(_file, _color), _eprefix, _ecolor(_file, ECOLOR_NORMAL)); \
|
|
||||||
fprintf(_file, " %s*%s ", _ecolor(_file, _color), _ecolor(_file, ECOLOR_NORMAL)); \
|
|
||||||
retval += _eindent(_file); \
|
|
||||||
{ \
|
|
||||||
va_list _ap; \
|
|
||||||
va_copy(_ap, ap); \
|
|
||||||
retval += vfprintf(_file, fmt, _ap) + 3; \
|
|
||||||
va_end(_ap); \
|
|
||||||
} \
|
|
||||||
if (colour_terminal(_file)) \
|
|
||||||
fprintf(_file, "%s", flush); \
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _einfovn(const char *__EINFO_RESTRICT fmt, va_list ap)
|
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
char *last = getenv("EINFO_LASTCMD");
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
EINFOVN(stdout, ECOLOR_GOOD);
|
if (last &&
|
||||||
|
!colour_terminal(f) &&
|
||||||
|
strcmp(last, "ewarn") != 0 &&
|
||||||
|
last[strlen(last) - 1] == 'n')
|
||||||
|
fprintf(f, "\n");
|
||||||
|
if (_eprefix)
|
||||||
|
fprintf(f, "%s%s%s|", _ecolor(f, color), _eprefix, _ecolor(f, ECOLOR_NORMAL));
|
||||||
|
fprintf(f, " %s*%s ", _ecolor(f, color), _ecolor(f, ECOLOR_NORMAL));
|
||||||
|
retval += _eindent(f);
|
||||||
|
va_copy(ap, va);
|
||||||
|
retval += vfprintf(f, fmt, ap) + 3;
|
||||||
|
va_end(ap); \
|
||||||
|
if (colour_terminal(f))
|
||||||
|
fprintf(f, "%s", flush);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _ewarnvn(const char *__EINFO_RESTRICT fmt, va_list ap)
|
#define _einfovn(fmt, ap) _einfo(stdout, ECOLOR_GOOD, fmt, ap)
|
||||||
{
|
#define _ewarnvn(fmt, ap) _einfo(stderr, ECOLOR_WARN, fmt, ap)
|
||||||
int retval = 0;
|
#define _eerrorvn(fmt, ap) _einfo(stderr, ECOLOR_BAD, fmt, ap)
|
||||||
|
|
||||||
EINFOVN(stderr, ECOLOR_WARN);
|
int
|
||||||
return retval;
|
einfon(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
}
|
|
||||||
|
|
||||||
static int _eerrorvn(const char *__EINFO_RESTRICT fmt, va_list ap)
|
|
||||||
{
|
|
||||||
int retval = 0;
|
|
||||||
|
|
||||||
EINFOVN(stderr, ECOLOR_BAD);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int einfon(const char *__EINFO_RESTRICT fmt, ...)
|
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt || is_quiet())
|
if (!fmt || is_quiet())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
retval = _einfovn(fmt, ap);
|
retval = _einfovn(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("einfon");
|
LASTCMD("einfon");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(einfon)
|
hidden_def(einfon)
|
||||||
|
|
||||||
int ewarnn(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
ewarnn(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt || is_quiet())
|
if (!fmt || is_quiet())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
retval = _ewarnvn(fmt, ap);
|
retval = _ewarnvn(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("ewarnn");
|
LASTCMD("ewarnn");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(ewarnn)
|
hidden_def(ewarnn)
|
||||||
|
|
||||||
int eerrorn(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
eerrorn(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -659,58 +645,53 @@ int eerrorn(const char *__EINFO_RESTRICT fmt, ...)
|
|||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
retval = _eerrorvn(fmt, ap);
|
retval = _eerrorvn(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("errorn");
|
LASTCMD("errorn");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(eerrorn)
|
hidden_def(eerrorn)
|
||||||
|
|
||||||
int einfo(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
einfo(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt || is_quiet())
|
if (!fmt || is_quiet())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
retval = _einfovn(fmt, ap);
|
retval = _einfovn(fmt, ap);
|
||||||
retval += printf("\n");
|
retval += printf("\n");
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("einfo");
|
LASTCMD("einfo");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(einfo)
|
hidden_def(einfo)
|
||||||
|
|
||||||
int ewarn(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
ewarn(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt || is_quiet())
|
if (!fmt || is_quiet())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
elogv(LOG_WARNING, fmt, ap);
|
elogv(LOG_WARNING, fmt, ap);
|
||||||
retval = _ewarnvn(fmt, ap);
|
retval = _ewarnvn(fmt, ap);
|
||||||
retval += fprintf(stderr, "\n");
|
retval += fprintf(stderr, "\n");
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("ewarn");
|
LASTCMD("ewarn");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(ewarn)
|
hidden_def(ewarn)
|
||||||
|
|
||||||
void ewarnx(const char *__EINFO_RESTRICT fmt, ...)
|
void
|
||||||
|
ewarnx(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (fmt && ! is_quiet()) {
|
if (fmt && !is_quiet()) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
elogv(LOG_WARNING, fmt, ap);
|
elogv(LOG_WARNING, fmt, ap);
|
||||||
retval = _ewarnvn(fmt, ap);
|
retval = _ewarnvn(fmt, ap);
|
||||||
@@ -721,27 +702,26 @@ void ewarnx(const char *__EINFO_RESTRICT fmt, ...)
|
|||||||
}
|
}
|
||||||
hidden_def(ewarnx)
|
hidden_def(ewarnx)
|
||||||
|
|
||||||
int eerror(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
eerror(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt)
|
if (!fmt)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
elogv(LOG_ERR, fmt, ap);
|
elogv(LOG_ERR, fmt, ap);
|
||||||
retval = _eerrorvn(fmt, ap);
|
retval = _eerrorvn(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
retval += fprintf(stderr, "\n");
|
retval += fprintf(stderr, "\n");
|
||||||
|
|
||||||
LASTCMD("eerror");
|
LASTCMD("eerror");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(eerror)
|
hidden_def(eerror)
|
||||||
|
|
||||||
void eerrorx(const char *__EINFO_RESTRICT fmt, ...)
|
void
|
||||||
|
eerrorx(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
@@ -752,46 +732,43 @@ void eerrorx(const char *__EINFO_RESTRICT fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
hidden_def(eerrorx)
|
hidden_def(eerrorx)
|
||||||
|
|
||||||
int ebegin(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
ebegin(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt || is_quiet())
|
if (!fmt || is_quiet())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
retval = _einfovn(fmt, ap);
|
retval = _einfovn(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
retval += printf(" ...");
|
retval += printf(" ...");
|
||||||
if (colour_terminal(stdout))
|
if (colour_terminal(stdout))
|
||||||
retval += printf("\n");
|
retval += printf("\n");
|
||||||
|
|
||||||
LASTCMD("ebegin");
|
LASTCMD("ebegin");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(ebegin)
|
hidden_def(ebegin)
|
||||||
|
|
||||||
static void _eend(FILE * __EINFO_RESTRICT fp, int col, ECOLOR color,
|
static void
|
||||||
const char *msg)
|
_eend(FILE * __EINFO_RESTRICT fp, int col, ECOLOR color, const char *msg)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int cols;
|
int cols;
|
||||||
|
|
||||||
if (! msg)
|
if (!msg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cols = get_term_columns(fp) - (strlen(msg) + 3);
|
cols = get_term_columns(fp) - (strlen(msg) + 3);
|
||||||
|
|
||||||
/* cons25 is special - we need to remove one char, otherwise things
|
/* cons25 is special - we need to remove one char, otherwise things
|
||||||
* do not align properly at all. */
|
* do not align properly at all. */
|
||||||
if (! term) {
|
if (!term) {
|
||||||
term = getenv("TERM");
|
term = getenv("TERM");
|
||||||
if (term && strcmp(term, "cons25") == 0)
|
if (term && strcmp(term, "cons25") == 0)
|
||||||
term_is_cons25 = true;
|
term_is_cons25 = true;
|
||||||
@@ -816,7 +793,8 @@ static void _eend(FILE * __EINFO_RESTRICT fp, int col, ECOLOR color,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _do_eend(const char *cmd, int retval, const char *__EINFO_RESTRICT fmt, va_list ap)
|
static int
|
||||||
|
_do_eend(const char *cmd, int retval, const char *__EINFO_RESTRICT fmt, va_list ap)
|
||||||
{
|
{
|
||||||
int col = 0;
|
int col = 0;
|
||||||
FILE *fp = stdout;
|
FILE *fp = stdout;
|
||||||
@@ -832,54 +810,51 @@ static int _do_eend(const char *cmd, int retval, const char *__EINFO_RESTRICT fm
|
|||||||
col += fprintf(fp, "\n");
|
col += fprintf(fp, "\n");
|
||||||
va_end(apc);
|
va_end(apc);
|
||||||
}
|
}
|
||||||
|
|
||||||
_eend(fp, col,
|
_eend(fp, col,
|
||||||
retval == 0 ? ECOLOR_GOOD : ECOLOR_BAD,
|
retval == 0 ? ECOLOR_GOOD : ECOLOR_BAD,
|
||||||
retval == 0 ? OK : NOT_OK);
|
retval == 0 ? OK : NOT_OK);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int eend(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
eend(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (is_quiet())
|
if (is_quiet())
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
_do_eend("eend", retval, fmt, ap);
|
_do_eend("eend", retval, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("eend");
|
LASTCMD("eend");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(eend)
|
hidden_def(eend)
|
||||||
|
|
||||||
int ewend(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
ewend(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (is_quiet())
|
if (is_quiet())
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
_do_eend("ewend", retval, fmt, ap);
|
_do_eend("ewend", retval, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("ewend");
|
LASTCMD("ewend");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(ewend)
|
hidden_def(ewend)
|
||||||
|
|
||||||
void ebracket(int col, ECOLOR color, const char *msg)
|
void
|
||||||
|
ebracket(int col, ECOLOR color, const char *msg)
|
||||||
{
|
{
|
||||||
_eend(stdout, col, color, msg);
|
_eend(stdout, col, color, msg);
|
||||||
}
|
}
|
||||||
hidden_def(ebracket)
|
hidden_def(ebracket)
|
||||||
|
|
||||||
void eindent(void)
|
void
|
||||||
|
eindent(void)
|
||||||
{
|
{
|
||||||
char *env = getenv("EINFO_INDENT");
|
char *env = getenv("EINFO_INDENT");
|
||||||
int amount = 0;
|
int amount = 0;
|
||||||
@@ -891,11 +866,9 @@ void eindent(void)
|
|||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
amount = 0;
|
amount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
amount += INDENT_WIDTH;
|
amount += INDENT_WIDTH;
|
||||||
if (amount > INDENT_MAX)
|
if (amount > INDENT_MAX)
|
||||||
amount = INDENT_MAX;
|
amount = INDENT_MAX;
|
||||||
|
|
||||||
snprintf(num, 10, "%08d", amount);
|
snprintf(num, 10, "%08d", amount);
|
||||||
setenv("EINFO_INDENT", num, 1);
|
setenv("EINFO_INDENT", num, 1);
|
||||||
}
|
}
|
||||||
@@ -908,16 +881,14 @@ void eoutdent(void)
|
|||||||
char num[10];
|
char num[10];
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
|
|
||||||
if (! env)
|
if (!env)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
amount = strtoimax(env, NULL, 0);
|
amount = strtoimax(env, NULL, 0);
|
||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
amount = 0;
|
amount = 0;
|
||||||
else
|
else
|
||||||
amount -= INDENT_WIDTH;
|
amount -= INDENT_WIDTH;
|
||||||
|
|
||||||
if (amount <= 0)
|
if (amount <= 0)
|
||||||
unsetenv("EINFO_INDENT");
|
unsetenv("EINFO_INDENT");
|
||||||
else {
|
else {
|
||||||
@@ -928,86 +899,79 @@ void eoutdent(void)
|
|||||||
}
|
}
|
||||||
hidden_def(eoutdent)
|
hidden_def(eoutdent)
|
||||||
|
|
||||||
int einfovn(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
einfovn(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt || ! is_verbose())
|
if (!fmt || !is_verbose())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
retval = _einfovn(fmt, ap);
|
retval = _einfovn(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("einfovn");
|
LASTCMD("einfovn");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(einfovn)
|
hidden_def(einfovn)
|
||||||
|
|
||||||
int ewarnvn(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
ewarnvn(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt || ! is_verbose())
|
if (!fmt || !is_verbose())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
retval = _ewarnvn(fmt, ap);
|
retval = _ewarnvn(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("ewarnvn");
|
LASTCMD("ewarnvn");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(ewarnvn)
|
hidden_def(ewarnvn)
|
||||||
|
|
||||||
int einfov(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
einfov(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt || ! is_verbose())
|
if (!fmt || !is_verbose())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
retval = _einfovn(fmt, ap);
|
retval = _einfovn(fmt, ap);
|
||||||
retval += printf("\n");
|
retval += printf("\n");
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("einfov");
|
LASTCMD("einfov");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(einfov)
|
hidden_def(einfov)
|
||||||
|
|
||||||
int ewarnv(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
ewarnv(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt || ! is_verbose())
|
if (!fmt || !is_verbose())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
retval = _ewarnvn(fmt, ap);
|
retval = _ewarnvn(fmt, ap);
|
||||||
retval += printf("\n");
|
retval += printf("\n");
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("ewarnv");
|
LASTCMD("ewarnv");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(ewarnv)
|
hidden_def(ewarnv)
|
||||||
|
|
||||||
int ebeginv(const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
ebeginv(const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! fmt || ! is_verbose())
|
if (!fmt || !is_verbose())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
@@ -1016,55 +980,51 @@ int ebeginv(const char *__EINFO_RESTRICT fmt, ...)
|
|||||||
if (colour_terminal(stdout))
|
if (colour_terminal(stdout))
|
||||||
retval += printf("\n");
|
retval += printf("\n");
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("ebeginv");
|
LASTCMD("ebeginv");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(ebeginv)
|
hidden_def(ebeginv)
|
||||||
|
|
||||||
int eendv(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
eendv(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! is_verbose())
|
if (!is_verbose())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
_do_eend("eendv", retval, fmt, ap);
|
_do_eend("eendv", retval, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("eendv");
|
LASTCMD("eendv");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(eendv)
|
hidden_def(eendv)
|
||||||
|
|
||||||
int ewendv(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
int
|
||||||
|
ewendv(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (! is_verbose())
|
if (!is_verbose())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
_do_eend("ewendv", retval, fmt, ap);
|
_do_eend("ewendv", retval, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LASTCMD("ewendv");
|
LASTCMD("ewendv");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
hidden_def(ewendv)
|
hidden_def(ewendv)
|
||||||
|
|
||||||
void eindentv(void)
|
void
|
||||||
|
eindentv(void)
|
||||||
{
|
{
|
||||||
if (is_verbose())
|
if (is_verbose())
|
||||||
eindent ();
|
eindent();
|
||||||
}
|
}
|
||||||
hidden_def(eindentv)
|
hidden_def(eindentv)
|
||||||
|
|
||||||
void eoutdentv(void)
|
void
|
||||||
|
eoutdentv(void)
|
||||||
{
|
{
|
||||||
if (is_verbose())
|
if (is_verbose())
|
||||||
eoutdent();
|
eoutdent();
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ VERSION_MAP= rc.map
|
|||||||
|
|
||||||
LDADD+= ${LIBKVM}
|
LDADD+= ${LIBKVM}
|
||||||
|
|
||||||
CFLAGS+= -I../includes
|
CPPFLAGS+= -I../includes
|
||||||
|
|
||||||
MK= ../../mk
|
MK= ../../mk
|
||||||
include ${MK}/lib.mk
|
include ${MK}/lib.mk
|
||||||
|
|||||||
@@ -40,11 +40,11 @@ static size_t strlcpy(char *dst, const char *src, size_t size)
|
|||||||
|
|
||||||
if (n && --n)
|
if (n && --n)
|
||||||
do {
|
do {
|
||||||
if (! (*dst++ = *src++))
|
if (!(*dst++ = *src++))
|
||||||
break;
|
break;
|
||||||
} while (--n);
|
} while (--n);
|
||||||
|
|
||||||
if (! n) {
|
if (!n) {
|
||||||
if (size)
|
if (size)
|
||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
while (*src++);
|
while (*src++);
|
||||||
@@ -56,82 +56,60 @@ static size_t strlcpy(char *dst, const char *src, size_t size)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
static bool pid_is_cmd(pid_t pid, const char *cmd)
|
|
||||||
|
static bool pid_is_exec(pid_t pid, const char *exec)
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int c;
|
int c;
|
||||||
|
bool retval = false;
|
||||||
|
|
||||||
|
exec = basename_c(exec);
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
|
snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
|
||||||
if ((fp = fopen(buffer, "r")) == NULL)
|
if ((fp = fopen(buffer, "r"))) {
|
||||||
return false;
|
while ((c = getc(fp)) != EOF && c != '(')
|
||||||
|
;
|
||||||
while ((c = getc(fp)) != EOF && c != '(')
|
if (c == '(') {
|
||||||
;
|
while ((c = getc(fp)) != EOF && c == *exec)
|
||||||
|
exec++;
|
||||||
if (c != '(') {
|
if (c == ')' && *exec == '\0')
|
||||||
|
retval = true;
|
||||||
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return retval;
|
||||||
while ((c = getc(fp)) != EOF && c == *cmd)
|
|
||||||
cmd++;
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return (c == ')' && *cmd == '\0') ? true : false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pid_is_exec(pid_t pid, const char *const *argv)
|
static bool pid_is_argv(pid_t pid, const char *const *argv)
|
||||||
{
|
{
|
||||||
char cmdline[32];
|
char cmdline[32];
|
||||||
|
int fd;
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
char *p;
|
char *p;
|
||||||
int fd = -1;
|
ssize_t bytes;
|
||||||
int r;
|
|
||||||
|
|
||||||
/* Check it's the right binary */
|
|
||||||
snprintf (cmdline, sizeof (cmdline), "/proc/%u/exe", pid);
|
|
||||||
memset (buffer, 0, sizeof (buffer));
|
|
||||||
if (readlink(cmdline, buffer, sizeof(buffer)) != -1) {
|
|
||||||
if (strcmp(*argv, buffer) == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/* We should cater for deleted binaries too */
|
|
||||||
if (strlen(buffer) > 10) {
|
|
||||||
p = buffer + (strlen(buffer) - 10);
|
|
||||||
if (strcmp(p, " (deleted)") == 0) {
|
|
||||||
*p = 0;
|
|
||||||
if (strcmp(buffer, *argv) == 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
|
snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
|
||||||
if ((fd = open(cmdline, O_RDONLY)) < 0)
|
if ((fd = open(cmdline, O_RDONLY)) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
bytes = read(fd, buffer, sizeof(buffer));
|
||||||
r = read(fd, buffer, sizeof(buffer));
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
if (bytes == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (r == -1)
|
buffer[bytes] = '\0';
|
||||||
return 0;
|
|
||||||
|
|
||||||
buffer[r] = 0;
|
|
||||||
p = buffer;
|
p = buffer;
|
||||||
while (*argv) {
|
while (*argv) {
|
||||||
if (strcmp(*argv, p) != 0)
|
if (strcmp(*argv, p) != 0)
|
||||||
return false;
|
return false;
|
||||||
argv++;
|
argv++;
|
||||||
p += strlen(p) + 1;
|
p += strlen(p) + 1;
|
||||||
if ((unsigned) (p - buffer) > sizeof (buffer))
|
if ((unsigned)(p - buffer) > sizeof(buffer))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
RC_PIDLIST *rc_find_pids(const char *exec, const char *const *argv,
|
||||||
uid_t uid, pid_t pid)
|
uid_t uid, pid_t pid)
|
||||||
{
|
{
|
||||||
DIR *procdir;
|
DIR *procdir;
|
||||||
@@ -166,27 +144,21 @@ RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
|||||||
while ((entry = readdir(procdir)) != NULL) {
|
while ((entry = readdir(procdir)) != NULL) {
|
||||||
if (sscanf(entry->d_name, "%d", &p) != 1)
|
if (sscanf(entry->d_name, "%d", &p) != 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (runscript_pid != 0 && runscript_pid == p)
|
if (runscript_pid != 0 && runscript_pid == p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pid != 0 && pid != p)
|
if (pid != 0 && pid != p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (uid) {
|
if (uid) {
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d", p);
|
snprintf(buffer, sizeof(buffer), "/proc/%d", p);
|
||||||
if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
|
if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (exec && !pid_is_exec(p, exec))
|
||||||
if (cmd && ! pid_is_cmd(p, cmd))
|
|
||||||
continue;
|
continue;
|
||||||
|
if (argv &&
|
||||||
if (argv && ! cmd && !
|
!pid_is_argv(p, (const char *const *)argv))
|
||||||
pid_is_exec(p, (const char *const *)argv))
|
|
||||||
continue;
|
continue;
|
||||||
|
if (!pids) {
|
||||||
if (! pids) {
|
|
||||||
pids = xmalloc(sizeof(*pids));
|
pids = xmalloc(sizeof(*pids));
|
||||||
LIST_INIT(pids);
|
LIST_INIT(pids);
|
||||||
}
|
}
|
||||||
@@ -195,7 +167,6 @@ RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
|||||||
LIST_INSERT_HEAD(pids, pi, entries);
|
LIST_INSERT_HEAD(pids, pi, entries);
|
||||||
}
|
}
|
||||||
closedir(procdir);
|
closedir(procdir);
|
||||||
|
|
||||||
return pids;
|
return pids;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_find_pids)
|
librc_hidden_def(rc_find_pids)
|
||||||
@@ -224,7 +195,7 @@ librc_hidden_def(rc_find_pids)
|
|||||||
# define _KVM_FLAGS O_RDONLY
|
# define _KVM_FLAGS O_RDONLY
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
RC_PIDLIST *rc_find_pids(const char *exec, const char *const *argv,
|
||||||
uid_t uid, pid_t pid)
|
uid_t uid, pid_t pid)
|
||||||
{
|
{
|
||||||
static kvm_t *kd = NULL;
|
static kvm_t *kd = NULL;
|
||||||
@@ -258,39 +229,34 @@ RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (exec)
|
||||||
|
exec = basename_c(exec);
|
||||||
for (i = 0; i < processes; i++) {
|
for (i = 0; i < processes; i++) {
|
||||||
p = _GET_KINFO_PID(kp[i]);
|
p = _GET_KINFO_PID(kp[i]);
|
||||||
if (pid != 0 && pid != p)
|
if (pid != 0 && pid != p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (uid != 0 && uid != _GET_KINFO_UID(kp[i]))
|
if (uid != 0 && uid != _GET_KINFO_UID(kp[i]))
|
||||||
continue;
|
continue;
|
||||||
|
if (exec) {
|
||||||
if (cmd) {
|
if (!_GET_KINFO_COMM(kp[i]) ||
|
||||||
if (! _GET_KINFO_COMM(kp[i]) ||
|
strcmp(exec, _GET_KINFO_COMM(kp[i])) != 0)
|
||||||
strcmp(cmd, _GET_KINFO_COMM(kp[i])) != 0)
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (argv && *argv) {
|
||||||
if (argv && *argv && ! cmd) {
|
|
||||||
pargv = _KVM_GETARGV(kd, &kp[i], pargc);
|
pargv = _KVM_GETARGV(kd, &kp[i], pargc);
|
||||||
if (! pargv || ! *pargv)
|
if (!pargv || !*pargv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
arg = argv;
|
arg = argv;
|
||||||
match = 1;
|
match = 1;
|
||||||
|
|
||||||
while (*arg && *pargv)
|
while (*arg && *pargv)
|
||||||
if (strcmp(*arg++, *pargv++) != 0) {
|
if (strcmp(*arg++, *pargv++) != 0) {
|
||||||
match = 0;
|
match = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!match)
|
||||||
if (! match)
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!pids) {
|
||||||
if (! pids) {
|
|
||||||
pids = xmalloc(sizeof(*pids));
|
pids = xmalloc(sizeof(*pids));
|
||||||
LIST_INIT(pids);
|
LIST_INIT(pids);
|
||||||
}
|
}
|
||||||
@@ -320,7 +286,7 @@ static bool _match_daemon(const char *path, const char *file,
|
|||||||
snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
|
snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
|
||||||
fp = fopen(ffile, "r");
|
fp = fopen(ffile, "r");
|
||||||
|
|
||||||
if (! fp)
|
if (!fp)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while ((rc_getline(&line, &len, fp))) {
|
while ((rc_getline(&line, &len, fp))) {
|
||||||
@@ -329,7 +295,7 @@ static bool _match_daemon(const char *path, const char *file,
|
|||||||
TAILQ_REMOVE(match, m, entries);
|
TAILQ_REMOVE(match, m, entries);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (! TAILQ_FIRST(match))
|
if (!TAILQ_FIRST(match))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -339,26 +305,26 @@ static bool _match_daemon(const char *path, const char *file,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RC_STRINGLIST *_match_list(const char* const* argv,
|
static RC_STRINGLIST *_match_list(const char *exec, const char* const* argv,
|
||||||
const char *name, const char *pidfile)
|
const char *pidfile)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *match = rc_stringlist_new();
|
RC_STRINGLIST *match = rc_stringlist_new();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t l;
|
size_t l;
|
||||||
char *m;
|
char *m;
|
||||||
|
|
||||||
while (argv && argv[i]) {
|
if (exec) {
|
||||||
l = strlen(*argv) + strlen("argv_=") + 16;
|
l = strlen(exec) + 6;
|
||||||
m = xmalloc(sizeof(char) * l);
|
m = xmalloc(sizeof(char) * l);
|
||||||
snprintf(m, l, "argv_0=%s", argv[i++]);
|
snprintf(m, l, "exec=%s", exec);
|
||||||
rc_stringlist_add(match, m);
|
rc_stringlist_add(match, m);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name) {
|
while (argv && argv[i]) {
|
||||||
l = strlen(name) + 6;
|
l = strlen(*argv) + strlen("argv_=") + 16;
|
||||||
m = xmalloc(sizeof (char) * l);
|
m = xmalloc(sizeof(char) * l);
|
||||||
snprintf(m, l, "name=%s", name);
|
snprintf(m, l, "argv_0=%s", argv[i++]);
|
||||||
rc_stringlist_add(match, m);
|
rc_stringlist_add(match, m);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
@@ -374,8 +340,9 @@ static RC_STRINGLIST *_match_list(const char* const* argv,
|
|||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rc_service_daemon_set(const char *service, const char *const *argv,
|
bool rc_service_daemon_set(const char *service, const char *exec,
|
||||||
const char *name, const char *pidfile, bool started)
|
const char *const *argv,
|
||||||
|
const char *pidfile, bool started)
|
||||||
{
|
{
|
||||||
char dirpath[PATH_MAX];
|
char dirpath[PATH_MAX];
|
||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
@@ -388,7 +355,7 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if (!(argv && *argv) && ! name && ! pidfile) {
|
if (!exec && !pidfile) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -398,7 +365,7 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
|||||||
|
|
||||||
/* Regardless, erase any existing daemon info */
|
/* Regardless, erase any existing daemon info */
|
||||||
if ((dp = opendir(dirpath))) {
|
if ((dp = opendir(dirpath))) {
|
||||||
match = _match_list(argv, name, pidfile);
|
match = _match_list(exec, argv, pidfile);
|
||||||
while ((d = readdir(dp))) {
|
while ((d = readdir(dp))) {
|
||||||
if (d->d_name[0] == '.')
|
if (d->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
@@ -407,7 +374,7 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
|||||||
dirpath, d->d_name);
|
dirpath, d->d_name);
|
||||||
nfiles++;
|
nfiles++;
|
||||||
|
|
||||||
if (! *oldfile) {
|
if (!*oldfile) {
|
||||||
if (_match_daemon(dirpath, d->d_name, match)) {
|
if (_match_daemon(dirpath, d->d_name, match)) {
|
||||||
unlink(file);
|
unlink(file);
|
||||||
strlcpy(oldfile, file, sizeof(oldfile));
|
strlcpy(oldfile, file, sizeof(oldfile));
|
||||||
@@ -428,13 +395,13 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
|||||||
snprintf(file, sizeof(file), "%s/%03d",
|
snprintf(file, sizeof(file), "%s/%03d",
|
||||||
dirpath, nfiles + 1);
|
dirpath, nfiles + 1);
|
||||||
if ((fp = fopen(file, "w"))) {
|
if ((fp = fopen(file, "w"))) {
|
||||||
|
fprintf(fp, "exec=");
|
||||||
|
if (exec)
|
||||||
|
fprintf(fp, "%s", exec);
|
||||||
while (argv && argv[i]) {
|
while (argv && argv[i]) {
|
||||||
fprintf(fp, "argv_%d=%s\n", i, argv[i]);
|
fprintf(fp, "\nargv_%d=%s", i, argv[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
fprintf(fp, "name=");
|
|
||||||
if (name)
|
|
||||||
fprintf(fp, "%s", name);
|
|
||||||
fprintf(fp, "\npidfile=");
|
fprintf(fp, "\npidfile=");
|
||||||
if (pidfile)
|
if (pidfile)
|
||||||
fprintf(fp, "%s", pidfile);
|
fprintf(fp, "%s", pidfile);
|
||||||
@@ -450,7 +417,8 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_daemon_set)
|
librc_hidden_def(rc_service_daemon_set)
|
||||||
|
|
||||||
bool rc_service_started_daemon(const char *service, const char *const *argv,
|
bool rc_service_started_daemon(const char *service,
|
||||||
|
const char *exec, const char *const *argv,
|
||||||
int indx)
|
int indx)
|
||||||
{
|
{
|
||||||
char dirpath[PATH_MAX];
|
char dirpath[PATH_MAX];
|
||||||
@@ -460,12 +428,12 @@ bool rc_service_started_daemon(const char *service, const char *const *argv,
|
|||||||
DIR *dp;
|
DIR *dp;
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
|
|
||||||
if (!service || !(argv && *argv))
|
if (!service || !exec)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||||
basename_c(service));
|
basename_c(service));
|
||||||
match = _match_list(argv, NULL, NULL);
|
match = _match_list(exec, argv, NULL);
|
||||||
|
|
||||||
if (indx > 0) {
|
if (indx > 0) {
|
||||||
snprintf(file, sizeof(file), "%03d", indx);
|
snprintf(file, sizeof(file), "%03d", indx);
|
||||||
@@ -515,7 +483,7 @@ bool rc_service_daemons_crashed(const char *service)
|
|||||||
path += snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
path += snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||||
basename_c(service));
|
basename_c(service));
|
||||||
|
|
||||||
if (! (dp = opendir(dirpath)))
|
if (!(dp = opendir(dirpath)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while ((d = readdir(dp))) {
|
while ((d = readdir(dp))) {
|
||||||
@@ -525,25 +493,25 @@ bool rc_service_daemons_crashed(const char *service)
|
|||||||
snprintf(path, sizeof(dirpath) - (path - dirpath), "/%s",
|
snprintf(path, sizeof(dirpath) - (path - dirpath), "/%s",
|
||||||
d->d_name);
|
d->d_name);
|
||||||
fp = fopen(dirpath, "r");
|
fp = fopen(dirpath, "r");
|
||||||
if (! fp)
|
if (!fp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
while ((rc_getline(&line, &len, fp))) {
|
while ((rc_getline(&line, &len, fp))) {
|
||||||
p = line;
|
p = line;
|
||||||
if ((token = strsep(&p, "=")) == NULL || ! p)
|
if ((token = strsep(&p, "=")) == NULL || !p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (! *p)
|
if (!*p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strncmp(token, "argv_", 5) == 0) {
|
if (strcmp(token, "exec") == 0) {
|
||||||
if (! list)
|
|
||||||
list = rc_stringlist_new();
|
|
||||||
rc_stringlist_add(list, p);
|
|
||||||
} else if (strcmp(token, "exec") == 0) {
|
|
||||||
if (exec)
|
if (exec)
|
||||||
free(exec);
|
free(exec);
|
||||||
exec = xstrdup(p);
|
exec = xstrdup(p);
|
||||||
|
} else if (strncmp(token, "argv_", 5) == 0) {
|
||||||
|
if (!list)
|
||||||
|
list = rc_stringlist_new();
|
||||||
|
rc_stringlist_add(list, p);
|
||||||
} else if (strcmp(token, "name") == 0) {
|
} else if (strcmp(token, "name") == 0) {
|
||||||
if (name)
|
if (name)
|
||||||
free(name);
|
free(name);
|
||||||
@@ -566,14 +534,16 @@ bool rc_service_daemons_crashed(const char *service)
|
|||||||
free(pidfile);
|
free(pidfile);
|
||||||
pidfile = NULL;
|
pidfile = NULL;
|
||||||
|
|
||||||
/* We have the pid, so no need to match on name */
|
/* We have the pid, so no need to match on exec or name */
|
||||||
|
free(exec);
|
||||||
|
exec = NULL;
|
||||||
free(name);
|
free(name);
|
||||||
name = NULL;
|
name = NULL;
|
||||||
} else {
|
} else {
|
||||||
if (exec) {
|
if (exec) {
|
||||||
if (! list)
|
if (!list)
|
||||||
list = rc_stringlist_new();
|
list = rc_stringlist_new();
|
||||||
if (! TAILQ_FIRST(list))
|
if (!TAILQ_FIRST(list))
|
||||||
rc_stringlist_add(list, exec);
|
rc_stringlist_add(list, exec);
|
||||||
|
|
||||||
free(exec);
|
free(exec);
|
||||||
@@ -593,9 +563,10 @@ bool rc_service_daemons_crashed(const char *service)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! retval) {
|
if (!retval) {
|
||||||
if ((pids = rc_find_pids((const char *const *)argv,
|
if ((pids = rc_find_pids(exec,
|
||||||
name, 0, pid)))
|
(const char *const *)argv,
|
||||||
|
0, pid)))
|
||||||
{
|
{
|
||||||
p1 = LIST_FIRST(pids);
|
p1 = LIST_FIRST(pids);
|
||||||
while (p1) {
|
while (p1) {
|
||||||
|
|||||||
@@ -37,7 +37,8 @@
|
|||||||
|
|
||||||
static const char *bootlevel = NULL;
|
static const char *bootlevel = NULL;
|
||||||
|
|
||||||
static char *get_shell_value(char *string)
|
static char *
|
||||||
|
get_shell_value(char *string)
|
||||||
{
|
{
|
||||||
char *p = string;
|
char *p = string;
|
||||||
char *e;
|
char *e;
|
||||||
@@ -60,24 +61,23 @@ static char *get_shell_value(char *string)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rc_deptree_free(RC_DEPTREE *deptree)
|
void
|
||||||
|
rc_deptree_free(RC_DEPTREE *deptree)
|
||||||
{
|
{
|
||||||
RC_DEPINFO *di;
|
RC_DEPINFO *di;
|
||||||
RC_DEPINFO *di2;
|
RC_DEPINFO *di2;
|
||||||
RC_DEPTYPE *dt;
|
RC_DEPTYPE *dt;
|
||||||
RC_DEPTYPE *dt2;
|
RC_DEPTYPE *dt2;
|
||||||
|
|
||||||
if (! deptree)
|
if (!deptree)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
di = STAILQ_FIRST(deptree);
|
di = TAILQ_FIRST(deptree);
|
||||||
while (di)
|
while (di) {
|
||||||
{
|
di2 = TAILQ_NEXT(di, entries);
|
||||||
di2 = STAILQ_NEXT(di, entries);
|
dt = TAILQ_FIRST(&di->depends);
|
||||||
dt = STAILQ_FIRST(&di->depends);
|
while (dt) {
|
||||||
while (dt)
|
dt2 = TAILQ_NEXT(dt, entries);
|
||||||
{
|
|
||||||
dt2 = STAILQ_NEXT(dt, entries);
|
|
||||||
rc_stringlist_free(dt->services);
|
rc_stringlist_free(dt->services);
|
||||||
free(dt->type);
|
free(dt->type);
|
||||||
free(dt);
|
free(dt);
|
||||||
@@ -91,31 +91,30 @@ void rc_deptree_free(RC_DEPTREE *deptree)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_deptree_free)
|
librc_hidden_def(rc_deptree_free)
|
||||||
|
|
||||||
static RC_DEPINFO *get_depinfo(const RC_DEPTREE *deptree,
|
static RC_DEPINFO *
|
||||||
const char *service)
|
get_depinfo(const RC_DEPTREE *deptree, const char *service)
|
||||||
{
|
{
|
||||||
RC_DEPINFO *di;
|
RC_DEPINFO *di;
|
||||||
|
|
||||||
STAILQ_FOREACH(di, deptree, entries)
|
TAILQ_FOREACH(di, deptree, entries)
|
||||||
if (strcmp(di->service, service) == 0)
|
if (strcmp(di->service, service) == 0)
|
||||||
return di;
|
return di;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RC_DEPTYPE *get_deptype(const RC_DEPINFO *depinfo,
|
static RC_DEPTYPE *
|
||||||
const char *type)
|
get_deptype(const RC_DEPINFO *depinfo, const char *type)
|
||||||
{
|
{
|
||||||
RC_DEPTYPE *dt;
|
RC_DEPTYPE *dt;
|
||||||
|
|
||||||
STAILQ_FOREACH(dt, &depinfo->depends, entries)
|
TAILQ_FOREACH(dt, &depinfo->depends, entries)
|
||||||
if (strcmp(dt->type, type) == 0)
|
if (strcmp(dt->type, type) == 0)
|
||||||
return dt;
|
return dt;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RC_DEPTREE *rc_deptree_load(void)
|
RC_DEPTREE *
|
||||||
|
rc_deptree_load(void)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
RC_DEPTREE *deptree;
|
RC_DEPTREE *deptree;
|
||||||
@@ -132,53 +131,43 @@ RC_DEPTREE *rc_deptree_load(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
deptree = xmalloc(sizeof(*deptree));
|
deptree = xmalloc(sizeof(*deptree));
|
||||||
STAILQ_INIT(deptree);
|
TAILQ_INIT(deptree);
|
||||||
|
|
||||||
while ((rc_getline(&line, &len, fp)))
|
while ((rc_getline(&line, &len, fp)))
|
||||||
{
|
{
|
||||||
p = line;
|
p = line;
|
||||||
e = strsep(&p, "_");
|
e = strsep(&p, "_");
|
||||||
if (! e || strcmp(e, "depinfo") != 0)
|
if (!e || strcmp(e, "depinfo") != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
e = strsep (&p, "_");
|
e = strsep (&p, "_");
|
||||||
if (! e || sscanf(e, "%d", &i) != 1)
|
if (!e || sscanf(e, "%d", &i) != 1)
|
||||||
continue;
|
continue;
|
||||||
|
if (!(type = strsep(&p, "_=")))
|
||||||
if (! (type = strsep(&p, "_=")))
|
|
||||||
continue;
|
continue;
|
||||||
|
if (strcmp(type, "service") == 0) {
|
||||||
if (strcmp(type, "service") == 0)
|
|
||||||
{
|
|
||||||
/* Sanity */
|
/* Sanity */
|
||||||
e = get_shell_value(p);
|
e = get_shell_value(p);
|
||||||
if (! e || *e == '\0')
|
if (! e || *e == '\0')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
depinfo = xmalloc(sizeof(*depinfo));
|
depinfo = xmalloc(sizeof(*depinfo));
|
||||||
STAILQ_INIT(&depinfo->depends);
|
TAILQ_INIT(&depinfo->depends);
|
||||||
depinfo->service = xstrdup(e);
|
depinfo->service = xstrdup(e);
|
||||||
STAILQ_INSERT_TAIL(deptree, depinfo, entries);
|
TAILQ_INSERT_TAIL(deptree, depinfo, entries);
|
||||||
deptype = NULL;
|
deptype = NULL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = strsep(&p, "=");
|
e = strsep(&p, "=");
|
||||||
if (! e || sscanf(e, "%d", &i) != 1)
|
if (!e || sscanf(e, "%d", &i) != 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Sanity */
|
/* Sanity */
|
||||||
e = get_shell_value(p);
|
e = get_shell_value(p);
|
||||||
if (! e || *e == '\0')
|
if (!e || *e == '\0')
|
||||||
continue;
|
continue;
|
||||||
|
if (!deptype || strcmp(deptype->type, type) != 0) {
|
||||||
if (! deptype || strcmp(deptype->type, type) != 0) {
|
|
||||||
deptype = xmalloc(sizeof(*deptype));
|
deptype = xmalloc(sizeof(*deptype));
|
||||||
deptype->services = rc_stringlist_new();
|
deptype->services = rc_stringlist_new();
|
||||||
deptype->type = xstrdup (type);
|
deptype->type = xstrdup(type);
|
||||||
STAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
|
TAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_stringlist_add(deptype->services, e);
|
rc_stringlist_add(deptype->services, e);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -188,21 +177,28 @@ RC_DEPTREE *rc_deptree_load(void)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_deptree_load)
|
librc_hidden_def(rc_deptree_load)
|
||||||
|
|
||||||
static bool valid_service(const char *runlevel, const char *service)
|
static bool
|
||||||
|
valid_service(const char *runlevel, const char *service, const char *type)
|
||||||
{
|
{
|
||||||
RC_SERVICE state = rc_service_state(service);
|
RC_SERVICE state;
|
||||||
|
|
||||||
return ((strcmp (runlevel, bootlevel) != 0 &&
|
if (!runlevel ||
|
||||||
|
strcmp(type, "ineed") == 0 ||
|
||||||
|
strcmp(type, "needsme") == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
state = rc_service_state(service);
|
||||||
|
return ((strcmp(runlevel, bootlevel) != 0 &&
|
||||||
rc_service_in_runlevel(service, bootlevel)) ||
|
rc_service_in_runlevel(service, bootlevel)) ||
|
||||||
rc_service_in_runlevel(service, runlevel) ||
|
rc_service_in_runlevel(service, runlevel) ||
|
||||||
state & RC_SERVICE_COLDPLUGGED ||
|
state & RC_SERVICE_COLDPLUGGED ||
|
||||||
state & RC_SERVICE_STARTED);
|
state & RC_SERVICE_STARTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_provided1(const char *runlevel, RC_STRINGLIST *providers,
|
static bool
|
||||||
RC_DEPTYPE *deptype,
|
get_provided1(const char *runlevel, RC_STRINGLIST *providers,
|
||||||
const char *level, bool coldplugged,
|
RC_DEPTYPE *deptype, const char *level,
|
||||||
RC_SERVICE state)
|
bool coldplugged, RC_SERVICE state)
|
||||||
{
|
{
|
||||||
RC_STRING *service;
|
RC_STRING *service;
|
||||||
RC_SERVICE st;
|
RC_SERVICE st;
|
||||||
@@ -219,12 +215,10 @@ static bool get_provided1(const char *runlevel, RC_STRINGLIST *providers,
|
|||||||
ok = rc_service_in_runlevel(svc, level);
|
ok = rc_service_in_runlevel(svc, level);
|
||||||
else if (coldplugged)
|
else if (coldplugged)
|
||||||
ok = (st & RC_SERVICE_COLDPLUGGED &&
|
ok = (st & RC_SERVICE_COLDPLUGGED &&
|
||||||
! rc_service_in_runlevel(svc, runlevel) &&
|
!rc_service_in_runlevel(svc, runlevel) &&
|
||||||
! rc_service_in_runlevel(svc, bootlevel));
|
!rc_service_in_runlevel(svc, bootlevel));
|
||||||
|
if (!ok)
|
||||||
if (! ok)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case RC_SERVICE_STARTED:
|
case RC_SERVICE_STARTED:
|
||||||
ok = (st & RC_SERVICE_STARTED);
|
ok = (st & RC_SERVICE_STARTED);
|
||||||
@@ -239,10 +233,8 @@ static bool get_provided1(const char *runlevel, RC_STRINGLIST *providers,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!ok)
|
||||||
if (! ok)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
retval = true;
|
retval = true;
|
||||||
rc_stringlist_add(providers, svc);
|
rc_stringlist_add(providers, svc);
|
||||||
}
|
}
|
||||||
@@ -259,50 +251,49 @@ static bool get_provided1(const char *runlevel, RC_STRINGLIST *providers,
|
|||||||
If there are any bugs in rc-depend, they will probably be here as
|
If there are any bugs in rc-depend, they will probably be here as
|
||||||
provided dependancy can change depending on runlevel state.
|
provided dependancy can change depending on runlevel state.
|
||||||
*/
|
*/
|
||||||
static RC_STRINGLIST *get_provided (const RC_DEPINFO *depinfo,
|
static RC_STRINGLIST *
|
||||||
const char *runlevel, int options)
|
get_provided(const RC_DEPINFO *depinfo, const char *runlevel, int options)
|
||||||
{
|
{
|
||||||
RC_DEPTYPE *dt;
|
RC_DEPTYPE *dt;
|
||||||
RC_STRINGLIST *providers = rc_stringlist_new();
|
RC_STRINGLIST *providers = rc_stringlist_new();
|
||||||
RC_STRING *service;
|
RC_STRING *service;
|
||||||
|
|
||||||
dt = get_deptype(depinfo, "providedby");
|
dt = get_deptype(depinfo, "providedby");
|
||||||
if (! dt)
|
if (!dt)
|
||||||
return providers;
|
return providers;
|
||||||
|
|
||||||
/* If we are stopping then all depends are true, regardless of state.
|
/* If we are stopping then all depends are true, regardless of state.
|
||||||
This is especially true for net services as they could force a restart
|
This is especially true for net services as they could force a restart
|
||||||
of the local dns resolver which may depend on net. */
|
of the local dns resolver which may depend on net. */
|
||||||
if (options & RC_DEP_STOP)
|
if (options & RC_DEP_STOP) {
|
||||||
{
|
|
||||||
TAILQ_FOREACH(service, dt->services, entries)
|
TAILQ_FOREACH(service, dt->services, entries)
|
||||||
rc_stringlist_add(providers, service->value);
|
rc_stringlist_add(providers, service->value);
|
||||||
return providers;
|
return providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're strict or startng, then only use what we have in our
|
/* If we're strict or starting, then only use what we have in our
|
||||||
* runlevel and bootlevel. If we starting then check cold-plugged too. */
|
* runlevel and bootlevel. If we starting then check cold-plugged too. */
|
||||||
if (options & RC_DEP_STRICT || options & RC_DEP_START)
|
if (options & RC_DEP_STRICT || options & RC_DEP_START) {
|
||||||
{
|
|
||||||
|
|
||||||
TAILQ_FOREACH(service, dt->services, entries)
|
TAILQ_FOREACH(service, dt->services, entries)
|
||||||
if (rc_service_in_runlevel(service->value, runlevel) ||
|
if (rc_service_in_runlevel(service->value, runlevel) ||
|
||||||
rc_service_in_runlevel(service->value, bootlevel) ||
|
rc_service_in_runlevel(service->value, bootlevel) ||
|
||||||
(options & RC_DEP_START &&
|
(options & RC_DEP_START &&
|
||||||
rc_service_state(service->value) & RC_SERVICE_COLDPLUGGED))
|
rc_service_state(service->value) & RC_SERVICE_COLDPLUGGED))
|
||||||
rc_stringlist_add(providers, service->value);
|
rc_stringlist_add(providers, service->value);
|
||||||
|
|
||||||
if (TAILQ_FIRST(providers))
|
if (TAILQ_FIRST(providers))
|
||||||
return providers;
|
return providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OK, we're not strict or there were no services in our runlevel.
|
/* OK, we're not strict or there were no services in our runlevel.
|
||||||
This is now where the logic gets a little fuzzy :)
|
* This is now where the logic gets a little fuzzy :)
|
||||||
If there is >1 running service then we return NULL.
|
* If there is >1 running service then we return NULL.
|
||||||
We do this so we don't hang around waiting for inactive services and
|
* We do this so we don't hang around waiting for inactive services and
|
||||||
our need has already been satisfied as it's not strict.
|
* our need has already been satisfied as it's not strict.
|
||||||
We apply this to our runlevel, coldplugged services, then bootlevel
|
* We apply this to these states in order:-
|
||||||
and finally any running.*/
|
* started, starting | stopping | inactive, stopped
|
||||||
|
* Our sub preference in each of these is in order:-
|
||||||
|
* runlevel, coldplugged, bootlevel, any
|
||||||
|
*/
|
||||||
#define DO \
|
#define DO \
|
||||||
if (TAILQ_FIRST(providers)) { \
|
if (TAILQ_FIRST(providers)) { \
|
||||||
if (TAILQ_NEXT(TAILQ_FIRST(providers), entries)) { \
|
if (TAILQ_NEXT(TAILQ_FIRST(providers), entries)) { \
|
||||||
@@ -312,45 +303,35 @@ static RC_STRINGLIST *get_provided (const RC_DEPINFO *depinfo,
|
|||||||
return providers; \
|
return providers; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Anything in the runlevel has to come first */
|
/* Anything running has to come first */
|
||||||
if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTED))
|
if (get_provided1(runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTED))
|
||||||
{ DO }
|
{ DO }
|
||||||
if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTING))
|
if (get_provided1(runlevel, providers, dt, NULL, true, RC_SERVICE_STARTED))
|
||||||
|
{ DO }
|
||||||
|
if (bootlevel && strcmp(runlevel, bootlevel) != 0 &&
|
||||||
|
get_provided1(runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTED))
|
||||||
|
{ DO }
|
||||||
|
if (get_provided1(runlevel, providers, dt, NULL, false, RC_SERVICE_STARTED))
|
||||||
|
{ DO }
|
||||||
|
|
||||||
|
/* Check starting services */
|
||||||
|
if (get_provided1(runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTING))
|
||||||
return providers;
|
return providers;
|
||||||
if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STOPPED))
|
if (get_provided1(runlevel, providers, dt, NULL, true, RC_SERVICE_STARTING))
|
||||||
return providers;
|
return providers;
|
||||||
|
if (bootlevel && strcmp(runlevel, bootlevel) != 0 &&
|
||||||
/* Check coldplugged services */
|
get_provided1(runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTING))
|
||||||
if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STARTED))
|
return providers;
|
||||||
{ DO }
|
if (get_provided1(runlevel, providers, dt, NULL, false, RC_SERVICE_STARTING))
|
||||||
if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STARTING))
|
|
||||||
return providers;
|
|
||||||
|
|
||||||
/* Check bootlevel if we're not in it */
|
|
||||||
if (bootlevel && strcmp (runlevel, bootlevel) != 0)
|
|
||||||
{
|
|
||||||
if (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTED))
|
|
||||||
{ DO }
|
|
||||||
if (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTING))
|
|
||||||
return providers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check coldplugged services */
|
|
||||||
if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STOPPED))
|
|
||||||
{ DO }
|
|
||||||
|
|
||||||
/* Check manually started */
|
|
||||||
if (get_provided1 (runlevel, providers, dt, NULL, false, RC_SERVICE_STARTED))
|
|
||||||
{ DO }
|
|
||||||
if (get_provided1 (runlevel, providers, dt, NULL, false, RC_SERVICE_STARTING))
|
|
||||||
return providers;
|
return providers;
|
||||||
|
|
||||||
/* Nothing started then. OK, lets get the stopped services */
|
/* Nothing started then. OK, lets get the stopped services */
|
||||||
if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STOPPED))
|
if (get_provided1(runlevel, providers, dt, runlevel, false, RC_SERVICE_STOPPED))
|
||||||
return providers;
|
return providers;
|
||||||
|
if (get_provided1(runlevel, providers, dt, NULL, true, RC_SERVICE_STOPPED))
|
||||||
if (bootlevel && (strcmp (runlevel, bootlevel) != 0)
|
{ DO }
|
||||||
&& (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STOPPED)))
|
if (bootlevel && (strcmp(runlevel, bootlevel) != 0) &&
|
||||||
|
get_provided1(runlevel, providers, dt, bootlevel, false, RC_SERVICE_STOPPED))
|
||||||
return providers;
|
return providers;
|
||||||
|
|
||||||
/* Still nothing? OK, list all services */
|
/* Still nothing? OK, list all services */
|
||||||
@@ -360,12 +341,13 @@ static RC_STRINGLIST *get_provided (const RC_DEPINFO *depinfo,
|
|||||||
return providers;
|
return providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void visit_service(const RC_DEPTREE *deptree,
|
static void
|
||||||
const RC_STRINGLIST *types,
|
visit_service(const RC_DEPTREE *deptree,
|
||||||
RC_STRINGLIST **sorted,
|
const RC_STRINGLIST *types,
|
||||||
RC_STRINGLIST *visited,
|
RC_STRINGLIST **sorted,
|
||||||
const RC_DEPINFO *depinfo,
|
RC_STRINGLIST *visited,
|
||||||
const char *runlevel, int options)
|
const RC_DEPINFO *depinfo,
|
||||||
|
const char *runlevel, int options)
|
||||||
{
|
{
|
||||||
RC_STRING *type;
|
RC_STRING *type;
|
||||||
RC_STRING *service;
|
RC_STRING *service;
|
||||||
@@ -379,7 +361,6 @@ static void visit_service(const RC_DEPTREE *deptree,
|
|||||||
TAILQ_FOREACH(type, visited, entries)
|
TAILQ_FOREACH(type, visited, entries)
|
||||||
if (strcmp(type->value, depinfo->service) == 0)
|
if (strcmp(type->value, depinfo->service) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Add ourselves as a visited service */
|
/* Add ourselves as a visited service */
|
||||||
rc_stringlist_add(visited, depinfo->service);
|
rc_stringlist_add(visited, depinfo->service);
|
||||||
|
|
||||||
@@ -389,10 +370,10 @@ static void visit_service(const RC_DEPTREE *deptree,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
TAILQ_FOREACH(service, dt->services, entries) {
|
TAILQ_FOREACH(service, dt->services, entries) {
|
||||||
if (! options & RC_DEP_TRACE ||
|
if (!(options & RC_DEP_TRACE) ||
|
||||||
strcmp(type->value, "iprovide") == 0)
|
strcmp(type->value, "iprovide") == 0)
|
||||||
{
|
{
|
||||||
if (! *sorted)
|
if (!*sorted)
|
||||||
*sorted = rc_stringlist_new();
|
*sorted = rc_stringlist_new();
|
||||||
rc_stringlist_add(*sorted, service->value);
|
rc_stringlist_add(*sorted, service->value);
|
||||||
continue;
|
continue;
|
||||||
@@ -405,18 +386,12 @@ static void visit_service(const RC_DEPTREE *deptree,
|
|||||||
if (TAILQ_FIRST(provided)) {
|
if (TAILQ_FIRST(provided)) {
|
||||||
TAILQ_FOREACH(p, provided, entries) {
|
TAILQ_FOREACH(p, provided, entries) {
|
||||||
di = get_depinfo(deptree, p->value);
|
di = get_depinfo(deptree, p->value);
|
||||||
if (di &&
|
if (di && valid_service(runlevel, di->service, type->value))
|
||||||
(strcmp(type->value, "ineed") == 0 ||
|
|
||||||
strcmp(type->value, "needsme") == 0 ||
|
|
||||||
valid_service(runlevel, di->service)))
|
|
||||||
visit_service(deptree, types, sorted, visited, di,
|
visit_service(deptree, types, sorted, visited, di,
|
||||||
runlevel, options | RC_DEP_TRACE);
|
runlevel, options | RC_DEP_TRACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (di &&
|
else if (di && valid_service(runlevel, service->value, type->value))
|
||||||
(strcmp(type->value, "ineed") == 0 ||
|
|
||||||
strcmp(type->value, "needsme") == 0 ||
|
|
||||||
valid_service(runlevel, service->value)))
|
|
||||||
visit_service(deptree, types, sorted, visited, di,
|
visit_service(deptree, types, sorted, visited, di,
|
||||||
runlevel, options | RC_DEP_TRACE);
|
runlevel, options | RC_DEP_TRACE);
|
||||||
|
|
||||||
@@ -431,12 +406,11 @@ static void visit_service(const RC_DEPTREE *deptree,
|
|||||||
TAILQ_FOREACH(service, dt->services, entries) {
|
TAILQ_FOREACH(service, dt->services, entries) {
|
||||||
if (!(di = get_depinfo(deptree, service->value)))
|
if (!(di = get_depinfo(deptree, service->value)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
provided = get_provided(di, runlevel, options);
|
provided = get_provided(di, runlevel, options);
|
||||||
TAILQ_FOREACH(p, provided, entries)
|
TAILQ_FOREACH(p, provided, entries)
|
||||||
if (strcmp (p->value, depinfo->service) == 0) {
|
if (strcmp (p->value, depinfo->service) == 0) {
|
||||||
//visit_service (deptree, types, sorted, visited, di,
|
visit_service (deptree, types, sorted, visited, di,
|
||||||
// runlevel, options | RC_DEP_TRACE);
|
runlevel, options | RC_DEP_TRACE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc_stringlist_free(provided);
|
rc_stringlist_free(provided);
|
||||||
@@ -446,16 +420,17 @@ static void 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)
|
if (!*sorted)
|
||||||
*sorted = rc_stringlist_new();
|
*sorted = rc_stringlist_new();
|
||||||
rc_stringlist_add(*sorted, depinfo->service);
|
rc_stringlist_add(*sorted, depinfo->service);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *deptree,
|
RC_STRINGLIST *
|
||||||
const char *service, const char *type)
|
rc_deptree_depend(const RC_DEPTREE *deptree,
|
||||||
|
const char *service, const char *type)
|
||||||
{
|
{
|
||||||
RC_DEPINFO *di;
|
RC_DEPINFO *di;
|
||||||
RC_DEPTYPE *dt;
|
RC_DEPTYPE *dt;
|
||||||
@@ -463,7 +438,7 @@ RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *deptree,
|
|||||||
RC_STRING *svc;
|
RC_STRING *svc;
|
||||||
|
|
||||||
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 NULL;
|
||||||
@@ -473,15 +448,15 @@ RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *deptree,
|
|||||||
svcs = rc_stringlist_new();
|
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;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_deptree_depend)
|
librc_hidden_def(rc_deptree_depend)
|
||||||
|
|
||||||
RC_STRINGLIST *rc_deptree_depends(const RC_DEPTREE *deptree,
|
RC_STRINGLIST *
|
||||||
const RC_STRINGLIST *types,
|
rc_deptree_depends(const RC_DEPTREE *deptree,
|
||||||
const RC_STRINGLIST *services,
|
const RC_STRINGLIST *types,
|
||||||
const char *runlevel, int options)
|
const RC_STRINGLIST *services,
|
||||||
|
const char *runlevel, int options)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *sorted = NULL;
|
RC_STRINGLIST *sorted = NULL;
|
||||||
RC_STRINGLIST *visited = rc_stringlist_new();
|
RC_STRINGLIST *visited = rc_stringlist_new();
|
||||||
@@ -489,11 +464,10 @@ RC_STRINGLIST *rc_deptree_depends(const RC_DEPTREE *deptree,
|
|||||||
const RC_STRING *service;
|
const RC_STRING *service;
|
||||||
|
|
||||||
bootlevel = getenv("RC_BOOTLEVEL");
|
bootlevel = getenv("RC_BOOTLEVEL");
|
||||||
if (! bootlevel)
|
if (!bootlevel)
|
||||||
bootlevel = RC_LEVEL_BOOT;
|
bootlevel = RC_LEVEL_BOOT;
|
||||||
|
|
||||||
TAILQ_FOREACH(service, services, entries) {
|
TAILQ_FOREACH(service, services, entries) {
|
||||||
if (! (di = get_depinfo(deptree, service->value))) {
|
if (!(di = get_depinfo(deptree, service->value))) {
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -501,14 +475,13 @@ RC_STRINGLIST *rc_deptree_depends(const RC_DEPTREE *deptree,
|
|||||||
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);
|
||||||
return sorted;
|
return sorted;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_deptree_depends)
|
librc_hidden_def(rc_deptree_depends)
|
||||||
|
|
||||||
RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
|
RC_STRINGLIST *
|
||||||
const char *runlevel, int options)
|
rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *list;
|
RC_STRINGLIST *list;
|
||||||
RC_STRINGLIST *list2;
|
RC_STRINGLIST *list2;
|
||||||
@@ -520,9 +493,9 @@ RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
|
|||||||
bootlevel = RC_LEVEL_BOOT;
|
bootlevel = RC_LEVEL_BOOT;
|
||||||
|
|
||||||
/* When shutting down, list all running services */
|
/* When shutting down, list all running services */
|
||||||
if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
|
if (strcmp(runlevel, RC_LEVEL_SINGLE) == 0 ||
|
||||||
strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
|
strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
|
||||||
strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
|
strcmp(runlevel, RC_LEVEL_REBOOT) == 0)
|
||||||
{
|
{
|
||||||
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);
|
||||||
@@ -554,7 +527,7 @@ RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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 (list2) {
|
||||||
if (list) {
|
if (list) {
|
||||||
@@ -572,21 +545,20 @@ RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
|
|||||||
rc_stringlist_add(types, "ineed");
|
rc_stringlist_add(types, "ineed");
|
||||||
rc_stringlist_add(types, "iuse");
|
rc_stringlist_add(types, "iuse");
|
||||||
rc_stringlist_add(types, "iafter");
|
rc_stringlist_add(types, "iafter");
|
||||||
|
|
||||||
services = rc_deptree_depends(deptree, types, list, runlevel,
|
services = rc_deptree_depends(deptree, types, list, runlevel,
|
||||||
RC_DEP_STRICT | RC_DEP_TRACE | options);
|
RC_DEP_STRICT | RC_DEP_TRACE | options);
|
||||||
rc_stringlist_free(list);
|
rc_stringlist_free(list);
|
||||||
rc_stringlist_free(types);
|
rc_stringlist_free(types);
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_deptree_order)
|
librc_hidden_def(rc_deptree_order)
|
||||||
|
|
||||||
bool rc_newer_than(const char *source, const char *target)
|
static bool
|
||||||
|
mtime_check(const char *source, const char *target, bool newer)
|
||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
time_t mtime;
|
time_t mtime;
|
||||||
bool newer = true;
|
bool retval = true;
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
@@ -597,36 +569,52 @@ bool rc_newer_than(const char *source, const char *target)
|
|||||||
return false;
|
return false;
|
||||||
mtime = buf.st_mtime;
|
mtime = buf.st_mtime;
|
||||||
|
|
||||||
/* Of course we are newer than targets that don't exist
|
/* If target does not exist, return true to mimic shell test */
|
||||||
such as broken symlinks */
|
|
||||||
if (stat(target, &buf) != 0)
|
if (stat(target, &buf) != 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (mtime < buf.st_mtime)
|
if (newer) {
|
||||||
return false;
|
if (mtime < buf.st_mtime)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (mtime > buf.st_mtime)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* If not a dir then reset errno */
|
/* If not a dir then reset errno */
|
||||||
if (! (dp = opendir(target))) {
|
if (!(dp = opendir(target))) {
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we're newer than all the entries in the dir */
|
/* Check all the entries in the dir */
|
||||||
while ((d = readdir(dp))) {
|
while ((d = readdir(dp))) {
|
||||||
if (d->d_name[0] == '.')
|
if (d->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
|
snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
|
||||||
newer = rc_newer_than(source, path);
|
retval = mtime_check(source, path, newer);
|
||||||
if (! newer)
|
if (!retval)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
return newer;
|
bool
|
||||||
|
rc_newer_than(const char *source, const char *target)
|
||||||
|
{
|
||||||
|
|
||||||
|
return mtime_check(source, target, true);
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_newer_than)
|
librc_hidden_def(rc_newer_than)
|
||||||
|
|
||||||
|
bool
|
||||||
|
rc_older_than(const char *source, const char *target)
|
||||||
|
{
|
||||||
|
return mtime_check(source, target, false);
|
||||||
|
}
|
||||||
|
librc_hidden_def(rc_older_than)
|
||||||
|
|
||||||
typedef struct deppair
|
typedef struct deppair
|
||||||
{
|
{
|
||||||
const char *depend;
|
const char *depend;
|
||||||
@@ -659,7 +647,8 @@ static const char *const depdirs[] =
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
bool rc_deptree_update_needed(void)
|
bool
|
||||||
|
rc_deptree_update_needed(void)
|
||||||
{
|
{
|
||||||
bool newer = false;
|
bool newer = false;
|
||||||
RC_STRINGLIST *config;
|
RC_STRINGLIST *config;
|
||||||
@@ -673,22 +662,22 @@ bool rc_deptree_update_needed(void)
|
|||||||
|
|
||||||
/* Quick test to see if anything we use has changed and we have
|
/* Quick test to see if anything we use has changed and we have
|
||||||
* data in our deptree */
|
* data in our deptree */
|
||||||
if (! existss(RC_DEPTREE_CACHE) ||
|
if (!existss(RC_DEPTREE_CACHE) ||
|
||||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR) ||
|
!rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR) ||
|
||||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR) ||
|
!rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR) ||
|
||||||
#ifdef RC_PKG_INITDIR
|
#ifdef RC_PKG_INITDIR
|
||||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR) ||
|
!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR) ||
|
||||||
#endif
|
#endif
|
||||||
#ifdef RC_PKG_CONFDIR
|
#ifdef RC_PKG_CONFDIR
|
||||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR) ||
|
!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR) ||
|
||||||
#endif
|
#endif
|
||||||
#ifdef RC_LOCAL_INITDIR
|
#ifdef RC_LOCAL_INITDIR
|
||||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR) ||
|
!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR) ||
|
||||||
#endif
|
#endif
|
||||||
#ifdef RC_LOCAL_CONFDIR
|
#ifdef RC_LOCAL_CONFDIR
|
||||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR) ||
|
!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR) ||
|
||||||
#endif
|
#endif
|
||||||
! rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf"))
|
!rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf"))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* Some init scripts dependencies change depending on config files
|
/* Some init scripts dependencies change depending on config files
|
||||||
@@ -696,100 +685,86 @@ bool rc_deptree_update_needed(void)
|
|||||||
config = rc_config_list(RC_DEPCONFIG);
|
config = rc_config_list(RC_DEPCONFIG);
|
||||||
if (config) {
|
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;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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)
|
||||||
|
|
||||||
/* This is a 5 phase operation
|
/* This is a 6 phase operation
|
||||||
Phase 1 is a shell script which loads each init script and config in turn
|
Phase 1 is a shell script which loads each init script and config in turn
|
||||||
and echos their dependency info to stdout
|
and echos their dependency info to stdout
|
||||||
Phase 2 takes that and populates a depinfo object with that data
|
Phase 2 takes that and populates a depinfo object with that data
|
||||||
Phase 3 adds any provided services to the depinfo object
|
Phase 3 adds any provided services to the depinfo object
|
||||||
Phase 4 scans that depinfo object and puts in backlinks
|
Phase 4 scans that depinfo object and puts in backlinks
|
||||||
Phase 5 saves the depinfo object to disk
|
Phase 5 removes broken before dependencies
|
||||||
|
Phase 6 saves the depinfo object to disk
|
||||||
*/
|
*/
|
||||||
bool rc_deptree_update(void)
|
bool
|
||||||
|
rc_deptree_update(void)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
RC_DEPTREE *deptree;
|
RC_DEPTREE *deptree, *providers;
|
||||||
RC_DEPTREE *providers;
|
RC_DEPINFO *depinfo = NULL, *depinfo_np, *di;
|
||||||
RC_DEPINFO *depinfo = NULL;
|
RC_DEPTYPE *deptype = NULL, *dt_np, *dt, *provide;
|
||||||
RC_DEPINFO *depinfo_np;
|
RC_STRINGLIST *config, *types, *sorted, *visited;
|
||||||
RC_DEPINFO *di;
|
RC_STRING *s, *s2, *s2_np, *s3, *s4;
|
||||||
RC_DEPTYPE *deptype = NULL;
|
|
||||||
RC_DEPTYPE *dt;
|
|
||||||
RC_DEPTYPE *dt_np;
|
|
||||||
RC_STRINGLIST *config;
|
|
||||||
RC_STRING *s;
|
|
||||||
RC_STRING *s2;
|
|
||||||
RC_DEPTYPE *provide;
|
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char *depend;
|
char *depend, *depends, *service, *type, *nosys;
|
||||||
char *depends;
|
size_t i, k, l;
|
||||||
char *service;
|
bool retval = true;
|
||||||
char *type;
|
|
||||||
size_t i;
|
|
||||||
size_t k;
|
|
||||||
size_t l;
|
|
||||||
int retval = true;
|
|
||||||
const char *sys = rc_sys();
|
const char *sys = rc_sys();
|
||||||
char *nosys;
|
|
||||||
|
|
||||||
/* Some init scripts need RC_LIBDIR to source stuff
|
/* Some init scripts need RC_LIBDIR to source stuff
|
||||||
Ideally we should be setting our full env instead */
|
Ideally we should be setting our full env instead */
|
||||||
if (! getenv("RC_LIBDIR"))
|
if (!getenv("RC_LIBDIR"))
|
||||||
setenv("RC_LIBDIR", RC_LIBDIR, 0);
|
setenv("RC_LIBDIR", RC_LIBDIR, 0);
|
||||||
|
|
||||||
/* Phase 1 - source all init scripts and print dependencies */
|
/* Phase 1 - source all init scripts and print dependencies */
|
||||||
if (! (fp = popen(GENDEP, "r")))
|
if (!(fp = popen(GENDEP, "r")))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
deptree = xmalloc(sizeof(*deptree));
|
deptree = xmalloc(sizeof(*deptree));
|
||||||
STAILQ_INIT(deptree);
|
TAILQ_INIT(deptree);
|
||||||
|
|
||||||
config = rc_stringlist_new();
|
config = rc_stringlist_new();
|
||||||
|
|
||||||
while ((rc_getline(&line, &len, fp)))
|
while ((rc_getline(&line, &len, fp)))
|
||||||
{
|
{
|
||||||
depends = line;
|
depends = line;
|
||||||
service = strsep(&depends, " ");
|
service = strsep(&depends, " ");
|
||||||
if (! service || ! *service)
|
if (!service || !*service)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
type = strsep(&depends, " ");
|
type = strsep(&depends, " ");
|
||||||
if (! depinfo || strcmp(depinfo->service, service) != 0) {
|
if (!depinfo || strcmp(depinfo->service, service) != 0) {
|
||||||
deptype = NULL;
|
deptype = NULL;
|
||||||
depinfo = get_depinfo(deptree, service);
|
depinfo = get_depinfo(deptree, service);
|
||||||
if (! depinfo) {
|
if (!depinfo) {
|
||||||
depinfo = xmalloc(sizeof(*depinfo));
|
depinfo = xmalloc(sizeof(*depinfo));
|
||||||
STAILQ_INIT(&depinfo->depends);
|
TAILQ_INIT(&depinfo->depends);
|
||||||
depinfo->service = xstrdup(service);
|
depinfo->service = xstrdup(service);
|
||||||
STAILQ_INSERT_TAIL(deptree, depinfo, entries);
|
TAILQ_INSERT_TAIL(deptree, depinfo, entries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We may not have any depends */
|
/* We may not have any depends */
|
||||||
if (! type || ! depends)
|
if (!type || !depends)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Get the type */
|
/* Get the type */
|
||||||
if (strcmp(type, "config") != 0) {
|
if (strcmp(type, "config") != 0) {
|
||||||
if (! deptype || strcmp (deptype->type, type) != 0)
|
if (!deptype || strcmp(deptype->type, type) != 0)
|
||||||
deptype = get_deptype(depinfo, type);
|
deptype = get_deptype(depinfo, type);
|
||||||
if (! deptype) {
|
if (!deptype) {
|
||||||
deptype = xmalloc(sizeof(*deptype));
|
deptype = xmalloc(sizeof(*deptype));
|
||||||
deptype->type = xstrdup(type);
|
deptype->type = xstrdup(type);
|
||||||
deptype->services = rc_stringlist_new();
|
deptype->services = rc_stringlist_new();
|
||||||
STAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
|
TAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -801,7 +776,7 @@ bool rc_deptree_update(void)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strcmp(type, "config") == 0) {
|
if (strcmp(type, "config") == 0) {
|
||||||
rc_stringlist_add(config, depend);
|
rc_stringlist_addu(config, depend);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -829,9 +804,9 @@ bool rc_deptree_update(void)
|
|||||||
rc_stringlist_delete(dt->services, depend);
|
rc_stringlist_delete(dt->services, depend);
|
||||||
}
|
}
|
||||||
/* If we're after something, remove us from the before list */
|
/* If we're after something, remove us from the before list */
|
||||||
if (strcmp (type, "iafter") == 0 ||
|
if (strcmp(type, "iafter") == 0 ||
|
||||||
strcmp (type, "ineed") == 0 ||
|
strcmp(type, "ineed") == 0 ||
|
||||||
strcmp (type, "iuse") == 0) {
|
strcmp(type, "iuse") == 0) {
|
||||||
if ((dt = get_deptype(depinfo, "ibefore")))
|
if ((dt = get_deptype(depinfo, "ibefore")))
|
||||||
rc_stringlist_delete(dt->services, depend);
|
rc_stringlist_delete(dt->services, depend);
|
||||||
}
|
}
|
||||||
@@ -851,20 +826,20 @@ bool rc_deptree_update(void)
|
|||||||
nosys[i + 2] = (char)tolower((unsigned char)sys[i]);
|
nosys[i + 2] = (char)tolower((unsigned char)sys[i]);
|
||||||
nosys[i + 2] = '\0';
|
nosys[i + 2] = '\0';
|
||||||
|
|
||||||
STAILQ_FOREACH_SAFE(depinfo, deptree, entries, depinfo_np)
|
TAILQ_FOREACH_SAFE(depinfo, deptree, entries, depinfo_np)
|
||||||
if ((deptype = get_deptype(depinfo, "keyword")))
|
if ((deptype = get_deptype(depinfo, "keyword")))
|
||||||
TAILQ_FOREACH(s, deptype->services, entries)
|
TAILQ_FOREACH(s, deptype->services, entries)
|
||||||
if (strcmp (s->value, nosys) == 0) {
|
if (strcmp(s->value, nosys) == 0) {
|
||||||
provide = get_deptype(depinfo, "iprovide");
|
provide = get_deptype(depinfo, "iprovide");
|
||||||
STAILQ_REMOVE(deptree, depinfo, rc_depinfo, entries);
|
TAILQ_REMOVE(deptree, depinfo, entries);
|
||||||
STAILQ_FOREACH(di, deptree, entries) {
|
TAILQ_FOREACH(di, deptree, entries) {
|
||||||
STAILQ_FOREACH_SAFE(dt, &di->depends, entries, dt_np) {
|
TAILQ_FOREACH_SAFE(dt, &di->depends, entries, dt_np) {
|
||||||
rc_stringlist_delete(dt->services, depinfo->service);
|
rc_stringlist_delete(dt->services, depinfo->service);
|
||||||
if (provide)
|
if (provide)
|
||||||
TAILQ_FOREACH(s2, provide->services, entries)
|
TAILQ_FOREACH(s2, provide->services, entries)
|
||||||
rc_stringlist_delete(dt->services, s2->value);
|
rc_stringlist_delete(dt->services, s2->value);
|
||||||
if (! TAILQ_FIRST(dt->services)) {
|
if (!TAILQ_FIRST(dt->services)) {
|
||||||
STAILQ_REMOVE(&di->depends, dt, rc_deptype, entries);
|
TAILQ_REMOVE(&di->depends, dt, entries);
|
||||||
free(dt->type);
|
free(dt->type);
|
||||||
free(dt->services);
|
free(dt->services);
|
||||||
free(dt);
|
free(dt);
|
||||||
@@ -872,38 +847,38 @@ bool rc_deptree_update(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free (nosys);
|
free(nosys);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Phase 3 - add our providers to the tree */
|
/* Phase 3 - add our providers to the tree */
|
||||||
providers = xmalloc(sizeof(*providers));
|
providers = xmalloc(sizeof(*providers));
|
||||||
STAILQ_INIT(providers);
|
TAILQ_INIT(providers);
|
||||||
STAILQ_FOREACH(depinfo, deptree, entries)
|
TAILQ_FOREACH(depinfo, deptree, entries)
|
||||||
if ((deptype = get_deptype(depinfo, "iprovide")))
|
if ((deptype = get_deptype(depinfo, "iprovide")))
|
||||||
TAILQ_FOREACH(s, deptype->services, entries) {
|
TAILQ_FOREACH(s, deptype->services, entries) {
|
||||||
STAILQ_FOREACH(di, providers, entries)
|
TAILQ_FOREACH(di, providers, entries)
|
||||||
if (strcmp(di->service, s->value) == 0)
|
if (strcmp(di->service, s->value) == 0)
|
||||||
break;
|
break;
|
||||||
if (! di) {
|
if (!di) {
|
||||||
di = xmalloc(sizeof(*di));
|
di = xmalloc(sizeof(*di));
|
||||||
STAILQ_INIT(&di->depends);
|
TAILQ_INIT(&di->depends);
|
||||||
di->service = xstrdup(s->value);
|
di->service = xstrdup(s->value);
|
||||||
STAILQ_INSERT_TAIL(providers, di, entries);
|
TAILQ_INSERT_TAIL(providers, di, entries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
STAILQ_CONCAT(deptree, providers);
|
TAILQ_CONCAT(deptree, providers, entries);
|
||||||
free(providers);
|
free(providers);
|
||||||
|
|
||||||
/* Phase 4 - backreference our depends */
|
/* Phase 4 - backreference our depends */
|
||||||
STAILQ_FOREACH(depinfo, deptree, entries)
|
TAILQ_FOREACH(depinfo, deptree, entries)
|
||||||
for (i = 0; deppairs[i].depend; i++) {
|
for (i = 0; deppairs[i].depend; i++) {
|
||||||
deptype = get_deptype(depinfo, deppairs[i].depend);
|
deptype = get_deptype(depinfo, deppairs[i].depend);
|
||||||
if (! deptype)
|
if (!deptype)
|
||||||
continue;
|
continue;
|
||||||
TAILQ_FOREACH(s, deptype->services, entries) {
|
TAILQ_FOREACH(s, deptype->services, entries) {
|
||||||
di = get_depinfo(deptree, s->value);
|
di = get_depinfo(deptree, s->value);
|
||||||
if (! di) {
|
if (!di) {
|
||||||
if (strcmp (deptype->type, "ineed") == 0)
|
if (strcmp(deptype->type, "ineed") == 0)
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"Service `%s' needs non"
|
"Service `%s' needs non"
|
||||||
" existant service `%s'\n",
|
" existant service `%s'\n",
|
||||||
@@ -912,28 +887,80 @@ bool rc_deptree_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dt = get_deptype(di, deppairs[i].addto);
|
dt = get_deptype(di, deppairs[i].addto);
|
||||||
if (! dt) {
|
if (!dt) {
|
||||||
dt = xmalloc(sizeof(*dt));
|
dt = xmalloc(sizeof(*dt));
|
||||||
dt->type = xstrdup(deppairs[i].addto);
|
dt->type = xstrdup(deppairs[i].addto);
|
||||||
dt->services = rc_stringlist_new();
|
dt->services = rc_stringlist_new();
|
||||||
STAILQ_INSERT_TAIL(&di->depends, dt, entries);
|
TAILQ_INSERT_TAIL(&di->depends, dt, entries);
|
||||||
}
|
}
|
||||||
rc_stringlist_add(dt->services, depinfo->service);
|
rc_stringlist_addu(dt->services, depinfo->service);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Phase 5 - save to disk
|
|
||||||
|
/* Phase 5 - Remove broken before directives */
|
||||||
|
types = rc_stringlist_new();
|
||||||
|
rc_stringlist_add(types, "ineed");
|
||||||
|
rc_stringlist_add(types, "iuse");
|
||||||
|
rc_stringlist_add(types, "iafter");
|
||||||
|
TAILQ_FOREACH(depinfo, deptree, entries) {
|
||||||
|
deptype = get_deptype(depinfo, "ibefore");
|
||||||
|
if (!deptype)
|
||||||
|
continue;
|
||||||
|
sorted = NULL;
|
||||||
|
visited = rc_stringlist_new();
|
||||||
|
visit_service(deptree, types, &sorted, visited, depinfo,
|
||||||
|
NULL, 0);
|
||||||
|
rc_stringlist_free(visited);
|
||||||
|
if (!sorted)
|
||||||
|
continue;
|
||||||
|
TAILQ_FOREACH_SAFE(s2, deptype->services, entries, s2_np) {
|
||||||
|
TAILQ_FOREACH(s3, sorted, entries) {
|
||||||
|
di = get_depinfo(deptree, s3->value);
|
||||||
|
if (!di)
|
||||||
|
continue;
|
||||||
|
if (strcmp(s2->value, s3->value) == 0) {
|
||||||
|
dt = get_deptype(di, "iafter");
|
||||||
|
if (dt)
|
||||||
|
rc_stringlist_delete(dt->services, depinfo->service);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dt = get_deptype(di, "iprovide");
|
||||||
|
if (!dt)
|
||||||
|
continue;
|
||||||
|
TAILQ_FOREACH(s4, dt->services, entries) {
|
||||||
|
if (strcmp(s4->value, s2->value) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (s4) {
|
||||||
|
di = get_depinfo(deptree, s4->value);
|
||||||
|
if (di) {
|
||||||
|
dt = get_deptype(di, "iafter");
|
||||||
|
if (dt)
|
||||||
|
rc_stringlist_delete(dt->services, depinfo->service);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s3)
|
||||||
|
rc_stringlist_delete(deptype->services, s2->value);
|
||||||
|
}
|
||||||
|
rc_stringlist_free(sorted);
|
||||||
|
}
|
||||||
|
rc_stringlist_free(types);
|
||||||
|
|
||||||
|
/* Phase 6 - save to disk
|
||||||
Now that we're purely in C, do we need to keep a shell parseable file?
|
Now that we're purely in C, do we need to keep a shell parseable file?
|
||||||
I think yes as then it stays human readable
|
I think yes as then it stays human readable
|
||||||
This works and should be entirely shell parseable provided that depend
|
This works and should be entirely shell parseable provided that depend
|
||||||
names don't have any non shell variable characters in
|
names don't have any non shell variable characters in
|
||||||
*/
|
*/
|
||||||
if ((fp = fopen (RC_DEPTREE_CACHE, "w"))) {
|
if ((fp = fopen(RC_DEPTREE_CACHE, "w"))) {
|
||||||
i = 0;
|
i = 0;
|
||||||
STAILQ_FOREACH(depinfo, deptree, entries) {
|
TAILQ_FOREACH(depinfo, deptree, entries) {
|
||||||
fprintf(fp, "depinfo_%zu_service='%s'\n",
|
fprintf(fp, "depinfo_%zu_service='%s'\n",
|
||||||
i, depinfo->service);
|
i, depinfo->service);
|
||||||
STAILQ_FOREACH(deptype, &depinfo->depends, entries) {
|
TAILQ_FOREACH(deptype, &depinfo->depends, entries) {
|
||||||
k = 0;
|
k = 0;
|
||||||
TAILQ_FOREACH(s, deptype->services, entries) {
|
TAILQ_FOREACH(s, deptype->services, entries) {
|
||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
@@ -962,13 +989,12 @@ bool rc_deptree_update(void)
|
|||||||
RC_DEPCONFIG, strerror(errno));
|
RC_DEPCONFIG, strerror(errno));
|
||||||
retval = false;
|
retval = false;
|
||||||
}
|
}
|
||||||
rc_stringlist_free (config);
|
|
||||||
} else {
|
} else {
|
||||||
unlink(RC_DEPCONFIG);
|
unlink(RC_DEPCONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc_stringlist_free(config);
|
||||||
rc_deptree_free(deptree);
|
rc_deptree_free(deptree);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_deptree_update)
|
librc_hidden_def(rc_deptree_update)
|
||||||
|
|||||||
@@ -31,38 +31,35 @@
|
|||||||
|
|
||||||
#include "librc.h"
|
#include "librc.h"
|
||||||
|
|
||||||
bool rc_yesno (const char *value)
|
bool rc_yesno(const char *value)
|
||||||
{
|
{
|
||||||
if (! value) {
|
if (!value) {
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp (value, "yes") == 0 ||
|
if (strcasecmp(value, "yes") == 0 ||
|
||||||
strcasecmp (value, "y") == 0 ||
|
strcasecmp(value, "y") == 0 ||
|
||||||
strcasecmp (value, "true") == 0 ||
|
strcasecmp(value, "true") == 0 ||
|
||||||
strcasecmp (value, "1") == 0)
|
strcasecmp(value, "1") == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (strcasecmp (value, "no") != 0 &&
|
if (strcasecmp(value, "no") != 0 &&
|
||||||
strcasecmp (value, "n") != 0 &&
|
strcasecmp(value, "n") != 0 &&
|
||||||
strcasecmp (value, "false") != 0 &&
|
strcasecmp(value, "false") != 0 &&
|
||||||
strcasecmp (value, "0") != 0)
|
strcasecmp(value, "0") != 0)
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_yesno)
|
librc_hidden_def(rc_yesno)
|
||||||
|
|
||||||
ssize_t rc_getline (char **line, size_t *len, FILE *fp)
|
ssize_t rc_getline(char **line, size_t *len, FILE *fp)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
size_t last = 0;
|
size_t last = 0;
|
||||||
|
|
||||||
if (feof(fp))
|
while(!feof(fp)) {
|
||||||
return 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (*line == NULL || last != 0) {
|
if (*line == NULL || last != 0) {
|
||||||
*len += BUFSIZ;
|
*len += BUFSIZ;
|
||||||
*line = xrealloc(*line, *len);
|
*line = xrealloc(*line, *len);
|
||||||
@@ -71,12 +68,11 @@ ssize_t rc_getline (char **line, size_t *len, FILE *fp)
|
|||||||
memset(p, 0, BUFSIZ);
|
memset(p, 0, BUFSIZ);
|
||||||
fgets(p, BUFSIZ, fp);
|
fgets(p, BUFSIZ, fp);
|
||||||
last += strlen(p);
|
last += strlen(p);
|
||||||
} while (! feof(fp) && (*line)[last - 1] != '\n');
|
if (last && (*line)[last - 1] == '\n') {
|
||||||
|
(*line)[last - 1] = '\0';
|
||||||
/* Trim the trailing newline */
|
break;
|
||||||
if (**line && (*line)[last - 1] == '\n')
|
}
|
||||||
(*line)[last - 1] = '\0';
|
}
|
||||||
|
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_getline)
|
librc_hidden_def(rc_getline)
|
||||||
@@ -108,7 +104,7 @@ 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)
|
if (!list)
|
||||||
list = rc_stringlist_new();
|
list = rc_stringlist_new();
|
||||||
rc_stringlist_add(list, token);
|
rc_stringlist_add(list, token);
|
||||||
}
|
}
|
||||||
@@ -135,17 +131,21 @@ RC_STRINGLIST *rc_config_load(const char *file)
|
|||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
list = rc_config_list(file);
|
list = rc_config_list(file);
|
||||||
if (! list)
|
if (!list)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
config = rc_stringlist_new();
|
config = rc_stringlist_new();
|
||||||
TAILQ_FOREACH(line, list, entries) {
|
TAILQ_FOREACH(line, list, entries) {
|
||||||
/* Get entry */
|
/* Get entry */
|
||||||
p = line->value;
|
p = line->value;
|
||||||
|
if (! p)
|
||||||
|
continue;
|
||||||
|
if (strncmp(p, "export ", 7) == 0)
|
||||||
|
p += 7;
|
||||||
if (! (token = strsep(&p, "=")))
|
if (! (token = strsep(&p, "=")))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
entry = xstrdup (token);
|
entry = xstrdup(token);
|
||||||
/* Preserve shell coloring */
|
/* Preserve shell coloring */
|
||||||
if (*p == '$')
|
if (*p == '$')
|
||||||
token = line->value;
|
token = line->value;
|
||||||
@@ -157,15 +157,15 @@ RC_STRINGLIST *rc_config_load(const char *file)
|
|||||||
|
|
||||||
/* Drop a newline if that's all we have */
|
/* Drop a newline if that's all we have */
|
||||||
if (token) {
|
if (token) {
|
||||||
i = strlen (token) - 1;
|
i = strlen(token) - 1;
|
||||||
if (token[i] == '\n')
|
if (token[i] == '\n')
|
||||||
token[i] = 0;
|
token[i] = 0;
|
||||||
|
|
||||||
i = strlen (entry) + strlen (token) + 2;
|
i = strlen(entry) + strlen(token) + 2;
|
||||||
newline = xmalloc(sizeof(char) * i);
|
newline = xmalloc(sizeof(char) * i);
|
||||||
snprintf(newline, i, "%s=%s", entry, token);
|
snprintf(newline, i, "%s=%s", entry, token);
|
||||||
} else {
|
} else {
|
||||||
i = strlen (entry) + 2;
|
i = strlen(entry) + 2;
|
||||||
newline = xmalloc(sizeof(char) * i);
|
newline = xmalloc(sizeof(char) * i);
|
||||||
snprintf(newline, i, "%s=", entry);
|
snprintf(newline, i, "%s=", entry);
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ RC_STRINGLIST *rc_config_load(const char *file)
|
|||||||
TAILQ_FOREACH(cline, config, entries) {
|
TAILQ_FOREACH(cline, config, entries) {
|
||||||
p = strchr(cline->value, '=');
|
p = strchr(cline->value, '=');
|
||||||
if (p && strncmp(entry, cline->value,
|
if (p && strncmp(entry, cline->value,
|
||||||
(size_t) (p - cline->value)) == 0)
|
(size_t)(p - cline->value)) == 0)
|
||||||
{
|
{
|
||||||
/* We have a match now - to save time we directly replace it */
|
/* We have a match now - to save time we directly replace it */
|
||||||
free(cline->value);
|
free(cline->value);
|
||||||
@@ -186,7 +186,7 @@ RC_STRINGLIST *rc_config_load(const char *file)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! replaced) {
|
if (!replaced) {
|
||||||
rc_stringlist_add(config, newline);
|
rc_stringlist_add(config, newline);
|
||||||
free(newline);
|
free(newline);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,33 @@ bool rc_stringlist_delete(RC_STRINGLIST *list, const char *value)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_stringlist_delete)
|
librc_hidden_def(rc_stringlist_delete)
|
||||||
|
|
||||||
|
RC_STRING *rc_stringlist_find(RC_STRINGLIST *list, const char *value)
|
||||||
|
{
|
||||||
|
RC_STRING *s;
|
||||||
|
|
||||||
|
if (list) {
|
||||||
|
TAILQ_FOREACH(s, list, entries)
|
||||||
|
if (strcmp(s->value, value) == 0)
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
librc_hidden_def(rc_stringlist_find)
|
||||||
|
|
||||||
|
RC_STRINGLIST *rc_stringlist_split(const char *value, const char *sep)
|
||||||
|
{
|
||||||
|
RC_STRINGLIST *list = rc_stringlist_new();
|
||||||
|
char *d = xstrdup(value);
|
||||||
|
char *p = d, *token;
|
||||||
|
|
||||||
|
while ((token = strsep(&p, sep)))
|
||||||
|
rc_stringlist_add(list, token);
|
||||||
|
free(d);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
librc_hidden_def(rc_stringlist_split)
|
||||||
|
|
||||||
void rc_stringlist_sort(RC_STRINGLIST **list)
|
void rc_stringlist_sort(RC_STRINGLIST **list)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *l = *list;
|
RC_STRINGLIST *l = *list;
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
|
|||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#define RC_RUNLEVEL RC_SVCDIR "/softlevel"
|
#define RC_RUNLEVEL RC_SVCDIR "/softlevel"
|
||||||
|
|
||||||
@@ -231,9 +230,11 @@ const char *rc_sys(void)
|
|||||||
else if (file_regex("/proc/self/status",
|
else if (file_regex("/proc/self/status",
|
||||||
"(s_context|VxID):[[:space:]]*[1-9]"))
|
"(s_context|VxID):[[:space:]]*[1-9]"))
|
||||||
return RC_SYS_VSERVER;
|
return RC_SYS_VSERVER;
|
||||||
|
else if (exists("/proc/vz/veinfo") && !exists("/proc/vz/version"))
|
||||||
|
return RC_SYS_OPENVZ;
|
||||||
else if (file_regex("/proc/self/status",
|
else if (file_regex("/proc/self/status",
|
||||||
"envID:[[:space:]]*[1-9]"))
|
"envID:[[:space:]]*[1-9]"))
|
||||||
return RC_SYS_OPENVZ;
|
return RC_SYS_OPENVZ; /* old test */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ librc_hidden_proto(rc_deptree_update_needed)
|
|||||||
librc_hidden_proto(rc_find_pids)
|
librc_hidden_proto(rc_find_pids)
|
||||||
librc_hidden_proto(rc_getline)
|
librc_hidden_proto(rc_getline)
|
||||||
librc_hidden_proto(rc_newer_than)
|
librc_hidden_proto(rc_newer_than)
|
||||||
|
librc_hidden_proto(rc_older_than)
|
||||||
librc_hidden_proto(rc_runlevel_exists)
|
librc_hidden_proto(rc_runlevel_exists)
|
||||||
librc_hidden_proto(rc_runlevel_get)
|
librc_hidden_proto(rc_runlevel_get)
|
||||||
librc_hidden_proto(rc_runlevel_list)
|
librc_hidden_proto(rc_runlevel_list)
|
||||||
@@ -115,8 +116,10 @@ librc_hidden_proto(rc_service_value_set)
|
|||||||
librc_hidden_proto(rc_stringlist_add)
|
librc_hidden_proto(rc_stringlist_add)
|
||||||
librc_hidden_proto(rc_stringlist_addu)
|
librc_hidden_proto(rc_stringlist_addu)
|
||||||
librc_hidden_proto(rc_stringlist_delete)
|
librc_hidden_proto(rc_stringlist_delete)
|
||||||
|
librc_hidden_proto(rc_stringlist_find)
|
||||||
librc_hidden_proto(rc_stringlist_free)
|
librc_hidden_proto(rc_stringlist_free)
|
||||||
librc_hidden_proto(rc_stringlist_new)
|
librc_hidden_proto(rc_stringlist_new)
|
||||||
|
librc_hidden_proto(rc_stringlist_split)
|
||||||
librc_hidden_proto(rc_stringlist_sort)
|
librc_hidden_proto(rc_stringlist_sort)
|
||||||
librc_hidden_proto(rc_sys)
|
librc_hidden_proto(rc_sys)
|
||||||
librc_hidden_proto(rc_yesno)
|
librc_hidden_proto(rc_yesno)
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ bool rc_service_delete(const char *, const char *);
|
|||||||
* @param name of the process (optional)
|
* @param name of the process (optional)
|
||||||
* @param pidfile of the process (optional)
|
* @param pidfile of the process (optional)
|
||||||
* @param started if true, add the arguments otherwise remove existing matching arguments */
|
* @param started if true, add the arguments otherwise remove existing matching arguments */
|
||||||
bool rc_service_daemon_set(const char *, const char *const *, const char *, const char *,
|
bool rc_service_daemon_set(const char *, const char *, const char *const *, const char *,
|
||||||
bool);
|
bool);
|
||||||
|
|
||||||
/*! Returns a description of what the service and/or option does.
|
/*! Returns a description of what the service and/or option does.
|
||||||
@@ -202,9 +202,11 @@ RC_SERVICE rc_service_state(const char *);
|
|||||||
/*! Check if the service started the daemon
|
/*! Check if the service started the daemon
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @param exec to check
|
* @param exec to check
|
||||||
|
* @param argv to check
|
||||||
* @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc)
|
* @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc)
|
||||||
* @return true if started by this service, otherwise false */
|
* @return true if started by this service, otherwise false */
|
||||||
bool rc_service_started_daemon(const char *, const char *const *, int);
|
bool rc_service_started_daemon(const char *, const char *,
|
||||||
|
const char *const *, int);
|
||||||
|
|
||||||
/*! Return a saved value for a service
|
/*! Return a saved value for a service
|
||||||
* @param service to check
|
* @param service to check
|
||||||
@@ -256,13 +258,13 @@ const char *rc_sys(void);
|
|||||||
* These options can change the services found by the rc_get_depinfo and
|
* These options can change the services found by the rc_get_depinfo and
|
||||||
* rc_get_depends functions. */
|
* rc_get_depends functions. */
|
||||||
/*! Trace provided services */
|
/*! Trace provided services */
|
||||||
#define RC_DEP_TRACE 0x01
|
#define RC_DEP_TRACE (1<<0)
|
||||||
/*! Only use services added to runlevels */
|
/*! Only use services added to runlevels */
|
||||||
#define RC_DEP_STRICT 0x02
|
#define RC_DEP_STRICT (1<<1)
|
||||||
/*! Runlevel is starting */
|
/*! Runlevel is starting */
|
||||||
#define RC_DEP_START 0x04
|
#define RC_DEP_START (1<<2)
|
||||||
/*! Runlevel is stopping */
|
/*! Runlevel is stopping */
|
||||||
#define RC_DEP_STOP 0x08
|
#define RC_DEP_STOP (1<<3)
|
||||||
|
|
||||||
/*! @name Dependencies
|
/*! @name Dependencies
|
||||||
* We analyse each init script and cache the resultant dependency tree.
|
* We analyse each init script and cache the resultant dependency tree.
|
||||||
@@ -281,7 +283,7 @@ typedef struct rc_deptype
|
|||||||
/*! list of services */
|
/*! list of services */
|
||||||
RC_STRINGLIST *services;
|
RC_STRINGLIST *services;
|
||||||
/*! list of types */
|
/*! list of types */
|
||||||
STAILQ_ENTRY(rc_deptype) entries;
|
TAILQ_ENTRY(rc_deptype) entries;
|
||||||
} RC_DEPTYPE;
|
} RC_DEPTYPE;
|
||||||
|
|
||||||
/*! Singly linked list of services and their dependencies */
|
/*! Singly linked list of services and their dependencies */
|
||||||
@@ -290,12 +292,12 @@ typedef struct rc_depinfo
|
|||||||
/*! Name of service */
|
/*! Name of service */
|
||||||
char *service;
|
char *service;
|
||||||
/*! Dependencies */
|
/*! Dependencies */
|
||||||
STAILQ_HEAD(, rc_deptype) depends;
|
TAILQ_HEAD(, rc_deptype) depends;
|
||||||
/*! List of entries */
|
/*! List of entries */
|
||||||
STAILQ_ENTRY(rc_depinfo) entries;
|
TAILQ_ENTRY(rc_depinfo) entries;
|
||||||
} RC_DEPINFO;
|
} RC_DEPINFO;
|
||||||
|
|
||||||
typedef STAILQ_HEAD(,rc_depinfo) RC_DEPTREE;
|
typedef TAILQ_HEAD(,rc_depinfo) RC_DEPTREE;
|
||||||
#else
|
#else
|
||||||
/* Handles to internal structures */
|
/* Handles to internal structures */
|
||||||
typedef void *RC_DEPTREE;
|
typedef void *RC_DEPTREE;
|
||||||
@@ -306,6 +308,11 @@ typedef void *RC_DEPTREE;
|
|||||||
* @return true if source is newer than target, otherwise false */
|
* @return true if source is newer than target, otherwise false */
|
||||||
bool rc_newer_than(const char *, const char *);
|
bool rc_newer_than(const char *, const char *);
|
||||||
|
|
||||||
|
/*! Check to see if source is newer than target.
|
||||||
|
* If target is a directory then we traverse it and it's children.
|
||||||
|
* @return true if source is newer than target, otherwise false */
|
||||||
|
bool rc_older_than(const char *, const char *);
|
||||||
|
|
||||||
/*! Update the cached dependency tree if it's older than any init script,
|
/*! Update the cached dependency tree if it's older than any init script,
|
||||||
* its configuration file or an external configuration file the init script
|
* its configuration file or an external configuration file the init script
|
||||||
* has specified.
|
* has specified.
|
||||||
@@ -438,6 +445,19 @@ RC_STRING *rc_stringlist_addu(RC_STRINGLIST *, const char *);
|
|||||||
* @return true on success, otherwise false */
|
* @return true on success, otherwise false */
|
||||||
bool rc_stringlist_delete(RC_STRINGLIST *, const char *);
|
bool rc_stringlist_delete(RC_STRINGLIST *, const char *);
|
||||||
|
|
||||||
|
/*! Find the item on the list.
|
||||||
|
* @param list to search
|
||||||
|
* @param item to find.
|
||||||
|
* @return pointer to item */
|
||||||
|
RC_STRING *rc_stringlist_find(RC_STRINGLIST *, const char *);
|
||||||
|
|
||||||
|
/*! Split a string into a stringlist based on seperator.
|
||||||
|
* @param string to split
|
||||||
|
* @param seperator
|
||||||
|
* @return new list */
|
||||||
|
RC_STRINGLIST *rc_stringlist_split(const char *, const char *);
|
||||||
|
|
||||||
|
|
||||||
/*! Sort the list according to C locale
|
/*! Sort the list according to C locale
|
||||||
* @param list to sort */
|
* @param list to sort */
|
||||||
void rc_stringlist_sort(RC_STRINGLIST **);
|
void rc_stringlist_sort(RC_STRINGLIST **);
|
||||||
@@ -458,11 +478,11 @@ typedef LIST_HEAD(rc_pidlist, rc_pid) RC_PIDLIST;
|
|||||||
* pid overrides anything else.
|
* pid overrides anything else.
|
||||||
* If both exec and cmd are given then we ignore exec.
|
* If both exec and cmd are given then we ignore exec.
|
||||||
* @param exec to check for
|
* @param exec to check for
|
||||||
* @param cmd to check for
|
* @param argv to check for
|
||||||
* @param uid to check for
|
* @param uid to check for
|
||||||
* @param pid to check for
|
* @param pid to check for
|
||||||
* @return NULL terminated list of pids */
|
* @return NULL terminated list of pids */
|
||||||
RC_PIDLIST *rc_find_pids(const char *const *, const char *, uid_t, pid_t);
|
RC_PIDLIST *rc_find_pids(const char *, const char *const *, uid_t, pid_t);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ global:
|
|||||||
rc_environ_fd;
|
rc_environ_fd;
|
||||||
rc_find_pids;
|
rc_find_pids;
|
||||||
rc_newer_than;
|
rc_newer_than;
|
||||||
|
rc_older_than;
|
||||||
rc_runlevel_exists;
|
rc_runlevel_exists;
|
||||||
rc_runlevel_get;
|
rc_runlevel_get;
|
||||||
rc_runlevel_list;
|
rc_runlevel_list;
|
||||||
@@ -43,6 +44,8 @@ global:
|
|||||||
rc_stringlist_add;
|
rc_stringlist_add;
|
||||||
rc_stringlist_addu;
|
rc_stringlist_addu;
|
||||||
rc_stringlist_delete;
|
rc_stringlist_delete;
|
||||||
|
rc_stringlist_find;
|
||||||
|
rc_stringlist_split;
|
||||||
rc_stringlist_new;
|
rc_stringlist_new;
|
||||||
rc_stringlist_sort;
|
rc_stringlist_sort;
|
||||||
rc_stringlist_free;
|
rc_stringlist_free;
|
||||||
|
|||||||
2
src/rc/.gitignore
vendored
2
src/rc/.gitignore
vendored
@@ -13,6 +13,7 @@ eerrorn
|
|||||||
eerror
|
eerror
|
||||||
ebegin
|
ebegin
|
||||||
eend
|
eend
|
||||||
|
ewaitfile
|
||||||
ewend
|
ewend
|
||||||
eindent
|
eindent
|
||||||
eoutdent
|
eoutdent
|
||||||
@@ -67,5 +68,6 @@ rc-status.o
|
|||||||
rc-update.o
|
rc-update.o
|
||||||
runscript.o
|
runscript.o
|
||||||
rc.o
|
rc.o
|
||||||
|
rc.core
|
||||||
rc
|
rc
|
||||||
.depend
|
.depend
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ LINKDIR= ${PREFIX}/${LIBNAME}/${PROG}
|
|||||||
BINLINKS= rc-status
|
BINLINKS= rc-status
|
||||||
SBINLINKS= rc-service rc-update runscript start-stop-daemon
|
SBINLINKS= rc-service rc-update runscript start-stop-daemon
|
||||||
RC_BINLINKS= einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
|
RC_BINLINKS= einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
|
||||||
eindent eoutdent esyslog eval_ecolors \
|
eindent eoutdent esyslog eval_ecolors ewaitfile \
|
||||||
veinfo vewarn vebegin veend vewend veindent veoutdent \
|
veinfo vewarn vebegin veend vewend veindent veoutdent \
|
||||||
service_starting service_started \
|
service_starting service_started \
|
||||||
service_stopping service_stopped \
|
service_stopping service_stopped \
|
||||||
@@ -30,15 +30,14 @@ RC_SBINLINKS= mark_service_starting mark_service_started \
|
|||||||
ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
|
ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
|
||||||
CLEANFILES+= ${ALL_LINKS}
|
CLEANFILES+= ${ALL_LINKS}
|
||||||
|
|
||||||
|
CPPFLAGS+= -I../includes -I../librc -I../libeinfo
|
||||||
LDFLAGS+= -L../librc -L../libeinfo
|
LDFLAGS+= -L../librc -L../libeinfo
|
||||||
LDADD+= -lutil -lrc -leinfo
|
LDADD+= -lutil -lrc -leinfo
|
||||||
|
|
||||||
MK= ../../mk
|
MK= ../../mk
|
||||||
|
include ${MK}/debug.mk
|
||||||
include ${MK}/prog.mk
|
include ${MK}/prog.mk
|
||||||
include ${MK}/cc.mk
|
include ${MK}/cc.mk
|
||||||
include ${MK}/debug.mk
|
|
||||||
|
|
||||||
CFLAGS+= -I../includes -I../librc -I../libeinfo
|
|
||||||
|
|
||||||
include ${MK}/${MKTERMCAP}.mk
|
include ${MK}/${MKTERMCAP}.mk
|
||||||
LDADD+= ${LIBDL} ${LIBKVM}
|
LDADD+= ${LIBDL} ${LIBKVM}
|
||||||
@@ -55,13 +54,13 @@ install: all
|
|||||||
${INSTALL} -d ${DESTDIR}${SBINDIR}
|
${INSTALL} -d ${DESTDIR}${SBINDIR}
|
||||||
${INSTALL} -m ${BINMODE} ${PROG} ${DESTDIR}${SBINDIR}
|
${INSTALL} -m ${BINMODE} ${PROG} ${DESTDIR}${SBINDIR}
|
||||||
${INSTALL} -d ${DESTDIR}${BINDIR}
|
${INSTALL} -d ${DESTDIR}${BINDIR}
|
||||||
for x in ${BINLINKS}; do ln -fs ${DESTDIR}${SBINDIR}/${PROG} ${DESTDIR}${BINDIR}/$$x; done
|
for x in ${BINLINKS}; do ln -fs ${SBINDIR}/${PROG} ${DESTDIR}${BINDIR}/$$x; done
|
||||||
${INSTALL} -d ${DESTDIR}${SBINDIR}
|
${INSTALL} -d ${DESTDIR}${SBINDIR}
|
||||||
for x in ${SBINLINKS}; do ln -fs ${PROG} ${DESTDIR}${SBINDIR}/$$x; done
|
for x in ${SBINLINKS}; do ln -fs ${PROG} ${DESTDIR}${SBINDIR}/$$x; done
|
||||||
${INSTALL} -d ${DESTDIR}${LINKDIR}/bin
|
${INSTALL} -d ${DESTDIR}${LINKDIR}/bin
|
||||||
for x in $(RC_BINLINKS); do ln -fs ${DESTDIR}${SBINDIR}/${PROG} ${DESTDIR}${LINKDIR}/bin/$$x; done
|
for x in $(RC_BINLINKS); do ln -fs ${SBINDIR}/${PROG} ${DESTDIR}${LINKDIR}/bin/$$x; done
|
||||||
${INSTALL} -d ${DESTDIR}${LINKDIR}/sbin
|
${INSTALL} -d ${DESTDIR}${LINKDIR}/sbin
|
||||||
for x in ${RC_SBINLINKS}; do ln -fs ${DESTDIR}${SBINDIR}/${PROG} ${DESTDIR}${LINKDIR}/sbin/$$x; done
|
for x in ${RC_SBINLINKS}; do ln -fs ${SBINDIR}/${PROG} ${DESTDIR}${LINKDIR}/sbin/$$x; done
|
||||||
if test "${MKPAM}" = pam; then \
|
if test "${MKPAM}" = pam; then \
|
||||||
${INSTALL} -d ${DESTDIR}${PAMDIR}; \
|
${INSTALL} -d ${DESTDIR}${PAMDIR}; \
|
||||||
${INSTALL} -m ${PAMMODE} start-stop-daemon.pam ${DESTDIR}${PAMDIR}/start-stop-daemon; \
|
${INSTALL} -m ${PAMMODE} start-stop-daemon.pam ${DESTDIR}${PAMDIR}/start-stop-daemon; \
|
||||||
|
|||||||
@@ -57,7 +57,9 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, int file)
|
|||||||
if (stat(path, &st)) {
|
if (stat(path, &st)) {
|
||||||
if (file) {
|
if (file) {
|
||||||
einfo("%s: creating file", path);
|
einfo("%s: creating file", path);
|
||||||
if ((fd = open(path, O_CREAT)) == -1) {
|
if (! mode)
|
||||||
|
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
|
||||||
|
if ((fd = open(path, O_CREAT, mode)) == -1) {
|
||||||
eerror("%s: open: %s", applet, strerror(errno));
|
eerror("%s: open: %s", applet, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -104,28 +106,6 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, int file)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Based on busybox */
|
|
||||||
static int parse_mode (mode_t *mode, char *text)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
unsigned long l;
|
|
||||||
|
|
||||||
/* Check for a numeric mode */
|
|
||||||
if ((*text - '0') < 8) {
|
|
||||||
l = strtoul(text, &p, 8);
|
|
||||||
if (*p || l > 07777U) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*mode = (mode_t) l;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We currently don't check g+w type stuff */
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_owner(struct passwd **user, struct group **group,
|
static int parse_owner(struct passwd **user, struct group **group,
|
||||||
const char *owner)
|
const char *owner)
|
||||||
{
|
{
|
||||||
@@ -228,6 +208,5 @@ int checkpath(int argc, char **argv)
|
|||||||
optind++;
|
optind++;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(retval);
|
return retval;
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,10 +98,10 @@ static int do_mount(struct ENT *ent)
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
argv[0] = (char *) "mount";
|
argv[0] = UNCONST("mount");
|
||||||
argv[1] = (char *) "-o";
|
argv[1] = UNCONST("-o");
|
||||||
argv[2] = ENT_OPTS(*ent);
|
argv[2] = ENT_OPTS(*ent);
|
||||||
argv[3] = (char *) "-t";
|
argv[3] = UNCONST("-t");
|
||||||
argv[4] = ENT_TYPE(*ent);
|
argv[4] = ENT_TYPE(*ent);
|
||||||
argv[5] = ENT_BLOCKDEVICE(*ent);
|
argv[5] = ENT_BLOCKDEVICE(*ent);
|
||||||
argv[6] = ENT_FILE(*ent);
|
argv[6] = ENT_FILE(*ent);
|
||||||
@@ -137,8 +137,8 @@ static const struct option longopts[] = {
|
|||||||
longopts_COMMON
|
longopts_COMMON
|
||||||
};
|
};
|
||||||
static const char * const longopts_help[] = {
|
static const char * const longopts_help[] = {
|
||||||
"Extract the block device",
|
|
||||||
"Mounts the filesytem from the mountpoint",
|
"Mounts the filesytem from the mountpoint",
|
||||||
|
"Extract the block device",
|
||||||
"Show arguments needed to mount the entry",
|
"Show arguments needed to mount the entry",
|
||||||
"Extract the options field",
|
"Extract the options field",
|
||||||
"Extract or query the pass number field",
|
"Extract or query the pass number field",
|
||||||
@@ -159,11 +159,11 @@ int fstabinfo(int argc, char **argv)
|
|||||||
struct ENT *ent;
|
struct ENT *ent;
|
||||||
int result = EXIT_SUCCESS;
|
int result = EXIT_SUCCESS;
|
||||||
char *token;
|
char *token;
|
||||||
int i;
|
int i, p;
|
||||||
int opt;
|
int opt;
|
||||||
int output = OUTPUT_FILE;
|
int output = OUTPUT_FILE;
|
||||||
RC_STRINGLIST *files = rc_stringlist_new();
|
RC_STRINGLIST *files = rc_stringlist_new();
|
||||||
RC_STRING *file;
|
RC_STRING *file, *file_np;
|
||||||
bool filtered = false;
|
bool filtered = false;
|
||||||
|
|
||||||
#ifdef HAVE_GETMNTENT
|
#ifdef HAVE_GETMNTENT
|
||||||
@@ -200,13 +200,17 @@ int fstabinfo(int argc, char **argv)
|
|||||||
argv[0], optarg + 1);
|
argv[0], optarg + 1);
|
||||||
|
|
||||||
filtered = true;
|
filtered = true;
|
||||||
|
opt = optarg[0];
|
||||||
START_ENT;
|
START_ENT;
|
||||||
while ((ent = GET_ENT)) {
|
while ((ent = GET_ENT)) {
|
||||||
if (((optarg[0] == '=' && i == ENT_PASS(ent)) ||
|
if (strcmp(ENT_FILE(ent), "none") == 0)
|
||||||
(optarg[0] == '<' && i > ENT_PASS(ent)) ||
|
continue;
|
||||||
(optarg[0] == '>' && i < ENT_PASS(ent))) &&
|
p = ENT_PASS(ent);
|
||||||
strcmp(ENT_FILE(ent), "none") != 0)
|
if ((opt == '=' && i == p) ||
|
||||||
rc_stringlist_add(files, ENT_FILE(ent));
|
(opt == '<' && i > p && p != 0) ||
|
||||||
|
(opt == '>' && i < p && p != 0))
|
||||||
|
rc_stringlist_add(files,
|
||||||
|
ENT_FILE(ent));
|
||||||
}
|
}
|
||||||
END_ENT;
|
END_ENT;
|
||||||
break;
|
break;
|
||||||
@@ -234,8 +238,18 @@ int fstabinfo(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (optind < argc) {
|
if (optind < argc) {
|
||||||
while (optind < argc)
|
if (files) {
|
||||||
rc_stringlist_add(files, argv[optind++]);
|
TAILQ_FOREACH_SAFE(file, files, entries, file_np) {
|
||||||
|
for (i = optind; i < argc; i++)
|
||||||
|
if (strcmp(argv[i], file->value) == 0)
|
||||||
|
break;
|
||||||
|
if (i >= argc)
|
||||||
|
rc_stringlist_delete(files, file->value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (optind < argc)
|
||||||
|
rc_stringlist_add(files, argv[optind++]);
|
||||||
|
}
|
||||||
} else if (! filtered) {
|
} else if (! filtered) {
|
||||||
START_ENT;
|
START_ENT;
|
||||||
while ((ent = GET_ENT))
|
while ((ent = GET_ENT))
|
||||||
@@ -246,6 +260,11 @@ int fstabinfo(int argc, char **argv)
|
|||||||
eerrorx("%s: emtpy fstab", argv[0]);
|
eerrorx("%s: emtpy fstab", argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!files || !TAILQ_FIRST(files)) {
|
||||||
|
rc_stringlist_free(files);
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure we always display something */
|
/* Ensure we always display something */
|
||||||
START_ENT;
|
START_ENT;
|
||||||
TAILQ_FOREACH(file, files, entries) {
|
TAILQ_FOREACH(file, files, entries) {
|
||||||
|
|||||||
@@ -481,6 +481,5 @@ int mountinfo(int argc, char **argv)
|
|||||||
REG_FREE(point_regex);
|
REG_FREE(point_regex);
|
||||||
REG_FREE(skip_point_regex);
|
REG_FREE(skip_point_regex);
|
||||||
|
|
||||||
exit(result);
|
return result;
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#define SYSLOG_NAMES
|
#define SYSLOG_NAMES
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -45,12 +46,17 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
|
|
||||||
|
/* usecs to wait while we poll the file existance */
|
||||||
|
#define WAIT_INTERVAL 20000000
|
||||||
|
#define ONE_SECOND 690000000
|
||||||
|
|
||||||
/* Applet is first parsed in rc.c - no point in doing it again */
|
/* Applet is first parsed in rc.c - no point in doing it again */
|
||||||
extern const char *applet;
|
extern const char *applet;
|
||||||
|
|
||||||
@@ -76,7 +82,10 @@ static int do_e(int argc, char **argv)
|
|||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
char *p;
|
char *p;
|
||||||
int level = 0;
|
int level = 0;
|
||||||
const char *fmt = "%s";
|
struct timespec ts;
|
||||||
|
struct timeval stop, now;
|
||||||
|
int (*e) (const char *, ...) __EINFO_PRINTF = NULL;
|
||||||
|
int (*ee) (int, const char *, ...) __EEND_PRINTF = NULL;
|
||||||
|
|
||||||
/* Punt applet */
|
/* Punt applet */
|
||||||
argc--;
|
argc--;
|
||||||
@@ -97,11 +106,14 @@ static int do_e(int argc, char **argv)
|
|||||||
if (strcmp(applet, "eend") == 0 ||
|
if (strcmp(applet, "eend") == 0 ||
|
||||||
strcmp(applet, "ewend") == 0 ||
|
strcmp(applet, "ewend") == 0 ||
|
||||||
strcmp(applet, "veend") == 0 ||
|
strcmp(applet, "veend") == 0 ||
|
||||||
strcmp(applet, "vweend") == 0)
|
strcmp(applet, "vweend") == 0 ||
|
||||||
|
strcmp(applet, "ewaitfile") == 0)
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
retval = (int) strtoimax(argv[0], NULL, 0);
|
retval = (int)strtoimax(argv[0], &p, 0);
|
||||||
if (errno != 0)
|
if (!p || *p != '\0')
|
||||||
|
errno = EINVAL;
|
||||||
|
if (errno)
|
||||||
retval = EXIT_FAILURE;
|
retval = EXIT_FAILURE;
|
||||||
else {
|
else {
|
||||||
argc--;
|
argc--;
|
||||||
@@ -124,6 +136,38 @@ static int do_e(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(applet, "ewaitfile") == 0) {
|
||||||
|
if (errno)
|
||||||
|
eerrorx("%s: invalid timeout", applet);
|
||||||
|
if (argc == 0)
|
||||||
|
eerrorx("%s: not enough arguments", applet);
|
||||||
|
|
||||||
|
gettimeofday(&stop, NULL);
|
||||||
|
/* retval stores the timeout */
|
||||||
|
stop.tv_sec += retval;
|
||||||
|
ts.tv_sec = 0;
|
||||||
|
ts.tv_nsec = WAIT_INTERVAL;
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
ebeginv("Waiting for %s", argv[i]);
|
||||||
|
for (;;){
|
||||||
|
if (exists(argv[i]))
|
||||||
|
break;
|
||||||
|
if (nanosleep(&ts, NULL) == -1)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
if (retval <= 0)
|
||||||
|
continue;
|
||||||
|
if (timercmp(&now, &stop, <))
|
||||||
|
continue;
|
||||||
|
eendv(EXIT_FAILURE,
|
||||||
|
"timed out waiting for %s", argv[i]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
eendv(EXIT_SUCCESS, NULL);
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
l += strlen(argv[i]) + 1;
|
l += strlen(argv[i]) + 1;
|
||||||
@@ -141,45 +185,42 @@ static int do_e(int argc, char **argv)
|
|||||||
*p = 0;
|
*p = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! message)
|
|
||||||
fmt = "";
|
|
||||||
|
|
||||||
if (strcmp(applet, "einfo") == 0)
|
if (strcmp(applet, "einfo") == 0)
|
||||||
einfo(fmt, message);
|
e = einfo;
|
||||||
else if (strcmp(applet, "einfon") == 0)
|
else if (strcmp(applet, "einfon") == 0)
|
||||||
einfon(fmt, message);
|
e = einfon;
|
||||||
else if (strcmp(applet, "ewarn") == 0)
|
else if (strcmp(applet, "ewarn") == 0)
|
||||||
ewarn(fmt, message);
|
e = ewarn;
|
||||||
else if (strcmp(applet, "ewarnn") == 0)
|
else if (strcmp(applet, "ewarnn") == 0)
|
||||||
ewarnn(fmt, message);
|
e = ewarnn;
|
||||||
else if (strcmp(applet, "eerror") == 0) {
|
else if (strcmp(applet, "eerror") == 0) {
|
||||||
eerror(fmt, message);
|
e = eerror;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
} else if (strcmp(applet, "eerrorn") == 0) {
|
} else if (strcmp(applet, "eerrorn") == 0) {
|
||||||
eerrorn(fmt, message);
|
e = eerrorn;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
} else if (strcmp(applet, "ebegin") == 0)
|
} else if (strcmp(applet, "ebegin") == 0)
|
||||||
ebegin(fmt, message);
|
e = ebegin;
|
||||||
else if (strcmp(applet, "eend") == 0)
|
else if (strcmp(applet, "eend") == 0)
|
||||||
eend(retval, fmt, message);
|
ee = eend;
|
||||||
else if (strcmp(applet, "ewend") == 0)
|
else if (strcmp(applet, "ewend") == 0)
|
||||||
ewend(retval, fmt, message);
|
ee = ewend;
|
||||||
else if (strcmp(applet, "esyslog") == 0)
|
else if (strcmp(applet, "esyslog") == 0)
|
||||||
elog(level, fmt, message);
|
ee = elog;
|
||||||
else if (strcmp(applet, "veinfo") == 0)
|
else if (strcmp(applet, "veinfo") == 0)
|
||||||
einfov(fmt, message);
|
e = einfov;
|
||||||
else if (strcmp(applet, "veinfon") == 0)
|
else if (strcmp(applet, "veinfon") == 0)
|
||||||
einfovn(fmt, message);
|
e = einfovn;
|
||||||
else if (strcmp(applet, "vewarn") == 0)
|
else if (strcmp(applet, "vewarn") == 0)
|
||||||
ewarnv(fmt, message);
|
e = ewarnv;
|
||||||
else if (strcmp(applet, "vewarnn") == 0)
|
else if (strcmp(applet, "vewarnn") == 0)
|
||||||
ewarnvn(fmt, message);
|
e = ewarnvn;
|
||||||
else if (strcmp(applet, "vebegin") == 0)
|
else if (strcmp(applet, "vebegin") == 0)
|
||||||
ebeginv(fmt, message);
|
e = ebeginv;
|
||||||
else if (strcmp(applet, "veend") == 0)
|
else if (strcmp(applet, "veend") == 0)
|
||||||
eendv(retval, fmt, message);
|
ee = eendv;
|
||||||
else if (strcmp(applet, "vewend") == 0)
|
else if (strcmp(applet, "vewend") == 0)
|
||||||
ewendv(retval, fmt, message);
|
ee = ewendv;
|
||||||
else if (strcmp(applet, "eindent") == 0)
|
else if (strcmp(applet, "eindent") == 0)
|
||||||
eindent();
|
eindent();
|
||||||
else if (strcmp(applet, "eoutdent") == 0)
|
else if (strcmp(applet, "eoutdent") == 0)
|
||||||
@@ -193,6 +234,18 @@ static int do_e(int argc, char **argv)
|
|||||||
retval = EXIT_FAILURE;
|
retval = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
if (e)
|
||||||
|
e("%s", message);
|
||||||
|
else if (ee)
|
||||||
|
ee(retval, "%s", message);
|
||||||
|
} else {
|
||||||
|
if (e)
|
||||||
|
e(NULL);
|
||||||
|
else if (ee)
|
||||||
|
ee(retval, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
free(message);
|
free(message);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -200,9 +253,9 @@ static int do_e(int argc, char **argv)
|
|||||||
static int do_service(int argc, char **argv)
|
static int do_service(int argc, char **argv)
|
||||||
{
|
{
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
char *service = NULL;
|
char *service;
|
||||||
|
char *exec;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
char *d[] = { NULL, NULL };
|
|
||||||
|
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
service = argv[1];
|
service = argv[1];
|
||||||
@@ -227,21 +280,19 @@ static int do_service(int argc, char **argv)
|
|||||||
else if (strcmp(applet, "service_wasinactive") == 0)
|
else if (strcmp(applet, "service_wasinactive") == 0)
|
||||||
ok = (rc_service_state(service) & RC_SERVICE_WASINACTIVE);
|
ok = (rc_service_state(service) & RC_SERVICE_WASINACTIVE);
|
||||||
else if (strcmp(applet, "service_started_daemon") == 0) {
|
else if (strcmp(applet, "service_started_daemon") == 0) {
|
||||||
d[0] = argv[1];
|
|
||||||
|
|
||||||
service = getenv("RC_SVCNAME");
|
service = getenv("RC_SVCNAME");
|
||||||
|
exec = argv[1];
|
||||||
if (argc > 3) {
|
if (argc > 3) {
|
||||||
service = argv[1];
|
service = argv[1];
|
||||||
d[0] = argv[2];
|
exec = argv[2];
|
||||||
sscanf(argv[3], "%d", &idx);
|
sscanf(argv[3], "%d", &idx);
|
||||||
} else if (argc == 3) {
|
} else if (argc == 3) {
|
||||||
if (sscanf(argv[2], "%d", &idx) != 1) {
|
if (sscanf(argv[2], "%d", &idx) != 1) {
|
||||||
service = argv[1];
|
service = argv[1];
|
||||||
d[0] = argv[2];
|
exec = argv[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ok = rc_service_started_daemon(service,
|
ok = rc_service_started_daemon(service, exec, NULL, idx);
|
||||||
(const char * const *)d, idx);
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
eerrorx("%s: unknown applet", applet);
|
eerrorx("%s: unknown applet", applet);
|
||||||
@@ -365,7 +416,6 @@ static int do_shell_var(int argc, char **argv)
|
|||||||
void run_applets(int argc, char **argv)
|
void run_applets(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i = 2;
|
int i = 2;
|
||||||
bool match = false;
|
|
||||||
char *p;
|
char *p;
|
||||||
pid_t pid = 0;
|
pid_t pid = 0;
|
||||||
|
|
||||||
@@ -394,16 +444,24 @@ void run_applets(int argc, char **argv)
|
|||||||
if (strcmp(applet, "shell_var") == 0)
|
if (strcmp(applet, "shell_var") == 0)
|
||||||
exit(do_shell_var(argc, argv));
|
exit(do_shell_var(argc, argv));
|
||||||
|
|
||||||
if (strcmp(applet, "is_newer_than") == 0 ||
|
/* This test is perverted - historically the baselayout function
|
||||||
strcmp(applet, "is_older_than") == 0)
|
* returns 0 on *failure*, which is plain wrong */
|
||||||
{
|
if (strcmp(applet, "is_older_than") == 0) {
|
||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
if (strcmp(applet, "is_newer_than") == 0)
|
|
||||||
match = true;
|
|
||||||
while (i < argc) {
|
while (i < argc) {
|
||||||
if (rc_newer_than(argv[1], argv[i++]) != match)
|
if (!rc_newer_than(argv[1], argv[i++]))
|
||||||
exit (EXIT_FAILURE);
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
};
|
||||||
|
/* This tets is correct as it's not present in baselayout */
|
||||||
|
if (strcmp(applet, "is_newer_than") == 0) {
|
||||||
|
if (argc < 3)
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
while (i < argc) {
|
||||||
|
if (!rc_newer_than(argv[1], argv[i++]))
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -54,8 +54,8 @@
|
|||||||
|
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc-logger.h"
|
#include "rc-logger.h"
|
||||||
#include "rc-misc.h"
|
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
|
#include "rc-misc.h"
|
||||||
|
|
||||||
#define LOGFILE RC_SVCDIR "/rc.log"
|
#define LOGFILE RC_SVCDIR "/rc.log"
|
||||||
#define PERMLOG "/var/log/rc.log"
|
#define PERMLOG "/var/log/rc.log"
|
||||||
|
|||||||
@@ -24,9 +24,14 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef RC_LOGGER_H
|
||||||
|
#define RC_LOGGER_H
|
||||||
|
|
||||||
pid_t rc_logger_pid;
|
pid_t rc_logger_pid;
|
||||||
int rc_logger_tty;
|
int rc_logger_tty;
|
||||||
extern bool rc_in_logger;
|
extern bool rc_in_logger;
|
||||||
|
|
||||||
void rc_logger_open (const char *runlevel);
|
void rc_logger_open(const char *runlevel);
|
||||||
void rc_logger_close ();
|
void rc_logger_close(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -124,57 +124,49 @@ void env_filter(void)
|
|||||||
RC_STRINGLIST *profile = NULL;
|
RC_STRINGLIST *profile = NULL;
|
||||||
RC_STRINGLIST *env_list;
|
RC_STRINGLIST *env_list;
|
||||||
RC_STRING *env;
|
RC_STRING *env;
|
||||||
RC_STRING *s;
|
|
||||||
char *env_name;
|
|
||||||
char *e;
|
char *e;
|
||||||
char *token;
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
/* Add the user defined list of vars */
|
/* Add the user defined list of vars */
|
||||||
env_allow = rc_stringlist_new();
|
env_allow = rc_stringlist_split(rc_conf_value ("rc_env_allow"), " ");
|
||||||
e = env_name = xstrdup(rc_conf_value ("rc_env_allow"));
|
|
||||||
while ((token = strsep(&e, " "))) {
|
|
||||||
if (token[0] == '*') {
|
|
||||||
free(env_name);
|
|
||||||
rc_stringlist_free(env_allow);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rc_stringlist_add(env_allow, token);
|
|
||||||
}
|
|
||||||
free(env_name);
|
|
||||||
|
|
||||||
if (exists(PROFILE_ENV))
|
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 remove safely */
|
/* Copy the env and work from this so we can manipulate it safely */
|
||||||
env_list = rc_stringlist_new();
|
env_list = rc_stringlist_new();
|
||||||
while (environ[i])
|
while (environ[i]) {
|
||||||
rc_stringlist_add(env_list, environ[i++]);
|
env = rc_stringlist_add(env_list, environ[i++]);
|
||||||
|
e = strchr(env->value, '=');
|
||||||
|
if (e)
|
||||||
|
*e = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(env, env_list, entries) {
|
TAILQ_FOREACH(env, env_list, entries) {
|
||||||
/* Check the whitelist */
|
/* Check the whitelist */
|
||||||
i = 0;
|
for (i = 0; env_whitelist[i]; i++) {
|
||||||
while (env_whitelist[i]) {
|
if (strcmp(env_whitelist[i], env->value) == 0)
|
||||||
if (strcmp(env_whitelist[i++], env->value))
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (env_whitelist[i])
|
if (env_whitelist[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check our user defined list */
|
/* Check our user defined list */
|
||||||
TAILQ_FOREACH(s, env_allow, entries)
|
if (rc_stringlist_find(env_allow, env->value))
|
||||||
if (strcmp(s->value, env->value) == 0)
|
|
||||||
break;
|
|
||||||
if (s)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Now check our profile */
|
|
||||||
|
|
||||||
/* OK, not allowed! */
|
/* OK, not allowed! */
|
||||||
e = strchr(env->value, '=');
|
|
||||||
*e = '\0';
|
|
||||||
unsetenv(env->value);
|
unsetenv(env->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now add anything missing from the profile */
|
||||||
|
TAILQ_FOREACH(env, profile, entries) {
|
||||||
|
e = strchr(env->value, '=');
|
||||||
|
*e = '\0';
|
||||||
|
if (!getenv(env->value))
|
||||||
|
setenv(env->value, e + 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -374,3 +366,25 @@ pid_t exec_service(const char *service, const char *arg)
|
|||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
parse_mode(mode_t *mode, char *text)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
unsigned long l;
|
||||||
|
|
||||||
|
/* Check for a numeric mode */
|
||||||
|
if ((*text - '0') < 8) {
|
||||||
|
l = strtoul(text, &p, 8);
|
||||||
|
if (*p || l > 07777U) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*mode = (mode_t) l;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We currently don't check g+w type stuff */
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ typedef struct plugin
|
|||||||
char *name;
|
char *name;
|
||||||
void *handle;
|
void *handle;
|
||||||
int (*hook)(RC_HOOK, const char *);
|
int (*hook)(RC_HOOK, const char *);
|
||||||
STAILQ_ENTRY(plugin) entries;
|
TAILQ_ENTRY(plugin) entries;
|
||||||
} PLUGIN;
|
} PLUGIN;
|
||||||
STAILQ_HEAD(, plugin) plugins;
|
TAILQ_HEAD(, plugin) plugins;
|
||||||
|
|
||||||
#ifndef __FreeBSD__
|
#ifndef __FreeBSD__
|
||||||
dlfunc_t dlfunc(void * __restrict handle, const char * __restrict symbol)
|
dlfunc_t dlfunc(void * __restrict handle, const char * __restrict symbol)
|
||||||
@@ -87,7 +87,7 @@ void rc_plugin_load(void)
|
|||||||
if (rc_in_plugin)
|
if (rc_in_plugin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
STAILQ_INIT(&plugins);
|
TAILQ_INIT(&plugins);
|
||||||
|
|
||||||
if (! (dp = opendir(RC_PLUGINDIR)))
|
if (! (dp = opendir(RC_PLUGINDIR)))
|
||||||
return;
|
return;
|
||||||
@@ -112,7 +112,7 @@ void rc_plugin_load(void)
|
|||||||
plugin->name = xstrdup(d->d_name);
|
plugin->name = xstrdup(d->d_name);
|
||||||
plugin->handle = h;
|
plugin->handle = h;
|
||||||
plugin->hook = fptr;
|
plugin->hook = fptr;
|
||||||
STAILQ_INSERT_TAIL(&plugins, plugin, entries);
|
TAILQ_INSERT_TAIL(&plugins, plugin, entries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
@@ -120,18 +120,15 @@ void rc_plugin_load(void)
|
|||||||
|
|
||||||
int rc_waitpid(pid_t pid)
|
int rc_waitpid(pid_t pid)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status;
|
||||||
pid_t savedpid = pid;
|
|
||||||
int retval = EXIT_FAILURE;
|
|
||||||
|
|
||||||
do {
|
while (waitpid(pid, &status, 0) == -1) {
|
||||||
pid = waitpid(savedpid, &status, 0);
|
if (errno != EINTR) {
|
||||||
if (pid == -1 && errno != EINTR)
|
status = -1;
|
||||||
return EXIT_FAILURE;
|
break;
|
||||||
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
}
|
||||||
if (pid == savedpid)
|
}
|
||||||
retval = WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE;
|
return status;
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rc_plugin_run(RC_HOOK hook, const char *value)
|
void rc_plugin_run(RC_HOOK hook, const char *value)
|
||||||
@@ -162,7 +159,7 @@ void rc_plugin_run(RC_HOOK hook, const char *value)
|
|||||||
sigemptyset(&empty);
|
sigemptyset(&empty);
|
||||||
sigfillset(&full);
|
sigfillset(&full);
|
||||||
|
|
||||||
STAILQ_FOREACH(plugin, &plugins, entries) {
|
TAILQ_FOREACH(plugin, &plugins, entries) {
|
||||||
/* We create a pipe so that plugins can affect our environment
|
/* We create a pipe so that plugins can affect our environment
|
||||||
* vars, which in turn influence our scripts. */
|
* vars, which in turn influence our scripts. */
|
||||||
if (pipe(pfd) == -1) {
|
if (pipe(pfd) == -1) {
|
||||||
@@ -239,15 +236,15 @@ void rc_plugin_run(RC_HOOK hook, const char *value)
|
|||||||
|
|
||||||
void rc_plugin_unload(void)
|
void rc_plugin_unload(void)
|
||||||
{
|
{
|
||||||
PLUGIN *plugin = STAILQ_FIRST(&plugins);
|
PLUGIN *plugin = TAILQ_FIRST(&plugins);
|
||||||
PLUGIN *next;
|
PLUGIN *next;
|
||||||
|
|
||||||
while (plugin) {
|
while (plugin) {
|
||||||
next = STAILQ_NEXT(plugin, entries);
|
next = TAILQ_NEXT(plugin, entries);
|
||||||
dlclose(plugin->handle);
|
dlclose(plugin->handle);
|
||||||
free(plugin->name);
|
free(plugin->name);
|
||||||
free(plugin);
|
free(plugin);
|
||||||
plugin = next;
|
plugin = next;
|
||||||
}
|
}
|
||||||
STAILQ_INIT(&plugins);
|
TAILQ_INIT(&plugins);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ static void print_service(const char *service)
|
|||||||
static void print_services(const char *runlevel, RC_STRINGLIST *services)
|
static void print_services(const char *runlevel, RC_STRINGLIST *services)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *l = NULL;
|
RC_STRINGLIST *l = NULL;
|
||||||
RC_STRING *s, *t;
|
RC_STRING *s;
|
||||||
char *r = NULL;
|
char *r = NULL;
|
||||||
|
|
||||||
if (! services)
|
if (! services)
|
||||||
@@ -156,10 +156,7 @@ static void print_services(const char *runlevel, RC_STRINGLIST *services)
|
|||||||
if (!l)
|
if (!l)
|
||||||
return;
|
return;
|
||||||
TAILQ_FOREACH(s, l, entries) {
|
TAILQ_FOREACH(s, l, entries) {
|
||||||
TAILQ_FOREACH(t, services, entries)
|
if (!rc_stringlist_find(services, s->value))
|
||||||
if (strcmp(t->value, s->value) == 0)
|
|
||||||
break;
|
|
||||||
if (!t)
|
|
||||||
continue;
|
continue;
|
||||||
if (!runlevel || rc_service_in_runlevel(s->value, runlevel))
|
if (!runlevel || rc_service_in_runlevel(s->value, runlevel))
|
||||||
print_service(s->value);
|
print_service(s->value);
|
||||||
@@ -289,6 +286,5 @@ exit:
|
|||||||
rc_stringlist_free(levels);
|
rc_stringlist_free(levels);
|
||||||
rc_deptree_free(deptree);
|
rc_deptree_free(deptree);
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
return(EXIT_SUCCESS);
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
}
|
||||||
|
|||||||
61
src/rc/rc.c
61
src/rc/rc.c
@@ -146,7 +146,7 @@ static void cleanup(void)
|
|||||||
rc_plugin_unload();
|
rc_plugin_unload();
|
||||||
|
|
||||||
if (! rc_in_plugin && termios_orig) {
|
if (! rc_in_plugin && termios_orig) {
|
||||||
tcsetattr(fileno(stdin), TCSANOW, termios_orig);
|
tcsetattr(STDIN_FILENO, TCSANOW, termios_orig);
|
||||||
free(termios_orig);
|
free(termios_orig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ static char read_key(bool block)
|
|||||||
{
|
{
|
||||||
struct termios termios;
|
struct termios termios;
|
||||||
char c = 0;
|
char c = 0;
|
||||||
int fd = fileno(stdin);
|
int fd = STDIN_FILENO;
|
||||||
|
|
||||||
if (! isatty(fd))
|
if (! isatty(fd))
|
||||||
return false;
|
return false;
|
||||||
@@ -308,7 +308,7 @@ static void run_program(const char *prog)
|
|||||||
sigprocmask(SIG_SETMASK, &old, NULL);
|
sigprocmask(SIG_SETMASK, &old, NULL);
|
||||||
|
|
||||||
if (termios_orig)
|
if (termios_orig)
|
||||||
tcsetattr(fileno(stdin), TCSANOW, termios_orig);
|
tcsetattr(STDIN_FILENO, TCSANOW, termios_orig);
|
||||||
|
|
||||||
execl(prog, prog, (char *) NULL);
|
execl(prog, prog, (char *) NULL);
|
||||||
eerror("%s: unable to exec `%s': %s", applet, prog,
|
eerror("%s: unable to exec `%s': %s", applet, prog,
|
||||||
@@ -338,12 +338,13 @@ static void sulogin(bool cont)
|
|||||||
if (! cont) {
|
if (! cont) {
|
||||||
rc_logger_close();
|
rc_logger_close();
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
execl("/sbin/sulogin", "/sbin/sulogin", (char *) NULL);
|
if (RUNLEVEL && strcmp(RUNLEVEL, "S") == 0) {
|
||||||
eerrorx("%s: unable to exec `/sbin/sulogin': %s",
|
execl("/sbin/sulogin", "/sbin/sulogin", (char *) NULL);
|
||||||
applet, strerror(errno));
|
eerrorx("%s: unable to exec `/sbin/sulogin': %s",
|
||||||
#else
|
applet, strerror(errno));
|
||||||
exit(EXIT_SUCCESS);
|
}
|
||||||
#endif
|
#endif
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@@ -353,7 +354,7 @@ static void sulogin(bool cont)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void single_user(void)
|
_dead static void single_user(void)
|
||||||
{
|
{
|
||||||
rc_logger_close();
|
rc_logger_close();
|
||||||
|
|
||||||
@@ -614,7 +615,7 @@ static void do_coldplug(void)
|
|||||||
if (coldplugged_services)
|
if (coldplugged_services)
|
||||||
TAILQ_FOREACH(s, coldplugged_services, entries)
|
TAILQ_FOREACH(s, coldplugged_services, entries)
|
||||||
printf(" %s", s->value);
|
printf(" %s", s->value);
|
||||||
printf ("%s\n", ecolor(ECOLOR_NORMAL));
|
printf("%s\n", ecolor(ECOLOR_NORMAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_newlevel(const char *newlevel)
|
static void do_newlevel(const char *newlevel)
|
||||||
@@ -733,17 +734,18 @@ static void do_newlevel(const char *newlevel)
|
|||||||
static bool runlevel_config(const char *service, const char *level)
|
static bool runlevel_config(const char *service, const char *level)
|
||||||
{
|
{
|
||||||
char *init = rc_service_resolve(service);
|
char *init = rc_service_resolve(service);
|
||||||
char *conf;
|
char *conf, *dir;
|
||||||
size_t l;
|
size_t l;
|
||||||
bool retval;
|
bool retval;
|
||||||
|
|
||||||
init = dirname(init);
|
dir = dirname(init);
|
||||||
init = dirname(init);
|
dir = dirname(init);
|
||||||
l = strlen(init) + strlen(level) + strlen(service) + 10;
|
l = strlen(dir) + strlen(level) + strlen(service) + 10;
|
||||||
conf = xmalloc(sizeof(char) * l);
|
conf = xmalloc(sizeof(char) * l);
|
||||||
snprintf(conf, l, "%s/conf.d/%s.%s", init, service, level);
|
snprintf(conf, l, "%s/conf.d/%s.%s", dir, service, level);
|
||||||
retval = exists(conf);
|
retval = exists(conf);
|
||||||
free(conf);
|
free(conf);
|
||||||
|
free(init);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -754,6 +756,7 @@ static void do_stop_services(const char *newlevel, bool going_down, bool paralle
|
|||||||
RC_STRING *service, *svc1, *svc2;
|
RC_STRING *service, *svc1, *svc2;
|
||||||
RC_STRINGLIST *deporder, *tmplist;
|
RC_STRINGLIST *deporder, *tmplist;
|
||||||
RC_SERVICE state;
|
RC_SERVICE state;
|
||||||
|
RC_STRINGLIST *nostop = rc_stringlist_split(rc_conf_value("rc_nostop"), " ");
|
||||||
|
|
||||||
if (! types_n) {
|
if (! types_n) {
|
||||||
types_n = rc_stringlist_new();
|
types_n = rc_stringlist_new();
|
||||||
@@ -766,6 +769,12 @@ static void do_stop_services(const char *newlevel, bool going_down, bool paralle
|
|||||||
if (state & RC_SERVICE_STOPPED || state & RC_SERVICE_FAILED)
|
if (state & RC_SERVICE_STOPPED || state & RC_SERVICE_FAILED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Sometimes we don't ever want to stop a service. */
|
||||||
|
if (rc_stringlist_find(nostop, service->value)) {
|
||||||
|
rc_service_mark(service->value, RC_SERVICE_FAILED);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* We always stop the service when in these runlevels */
|
/* We always stop the service when in these runlevels */
|
||||||
if (going_down || ! start_services) {
|
if (going_down || ! start_services) {
|
||||||
pid = service_stop(service->value);
|
pid = service_stop(service->value);
|
||||||
@@ -775,10 +784,7 @@ static void do_stop_services(const char *newlevel, bool going_down, bool paralle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If we're in the start list then don't bother stopping us */
|
/* If we're in the start list then don't bother stopping us */
|
||||||
TAILQ_FOREACH(svc1, start_services, entries)
|
svc1 = rc_stringlist_find(start_services, service->value);
|
||||||
if (strcmp (svc1->value, service->value) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (svc1) {
|
if (svc1) {
|
||||||
if (newlevel && strcmp(runlevel, newlevel) != 0) {
|
if (newlevel && strcmp(runlevel, newlevel) != 0) {
|
||||||
/* So we're in the start list. But we should
|
/* So we're in the start list. But we should
|
||||||
@@ -799,13 +805,12 @@ static void do_stop_services(const char *newlevel, bool going_down, bool paralle
|
|||||||
tmplist = rc_stringlist_new();
|
tmplist = rc_stringlist_new();
|
||||||
rc_stringlist_add(tmplist, service->value);
|
rc_stringlist_add(tmplist, service->value);
|
||||||
deporder = rc_deptree_depends(deptree, types_n, tmplist,
|
deporder = rc_deptree_depends(deptree, types_n, tmplist,
|
||||||
runlevel, RC_DEP_STRICT);
|
newlevel ? newlevel : runlevel,
|
||||||
|
RC_DEP_STRICT | RC_DEP_TRACE);
|
||||||
rc_stringlist_free(tmplist);
|
rc_stringlist_free(tmplist);
|
||||||
svc2 = NULL;
|
svc2 = NULL;
|
||||||
TAILQ_FOREACH (svc1, deporder, entries) {
|
TAILQ_FOREACH (svc1, deporder, entries) {
|
||||||
TAILQ_FOREACH(svc2, start_services, entries)
|
svc2 = rc_stringlist_find(start_services, svc1->value);
|
||||||
if (strcmp (svc1->value, svc2->value) == 0)
|
|
||||||
break;
|
|
||||||
if (svc2)
|
if (svc2)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -825,6 +830,8 @@ static void do_stop_services(const char *newlevel, bool going_down, bool paralle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc_stringlist_free(nostop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_start_services(bool parallel)
|
static void do_start_services(bool parallel)
|
||||||
@@ -1085,6 +1092,7 @@ int main(int argc, char **argv)
|
|||||||
going_down = true;
|
going_down = true;
|
||||||
rc_runlevel_set(newlevel);
|
rc_runlevel_set(newlevel);
|
||||||
setenv("RC_RUNLEVEL", newlevel, 1);
|
setenv("RC_RUNLEVEL", newlevel, 1);
|
||||||
|
setenv("RC_GOINGDOWN", "YES", 1);
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
/* FIXME: we shouldn't have todo this */
|
/* FIXME: we shouldn't have todo this */
|
||||||
@@ -1181,10 +1189,6 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save our runlevel now */
|
|
||||||
if (going_down)
|
|
||||||
rc_runlevel_set(newlevel);
|
|
||||||
|
|
||||||
parallel = rc_conf_yesno("rc_parallel");
|
parallel = rc_conf_yesno("rc_parallel");
|
||||||
|
|
||||||
/* Now stop the services that shouldn't be running */
|
/* Now stop the services that shouldn't be running */
|
||||||
@@ -1195,7 +1199,8 @@ int main(int argc, char **argv)
|
|||||||
wait_for_services();
|
wait_for_services();
|
||||||
|
|
||||||
/* Notify the plugins we have finished */
|
/* Notify the plugins we have finished */
|
||||||
rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, runlevel);
|
rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT,
|
||||||
|
going_down ? newlevel : runlevel);
|
||||||
hook_out = 0;
|
hook_out = 0;
|
||||||
|
|
||||||
rmdir(RC_STOPPING);
|
rmdir(RC_STOPPING);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/file.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -92,7 +94,6 @@ static bool in_background = false;
|
|||||||
static RC_HOOK hook_out = 0;
|
static RC_HOOK hook_out = 0;
|
||||||
static pid_t service_pid = 0;
|
static pid_t service_pid = 0;
|
||||||
static char *prefix = NULL;
|
static char *prefix = NULL;
|
||||||
static bool prefix_locked = false;
|
|
||||||
static int signal_pipe[2] = { -1, -1 };
|
static int signal_pipe[2] = { -1, -1 };
|
||||||
static int master_tty = -1;
|
static int master_tty = -1;
|
||||||
|
|
||||||
@@ -314,8 +315,6 @@ static void cleanup(void)
|
|||||||
restore_state();
|
restore_state();
|
||||||
|
|
||||||
if (! rc_in_plugin) {
|
if (! rc_in_plugin) {
|
||||||
if (prefix_locked)
|
|
||||||
unlink(PREFIX_LOCK);
|
|
||||||
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)
|
||||||
@@ -358,7 +357,16 @@ static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) {
|
|||||||
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);
|
||||||
ssize_t ret = 0;
|
ssize_t ret = 0;
|
||||||
int fd = fileno(stdout);
|
int fd = fileno(stdout), lock_fd = -1;
|
||||||
|
|
||||||
|
/* Spin until we lock the prefix */
|
||||||
|
for (;;) {
|
||||||
|
lock_fd = open(PREFIX_LOCK, O_WRONLY | O_CREAT, 0664);
|
||||||
|
if (lock_fd != -1)
|
||||||
|
if (flock(lock_fd, LOCK_EX) == 0)
|
||||||
|
break;
|
||||||
|
close(lock_fd);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < bytes; i++) {
|
for (i = 0; i < bytes; i++) {
|
||||||
/* We don't prefix escape codes, like eend */
|
/* We don't prefix escape codes, like eend */
|
||||||
@@ -378,6 +386,9 @@ static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) {
|
|||||||
ret += write(fd, buffer + i, 1);
|
ret += write(fd, buffer + i, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Release the lock */
|
||||||
|
close(lock_fd);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,22 +513,16 @@ static bool svc_wait(const char *svc)
|
|||||||
char fifo[PATH_MAX];
|
char fifo[PATH_MAX];
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
int nloops = WAIT_MAX * (ONE_SECOND / WAIT_INTERVAL);
|
int nloops = WAIT_MAX * (ONE_SECOND / WAIT_INTERVAL);
|
||||||
|
int sloops = (ONE_SECOND / WAIT_INTERVAL) * 5;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
bool forever = false;
|
bool forever = false;
|
||||||
RC_STRINGLIST *keywords;
|
RC_STRINGLIST *keywords;
|
||||||
RC_STRING *s;
|
|
||||||
|
|
||||||
/* Some services don't have a timeout, like fsck */
|
/* Some services don't have a timeout, like fsck */
|
||||||
keywords = rc_deptree_depend(deptree, svc, "keyword");
|
keywords = rc_deptree_depend(deptree, svc, "keyword");
|
||||||
if (keywords) {
|
if (rc_stringlist_find(keywords, "notimeout"))
|
||||||
TAILQ_FOREACH(s, keywords, entries) {
|
forever = true;
|
||||||
if (strcmp (s->value, "notimeout") == 0) {
|
rc_stringlist_free(keywords);
|
||||||
forever = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
||||||
@@ -536,6 +541,11 @@ static bool svc_wait(const char *svc)
|
|||||||
|
|
||||||
if (! forever)
|
if (! forever)
|
||||||
nloops --;
|
nloops --;
|
||||||
|
|
||||||
|
if (--sloops == 0) {
|
||||||
|
ewarn("%s: waiting for %s", applet, svc);
|
||||||
|
sloops = (ONE_SECOND / WAIT_INTERVAL) * 5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! exists(fifo))
|
if (! exists(fifo))
|
||||||
@@ -546,18 +556,18 @@ static bool svc_wait(const char *svc)
|
|||||||
static RC_SERVICE svc_status(void)
|
static RC_SERVICE svc_status(void)
|
||||||
{
|
{
|
||||||
char status[10];
|
char status[10];
|
||||||
int (*e) (const char *fmt, ...) = &einfo;
|
int (*e) (const char *fmt, ...) __EINFO_PRINTF = einfo;
|
||||||
RC_SERVICE state = rc_service_state(service);
|
RC_SERVICE state = rc_service_state(service);
|
||||||
|
|
||||||
if (state & RC_SERVICE_STOPPING) {
|
if (state & RC_SERVICE_STOPPING) {
|
||||||
snprintf(status, sizeof(status), "stopping");
|
snprintf(status, sizeof(status), "stopping");
|
||||||
e = &ewarn;
|
e = ewarn;
|
||||||
} else if (state & RC_SERVICE_STARTING) {
|
} else if (state & RC_SERVICE_STARTING) {
|
||||||
snprintf(status, sizeof(status), "starting");
|
snprintf(status, sizeof(status), "starting");
|
||||||
e = &ewarn;
|
e = ewarn;
|
||||||
} else if (state & RC_SERVICE_INACTIVE) {
|
} else if (state & RC_SERVICE_INACTIVE) {
|
||||||
snprintf(status, sizeof(status), "inactive");
|
snprintf(status, sizeof(status), "inactive");
|
||||||
e = &ewarn;
|
e = ewarn;
|
||||||
} else if (state & RC_SERVICE_STARTED) {
|
} else if (state & RC_SERVICE_STARTED) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (_rc_can_find_pids() &&
|
if (_rc_can_find_pids() &&
|
||||||
@@ -565,7 +575,7 @@ static RC_SERVICE svc_status(void)
|
|||||||
errno != EACCES)
|
errno != EACCES)
|
||||||
{
|
{
|
||||||
snprintf(status, sizeof(status), "crashed");
|
snprintf(status, sizeof(status), "crashed");
|
||||||
e = &eerror;
|
e = eerror;
|
||||||
} else
|
} else
|
||||||
snprintf(status, sizeof(status), "started");
|
snprintf(status, sizeof(status), "started");
|
||||||
} else
|
} else
|
||||||
@@ -650,19 +660,6 @@ static void setup_types(void)
|
|||||||
rc_stringlist_add(types_mua, "beforeme");
|
rc_stringlist_add(types_mua, "beforeme");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool in_list(RC_STRINGLIST *list, char *string)
|
|
||||||
{
|
|
||||||
RC_STRING *s;
|
|
||||||
|
|
||||||
if (! list)
|
|
||||||
return false;
|
|
||||||
TAILQ_FOREACH(s, list, entries)
|
|
||||||
if (strcmp(s->value, string) == 0)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void svc_start(bool deps)
|
static void svc_start(bool deps)
|
||||||
{
|
{
|
||||||
bool started;
|
bool started;
|
||||||
@@ -707,7 +704,8 @@ static void svc_start(bool deps)
|
|||||||
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);
|
||||||
|
|
||||||
if (rc_conf_yesno("rc_depend_strict"))
|
errno = 0;
|
||||||
|
if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT)
|
||||||
depoptions |= RC_DEP_STRICT;
|
depoptions |= RC_DEP_STRICT;
|
||||||
|
|
||||||
if (deps) {
|
if (deps) {
|
||||||
@@ -772,8 +770,8 @@ static void svc_start(bool deps)
|
|||||||
if (state & RC_SERVICE_STARTING &&
|
if (state & RC_SERVICE_STARTING &&
|
||||||
state & RC_SERVICE_WASINACTIVE)
|
state & RC_SERVICE_WASINACTIVE)
|
||||||
{
|
{
|
||||||
if (!in_list(need_services, svc->value) &&
|
if (!rc_stringlist_find(need_services, svc->value) &&
|
||||||
!in_list(use_services, svc->value))
|
!rc_stringlist_find(use_services, svc->value))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -783,14 +781,14 @@ static void svc_start(bool deps)
|
|||||||
state = rc_service_state(svc->value);
|
state = rc_service_state(svc->value);
|
||||||
if (state & RC_SERVICE_STARTED)
|
if (state & RC_SERVICE_STARTED)
|
||||||
continue;
|
continue;
|
||||||
if (in_list(need_services, svc->value)) {
|
if (rc_stringlist_find(need_services, svc->value)) {
|
||||||
if (state & RC_SERVICE_INACTIVE ||
|
if (state & RC_SERVICE_INACTIVE ||
|
||||||
state & RC_SERVICE_WASINACTIVE)
|
state & RC_SERVICE_WASINACTIVE)
|
||||||
{
|
{
|
||||||
if (! tmplist)
|
if (! tmplist)
|
||||||
tmplist = rc_stringlist_new();
|
tmplist = rc_stringlist_new();
|
||||||
rc_stringlist_add(tmplist, svc->value);
|
rc_stringlist_add(tmplist, svc->value);
|
||||||
} else
|
} else if (!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);
|
||||||
@@ -875,11 +873,13 @@ static void svc_start(bool deps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do the same for any services we provide */
|
/* Do the same for any services we provide */
|
||||||
tmplist = rc_deptree_depend(deptree, "iprovide", applet);
|
if (deptree) {
|
||||||
if (tmplist) {
|
tmplist = rc_deptree_depend(deptree, "iprovide", applet);
|
||||||
TAILQ_FOREACH(svc, tmplist, entries) {
|
if (tmplist) {
|
||||||
services = rc_services_scheduled(svc->value);
|
TAILQ_FOREACH(svc, tmplist, entries) {
|
||||||
if (services) {
|
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);
|
||||||
@@ -933,8 +933,8 @@ static void svc_stop(bool deps)
|
|||||||
ewarn ("WARNING: you are stopping a boot service");
|
ewarn ("WARNING: you are stopping a boot service");
|
||||||
|
|
||||||
if (deps && ! (state & RC_SERVICE_WASINACTIVE)) {
|
if (deps && ! (state & RC_SERVICE_WASINACTIVE)) {
|
||||||
|
errno = 0;
|
||||||
if (rc_conf_yesno("rc_depend_strict"))
|
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))
|
||||||
@@ -943,7 +943,6 @@ static void svc_stop(bool deps)
|
|||||||
if (! types_m)
|
if (! types_m)
|
||||||
setup_types();
|
setup_types();
|
||||||
|
|
||||||
tmplist = NULL;
|
|
||||||
services = rc_deptree_depends(deptree, types_m, applet_list,
|
services = rc_deptree_depends(deptree, types_m, applet_list,
|
||||||
runlevel, depoptions);
|
runlevel, depoptions);
|
||||||
if (services) {
|
if (services) {
|
||||||
@@ -1010,7 +1009,7 @@ static void svc_stop(bool deps)
|
|||||||
continue;
|
continue;
|
||||||
svc_wait(svc->value);
|
svc_wait(svc->value);
|
||||||
}
|
}
|
||||||
rc_stringlist_free (services);
|
rc_stringlist_free(services);
|
||||||
services = NULL;
|
services = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1102,39 +1101,73 @@ int runscript(int argc, char **argv)
|
|||||||
int retval;
|
int retval;
|
||||||
int opt;
|
int opt;
|
||||||
RC_STRING *svc;
|
RC_STRING *svc;
|
||||||
char dir[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
char lnk[PATH_MAX];
|
||||||
size_t l = 0;
|
size_t l = 0;
|
||||||
size_t ll;
|
size_t ll;
|
||||||
char *save;
|
char *dir, *save = NULL;
|
||||||
|
const char *file;
|
||||||
int depoptions = RC_DEP_TRACE;
|
int depoptions = RC_DEP_TRACE;
|
||||||
|
struct stat stbuf;
|
||||||
|
|
||||||
/* Show help if insufficient args */
|
/* Show help if insufficient args */
|
||||||
if (argc < 2 || ! exists(argv[1])) {
|
if (argc < 2 || ! exists(argv[1])) {
|
||||||
fprintf(stderr, "runscript is not meant to be to run directly\n");
|
fprintf(stderr, "runscript should not be run directly\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
applet = basename_c(argv[1]);
|
if (stat(argv[1], &stbuf) != 0) {
|
||||||
if (argc < 3)
|
fprintf(stderr, "runscript `%s': %s\n",
|
||||||
usage(EXIT_FAILURE);
|
argv[1], strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
if (*argv[1] == '/')
|
|
||||||
service = xstrdup(argv[1]);
|
|
||||||
else {
|
|
||||||
getcwd(dir, sizeof(dir));
|
|
||||||
l = strlen(dir) + strlen(argv[1]) + 2;
|
|
||||||
service = xmalloc(sizeof (char) * l);
|
|
||||||
snprintf(service, l, "%s/%s", dir, argv[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
atexit(cleanup);
|
atexit(cleanup);
|
||||||
|
|
||||||
|
/* We need to work out the real full path to our service.
|
||||||
|
* This works fine, provided that we ONLY allow mulitplexed services
|
||||||
|
* to exist in the same directory as the master link.
|
||||||
|
* Also, the master link as to be a real file in the init dir. */
|
||||||
|
if (!realpath(argv[1], path)) {
|
||||||
|
fprintf(stderr, "realpath: %s\n", strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
memset(lnk, 0, sizeof(lnk));
|
||||||
|
if (readlink(argv[1], lnk, sizeof(lnk)-1)) {
|
||||||
|
dir = dirname(path);
|
||||||
|
if (strchr(lnk, '/')) {
|
||||||
|
save = xstrdup(dir);
|
||||||
|
dir = dirname(lnk);
|
||||||
|
if (strcmp(dir, save) == 0)
|
||||||
|
file = basename_c(argv[1]);
|
||||||
|
else
|
||||||
|
file = basename_c(lnk);
|
||||||
|
dir = save;
|
||||||
|
} else
|
||||||
|
file = basename_c(argv[1]);
|
||||||
|
ll = strlen(dir) + strlen(file) + 2;
|
||||||
|
service = xmalloc(ll);
|
||||||
|
snprintf(service, ll, "%s/%s", dir, file);
|
||||||
|
if (stat(service, &stbuf) != 0) {
|
||||||
|
free(service);
|
||||||
|
service = xstrdup(lnk);
|
||||||
|
}
|
||||||
|
free(save);
|
||||||
|
}
|
||||||
|
if (!service)
|
||||||
|
service = xstrdup(path);
|
||||||
|
applet = basename_c(service);
|
||||||
|
|
||||||
|
if (argc < 3)
|
||||||
|
usage(EXIT_FAILURE);
|
||||||
|
|
||||||
/* 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__
|
#ifdef __linux__
|
||||||
/* coldplug events can trigger init scripts, but we don't want to run them
|
/* coldplug events can trigger init scripts, but we don't want to run
|
||||||
until after rc sysinit has completed so we punt them to the boot runlevel */
|
* them until after rc sysinit has completed so we punt them to the
|
||||||
|
* boot runlevel */
|
||||||
if (exists("/dev/.rcsysinit")) {
|
if (exists("/dev/.rcsysinit")) {
|
||||||
eerror("%s: cannot run until sysvinit completes", applet);
|
eerror("%s: cannot run until sysvinit completes", applet);
|
||||||
if (mkdir("/dev/.rcboot", 0755) != 0 && errno != EEXIST)
|
if (mkdir("/dev/.rcboot", 0755) != 0 && errno != EEXIST)
|
||||||
@@ -1164,11 +1197,15 @@ 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);
|
||||||
TAILQ_FOREACH(svc, services, entries) {
|
if (services) {
|
||||||
ll = strlen(svc->value);
|
TAILQ_FOREACH(svc, services, entries) {
|
||||||
if (ll > l)
|
ll = strlen(svc->value);
|
||||||
l = ll;
|
if (ll > l)
|
||||||
}
|
l = ll;
|
||||||
|
}
|
||||||
|
rc_stringlist_free(services);
|
||||||
|
services = NULL;
|
||||||
|
} else l = strlen(applet);
|
||||||
|
|
||||||
/* Make our prefix string */
|
/* Make our prefix string */
|
||||||
prefix = xmalloc(sizeof(char) * l + 1);
|
prefix = xmalloc(sizeof(char) * l + 1);
|
||||||
@@ -1256,6 +1293,7 @@ int runscript(int argc, char **argv)
|
|||||||
prefix = NULL;
|
prefix = NULL;
|
||||||
svc_exec(optarg, NULL);
|
svc_exec(optarg, NULL);
|
||||||
eprefix(save);
|
eprefix(save);
|
||||||
|
prefix = save;
|
||||||
} else if (strcmp(optarg, "ineed") == 0 ||
|
} else if (strcmp(optarg, "ineed") == 0 ||
|
||||||
strcmp(optarg, "iuse") == 0 ||
|
strcmp(optarg, "iuse") == 0 ||
|
||||||
strcmp(optarg, "needsme") == 0 ||
|
strcmp(optarg, "needsme") == 0 ||
|
||||||
@@ -1264,7 +1302,8 @@ int runscript(int argc, char **argv)
|
|||||||
strcmp(optarg, "ibefore") == 0 ||
|
strcmp(optarg, "ibefore") == 0 ||
|
||||||
strcmp(optarg, "iprovide") == 0)
|
strcmp(optarg, "iprovide") == 0)
|
||||||
{
|
{
|
||||||
if (rc_conf_yesno("rc_depend_strict"))
|
errno = 0;
|
||||||
|
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))
|
||||||
|
|||||||
@@ -36,7 +36,6 @@
|
|||||||
/* nano seconds */
|
/* nano seconds */
|
||||||
#define POLL_INTERVAL 20000000
|
#define POLL_INTERVAL 20000000
|
||||||
#define WAIT_PIDFILE 500000000
|
#define WAIT_PIDFILE 500000000
|
||||||
#define START_WAIT 100000000
|
|
||||||
#define ONE_SECOND 1000000000
|
#define ONE_SECOND 1000000000
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -94,32 +93,33 @@ typedef struct scheduleitem
|
|||||||
} type;
|
} type;
|
||||||
int value;
|
int value;
|
||||||
struct scheduleitem *gotoitem;
|
struct scheduleitem *gotoitem;
|
||||||
STAILQ_ENTRY(scheduleitem) entries;
|
TAILQ_ENTRY(scheduleitem) entries;
|
||||||
} SCHEDULEITEM;
|
} SCHEDULEITEM;
|
||||||
STAILQ_HEAD(, scheduleitem) schedule;
|
TAILQ_HEAD(, scheduleitem) schedule;
|
||||||
|
static char **nav = NULL;
|
||||||
|
|
||||||
extern const char *applet;
|
extern const char *applet;
|
||||||
static char *changeuser;
|
static char *changeuser = NULL;
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
static void free_schedulelist(void)
|
static void free_schedulelist(void)
|
||||||
{
|
{
|
||||||
SCHEDULEITEM *s1 = STAILQ_FIRST(&schedule);
|
SCHEDULEITEM *s1 = TAILQ_FIRST(&schedule);
|
||||||
SCHEDULEITEM *s2;
|
SCHEDULEITEM *s2;
|
||||||
|
|
||||||
while (s1) {
|
while (s1) {
|
||||||
s2 = STAILQ_NEXT(s1, entries);
|
s2 = TAILQ_NEXT(s1, entries);
|
||||||
free(s1);
|
free(s1);
|
||||||
s1 = s2;
|
s1 = s2;
|
||||||
}
|
}
|
||||||
STAILQ_INIT(&schedule);
|
TAILQ_INIT(&schedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup(void)
|
static void cleanup(void)
|
||||||
{
|
{
|
||||||
if (changeuser)
|
free(changeuser);
|
||||||
free(changeuser);
|
free(nav);
|
||||||
|
|
||||||
free_schedulelist();
|
free_schedulelist();
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ static int parse_signal(const char *sig)
|
|||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
const char *s;
|
const char *s;
|
||||||
|
|
||||||
if (! sig || *sig == '\0')
|
if (!sig || *sig == '\0')
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (sscanf(sig, "%u", &i) == 1) {
|
if (sscanf(sig, "%u", &i) == 1) {
|
||||||
@@ -229,12 +229,12 @@ static void parse_schedule(const char *string, int timeout)
|
|||||||
item->type = SC_SIGNAL;
|
item->type = SC_SIGNAL;
|
||||||
item->value = timeout;
|
item->value = timeout;
|
||||||
item->gotoitem = NULL;
|
item->gotoitem = NULL;
|
||||||
STAILQ_INSERT_TAIL(&schedule, item, entries);
|
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||||
|
|
||||||
item = xmalloc(sizeof(*item));
|
item = xmalloc(sizeof(*item));
|
||||||
item->type = SC_TIMEOUT;
|
item->type = SC_TIMEOUT;
|
||||||
item->gotoitem = NULL;
|
item->gotoitem = NULL;
|
||||||
STAILQ_INSERT_TAIL(&schedule, item, entries);
|
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||||
if (string) {
|
if (string) {
|
||||||
if (sscanf(string, "%d", &item->value) != 1)
|
if (sscanf(string, "%d", &item->value) != 1)
|
||||||
eerrorx("%s: invalid timeout value in schedule", applet);
|
eerrorx("%s: invalid timeout value in schedule", applet);
|
||||||
@@ -258,7 +258,7 @@ static void parse_schedule(const char *string, int timeout)
|
|||||||
string = slash ? slash + 1 : NULL;
|
string = slash ? slash + 1 : NULL;
|
||||||
|
|
||||||
item = parse_schedule_item(buffer);
|
item = parse_schedule_item(buffer);
|
||||||
STAILQ_INSERT_TAIL(&schedule, item, entries);
|
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||||
if (item->type == SC_FOREVER) {
|
if (item->type == SC_FOREVER) {
|
||||||
if (repeatat)
|
if (repeatat)
|
||||||
eerrorx("%s: invalid schedule, `forever' "
|
eerrorx("%s: invalid schedule, `forever' "
|
||||||
@@ -274,7 +274,7 @@ static void parse_schedule(const char *string, int timeout)
|
|||||||
item->type = SC_GOTO;
|
item->type = SC_GOTO;
|
||||||
item->value = 0;
|
item->value = 0;
|
||||||
item->gotoitem = repeatat;
|
item->gotoitem = repeatat;
|
||||||
STAILQ_INSERT_TAIL(&schedule, item, entries);
|
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -289,13 +289,13 @@ static pid_t get_pid(const char *pidfile, bool quiet)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((fp = fopen(pidfile, "r")) == NULL) {
|
if ((fp = fopen(pidfile, "r")) == NULL) {
|
||||||
if (! quiet)
|
if (!quiet)
|
||||||
eerror("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
|
eerror("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fscanf(fp, "%d", &pid) != 1) {
|
if (fscanf(fp, "%d", &pid) != 1) {
|
||||||
if (! quiet)
|
if (!quiet)
|
||||||
eerror("%s: no pid found in `%s'", applet, pidfile);
|
eerror("%s: no pid found in `%s'", applet, pidfile);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -307,8 +307,8 @@ static pid_t get_pid(const char *pidfile, bool quiet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* return number of processed killed, -1 on error */
|
/* return number of processed killed, -1 on error */
|
||||||
static int do_stop(const char *const *argv, const char *cmd,
|
static int do_stop(const char *exec, const char *const *argv,
|
||||||
const char *pidfile, uid_t uid,int sig,
|
pid_t pid, uid_t uid,int sig,
|
||||||
bool quiet, bool verbose, bool test)
|
bool quiet, bool verbose, bool test)
|
||||||
{
|
{
|
||||||
RC_PIDLIST *pids;
|
RC_PIDLIST *pids;
|
||||||
@@ -316,21 +316,18 @@ static int do_stop(const char *const *argv, const char *cmd,
|
|||||||
RC_PID *np;
|
RC_PID *np;
|
||||||
bool killed;
|
bool killed;
|
||||||
int nkilled = 0;
|
int nkilled = 0;
|
||||||
pid_t pid = 0;
|
|
||||||
|
|
||||||
if (pidfile) {
|
if (pid)
|
||||||
if ((pid = get_pid(pidfile, quiet)) == -1)
|
|
||||||
return quiet ? 0 : -1;
|
|
||||||
pids = rc_find_pids(NULL, NULL, 0, pid);
|
pids = rc_find_pids(NULL, NULL, 0, pid);
|
||||||
} else
|
else
|
||||||
pids = rc_find_pids(argv, cmd, uid, pid);
|
pids = rc_find_pids(exec, argv, uid, pid);
|
||||||
|
|
||||||
if (! pids)
|
if (!pids)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
LIST_FOREACH_SAFE(pi, pids, entries, np) {
|
LIST_FOREACH_SAFE(pi, pids, entries, np) {
|
||||||
if (test) {
|
if (test) {
|
||||||
if (! quiet)
|
if (!quiet)
|
||||||
einfo("Would send signal %d to PID %d",
|
einfo("Would send signal %d to PID %d",
|
||||||
sig, pi->pid);
|
sig, pi->pid);
|
||||||
nkilled++;
|
nkilled++;
|
||||||
@@ -345,7 +342,7 @@ static int do_stop(const char *const *argv, const char *cmd,
|
|||||||
eend(killed ? 0 : 1,
|
eend(killed ? 0 : 1,
|
||||||
"%s: failed to send signal %d to PID %d: %s",
|
"%s: failed to send signal %d to PID %d: %s",
|
||||||
applet, sig, pi->pid, strerror(errno));
|
applet, sig, pi->pid, strerror(errno));
|
||||||
if (! killed) {
|
if (!killed) {
|
||||||
nkilled = -1;
|
nkilled = -1;
|
||||||
} else {
|
} else {
|
||||||
if (nkilled != -1)
|
if (nkilled != -1)
|
||||||
@@ -359,26 +356,33 @@ static int do_stop(const char *const *argv, const char *cmd,
|
|||||||
return nkilled;
|
return nkilled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_stop_schedule(const char *const *argv, const char *cmd,
|
static int run_stop_schedule(const char *exec, const char *const *argv,
|
||||||
const char *pidfile, uid_t uid,
|
const char *pidfile, uid_t uid,
|
||||||
bool quiet, bool verbose, bool test)
|
bool quiet, bool verbose, bool test)
|
||||||
{
|
{
|
||||||
SCHEDULEITEM *item = STAILQ_FIRST(&schedule);
|
SCHEDULEITEM *item = TAILQ_FIRST(&schedule);
|
||||||
int nkilled = 0;
|
int nkilled = 0;
|
||||||
int tkilled = 0;
|
int tkilled = 0;
|
||||||
int nrunning = 0;
|
int nrunning = 0;
|
||||||
long nloops;
|
long nloops;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
pid_t pid = 0;
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
|
if (exec)
|
||||||
|
einfo ("Will stop %s\n", exec);
|
||||||
if (pidfile)
|
if (pidfile)
|
||||||
einfo("Will stop PID in pidfile `%s'", pidfile);
|
einfo("Will stop PID in pidfile `%s'", pidfile);
|
||||||
if (uid)
|
if (uid)
|
||||||
einfo("Will stop processes owned by UID %d", uid);
|
einfo("Will stop processes owned by UID %d", uid);
|
||||||
if (argv && *argv)
|
if (argv && *argv)
|
||||||
einfo("Will stop processes of `%s'", *argv);
|
einfo("Will stop processes of `%s'", *argv);
|
||||||
if (cmd)
|
}
|
||||||
einfo("Will stop processes called `%s'", cmd);
|
|
||||||
|
if (pidfile) {
|
||||||
|
pid = get_pid(pidfile, quiet);
|
||||||
|
if (pid == -1)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (item) {
|
while (item) {
|
||||||
@@ -389,7 +393,7 @@ static int run_stop_schedule(const char *const *argv, const char *cmd,
|
|||||||
|
|
||||||
case SC_SIGNAL:
|
case SC_SIGNAL:
|
||||||
nrunning = 0;
|
nrunning = 0;
|
||||||
nkilled = do_stop(argv, cmd, pidfile, uid, item->value,
|
nkilled = do_stop(exec, argv, pid, uid, item->value,
|
||||||
quiet, verbose, test);
|
quiet, verbose, test);
|
||||||
if (nkilled == 0) {
|
if (nkilled == 0) {
|
||||||
if (tkilled == 0) {
|
if (tkilled == 0) {
|
||||||
@@ -415,9 +419,9 @@ static int run_stop_schedule(const char *const *argv, const char *cmd,
|
|||||||
ts.tv_nsec = POLL_INTERVAL;
|
ts.tv_nsec = POLL_INTERVAL;
|
||||||
|
|
||||||
while (nloops) {
|
while (nloops) {
|
||||||
if ((nrunning = do_stop(argv, cmd, pidfile,
|
if ((nrunning = do_stop(exec, argv, pid,
|
||||||
uid, 0, true, false, true)) == 0)
|
uid, 0, true, false, true)) == 0)
|
||||||
return true;
|
return 0;
|
||||||
|
|
||||||
if (nanosleep(&ts, NULL) == -1) {
|
if (nanosleep(&ts, NULL) == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
@@ -438,7 +442,7 @@ static int run_stop_schedule(const char *const *argv, const char *cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (item)
|
if (item)
|
||||||
item = STAILQ_NEXT(item, entries);
|
item = TAILQ_NEXT(item, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test || (tkilled > 0 && nrunning == 0))
|
if (test || (tkilled > 0 && nrunning == 0))
|
||||||
@@ -462,15 +466,15 @@ static void handle_signal(int sig)
|
|||||||
|
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
if (! signame[0])
|
if (!signame[0])
|
||||||
snprintf(signame, sizeof(signame), "SIGINT");
|
snprintf(signame, sizeof(signame), "SIGINT");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
if (! signame[0])
|
if (!signame[0])
|
||||||
snprintf(signame, sizeof(signame), "SIGTERM");
|
snprintf(signame, sizeof(signame), "SIGTERM");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGQUIT:
|
case SIGQUIT:
|
||||||
if (! signame[0])
|
if (!signame[0])
|
||||||
snprintf(signame, sizeof(signame), "SIGQUIT");
|
snprintf(signame, sizeof(signame), "SIGQUIT");
|
||||||
eerrorx("%s: caught %s, aborting", applet, signame);
|
eerrorx("%s: caught %s, aborting", applet, signame);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
@@ -495,7 +499,7 @@ static void handle_signal(int sig)
|
|||||||
|
|
||||||
|
|
||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
#define getoptstring "KN:R:Sbc:d:g:mn:op:s:tu:r:x:1:2:" getoptstring_COMMON
|
#define getoptstring "KN:R:Sbc:d:e:g:k:mn:op:s:tu:r:x:1:2:" getoptstring_COMMON
|
||||||
static const struct option longopts[] = {
|
static const struct option longopts[] = {
|
||||||
{ "stop", 0, NULL, 'K'},
|
{ "stop", 0, NULL, 'K'},
|
||||||
{ "nicelevel", 1, NULL, 'N'},
|
{ "nicelevel", 1, NULL, 'N'},
|
||||||
@@ -506,6 +510,7 @@ static const struct option longopts[] = {
|
|||||||
{ "chuid", 1, NULL, 'c'},
|
{ "chuid", 1, NULL, 'c'},
|
||||||
{ "chdir", 1, NULL, 'd'},
|
{ "chdir", 1, NULL, 'd'},
|
||||||
{ "env", 1, NULL, 'e'},
|
{ "env", 1, NULL, 'e'},
|
||||||
|
{ "umask", 1, NULL, 'k'},
|
||||||
{ "group", 1, NULL, 'g'},
|
{ "group", 1, NULL, 'g'},
|
||||||
{ "make-pidfile", 0, NULL, 'm'},
|
{ "make-pidfile", 0, NULL, 'm'},
|
||||||
{ "name", 1, NULL, 'n'},
|
{ "name", 1, NULL, 'n'},
|
||||||
@@ -525,11 +530,12 @@ static const char * const longopts_help[] = {
|
|||||||
"Set a nicelevel when starting",
|
"Set a nicelevel when starting",
|
||||||
"Retry schedule to use when stopping",
|
"Retry schedule to use when stopping",
|
||||||
"Start daemon",
|
"Start daemon",
|
||||||
"deprecated, use --exec",
|
"deprecated, use --exec or --name",
|
||||||
"Force daemon to background",
|
"Force daemon to background",
|
||||||
"deprecated, use --user",
|
"deprecated, use --user",
|
||||||
"Change the PWD",
|
"Change the PWD",
|
||||||
"Set an environment string",
|
"Set an environment string",
|
||||||
|
"Set the umask for the daemon",
|
||||||
"Change the process group",
|
"Change the process group",
|
||||||
"Create a pidfile",
|
"Create a pidfile",
|
||||||
"Match process name",
|
"Match process name",
|
||||||
@@ -559,14 +565,14 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
bool start = false;
|
bool start = true;
|
||||||
bool stop = false;
|
|
||||||
bool oknodo = false;
|
bool oknodo = false;
|
||||||
bool test = false;
|
bool test = false;
|
||||||
bool quiet;
|
bool quiet;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
char *exec = NULL;
|
char *exec = NULL;
|
||||||
char *cmd = NULL;
|
char *startas = NULL;
|
||||||
|
char *name = NULL;
|
||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
int sig = SIGTERM;
|
int sig = SIGTERM;
|
||||||
int nicelevel = 0;
|
int nicelevel = 0;
|
||||||
@@ -581,40 +587,44 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
char *redirect_stdout = NULL;
|
char *redirect_stdout = NULL;
|
||||||
int stdout_fd;
|
int stdout_fd;
|
||||||
int stderr_fd;
|
int stderr_fd;
|
||||||
pid_t pid;
|
pid_t pid, spid;
|
||||||
int i;
|
int i;
|
||||||
char *svcname = getenv("RC_SVCNAME");
|
char *svcname = getenv("RC_SVCNAME");
|
||||||
RC_STRINGLIST *env_list;
|
RC_STRINGLIST *env_list;
|
||||||
RC_STRING *env;
|
RC_STRING *env;
|
||||||
char *path;
|
char *tmp, *newpath, *np;
|
||||||
bool sethome = false;
|
bool sethome = false;
|
||||||
bool setuser = false;
|
bool setuser = false;
|
||||||
char *p;
|
char *p;
|
||||||
char *tmp;
|
char *token;
|
||||||
char exec_file[PATH_MAX];
|
char exec_file[PATH_MAX];
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct group *gr;
|
struct group *gr;
|
||||||
char line[130];
|
char line[130];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
bool setumask = false;
|
||||||
|
mode_t numask;
|
||||||
|
char **margv;
|
||||||
|
unsigned int start_wait = 0;
|
||||||
|
|
||||||
STAILQ_INIT(&schedule);
|
TAILQ_INIT(&schedule);
|
||||||
atexit(cleanup);
|
atexit(cleanup);
|
||||||
|
|
||||||
signal_setup(SIGINT, handle_signal);
|
signal_setup(SIGINT, handle_signal);
|
||||||
signal_setup(SIGQUIT, handle_signal);
|
signal_setup(SIGQUIT, handle_signal);
|
||||||
signal_setup(SIGTERM, handle_signal);
|
signal_setup(SIGTERM, handle_signal);
|
||||||
|
|
||||||
if ((path = getenv("SSD_NICELEVEL")))
|
if ((tmp = getenv("SSD_NICELEVEL")))
|
||||||
if (sscanf(path, "%d", &nicelevel) != 1)
|
if (sscanf(tmp, "%d", &nicelevel) != 1)
|
||||||
eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
|
eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
|
||||||
applet, path);
|
applet, tmp);
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "e:" getoptstring, longopts,
|
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
|
||||||
(int *) 0)) != -1)
|
(int *) 0)) != -1)
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'K': /* --stop */
|
case 'K': /* --stop */
|
||||||
stop = true;
|
start = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'N': /* --nice */
|
case 'N': /* --nice */
|
||||||
@@ -692,12 +702,19 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'k':
|
||||||
|
if (parse_mode(&numask, optarg))
|
||||||
|
eerrorx("%s: invalid mode `%s'",
|
||||||
|
applet, optarg);
|
||||||
|
setumask = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'm': /* --make-pidfile */
|
case 'm': /* --make-pidfile */
|
||||||
makepidfile = true;
|
makepidfile = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n': /* --name <process-name> */
|
case 'n': /* --name <process-name> */
|
||||||
cmd = optarg;
|
name = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o': /* --oknodo */
|
case 'o': /* --oknodo */
|
||||||
@@ -720,7 +737,9 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
ch_root = optarg;
|
ch_root = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a': /* --startas <name> */
|
||||||
|
startas = optarg;
|
||||||
|
break;
|
||||||
case 'x': /* --exec <executable> */
|
case 'x': /* --exec <executable> */
|
||||||
exec = optarg;
|
exec = optarg;
|
||||||
break;
|
break;
|
||||||
@@ -736,106 +755,67 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endpwent();
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
quiet = rc_yesno(getenv("EINFO_QUIET"));
|
quiet = rc_yesno(getenv("EINFO_QUIET"));
|
||||||
verbose = rc_yesno(getenv("EINFO_VERBOSE"));
|
verbose = rc_yesno(getenv("EINFO_VERBOSE"));
|
||||||
|
|
||||||
/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq
|
/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq
|
||||||
* instead of forcing --stop --oknodo as well */
|
* instead of forcing --stop --oknodo as well */
|
||||||
if (! start && ! stop)
|
if (!start &&
|
||||||
if (sig != SIGINT &&
|
sig != SIGINT &&
|
||||||
sig != SIGTERM &&
|
sig != SIGTERM &&
|
||||||
sig != SIGQUIT &&
|
sig != SIGQUIT &&
|
||||||
sig != SIGKILL)
|
sig != SIGKILL)
|
||||||
{
|
oknodo = true;
|
||||||
oknodo = true;
|
|
||||||
stop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start == stop)
|
if (!exec)
|
||||||
eerrorx("%s: need one of --start or --stop", applet);
|
exec = startas;
|
||||||
|
else if (!name)
|
||||||
|
name = startas;
|
||||||
|
|
||||||
if (start && ! exec)
|
if (!exec) {
|
||||||
eerrorx("%s: --start needs --exec", applet);
|
exec = *argv;
|
||||||
|
if (name)
|
||||||
|
*argv = name;
|
||||||
|
} else if (name)
|
||||||
|
*--argv = name;
|
||||||
|
else
|
||||||
|
*--argv = exec;
|
||||||
|
|
||||||
if (stop && ! exec && ! pidfile && ! cmd && ! uid)
|
|
||||||
|
if (start && !exec)
|
||||||
|
eerrorx("%s: nothing to start", applet);
|
||||||
|
|
||||||
|
if (!start && !*argv && !pidfile && !name && !uid)
|
||||||
eerrorx("%s: --stop needs --exec, --pidfile, --name or --user", applet);
|
eerrorx("%s: --stop needs --exec, --pidfile, --name or --user", applet);
|
||||||
|
|
||||||
if (makepidfile && ! pidfile)
|
if (makepidfile && !pidfile)
|
||||||
eerrorx("%s: --make-pidfile is only relevant with --pidfile", applet);
|
eerrorx("%s: --make-pidfile is only relevant with --pidfile", applet);
|
||||||
|
|
||||||
if (background && ! start)
|
if (background && !start)
|
||||||
eerrorx("%s: --background is only relevant with --start", applet);
|
eerrorx("%s: --background is only relevant with --start", applet);
|
||||||
|
|
||||||
if ((redirect_stdout || redirect_stderr) && ! background)
|
if ((redirect_stdout || redirect_stderr) && !background)
|
||||||
eerrorx("%s: --stdout and --stderr are only relevant with --background",
|
eerrorx("%s: --stdout and --stderr are only relevant with --background",
|
||||||
applet);
|
applet);
|
||||||
|
|
||||||
argc -= optind;
|
if (!start) {
|
||||||
argv += optind;
|
if (!TAILQ_FIRST(&schedule)) {
|
||||||
|
|
||||||
/* Validate that the binary exists if we are starting */
|
|
||||||
if (exec) {
|
|
||||||
if (ch_root) {
|
|
||||||
snprintf(exec_file, sizeof(exec_file), "%s/%s", ch_root, exec);
|
|
||||||
tmp = exec_file;
|
|
||||||
} else
|
|
||||||
tmp = exec;
|
|
||||||
if (start && ! exists(tmp)) {
|
|
||||||
eerror("%s: %s does not exist", applet, tmp);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we don't have a pidfile or name, check it's not
|
|
||||||
* interpreted, otherwise we should fail */
|
|
||||||
if (! pidfile && ! cmd) {
|
|
||||||
fp = fopen (tmp, "r");
|
|
||||||
if (fp) {
|
|
||||||
fgets(line, sizeof(line), fp);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
if (line[0] == '#' && line[1] == '!') {
|
|
||||||
len = strlen (line) - 1;
|
|
||||||
|
|
||||||
/* Remove the trailing newline */
|
|
||||||
if (line[len] == '\n')
|
|
||||||
line[len] = '\0';
|
|
||||||
|
|
||||||
eerror("%s: %s is a script",
|
|
||||||
applet, exec);
|
|
||||||
eerror("%s: and should be started, stopped"
|
|
||||||
" or signalled with ", applet);
|
|
||||||
eerror("%s: --exec %s %s",
|
|
||||||
applet, line + 2, exec);
|
|
||||||
eerror("%s: or you should specify a pidfile"
|
|
||||||
" or process name", applet);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add exec to our arguments */
|
|
||||||
*--argv = exec;
|
|
||||||
|
|
||||||
if (stop) {
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (! STAILQ_FIRST(&schedule)) {
|
|
||||||
if (test || oknodo)
|
if (test || oknodo)
|
||||||
parse_schedule("0", sig);
|
parse_schedule("0", sig);
|
||||||
else
|
else
|
||||||
parse_schedule(NULL, sig);
|
parse_schedule(NULL, sig);
|
||||||
}
|
}
|
||||||
|
i = run_stop_schedule(exec, (const char *const *)argv,
|
||||||
|
pidfile, uid, quiet, verbose, test);
|
||||||
|
|
||||||
result = run_stop_schedule((const char *const *)argv, cmd,
|
if (i < 0)
|
||||||
pidfile, uid, quiet, verbose, test);
|
|
||||||
|
|
||||||
if (result < 0)
|
|
||||||
/* We failed to stop something */
|
/* We failed to stop something */
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (test || oknodo)
|
if (test || oknodo)
|
||||||
return result > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
return i > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
|
||||||
/* Even if we have not actually killed anything, we should
|
/* Even if we have not actually killed anything, we should
|
||||||
* remove information about it as it may have unexpectedly
|
* remove information about it as it may have unexpectedly
|
||||||
@@ -843,16 +823,83 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
* result would be the same. */
|
* result would be the same. */
|
||||||
if (pidfile && exists(pidfile))
|
if (pidfile && exists(pidfile))
|
||||||
unlink(pidfile);
|
unlink(pidfile);
|
||||||
|
|
||||||
if (svcname)
|
if (svcname)
|
||||||
rc_service_daemon_set(svcname,
|
rc_service_daemon_set(svcname, exec,
|
||||||
(const char *const *)argv,
|
(const char *const *)argv,
|
||||||
cmd, pidfile, false);
|
pidfile, false);
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_stop((const char * const *)argv, cmd, pidfile, uid,
|
/* Validate that the binary exists if we are starting */
|
||||||
|
if (*exec == '/' || *exec == '.') {
|
||||||
|
/* Full or relative path */
|
||||||
|
if (ch_root)
|
||||||
|
snprintf(exec_file, sizeof(exec_file), "%s/%s", ch_root, exec);
|
||||||
|
else
|
||||||
|
snprintf(exec_file, sizeof(exec_file), "%s", exec);
|
||||||
|
} else {
|
||||||
|
/* Something in $PATH */
|
||||||
|
p = tmp = xstrdup(getenv("PATH"));
|
||||||
|
*exec_file = '\0';
|
||||||
|
while ((token = strsep(&p, ":"))) {
|
||||||
|
if (ch_root)
|
||||||
|
snprintf(exec_file, sizeof(exec_file), "%s/%s/%s", ch_root, token, exec);
|
||||||
|
else
|
||||||
|
snprintf(exec_file, sizeof(exec_file), "%s/%s", token, exec);
|
||||||
|
if (exists(exec_file))
|
||||||
|
break;
|
||||||
|
*exec_file = '\0';
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
if (!exists(exec_file)) {
|
||||||
|
eerror("%s: %s does not exist", applet,
|
||||||
|
*exec_file ? exec_file : exec);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we don't have a pidfile we should check if it's interpreted
|
||||||
|
* or not. If it we, we need to pass the interpreter through
|
||||||
|
* to our daemon calls to find it correctly. */
|
||||||
|
if (!pidfile) {
|
||||||
|
fp = fopen(exec_file, "r");
|
||||||
|
if (fp) {
|
||||||
|
fgets(line, sizeof(line), fp);
|
||||||
|
fclose(fp);
|
||||||
|
if (line[0] == '#' && line[1] == '!') {
|
||||||
|
p = line + 2;
|
||||||
|
/* Strip leading spaces */
|
||||||
|
while (*p == ' ' || *p == '\t')
|
||||||
|
p++;
|
||||||
|
/* Remove the trailing newline */
|
||||||
|
len = strlen(p) - 1;
|
||||||
|
if (p[len] == '\n')
|
||||||
|
p[len] = '\0';
|
||||||
|
token = strsep(&p, " ");
|
||||||
|
strncpy(exec_file, token, sizeof(exec_file));
|
||||||
|
opt = 0;
|
||||||
|
for (nav = argv; *nav; nav++)
|
||||||
|
opt++;
|
||||||
|
nav = xmalloc(sizeof(char *) * (opt + 3));
|
||||||
|
nav[0] = exec_file;
|
||||||
|
len = 1;
|
||||||
|
if (p)
|
||||||
|
nav[len++] = p;
|
||||||
|
for (i = 0; i < opt; i++)
|
||||||
|
nav[i + len] = argv[i];
|
||||||
|
nav[i + len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
margv = nav ? nav : argv;
|
||||||
|
|
||||||
|
if (pidfile)
|
||||||
|
pid = get_pid(pidfile, true);
|
||||||
|
else
|
||||||
|
pid = 0;
|
||||||
|
|
||||||
|
if (do_stop(exec, (const char * const *)margv, pid, uid,
|
||||||
0, true, false, true) > 0)
|
0, true, false, true) > 0)
|
||||||
eerrorx("%s: %s is already running", applet, exec);
|
eerrorx("%s: %s is already running", applet, exec);
|
||||||
|
|
||||||
@@ -875,6 +922,8 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
einfo("in dir `%s'", ch_dir);
|
einfo("in dir `%s'", ch_dir);
|
||||||
if (nicelevel != 0)
|
if (nicelevel != 0)
|
||||||
einfo("with a priority of %d", nicelevel);
|
einfo("with a priority of %d", nicelevel);
|
||||||
|
if (name)
|
||||||
|
einfo ("with a process name of %s", name);
|
||||||
eoutdent();
|
eoutdent();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
@@ -893,6 +942,8 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
/* Child process - lets go! */
|
/* Child process - lets go! */
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
pid_t mypid = getpid();
|
pid_t mypid = getpid();
|
||||||
|
if (setumask)
|
||||||
|
umask(numask);
|
||||||
|
|
||||||
#ifdef TIOCNOTTY
|
#ifdef TIOCNOTTY
|
||||||
tty_fd = open("/dev/tty", O_RDWR);
|
tty_fd = open("/dev/tty", O_RDWR);
|
||||||
@@ -909,7 +960,7 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
if (ch_root && chroot(ch_root) < 0)
|
if (ch_root && chroot(ch_root) < 0)
|
||||||
eerrorx("%s: chroot `%s': %s", applet, ch_root, strerror(errno));
|
eerrorx("%s: chroot `%s': %s", applet, ch_root, strerror(errno));
|
||||||
|
|
||||||
if (ch_dir && chdir (ch_dir) < 0)
|
if (ch_dir && chdir(ch_dir) < 0)
|
||||||
eerrorx("%s: chdir `%s': %s", applet, ch_dir, strerror(errno));
|
eerrorx("%s: chdir `%s': %s", applet, ch_dir, strerror(errno));
|
||||||
|
|
||||||
if (makepidfile && pidfile) {
|
if (makepidfile && pidfile) {
|
||||||
@@ -946,12 +997,12 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
else {
|
else {
|
||||||
pw = getpwuid(uid);
|
pw = getpwuid(uid);
|
||||||
if (pw) {
|
if (pw) {
|
||||||
if (! sethome) {
|
if (!sethome) {
|
||||||
unsetenv("HOME");
|
unsetenv("HOME");
|
||||||
if (pw->pw_dir)
|
if (pw->pw_dir)
|
||||||
setenv("HOME", pw->pw_dir, 1);
|
setenv("HOME", pw->pw_dir, 1);
|
||||||
}
|
}
|
||||||
if (! setuser) {
|
if (!setuser) {
|
||||||
unsetenv("USER");
|
unsetenv("USER");
|
||||||
if (pw->pw_name)
|
if (pw->pw_name)
|
||||||
setenv("USER", pw->pw_name, 1);
|
setenv("USER", pw->pw_name, 1);
|
||||||
@@ -987,26 +1038,22 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
rc_stringlist_free(env_list);
|
rc_stringlist_free(env_list);
|
||||||
|
|
||||||
/* For the path, remove the rcscript bin dir from it */
|
/* For the path, remove the rcscript bin dir from it */
|
||||||
if ((path = getenv("PATH"))) {
|
if ((tmp = xstrdup(getenv("PATH")))) {
|
||||||
size_t mx = strlen(path);
|
len = strlen(tmp);
|
||||||
char *newpath = xmalloc(mx);
|
newpath = np = xmalloc(len);
|
||||||
char *token;
|
p = tmp;
|
||||||
char *np = newpath;
|
while ((token = strsep(&p, ":"))) {
|
||||||
size_t l;
|
if (strcmp(token, RC_LIBDIR "/bin") == 0 ||
|
||||||
|
strcmp(token, RC_LIBDIR "/sbin") == 0)
|
||||||
p = path;
|
|
||||||
while ((token = strsep (&p, ":"))) {
|
|
||||||
if (strcmp (token, RC_LIBDIR "/bin") == 0 ||
|
|
||||||
strcmp (token, RC_LIBDIR "/sbin") == 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
len = strlen(token);
|
||||||
l = strlen (token);
|
|
||||||
if (np != newpath)
|
if (np != newpath)
|
||||||
*np++ = ':';
|
*np++ = ':';
|
||||||
memcpy (np, token, l);
|
memcpy(np, token, len);
|
||||||
np += l;
|
np += len;
|
||||||
*np = '\0';
|
*np = '\0';
|
||||||
}
|
}
|
||||||
|
free(tmp);
|
||||||
unsetenv("PATH");
|
unsetenv("PATH");
|
||||||
setenv("PATH", newpath, 1);
|
setenv("PATH", newpath, 1);
|
||||||
}
|
}
|
||||||
@@ -1038,43 +1085,51 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
close(i);
|
close(i);
|
||||||
|
|
||||||
setsid();
|
setsid();
|
||||||
execv(exec, argv);
|
execvp(exec, argv);
|
||||||
#ifdef HAVE_PAM
|
#ifdef HAVE_PAM
|
||||||
if (pamr == PAM_SUCCESS)
|
if (pamr == PAM_SUCCESS)
|
||||||
pam_close_session(pamh, PAM_SILENT);
|
pam_close_session(pamh, PAM_SILENT);
|
||||||
#endif
|
#endif
|
||||||
eerrorx("%s: failed to exec `%s': %s", applet, exec, strerror(errno));
|
eerrorx("%s: failed to exec `%s': %s",
|
||||||
|
applet, exec,strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parent process */
|
/* Parent process */
|
||||||
if (! background) {
|
if (!background) {
|
||||||
/* As we're not backgrounding the process, wait for our pid to return */
|
/* As we're not backgrounding the process, wait for our pid
|
||||||
int status = 0;
|
* to return */
|
||||||
int savepid = pid;
|
i = 0;
|
||||||
|
spid = pid;
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
do {
|
do {
|
||||||
pid = waitpid(savepid, &status, 0);
|
pid = waitpid(spid, &i, 0);
|
||||||
if (pid < 1) {
|
if (pid < 1) {
|
||||||
eerror("waitpid %d: %s", savepid, strerror(errno));
|
eerror("waitpid %d: %s", spid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} while (! WIFEXITED(status) && ! WIFSIGNALED(status));
|
} while (!WIFEXITED(i) && !WIFSIGNALED(i));
|
||||||
|
if (!WIFEXITED(i) || WEXITSTATUS(i) != 0) {
|
||||||
if (! WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
if (!quiet)
|
||||||
if (! quiet)
|
|
||||||
eerrorx("%s: failed to start `%s'", applet, exec);
|
eerrorx("%s: failed to start `%s'", applet, exec);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
pid = spid;
|
||||||
pid = savepid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait a little bit and check that process is still running
|
/* Wait a little bit and check that process is still running
|
||||||
We do this as some badly written daemons fork and then barf */
|
We do this as some badly written daemons fork and then barf */
|
||||||
if (START_WAIT > 0) {
|
if ((p = getenv("SSD_STARTWAIT")) ||
|
||||||
|
(p = rc_conf_value("rc_start_wait")))
|
||||||
|
{
|
||||||
|
if (sscanf(p, "%u", &start_wait) == 1)
|
||||||
|
start_wait *= 1000000;
|
||||||
|
else
|
||||||
|
start_wait = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_wait > 0) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
int nloops = START_WAIT / POLL_INTERVAL;
|
int nloops = start_wait / POLL_INTERVAL;
|
||||||
int nloopsp = WAIT_PIDFILE / POLL_INTERVAL;
|
int nloopsp = WAIT_PIDFILE / POLL_INTERVAL;
|
||||||
bool alive = false;
|
bool alive = false;
|
||||||
|
|
||||||
@@ -1091,48 +1146,55 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We wait for a specific amount of time for a pidfile to be
|
/* We wait for a specific amount of time for a pidfile
|
||||||
* created. Once everything is in place we then wait some more
|
* to be created.
|
||||||
* to ensure that the daemon really is running and won't abort due
|
* Once everything is in place we then wait some more
|
||||||
* to a config error. */
|
* to ensure that the daemon really is running and won't
|
||||||
if (! background && pidfile && nloopsp)
|
* abort due to a config error. */
|
||||||
nloopsp --;
|
if (!background && pidfile && nloopsp)
|
||||||
|
nloopsp--;
|
||||||
else
|
else
|
||||||
nloops --;
|
nloops--;
|
||||||
|
|
||||||
/* This is knarly.
|
/* This is knarly.
|
||||||
If we backgrounded then we know the exact pid.
|
* If we backgrounded then we know the exact pid.
|
||||||
Otherwise if we have a pidfile then it *may* know the exact pid.
|
* Otherwise if we have a pidfile then it *may* know
|
||||||
Failing that, we'll have to query processes.
|
* the exact pid.
|
||||||
We sleep first as some programs like ntp like to fork, and write
|
* Failing that, we'll have to query processes.
|
||||||
their pidfile a LONG time later. */
|
* We sleep first as some programs like ntp like to
|
||||||
|
* fork, and write their pidfile a LONG time later. */
|
||||||
if (background) {
|
if (background) {
|
||||||
if (kill (pid, 0) == 0)
|
if (kill (pid, 0) == 0)
|
||||||
alive = true;
|
alive = true;
|
||||||
} else {
|
} else {
|
||||||
if (pidfile) {
|
if (pidfile) {
|
||||||
/* The pidfile may not have been written yet - give it some time */
|
/* The pidfile may not have been
|
||||||
if (get_pid(pidfile, true) == -1) {
|
* written yet - give it some time */
|
||||||
|
if ((pid = get_pid(pidfile, true)) == -1) {
|
||||||
if (! nloopsp)
|
if (! nloopsp)
|
||||||
eerrorx("%s: did not create a valid pid in `%s'",
|
eerrorx("%s: did not "
|
||||||
|
"create a valid"
|
||||||
|
" pid in `%s'",
|
||||||
applet, pidfile);
|
applet, pidfile);
|
||||||
alive = true;
|
alive = true;
|
||||||
|
pid = 0;
|
||||||
} else
|
} else
|
||||||
nloopsp = 0;
|
nloopsp = 0;
|
||||||
}
|
} else
|
||||||
if (do_stop((const char *const *)argv, cmd,
|
pid = 0;
|
||||||
pidfile, uid, 0, true, false, true) > 0)
|
if (do_stop(exec, (const char *const *)margv,
|
||||||
|
pid, uid, 0, true, false, true) > 0)
|
||||||
alive = true;
|
alive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! alive)
|
if (!alive)
|
||||||
eerrorx("%s: %s died", applet, exec);
|
eerrorx("%s: %s died", applet, exec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (svcname)
|
if (svcname)
|
||||||
rc_service_daemon_set(svcname, (const char *const *)argv,
|
rc_service_daemon_set(svcname, exec, (const char *const *)margv,
|
||||||
cmd, pidfile, true);
|
pidfile, true);
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
|||||||
1
src/test/.gitignore
vendored
1
src/test/.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
/*.out
|
/*.out
|
||||||
|
tmp-*
|
||||||
|
|||||||
@@ -7,5 +7,8 @@ gitignore:
|
|||||||
check test::
|
check test::
|
||||||
./runtests.sh
|
./runtests.sh
|
||||||
|
|
||||||
|
verbose-test:
|
||||||
|
VERBOSE=yes ./runtests.sh
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.out
|
rm -rf *.out tmp-*
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ rc_deptree_update_needed
|
|||||||
rc_find_pids
|
rc_find_pids
|
||||||
rc_getline
|
rc_getline
|
||||||
rc_newer_than
|
rc_newer_than
|
||||||
|
rc_older_than
|
||||||
rc_runlevel_exists
|
rc_runlevel_exists
|
||||||
rc_runlevel_get
|
rc_runlevel_get
|
||||||
rc_runlevel_list
|
rc_runlevel_list
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ rc_find_pids
|
|||||||
rc_find_pids@@RC_1.0
|
rc_find_pids@@RC_1.0
|
||||||
rc_newer_than
|
rc_newer_than
|
||||||
rc_newer_than@@RC_1.0
|
rc_newer_than@@RC_1.0
|
||||||
|
rc_older_than
|
||||||
|
rc_older_than@@RC_1.0
|
||||||
rc_runlevel_exists
|
rc_runlevel_exists
|
||||||
rc_runlevel_exists@@RC_1.0
|
rc_runlevel_exists@@RC_1.0
|
||||||
rc_runlevel_get
|
rc_runlevel_get
|
||||||
|
|||||||
@@ -66,4 +66,14 @@ syms=$(diff -u librc.funcs.hidden.list librc.funcs.hidden.out | sed -n '/^+[^+]/
|
|||||||
eend $? "Missing hidden defs:"$'\n'"${syms}"
|
eend $? "Missing hidden defs:"$'\n'"${syms}"
|
||||||
ret=$(($ret + $?))
|
ret=$(($ret + $?))
|
||||||
|
|
||||||
|
einfo "Running unit tests"
|
||||||
|
eindent
|
||||||
|
for u in units/*; do
|
||||||
|
[ -x "${u}" -a -f "${u}" ] || continue
|
||||||
|
ebegin "$(basename "${u}")"
|
||||||
|
./"${u}"
|
||||||
|
eend $?
|
||||||
|
ret=$(($ret + $?))
|
||||||
|
done
|
||||||
|
|
||||||
exit ${ret}
|
exit ${ret}
|
||||||
|
|||||||
1
src/test/units/.gitignore
vendored
Normal file
1
src/test/units/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
tmp-*
|
||||||
71
src/test/units/is_older_than
Executable file
71
src/test/units/is_older_than
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# unit test for is_older_than code of baselayout (2008/06/19)
|
||||||
|
# Author: Matthias Schwarzott <zzam@gentoo.org>
|
||||||
|
|
||||||
|
TMPDIR=tmp-"$(basename "$0")"
|
||||||
|
|
||||||
|
# Please note that we added this unit test because the function
|
||||||
|
# should really be called is_newer_than as it's what it's really testing.
|
||||||
|
# Or more perversly, returning 0 on failure and 1 and success.
|
||||||
|
|
||||||
|
# bool is_older_than(reference, files/dirs to check)
|
||||||
|
#
|
||||||
|
# return 0 if any of the files/dirs are newer than
|
||||||
|
# the reference file
|
||||||
|
#
|
||||||
|
# EXAMPLE: if is_older_than a.out *.o ; then ...
|
||||||
|
ref_is_older_than() {
|
||||||
|
local x= ref="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
for x; do
|
||||||
|
[ "${x}" -nt "${ref}" ] && return 0
|
||||||
|
[ -d "${x}" ] && ref_is_older_than "${ref}" "${x}"/* && return 0
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
rm -rf "${TMPDIR}"
|
||||||
|
mkdir "${TMPDIR}"
|
||||||
|
|
||||||
|
do_test() {
|
||||||
|
local r1= r2=
|
||||||
|
|
||||||
|
ref_is_older_than "$@"
|
||||||
|
r1=$?
|
||||||
|
is_older_than "$@"
|
||||||
|
r2=$?
|
||||||
|
|
||||||
|
[ -n "${VERBOSE}" ] && echo "reference = $r1 | OpenRC = $r2"
|
||||||
|
[ $r1 = $r2 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_cmd() {
|
||||||
|
[ -n "${VERBOSE}" ] && echo "$@"
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_it() {
|
||||||
|
do_test "${TMPDIR}"/ref "${TMPDIR}"/dir1 "${TMPDIR}"/dir2 || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_cmd mkdir -p "${TMPDIR}"/dir1 "${TMPDIR}"/dir2
|
||||||
|
echo_cmd touch "${TMPDIR}"/dir1/f1 "${TMPDIR}"/dir1/f2 "${TMPDIR}"/dir1/f3 "${TMPDIR}"/dir2/f1 "${TMPDIR}"/dir2/f2 "${TMPDIR}"/dir2/f3
|
||||||
|
echo_cmd sleep 1
|
||||||
|
echo_cmd touch "${TMPDIR}"/ref
|
||||||
|
test_it
|
||||||
|
|
||||||
|
echo_cmd sleep 1
|
||||||
|
echo_cmd touch "${TMPDIR}"/dir1/f2
|
||||||
|
test_it
|
||||||
|
|
||||||
|
echo_cmd sleep 1
|
||||||
|
echo_cmd touch "${TMPDIR}"/ref
|
||||||
|
test_it
|
||||||
|
|
||||||
|
echo_cmd sleep 1
|
||||||
|
echo_cmd touch "${TMPDIR}"/dir2/f2
|
||||||
|
test_it
|
||||||
|
|
||||||
|
rm -rf "${TMPDIR}"
|
||||||
|
exit 0
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user