Compare commits
88 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 |
2
Makefile
2
Makefile
@@ -3,7 +3,7 @@
|
||||
# All rights reserved. Released under the 2-clause BSD license.
|
||||
|
||||
NAME= openrc
|
||||
VERSION= 0.2.5
|
||||
VERSION= 0.3.0
|
||||
PKG= ${NAME}-${VERSION}
|
||||
|
||||
SUBDIR= conf.d doc etc init.d man net sh src
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
DIR= ${CONFDIR}
|
||||
CONF= bootmisc fsck hostname local net urandom
|
||||
CONF= bootmisc fsck hostname local localmount net urandom
|
||||
|
||||
MK= ../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="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.
|
||||
#module_ieee1394_args="debug"
|
||||
#module_ieee1394_args_2_6_23_gentoo_r5="ieee1394 ohci1394"
|
||||
|
||||
@@ -569,12 +569,18 @@
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# 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
|
||||
#slaves_bond0="eth0 eth1 eth2"
|
||||
#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
|
||||
# ppp devices - we need to depend function on the bonded interfaces
|
||||
#rc_need_bond0="net.eth0 net.eth1"
|
||||
@@ -1010,7 +1016,7 @@
|
||||
|
||||
#postdown() {
|
||||
# # 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 ;)
|
||||
# [ "${IFACE}" != "lo" ] && ethtool -s "${IFACE}" wol g
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# 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
|
||||
# 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"
|
||||
|
||||
# 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.
|
||||
# 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
|
||||
# There variables are shared between many init scripts
|
||||
|
||||
@@ -88,7 +88,11 @@ start()
|
||||
for x in $(find /var/run ! -type d ! -name utmp \
|
||||
! -name random-seed ! -name dev.db \
|
||||
! -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
|
||||
# Do not remove pidfiles of already running daemons
|
||||
case "${x}" in
|
||||
|
||||
@@ -33,7 +33,7 @@ start()
|
||||
ewarn "Skipping fsck due to /fastboot"
|
||||
return 0
|
||||
fi
|
||||
if [ -e /forcefsck ]; then
|
||||
if [ -e /forcefsck ] || get_bootparam forcefsck; then
|
||||
fsck_opts="${fsck_opts} -f"
|
||||
check_extra="(check forced)"
|
||||
fi
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
. @SYSCONFDIR@/init.d/functions.sh
|
||||
. "${RC_LIBDIR}"/sh/rc-functions.sh
|
||||
[ -r @SYSCONFDIR@/conf.d/localmount ] && . @SYSCONFDIR@/conf.d/localmount
|
||||
[ -r @SYSCONFDIR@/rc.conf ] && . @SYSCONFDIR@/rc.conf
|
||||
|
||||
# Support LiveCD foo
|
||||
@@ -38,7 +39,11 @@ fi
|
||||
|
||||
# If $svcdir is still mounted, preserve it if we can
|
||||
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"
|
||||
[ "${RC_UNAME}" = "Linux" ] && f_opts="-c"
|
||||
if type fuser >/dev/null 2>&1; then
|
||||
@@ -75,13 +80,27 @@ if [ "${RC_UNAME}" = "Linux" ]; then
|
||||
# We need the do_unmount function
|
||||
. "${RC_LIBDIR}"/sh/rc-mount.sh
|
||||
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=
|
||||
for x in ${net_fs_list}; do
|
||||
fs="${fs}${fs:+|}${x}"
|
||||
done
|
||||
[ -n "${fs}" ] && fs="^(${fs})$"
|
||||
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
|
||||
eoutdent
|
||||
eend $?
|
||||
|
||||
@@ -74,8 +74,12 @@ start()
|
||||
fi
|
||||
|
||||
ebegin "Setting system clock using the hardware clock [${utc}]"
|
||||
if [ -e /proc/modules -a ! -e /dev/rtc ]; then
|
||||
modprobe -q rtc || modprobe -q genrtc
|
||||
local rtc=
|
||||
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
|
||||
|
||||
if [ -e /etc/adjtime ] && yesno ${clock_adjfile}; then
|
||||
|
||||
@@ -20,6 +20,10 @@ ipfw() {
|
||||
/sbin/ipfw -f -q "$@"
|
||||
}
|
||||
|
||||
have_ip6() {
|
||||
sysctl net.ipv6 2>/dev/null
|
||||
}
|
||||
|
||||
init() {
|
||||
# Load the kernel module
|
||||
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 ip from 127.0.0.0/8 to any
|
||||
|
||||
ipfw add pass ip6 from any to any via lo0
|
||||
ipfw add deny ip6 from any to ::1
|
||||
ipfw add deny ip6 from ::1 to any
|
||||
if have_ip6; then
|
||||
ipfw add pass ip6 from any to any via lo0
|
||||
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 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 :: 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 ff02::/16 proto ipv6-icmp
|
||||
fi
|
||||
}
|
||||
|
||||
start() {
|
||||
@@ -62,9 +68,11 @@ start() {
|
||||
ipfw add pass udp 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
|
||||
ipfw add pass udp from me6 to any keep-state
|
||||
ipfw add pass icmp from me6 to any keep-state
|
||||
if have_ip6; then
|
||||
ipfw add pass tcp from me6 to any setup 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.
|
||||
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.
|
||||
ipfw add pass icmp from any to any icmptype 3,4,11
|
||||
|
||||
# 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)
|
||||
ipfw add pass ip6 from any to any icmp6types 2,135,136 proto ipv6-icmp
|
||||
if have_ip6; then
|
||||
# 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)
|
||||
ipfw add pass ip6 from any to any icmp6types 2,135,136 proto ipv6-icmp
|
||||
fi
|
||||
|
||||
# Add permits for this workstations published services below
|
||||
# Only IPs and nets in firewall_allowservices is allowed in.
|
||||
|
||||
@@ -30,13 +30,13 @@ start()
|
||||
stop()
|
||||
{
|
||||
# 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
|
||||
OIFS=${IFS} SIFS=${IFS-y}
|
||||
IFS=$IFS:
|
||||
for x in ${no_umounts} ${RC_NO_UMOUNTS}; do
|
||||
no_umounts="${no_umounts}|${x}"
|
||||
no_umounts_r="${no_umounts_r}|${x}"
|
||||
done
|
||||
if [ "${SIFS}" = "y" ]; then
|
||||
IFS=$OIFS
|
||||
@@ -45,9 +45,9 @@ stop()
|
||||
fi
|
||||
|
||||
if [ "${RC_UNAME}" = "Linux" ]; then
|
||||
no_umounts="${no_umounts}|/proc|/proc/.*|/sys|/sys/.*"
|
||||
no_umounts_r="${no_umounts_r}|/proc|/proc/.*|/sys|/sys/.*"
|
||||
fi
|
||||
no_umounts="^(${no_umounts})$"
|
||||
no_umounts_r="^(${no_umounts_r})$"
|
||||
|
||||
# Flush all pending disk writes now
|
||||
sync; sync
|
||||
@@ -63,7 +63,7 @@ stop()
|
||||
# Umount loopback devices
|
||||
einfo "Unmounting loopback devices"
|
||||
eindent
|
||||
do_unmount "umount -d" --skip-point-regex "${no_umounts}" \
|
||||
do_unmount "umount -d" --skip-point-regex "${no_umounts_r}" \
|
||||
--node-regex "^/dev/loop"
|
||||
eoutdent
|
||||
|
||||
@@ -76,7 +76,7 @@ stop()
|
||||
fs="${fs}${fs:+|}${x}"
|
||||
done
|
||||
[ -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
|
||||
eoutdent
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ start()
|
||||
x=${KV#*.*.}
|
||||
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}" \
|
||||
${KV_MAJOR}.${KV_MINOR}.${KV_MICRO} \
|
||||
${KV_MAJOR}.${KV_MINOR} \
|
||||
@@ -34,17 +34,29 @@ start()
|
||||
[ -z "${list}" ] && list=${modules}
|
||||
|
||||
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}")
|
||||
for y in "${KV}" \
|
||||
${KV_MAJOR}.${KV_MINOR}.${KV_MICRO} \
|
||||
${KV_MAJOR}.${KV_MINOR} \
|
||||
; do
|
||||
eval args=\$module_${aa}_args_$(shell_var "${y}")
|
||||
[ -n "${args}" ] && break
|
||||
eval args=\$module_${xx}_args_$(shell_var "${y}")
|
||||
[ -n "${args}" ] && break
|
||||
done
|
||||
[ -z "${args}" ] && eval args=\$module_${aa}_args
|
||||
[ -z "${args}" ] && eval args=\$module_${xx}_args
|
||||
eval modprobe -q "${x}" "${args}"
|
||||
eval modprobe -q "${mpargs}" "${x}" "${args}"
|
||||
eend $? "Failed to load ${x}" && cnt=$((${cnt} + 1))
|
||||
done
|
||||
einfo "Autoloaded ${cnt} module(s)"
|
||||
|
||||
@@ -668,7 +668,7 @@ stop()
|
||||
if ! yesno ${IN_BACKGROUND} && \
|
||||
[ "${IFACE}" != "lo" -a "${IFACE}" != "lo0" ]; then
|
||||
eval module=\$ifdown_${IFVAR}
|
||||
module=${module:-YES}
|
||||
module=${module:-${ifdown:-YES}}
|
||||
yesno ${module} && _down 2>/dev/null
|
||||
fi
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ depend()
|
||||
config /etc/fstab
|
||||
need net ${pmap}
|
||||
use afc-client amd autofs openvpn
|
||||
use dns nfs nfsmount portmap rpcbind rpc.statd
|
||||
keyword nojail noopenvz noprefix novserver
|
||||
use dns nfs nfsmount portmap rpcbind rpc.statd rpc.lockd
|
||||
keyword nojail noprefix novserver
|
||||
}
|
||||
|
||||
start()
|
||||
|
||||
@@ -202,4 +202,4 @@ Rinse and repeat for the other verbose functions.
|
||||
.Sh SEE ALSO
|
||||
.Xr printf 3 ,
|
||||
.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 stdout 3
|
||||
.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-update 8
|
||||
.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-status 8
|
||||
.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-update 8
|
||||
.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 sh 1
|
||||
.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 runscript 8
|
||||
.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 queue 3
|
||||
.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 runscript 8
|
||||
.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 rc_stringlist_free 3
|
||||
.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 start-stop-daemon 8
|
||||
.Sh AUTHORS
|
||||
.An "Roy Marples" Aq roy@marples.name
|
||||
.An Roy Marples" <roy@marples.name>
|
||||
|
||||
@@ -85,4 +85,4 @@ itself.
|
||||
.Xr queue 3 ,
|
||||
.Xr strcmp 3
|
||||
.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
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd Mar 19, 2008
|
||||
.Dd September 19, 2008
|
||||
.Dt RUNSCRIPT 8 SMM
|
||||
.Os OpenRC
|
||||
.Sh NAME
|
||||
@@ -173,8 +173,9 @@ If
|
||||
does not equal 0 then output the string using
|
||||
.Ic eerror
|
||||
and !! in square brackets
|
||||
at the end of the line. Otherwise output ok in square brackets at the end of
|
||||
the line. The value of
|
||||
at the end of the line.
|
||||
Otherwise output ok in square brackets at the end of the line.
|
||||
The value of
|
||||
.Ar retval
|
||||
is returned.
|
||||
.It Ic ewend Ar retval Op Ar string
|
||||
@@ -193,6 +194,14 @@ output when the environment variable
|
||||
.Va EINFO_VERBOSE
|
||||
is true.
|
||||
.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 ...
|
||||
If
|
||||
.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 ...
|
||||
If
|
||||
.Ar file1
|
||||
is older than
|
||||
is newer than
|
||||
.Ar file2
|
||||
return 0, otherwise 1.
|
||||
If
|
||||
@@ -432,6 +441,16 @@ show()
|
||||
}
|
||||
|
||||
.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
|
||||
.Xr einfo 3 ,
|
||||
.Xr rc 8 ,
|
||||
@@ -442,4 +461,4 @@ show()
|
||||
.Xr start-stop-daemon 8 ,
|
||||
.Xr uname 1
|
||||
.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
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd Feb 24, 2008
|
||||
.Dd September 27, 2008
|
||||
.Dt START-STOP-DAEMON 8 SMM
|
||||
.Os OpenRC
|
||||
.Sh NAME
|
||||
@@ -44,6 +44,11 @@
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
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,
|
||||
.Nm
|
||||
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
|
||||
.Ar daemon
|
||||
we start or stop.
|
||||
If the
|
||||
.Ar daemon
|
||||
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
|
||||
If this option is not specified, then the first non option argument
|
||||
is used.
|
||||
.It Fl p , -pidfile Ar pidfile
|
||||
When starting, we expect the daemon to create a valid
|
||||
.Ar pidfile
|
||||
@@ -97,10 +94,17 @@ name here also.
|
||||
.It Fl t , -test
|
||||
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.
|
||||
.It Fl v , -verbose
|
||||
P
|
||||
Print the action(s) that are taken just before doing them.
|
||||
.El
|
||||
.Pp
|
||||
These options are only used for starting daemons:
|
||||
.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
|
||||
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
|
||||
@@ -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.
|
||||
.It Fl g , -group Ar 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
|
||||
Saves the pid of the daemon in the file specified by the
|
||||
.Fl p , -pidfile
|
||||
@@ -149,6 +155,12 @@ assumed.
|
||||
.Va SSD_NICELEVEL
|
||||
can also set the scheduling priority of the daemon, but the command line
|
||||
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
|
||||
.Nm
|
||||
uses
|
||||
@@ -163,6 +175,9 @@ to stop or signal.
|
||||
.Xr getopt 3 ,
|
||||
.Xr nice 2 ,
|
||||
.Xr rc_find_pids 3
|
||||
.Sh BUGS
|
||||
.Nm
|
||||
cannot stop an interperted daemon that no longer exists without a pidfile.
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
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
|
||||
OpenRC library (librc, -lrc) so other programs can make use of it.
|
||||
.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>
|
||||
# All rights reserved. Released under the 2-clause BSD license.
|
||||
|
||||
# Setup some good default CFLAGS
|
||||
CFLAGS?= -O2
|
||||
@@ -10,15 +9,25 @@ _CSTD_SH= if test -n "${CSTD}"; then echo "-std=${CSTD}"; else echo ""; fi
|
||||
_CSTD!= ${_CSTD_SH}
|
||||
CFLAGS+= ${_CSTD}$(shell ${_CSTD_SH})
|
||||
|
||||
# Try and use some good cc flags
|
||||
_CC_FLAGS= -pedantic -Wall -Wunused -Wimplicit -Wshadow -Wformat=2 \
|
||||
-Wmissing-declarations -Wno-missing-prototypes -Wwrite-strings \
|
||||
-Wbad-function-cast -Wnested-externs -Wcomment -Winline \
|
||||
-Wchar-subscripts -Wcast-align -Wno-format-nonliteral \
|
||||
-Wdeclaration-after-statement -Wsequence-point -Wextra
|
||||
_CC_FLAGS_SH= for f in ${_CC_FLAGS}; do \
|
||||
if ${CC} $$f -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \
|
||||
# Try and use some good cc flags if we're building from git
|
||||
# We don't use -pedantic as it will warn about our perfectly valid
|
||||
# use of %m in our logger.
|
||||
_CCFLAGS= -Wall -Wextra -Wimplicit -Wshadow -Wformat=2 \
|
||||
-Wmissing-prototypes -Wmissing-declarations \
|
||||
-Wmissing-noreturn -Wmissing-format-attribute \
|
||||
-Wnested-externs \
|
||||
-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 \
|
||||
done
|
||||
done;
|
||||
_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!= ${_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?
|
||||
_LD_DEBUG_SH= case "${DEBUG}" in "") echo "";; *) echo "-Wl,--rpath=../librc -Wl,--rpath=../libeinfo";; esac
|
||||
|
||||
@@ -8,6 +8,6 @@ CLEANFILES+= .depend
|
||||
IGNOREFILES+= .depend
|
||||
|
||||
.depend: ${SRCS}
|
||||
${CC} ${CFLAGS} -MM ${SRCS} > .depend
|
||||
${CC} ${CPPFLAGS} -MM ${SRCS} > .depend
|
||||
|
||||
depend: .depend
|
||||
|
||||
@@ -17,7 +17,7 @@ CLEANFILES+= ${OBJS} ${SOBJS} ${_LIBS} ${SHLIB_LINK}
|
||||
.SUFFIXES: .So
|
||||
|
||||
.c.So:
|
||||
${CC} ${PICFLAG} -DPIC ${CFLAGS} -c $< -o $@
|
||||
${CC} ${PICFLAG} -DPIC ${CPPFLAGS} ${CFLAGS} -c $< -o $@
|
||||
|
||||
all: depend ${_LIBS}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
LIBTERMCAP?= -lncurses
|
||||
CFLAGS+= -DHAVE_TERMCAP
|
||||
CPPFLAGS+= -DHAVE_TERMCAP
|
||||
LDADD+= ${LIBTERMCAP}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright 2008 Roy Marples <roy@marples.name>
|
||||
# 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
LIBPAM?= -lpam
|
||||
CFLAGS+= -DHAVE_PAM
|
||||
CPPFLAGS+= -DHAVE_PAM
|
||||
LDADD+= ${LIBPAM}
|
||||
|
||||
PAMDIR?= /etc/pam.d
|
||||
|
||||
@@ -24,6 +24,9 @@ CLEANFILES+= ${OBJS} ${PROG}
|
||||
|
||||
all: depend ${PROG}
|
||||
|
||||
.c.o:
|
||||
${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@
|
||||
|
||||
${PROG}: ${SCRIPTS} ${OBJS}
|
||||
${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
LIBTERMCAP?= -ltermcap
|
||||
CFLAGS+= -DHAVE_TERMCAP
|
||||
CPPFLAGS+= -DHAVE_TERMCAP
|
||||
LDADD+= ${LIBTERMCAP}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
bonding_depend()
|
||||
{
|
||||
before interface macchanger
|
||||
program /sbin/ifenslave
|
||||
}
|
||||
|
||||
_config_vars="$_config_vars slaves"
|
||||
@@ -16,7 +15,7 @@ _is_bond()
|
||||
|
||||
bonding_pre_start()
|
||||
{
|
||||
local s= slaves="$(_get_array "slaves_${IFVAR}")"
|
||||
local x= s= slaves="$(_get_array "slaves_${IFVAR}")"
|
||||
|
||||
[ -z "${slaves}" ] && return 0
|
||||
|
||||
@@ -40,6 +39,16 @@ bonding_pre_start()
|
||||
return 1
|
||||
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}"
|
||||
eindent
|
||||
einfo "${slaves}"
|
||||
@@ -53,7 +62,7 @@ bonding_pre_start()
|
||||
# Must force the slaves to a particular state before adding them
|
||||
for IFACE in ${slaves}; do
|
||||
_delete_addresses
|
||||
_up
|
||||
_down
|
||||
done
|
||||
)
|
||||
|
||||
@@ -62,7 +71,13 @@ bonding_pre_start()
|
||||
|
||||
# finally add in slaves
|
||||
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 $?
|
||||
|
||||
return 0 #important
|
||||
@@ -84,7 +99,13 @@ bonding_stop()
|
||||
eindent
|
||||
einfo "${slaves}"
|
||||
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
|
||||
(
|
||||
|
||||
@@ -16,12 +16,15 @@ _is_bridge()
|
||||
|
||||
bridge_pre_start()
|
||||
{
|
||||
local ports= brif= iface="${IFACE}" e= x=
|
||||
local brif= iface="${IFACE}" e= x=
|
||||
local ports="$(_get_array "bridge_${IFVAR}")"
|
||||
local opts="$(_get_array "brctl_${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
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ dhcpcd_start()
|
||||
{
|
||||
local args= opt= opts= pidfile="/var/run/dhcpcd-${IFACE}.pid" new=true
|
||||
eval args=\$dhcpcd_${IFVAR}
|
||||
[ -z "${args}" ] && args=${dhcpcd}
|
||||
|
||||
# Get our options
|
||||
eval opts=\$dhcp_${IFVAR}
|
||||
|
||||
@@ -54,7 +54,6 @@ ifwatchd_stop()
|
||||
ebegin "Stopping ifwatchd on" "${IFACE}"
|
||||
start-stop-daemon --stop --exec /usr/sbin/ifwatchd \
|
||||
-- -c "${RC_LIBDIR}/sh/ifwatchd-carrier.sh" \
|
||||
-n "${RC_LIBDIR}/sh/ifwatchd-nocarrier.sh" "${IFACE}" \
|
||||
&& return 0
|
||||
-n "${RC_LIBDIR}/sh/ifwatchd-nocarrier.sh" "${IFACE}"
|
||||
eend $?
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ iwconfig_scan()
|
||||
[ -z "${a}" ] && break
|
||||
eval b=\$QUALITY_${k}
|
||||
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 ${x}_${i}=\$${x}_${k}
|
||||
eval ${x}_${k}=\$t
|
||||
@@ -457,7 +457,7 @@ iwconfig_scan()
|
||||
local u=${k}
|
||||
# We need to split this into two tests, otherwise bash errors
|
||||
[ -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
|
||||
k=$((${k} + 1))
|
||||
done
|
||||
@@ -503,7 +503,7 @@ iwconfig_scan()
|
||||
for x; do
|
||||
if [ "${x}" = "${s}" ]; then
|
||||
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
|
||||
done
|
||||
i=$((${i} + 1))
|
||||
@@ -601,10 +601,8 @@ iwconfig_connect_not_preferred()
|
||||
|
||||
iwconfig_defaults()
|
||||
{
|
||||
local x=
|
||||
for x in txpower rate rts frag; do
|
||||
iwconfig "${IFACE}" "${x}" auto 2>/dev/null
|
||||
done
|
||||
# Turn on the radio
|
||||
iwconfig "${IFACE}" txpower on 2>/dev/null
|
||||
|
||||
# Release the AP forced
|
||||
# Must do ap and then ssid otherwise scanning borks
|
||||
@@ -739,7 +737,7 @@ iwconfig_pre_start()
|
||||
# which reports NOT READY!
|
||||
x="$(iwconfig_get_type)"
|
||||
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
|
||||
fi
|
||||
|
||||
|
||||
2
sh/.gitignore
vendored
2
sh/.gitignore
vendored
@@ -3,6 +3,8 @@ gendepends.sh
|
||||
net.sh
|
||||
rc-functions.sh
|
||||
runscript.sh
|
||||
init-common-post.sh
|
||||
init-early.sh
|
||||
init.sh
|
||||
ifwatchd-carrier.sh
|
||||
ifwatchd-nocarrier.sh
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
DIR= ${PREFIX}/${RC_LIB}/sh
|
||||
SRCS= functions.sh.in gendepends.sh.in \
|
||||
SRCS= functions.sh.in gendepends.sh.in init-common-post.sh.in \
|
||||
rc-functions.sh.in runscript.sh.in
|
||||
INC= init-common-post.sh rc-mount.sh functions.sh rc-functions.sh
|
||||
BIN= gendepends.sh init.sh runscript.sh
|
||||
|
||||
@@ -6,9 +6,10 @@ retval=0
|
||||
# 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
|
||||
# the old service state data
|
||||
RC_SVCDIR=${RC_SVCDIR:-/@LIB@/rc/init.d}
|
||||
if [ "${RC_SVCDIR}" != "/" ] && mkdir "${RC_SVCDIR}/.test.$$" 2>/dev/null; then
|
||||
rmdir "${RC_SVCDIR}/.test.$$"
|
||||
for x in ${RC_SVCDIR:-/@LIB@/rc/init.d}/*; do
|
||||
for x in ${RC_SVCDIR}/*; do
|
||||
[ -e "${x}" ] || continue
|
||||
case ${x##*/} in
|
||||
depconfig|deptree|ksoftlevel|rc.log);;
|
||||
@@ -108,8 +108,7 @@ if [ -r /sbin/livecd-functions.sh ]; then
|
||||
fi
|
||||
|
||||
if [ "${RC_UNAME}" != "GNU/kFreeBSD" \
|
||||
-a "${RC_SYS}" != "VSERVER" \
|
||||
-a "${RC_SYS}" != "OPENVZ" ]
|
||||
-a "${RC_SYS}" != "VSERVER" ];
|
||||
then
|
||||
if grep -Eq "[[:space:]]+sysfs$" /proc/filesystems; then
|
||||
if [ -d /sys ]; then
|
||||
@@ -126,10 +125,14 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Default OpenVZ to static devices
|
||||
if [ "${RC_SYS}" = "OPENVZ" ]; then
|
||||
rc_devices=${rc_devices:-static}
|
||||
fi
|
||||
|
||||
# Try to figure out how the user wants /dev handled
|
||||
if [ "${rc_devices}" = "static" \
|
||||
-o "${RC_SYS}" = "VSERVER" \
|
||||
-o "${RC_SYS}" = "OPENVZ" \
|
||||
-o "${RC_UNAME}" = "GNU/kFreeBSD" ]
|
||||
then
|
||||
ebegin "Using existing device nodes in /dev"
|
||||
|
||||
@@ -58,6 +58,7 @@ get_bootparam()
|
||||
|
||||
set -- $(cat /proc/cmdline)
|
||||
while [ -n "$1" ]; do
|
||||
[ "$1" = "${match}" ] && return 0
|
||||
case "$1" in
|
||||
gentoo=*)
|
||||
local params="${1##*=}"
|
||||
|
||||
@@ -52,26 +52,20 @@
|
||||
|
||||
#define ERRX fprintf (stderr, "out of memory\n"); exit (1)
|
||||
|
||||
#define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
|
||||
|
||||
#ifdef lint
|
||||
# define _unused
|
||||
#endif
|
||||
#if __GNUC__ > 2 || defined(__INTEL_COMPILER)
|
||||
# define _dead __attribute__((__noreturn__))
|
||||
# define _unused __attribute__((__unused__))
|
||||
#else
|
||||
# define _dead
|
||||
# define _unused
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||
if (!TAILQ_EMPTY(head2)) { \
|
||||
@@ -83,13 +77,6 @@
|
||||
} while (0)
|
||||
#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
|
||||
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
@@ -174,4 +161,5 @@ _unused static const char *basename_c(const char *path)
|
||||
return (path);
|
||||
}
|
||||
|
||||
int parse_mode(mode_t *, char *);
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,7 @@ SRCS= libeinfo.c
|
||||
INCS= einfo.h
|
||||
VERSION_MAP= einfo.map
|
||||
|
||||
CFLAGS+= -I../includes
|
||||
CPPFLAGS+= -I../includes
|
||||
|
||||
MK= ../../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 */
|
||||
#ifdef __GLIBC__
|
||||
# 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;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
size_t n = size;
|
||||
|
||||
if (n && --n)
|
||||
do {
|
||||
if (! (*dst++ = *src++))
|
||||
if (!(*dst++ = *src++))
|
||||
break;
|
||||
} while (--n);
|
||||
|
||||
if (! n) {
|
||||
if (!n) {
|
||||
if (size)
|
||||
*dst = '\0';
|
||||
while (*src++);
|
||||
@@ -248,9 +250,10 @@ static size_t strlcpy(char *dst, const char *src, size_t size)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static bool yesno(const char *value)
|
||||
static bool
|
||||
yesno(const char *value)
|
||||
{
|
||||
if (! value) {
|
||||
if (!value) {
|
||||
errno = ENOENT;
|
||||
return false;
|
||||
}
|
||||
@@ -272,7 +275,8 @@ static bool yesno(const char *value)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool noyes(const char *value)
|
||||
static bool
|
||||
noyes(const char *value)
|
||||
{
|
||||
int serrno = errno;
|
||||
bool retval;
|
||||
@@ -280,26 +284,29 @@ static bool noyes(const char *value)
|
||||
errno = 0;
|
||||
retval = yesno(value);
|
||||
if (errno == 0) {
|
||||
retval = ! retval;
|
||||
retval = !retval;
|
||||
errno = serrno;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool is_quiet(void)
|
||||
static bool
|
||||
is_quiet(void)
|
||||
{
|
||||
return yesno(getenv("EINFO_QUIET"));
|
||||
}
|
||||
|
||||
static bool is_verbose(void)
|
||||
static bool
|
||||
is_verbose(void)
|
||||
{
|
||||
return yesno(getenv ("EINFO_VERBOSE"));
|
||||
}
|
||||
|
||||
/* Fake tgoto call - very crapy, but works for our needs */
|
||||
#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];
|
||||
|
||||
@@ -308,22 +315,22 @@ static char *tgoto(const char *cap, int a, int b)
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool colour_terminal(FILE * __EINFO_RESTRICT f)
|
||||
static bool
|
||||
colour_terminal(FILE * __EINFO_RESTRICT f)
|
||||
{
|
||||
static int in_colour = -1;
|
||||
char *e;
|
||||
char *e, *ee, *end, *d, *p;
|
||||
int c;
|
||||
const char *_af = NULL;
|
||||
const char *_ce = NULL;
|
||||
const char *_ch = NULL;
|
||||
const char *_md = NULL;
|
||||
const char *_me = NULL;
|
||||
const char *_up = NULL;
|
||||
const char *_af = NULL, *_ce = NULL, *_ch = NULL;
|
||||
const char *_md = NULL, *_me = NULL, *_up = NULL;
|
||||
const char *bold;
|
||||
char tmp[100];
|
||||
char *p;
|
||||
unsigned int i = 0;
|
||||
#ifdef HAVE_TERMCAP
|
||||
char *bp;
|
||||
#endif
|
||||
|
||||
if (f && ! isatty(fileno(f)))
|
||||
if (f && !isatty(fileno(f)))
|
||||
return false;
|
||||
|
||||
if (noyes(getenv("EINFO_COLOR")))
|
||||
@@ -335,26 +342,23 @@ static bool colour_terminal(FILE * __EINFO_RESTRICT f)
|
||||
return true;
|
||||
|
||||
term_is_cons25 = false;
|
||||
|
||||
if (! term) {
|
||||
if (!term) {
|
||||
term = getenv("TERM");
|
||||
if (! term)
|
||||
if (!term)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcmp(term, "cons25") == 0)
|
||||
term_is_cons25 = true;
|
||||
|
||||
#ifdef HAVE_TERMCAP
|
||||
/* Check termcap to see if we can do colour or not */
|
||||
if (tgetent(termcapbuf, term) == 1) {
|
||||
char *bp = tcapbuf;
|
||||
|
||||
bp = tcapbuf;
|
||||
_af = tgetstr("AF", &bp);
|
||||
_ce = tgetstr("ce", &bp);
|
||||
_ch = tgetstr("ch", &bp);
|
||||
/* Our ch use also works with RI .... for now */
|
||||
if (! _ch)
|
||||
if (!_ch)
|
||||
_ch = tgetstr("RI", &bp);
|
||||
_md = tgetstr("md", &bp);
|
||||
_me = tgetstr("me", &bp);
|
||||
@@ -377,29 +381,29 @@ static bool colour_terminal(FILE * __EINFO_RESTRICT f)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (! _af)
|
||||
if (!_af)
|
||||
_af = AF;
|
||||
if (! _ce)
|
||||
if (!_ce)
|
||||
_ce = CE;
|
||||
if (! _ch)
|
||||
if (!_ch)
|
||||
_ch = CH;
|
||||
if (! _md)
|
||||
if (!_md)
|
||||
_md = MD;
|
||||
if (! _me)
|
||||
if (!_me)
|
||||
_me = ME;
|
||||
if (! _up)
|
||||
if (!_up)
|
||||
_up = UP;
|
||||
#ifdef HAVE_TERMCAP
|
||||
}
|
||||
|
||||
if (! _af || ! _ce || ! _me || !_md || ! _up) {
|
||||
if (!_af || !_ce || !_me || !_md || !_up) {
|
||||
in_colour = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Many termcap databases don't have ch or RI even though they
|
||||
* do work */
|
||||
if (! _ch)
|
||||
if (!_ch)
|
||||
_ch = CH;
|
||||
#endif
|
||||
|
||||
@@ -407,33 +411,28 @@ static bool colour_terminal(FILE * __EINFO_RESTRICT f)
|
||||
p = ebuffer;
|
||||
for (i = 0; i < sizeof(ecolors) / sizeof(ecolors[0]); i++) {
|
||||
tmp[0] = '\0';
|
||||
|
||||
if (ecolors[i].name) {
|
||||
const char *bold = _md;
|
||||
bold = _md;
|
||||
c = ecolors[i].def;
|
||||
|
||||
/* See if the user wants to override the colour
|
||||
* We use a :col;bold: format like 2;1: for bold green
|
||||
* and 1;0: for a normal red */
|
||||
if ((e = getenv("EINFO_COLOR"))) {
|
||||
char *ee = strstr(e, ecolors[i].name);
|
||||
|
||||
ee = strstr(e, ecolors[i].name);
|
||||
if (ee)
|
||||
ee += strlen(ecolors[i].name);
|
||||
|
||||
if (ee && *ee == '=') {
|
||||
char *d = strdup(ee + 1);
|
||||
d = strdup(ee + 1);
|
||||
if (d) {
|
||||
char *end = strchr(d, ':');
|
||||
end = strchr(d, ':');
|
||||
if (end)
|
||||
*end = '\0';
|
||||
|
||||
c = atoi(d);
|
||||
|
||||
end = strchr(d, ';');
|
||||
if (end && *++end == '0')
|
||||
bold = _me;
|
||||
|
||||
free(d);
|
||||
}
|
||||
}
|
||||
@@ -460,7 +459,8 @@ static bool colour_terminal(FILE * __EINFO_RESTRICT f)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int get_term_columns(FILE * __EINFO_RESTRICT stream)
|
||||
static int
|
||||
get_term_columns(FILE * __EINFO_RESTRICT stream)
|
||||
{
|
||||
struct winsize ws;
|
||||
char *env = getenv("COLUMNS");
|
||||
@@ -469,7 +469,7 @@ static int get_term_columns(FILE * __EINFO_RESTRICT stream)
|
||||
|
||||
if (env) {
|
||||
i = strtoimax(env, &p, 10);
|
||||
if (! *p)
|
||||
if (!*p)
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -479,13 +479,15 @@ static int get_term_columns(FILE * __EINFO_RESTRICT stream)
|
||||
return DEFAULT_COLS;
|
||||
}
|
||||
|
||||
void eprefix(const char *__EINFO_RESTRICT prefix)
|
||||
void
|
||||
eprefix(const char *__EINFO_RESTRICT prefix)
|
||||
{
|
||||
_eprefix = prefix;
|
||||
}
|
||||
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");
|
||||
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;
|
||||
|
||||
@@ -510,7 +513,8 @@ void elog(int level, const char *__EINFO_RESTRICT fmt, ...)
|
||||
}
|
||||
hidden_def(elog)
|
||||
|
||||
static int _eindent(FILE * __EINFO_RESTRICT stream)
|
||||
static int
|
||||
_eindent(FILE * __EINFO_RESTRICT stream)
|
||||
{
|
||||
char *env = getenv("EINFO_INDENT");
|
||||
int amount = 0;
|
||||
@@ -525,7 +529,7 @@ static int _eindent(FILE * __EINFO_RESTRICT stream)
|
||||
amount = INDENT_MAX;
|
||||
|
||||
if (amount > 0)
|
||||
memset(indent, ' ', (size_t) amount);
|
||||
memset(indent, ' ', (size_t)amount);
|
||||
}
|
||||
|
||||
/* Terminate it */
|
||||
@@ -533,32 +537,32 @@ static int _eindent(FILE * __EINFO_RESTRICT stream)
|
||||
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;
|
||||
|
||||
if (! colour_terminal(f))
|
||||
if (!colour_terminal(f))
|
||||
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)
|
||||
return ecolors_str[i];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
hidden_def(ecolor)
|
||||
|
||||
const char *ecolor(ECOLOR color)
|
||||
const char *
|
||||
ecolor(ECOLOR color)
|
||||
{
|
||||
FILE *f = stdout;
|
||||
|
||||
/* Try and guess a valid tty */
|
||||
if (! isatty(fileno(f))) {
|
||||
if (!isatty(fileno(f))) {
|
||||
f = stderr;
|
||||
if (! isatty(fileno(f))) {
|
||||
if (!isatty(fileno(f))) {
|
||||
f = stdin;
|
||||
if (! isatty(fileno(f)))
|
||||
if (!isatty(fileno(f)))
|
||||
f = NULL;
|
||||
}
|
||||
}
|
||||
@@ -571,87 +575,69 @@ const char *ecolor(ECOLOR color)
|
||||
setenv("EINFO_LASTCMD", _cmd, 1); \
|
||||
}
|
||||
|
||||
#define EINFOVN(_file, _color) \
|
||||
{ \
|
||||
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
|
||||
_einfo(FILE *f, ECOLOR color, const char *__EINFO_RESTRICT fmt, va_list va)
|
||||
|
||||
static int _einfovn(const char *__EINFO_RESTRICT fmt, va_list ap)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static int _ewarnvn(const char *__EINFO_RESTRICT fmt, va_list ap)
|
||||
{
|
||||
int retval = 0;
|
||||
#define _einfovn(fmt, ap) _einfo(stdout, ECOLOR_GOOD, fmt, ap)
|
||||
#define _ewarnvn(fmt, ap) _einfo(stderr, ECOLOR_WARN, fmt, ap)
|
||||
#define _eerrorvn(fmt, ap) _einfo(stderr, ECOLOR_BAD, fmt, ap)
|
||||
|
||||
EINFOVN(stderr, ECOLOR_WARN);
|
||||
return retval;
|
||||
}
|
||||
|
||||
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
|
||||
einfon(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt || is_quiet())
|
||||
if (!fmt || is_quiet())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
retval = _einfovn(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("einfon");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(einfon)
|
||||
|
||||
int ewarnn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
ewarnn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt || is_quiet())
|
||||
if (!fmt || is_quiet())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
retval = _ewarnvn(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("ewarnn");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(ewarnn)
|
||||
|
||||
int eerrorn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
eerrorn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
@@ -659,58 +645,53 @@ int eerrorn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
va_start(ap, fmt);
|
||||
retval = _eerrorvn(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("errorn");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(eerrorn)
|
||||
|
||||
int einfo(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
einfo(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt || is_quiet())
|
||||
if (!fmt || is_quiet())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
retval = _einfovn(fmt, ap);
|
||||
retval += printf("\n");
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("einfo");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(einfo)
|
||||
|
||||
int ewarn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
ewarn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt || is_quiet())
|
||||
if (!fmt || is_quiet())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
elogv(LOG_WARNING, fmt, ap);
|
||||
retval = _ewarnvn(fmt, ap);
|
||||
retval += fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("ewarn");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(ewarn)
|
||||
|
||||
void ewarnx(const char *__EINFO_RESTRICT fmt, ...)
|
||||
void
|
||||
ewarnx(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (fmt && ! is_quiet()) {
|
||||
if (fmt && !is_quiet()) {
|
||||
va_start(ap, fmt);
|
||||
elogv(LOG_WARNING, fmt, ap);
|
||||
retval = _ewarnvn(fmt, ap);
|
||||
@@ -721,27 +702,26 @@ void ewarnx(const char *__EINFO_RESTRICT fmt, ...)
|
||||
}
|
||||
hidden_def(ewarnx)
|
||||
|
||||
int eerror(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
eerror(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt)
|
||||
if (!fmt)
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
elogv(LOG_ERR, fmt, ap);
|
||||
retval = _eerrorvn(fmt, ap);
|
||||
va_end(ap);
|
||||
retval += fprintf(stderr, "\n");
|
||||
|
||||
LASTCMD("eerror");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(eerror)
|
||||
|
||||
void eerrorx(const char *__EINFO_RESTRICT fmt, ...)
|
||||
void
|
||||
eerrorx(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -752,46 +732,43 @@ void eerrorx(const char *__EINFO_RESTRICT fmt, ...)
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
hidden_def(eerrorx)
|
||||
|
||||
int ebegin(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
ebegin(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt || is_quiet())
|
||||
if (!fmt || is_quiet())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
retval = _einfovn(fmt, ap);
|
||||
va_end(ap);
|
||||
retval += printf(" ...");
|
||||
if (colour_terminal(stdout))
|
||||
retval += printf("\n");
|
||||
|
||||
LASTCMD("ebegin");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(ebegin)
|
||||
|
||||
static void _eend(FILE * __EINFO_RESTRICT fp, int col, ECOLOR color,
|
||||
const char *msg)
|
||||
static void
|
||||
_eend(FILE * __EINFO_RESTRICT fp, int col, ECOLOR color, const char *msg)
|
||||
{
|
||||
int i;
|
||||
int cols;
|
||||
|
||||
if (! msg)
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
cols = get_term_columns(fp) - (strlen(msg) + 3);
|
||||
|
||||
/* cons25 is special - we need to remove one char, otherwise things
|
||||
* do not align properly at all. */
|
||||
if (! term) {
|
||||
if (!term) {
|
||||
term = getenv("TERM");
|
||||
if (term && strcmp(term, "cons25") == 0)
|
||||
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;
|
||||
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");
|
||||
va_end(apc);
|
||||
}
|
||||
|
||||
_eend(fp, col,
|
||||
retval == 0 ? ECOLOR_GOOD : ECOLOR_BAD,
|
||||
retval == 0 ? OK : NOT_OK);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int eend(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
eend(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (is_quiet())
|
||||
return retval;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_do_eend("eend", retval, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("eend");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(eend)
|
||||
|
||||
int ewend(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
ewend(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (is_quiet())
|
||||
return retval;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_do_eend("ewend", retval, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("ewend");
|
||||
|
||||
return retval;
|
||||
}
|
||||
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);
|
||||
}
|
||||
hidden_def(ebracket)
|
||||
|
||||
void eindent(void)
|
||||
void
|
||||
eindent(void)
|
||||
{
|
||||
char *env = getenv("EINFO_INDENT");
|
||||
int amount = 0;
|
||||
@@ -891,11 +866,9 @@ void eindent(void)
|
||||
if (errno != 0)
|
||||
amount = 0;
|
||||
}
|
||||
|
||||
amount += INDENT_WIDTH;
|
||||
if (amount > INDENT_MAX)
|
||||
amount = INDENT_MAX;
|
||||
|
||||
snprintf(num, 10, "%08d", amount);
|
||||
setenv("EINFO_INDENT", num, 1);
|
||||
}
|
||||
@@ -908,16 +881,14 @@ void eoutdent(void)
|
||||
char num[10];
|
||||
int serrno = errno;
|
||||
|
||||
if (! env)
|
||||
if (!env)
|
||||
return;
|
||||
|
||||
errno = 0;
|
||||
amount = strtoimax(env, NULL, 0);
|
||||
if (errno != 0)
|
||||
amount = 0;
|
||||
else
|
||||
amount -= INDENT_WIDTH;
|
||||
|
||||
if (amount <= 0)
|
||||
unsetenv("EINFO_INDENT");
|
||||
else {
|
||||
@@ -928,86 +899,79 @@ void eoutdent(void)
|
||||
}
|
||||
hidden_def(eoutdent)
|
||||
|
||||
int einfovn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
einfovn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt || ! is_verbose())
|
||||
if (!fmt || !is_verbose())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
retval = _einfovn(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("einfovn");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(einfovn)
|
||||
|
||||
int ewarnvn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
ewarnvn(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt || ! is_verbose())
|
||||
if (!fmt || !is_verbose())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
retval = _ewarnvn(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("ewarnvn");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(ewarnvn)
|
||||
|
||||
int einfov(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
einfov(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt || ! is_verbose())
|
||||
if (!fmt || !is_verbose())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
retval = _einfovn(fmt, ap);
|
||||
retval += printf("\n");
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("einfov");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(einfov)
|
||||
|
||||
int ewarnv(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
ewarnv(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt || ! is_verbose())
|
||||
if (!fmt || !is_verbose())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
retval = _ewarnvn(fmt, ap);
|
||||
retval += printf("\n");
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("ewarnv");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(ewarnv)
|
||||
|
||||
int ebeginv(const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
ebeginv(const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
if (! fmt || ! is_verbose())
|
||||
if (!fmt || !is_verbose())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
@@ -1016,55 +980,51 @@ int ebeginv(const char *__EINFO_RESTRICT fmt, ...)
|
||||
if (colour_terminal(stdout))
|
||||
retval += printf("\n");
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("ebeginv");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(ebeginv)
|
||||
|
||||
int eendv(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
eendv(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (! is_verbose())
|
||||
if (!is_verbose())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_do_eend("eendv", retval, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("eendv");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(eendv)
|
||||
|
||||
int ewendv(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||
int
|
||||
ewendv(int retval, const char *__EINFO_RESTRICT fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (! is_verbose())
|
||||
if (!is_verbose())
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_do_eend("ewendv", retval, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
LASTCMD("ewendv");
|
||||
|
||||
return retval;
|
||||
}
|
||||
hidden_def(ewendv)
|
||||
|
||||
void eindentv(void)
|
||||
void
|
||||
eindentv(void)
|
||||
{
|
||||
if (is_verbose())
|
||||
eindent ();
|
||||
eindent();
|
||||
}
|
||||
hidden_def(eindentv)
|
||||
|
||||
void eoutdentv(void)
|
||||
void
|
||||
eoutdentv(void)
|
||||
{
|
||||
if (is_verbose())
|
||||
eoutdent();
|
||||
|
||||
@@ -7,7 +7,7 @@ VERSION_MAP= rc.map
|
||||
|
||||
LDADD+= ${LIBKVM}
|
||||
|
||||
CFLAGS+= -I../includes
|
||||
CPPFLAGS+= -I../includes
|
||||
|
||||
MK= ../../mk
|
||||
include ${MK}/lib.mk
|
||||
|
||||
@@ -40,11 +40,11 @@ static size_t strlcpy(char *dst, const char *src, size_t size)
|
||||
|
||||
if (n && --n)
|
||||
do {
|
||||
if (! (*dst++ = *src++))
|
||||
if (!(*dst++ = *src++))
|
||||
break;
|
||||
} while (--n);
|
||||
|
||||
if (! n) {
|
||||
if (!n) {
|
||||
if (size)
|
||||
*dst = '\0';
|
||||
while (*src++);
|
||||
@@ -57,21 +57,22 @@ static size_t strlcpy(char *dst, const char *src, size_t size)
|
||||
|
||||
#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];
|
||||
FILE *fp;
|
||||
int c;
|
||||
bool retval = false;
|
||||
|
||||
exec = basename_c(exec);
|
||||
snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
|
||||
if ((fp = fopen(buffer, "r"))) {
|
||||
while ((c = getc(fp)) != EOF && c != '(')
|
||||
;
|
||||
if (c == '(') {
|
||||
while ((c = getc(fp)) != EOF && c == *cmd)
|
||||
cmd++;
|
||||
if (c == ')' && *cmd == '\0')
|
||||
while ((c = getc(fp)) != EOF && c == *exec)
|
||||
exec++;
|
||||
if (c == ')' && *exec == '\0')
|
||||
retval = true;
|
||||
}
|
||||
fclose(fp);
|
||||
@@ -79,7 +80,7 @@ static bool pid_is_cmd(pid_t pid, const char *cmd)
|
||||
return retval;
|
||||
}
|
||||
|
||||
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];
|
||||
int fd;
|
||||
@@ -108,7 +109,7 @@ static bool pid_is_exec(pid_t pid, const char *const *argv)
|
||||
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)
|
||||
{
|
||||
DIR *procdir;
|
||||
@@ -143,27 +144,21 @@ RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
||||
while ((entry = readdir(procdir)) != NULL) {
|
||||
if (sscanf(entry->d_name, "%d", &p) != 1)
|
||||
continue;
|
||||
|
||||
if (runscript_pid != 0 && runscript_pid == p)
|
||||
continue;
|
||||
|
||||
if (pid != 0 && pid != p)
|
||||
continue;
|
||||
|
||||
if (uid) {
|
||||
snprintf(buffer, sizeof(buffer), "/proc/%d", p);
|
||||
if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cmd && ! pid_is_cmd(p, cmd))
|
||||
if (exec && !pid_is_exec(p, exec))
|
||||
continue;
|
||||
|
||||
if (argv && ! cmd && !
|
||||
pid_is_exec(p, (const char *const *)argv))
|
||||
if (argv &&
|
||||
!pid_is_argv(p, (const char *const *)argv))
|
||||
continue;
|
||||
|
||||
if (! pids) {
|
||||
if (!pids) {
|
||||
pids = xmalloc(sizeof(*pids));
|
||||
LIST_INIT(pids);
|
||||
}
|
||||
@@ -172,7 +167,6 @@ RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
||||
LIST_INSERT_HEAD(pids, pi, entries);
|
||||
}
|
||||
closedir(procdir);
|
||||
|
||||
return pids;
|
||||
}
|
||||
librc_hidden_def(rc_find_pids)
|
||||
@@ -201,7 +195,7 @@ librc_hidden_def(rc_find_pids)
|
||||
# define _KVM_FLAGS O_RDONLY
|
||||
# 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)
|
||||
{
|
||||
static kvm_t *kd = NULL;
|
||||
@@ -235,39 +229,34 @@ RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (exec)
|
||||
exec = basename_c(exec);
|
||||
for (i = 0; i < processes; i++) {
|
||||
p = _GET_KINFO_PID(kp[i]);
|
||||
if (pid != 0 && pid != p)
|
||||
continue;
|
||||
|
||||
if (uid != 0 && uid != _GET_KINFO_UID(kp[i]))
|
||||
continue;
|
||||
|
||||
if (cmd) {
|
||||
if (! _GET_KINFO_COMM(kp[i]) ||
|
||||
strcmp(cmd, _GET_KINFO_COMM(kp[i])) != 0)
|
||||
if (exec) {
|
||||
if (!_GET_KINFO_COMM(kp[i]) ||
|
||||
strcmp(exec, _GET_KINFO_COMM(kp[i])) != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv && *argv && ! cmd) {
|
||||
if (argv && *argv) {
|
||||
pargv = _KVM_GETARGV(kd, &kp[i], pargc);
|
||||
if (! pargv || ! *pargv)
|
||||
if (!pargv || !*pargv)
|
||||
continue;
|
||||
|
||||
arg = argv;
|
||||
match = 1;
|
||||
|
||||
while (*arg && *pargv)
|
||||
if (strcmp(*arg++, *pargv++) != 0) {
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (! match)
|
||||
if (!match)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! pids) {
|
||||
if (!pids) {
|
||||
pids = xmalloc(sizeof(*pids));
|
||||
LIST_INIT(pids);
|
||||
}
|
||||
@@ -297,7 +286,7 @@ static bool _match_daemon(const char *path, const char *file,
|
||||
snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
|
||||
fp = fopen(ffile, "r");
|
||||
|
||||
if (! fp)
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
while ((rc_getline(&line, &len, fp))) {
|
||||
@@ -306,7 +295,7 @@ static bool _match_daemon(const char *path, const char *file,
|
||||
TAILQ_REMOVE(match, m, entries);
|
||||
break;
|
||||
}
|
||||
if (! TAILQ_FIRST(match))
|
||||
if (!TAILQ_FIRST(match))
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
@@ -316,14 +305,22 @@ static bool _match_daemon(const char *path, const char *file,
|
||||
return true;
|
||||
}
|
||||
|
||||
static RC_STRINGLIST *_match_list(const char* const* argv,
|
||||
const char *name, const char *pidfile)
|
||||
static RC_STRINGLIST *_match_list(const char *exec, const char* const* argv,
|
||||
const char *pidfile)
|
||||
{
|
||||
RC_STRINGLIST *match = rc_stringlist_new();
|
||||
int i = 0;
|
||||
size_t l;
|
||||
char *m;
|
||||
|
||||
if (exec) {
|
||||
l = strlen(exec) + 6;
|
||||
m = xmalloc(sizeof(char) * l);
|
||||
snprintf(m, l, "exec=%s", exec);
|
||||
rc_stringlist_add(match, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
while (argv && argv[i]) {
|
||||
l = strlen(*argv) + strlen("argv_=") + 16;
|
||||
m = xmalloc(sizeof(char) * l);
|
||||
@@ -332,14 +329,6 @@ static RC_STRINGLIST *_match_list(const char* const* argv,
|
||||
free(m);
|
||||
}
|
||||
|
||||
if (name) {
|
||||
l = strlen(name) + 6;
|
||||
m = xmalloc(sizeof (char) * l);
|
||||
snprintf(m, l, "name=%s", name);
|
||||
rc_stringlist_add(match, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
if (pidfile) {
|
||||
l = strlen(pidfile) + 9;
|
||||
m = xmalloc(sizeof (char) * l);
|
||||
@@ -351,8 +340,9 @@ static RC_STRINGLIST *_match_list(const char* const* argv,
|
||||
return match;
|
||||
}
|
||||
|
||||
bool rc_service_daemon_set(const char *service, const char *const *argv,
|
||||
const char *name, const char *pidfile, bool started)
|
||||
bool rc_service_daemon_set(const char *service, const char *exec,
|
||||
const char *const *argv,
|
||||
const char *pidfile, bool started)
|
||||
{
|
||||
char dirpath[PATH_MAX];
|
||||
char file[PATH_MAX];
|
||||
@@ -365,7 +355,7 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
||||
int i = 0;
|
||||
FILE *fp;
|
||||
|
||||
if (!(argv && *argv) && ! name && ! pidfile) {
|
||||
if (!exec && !pidfile) {
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
@@ -375,7 +365,7 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
||||
|
||||
/* Regardless, erase any existing daemon info */
|
||||
if ((dp = opendir(dirpath))) {
|
||||
match = _match_list(argv, name, pidfile);
|
||||
match = _match_list(exec, argv, pidfile);
|
||||
while ((d = readdir(dp))) {
|
||||
if (d->d_name[0] == '.')
|
||||
continue;
|
||||
@@ -384,7 +374,7 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
||||
dirpath, d->d_name);
|
||||
nfiles++;
|
||||
|
||||
if (! *oldfile) {
|
||||
if (!*oldfile) {
|
||||
if (_match_daemon(dirpath, d->d_name, match)) {
|
||||
unlink(file);
|
||||
strlcpy(oldfile, file, sizeof(oldfile));
|
||||
@@ -405,13 +395,13 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
||||
snprintf(file, sizeof(file), "%s/%03d",
|
||||
dirpath, nfiles + 1);
|
||||
if ((fp = fopen(file, "w"))) {
|
||||
fprintf(fp, "exec=");
|
||||
if (exec)
|
||||
fprintf(fp, "%s", exec);
|
||||
while (argv && argv[i]) {
|
||||
fprintf(fp, "argv_%d=%s\n", i, argv[i]);
|
||||
fprintf(fp, "\nargv_%d=%s", i, argv[i]);
|
||||
i++;
|
||||
}
|
||||
fprintf(fp, "name=");
|
||||
if (name)
|
||||
fprintf(fp, "%s", name);
|
||||
fprintf(fp, "\npidfile=");
|
||||
if (pidfile)
|
||||
fprintf(fp, "%s", pidfile);
|
||||
@@ -427,7 +417,8 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
||||
}
|
||||
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)
|
||||
{
|
||||
char dirpath[PATH_MAX];
|
||||
@@ -437,12 +428,12 @@ bool rc_service_started_daemon(const char *service, const char *const *argv,
|
||||
DIR *dp;
|
||||
struct dirent *d;
|
||||
|
||||
if (!service || !(argv && *argv))
|
||||
if (!service || !exec)
|
||||
return false;
|
||||
|
||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||
basename_c(service));
|
||||
match = _match_list(argv, NULL, NULL);
|
||||
match = _match_list(exec, argv, NULL);
|
||||
|
||||
if (indx > 0) {
|
||||
snprintf(file, sizeof(file), "%03d", indx);
|
||||
@@ -492,7 +483,7 @@ bool rc_service_daemons_crashed(const char *service)
|
||||
path += snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||
basename_c(service));
|
||||
|
||||
if (! (dp = opendir(dirpath)))
|
||||
if (!(dp = opendir(dirpath)))
|
||||
return false;
|
||||
|
||||
while ((d = readdir(dp))) {
|
||||
@@ -502,25 +493,25 @@ bool rc_service_daemons_crashed(const char *service)
|
||||
snprintf(path, sizeof(dirpath) - (path - dirpath), "/%s",
|
||||
d->d_name);
|
||||
fp = fopen(dirpath, "r");
|
||||
if (! fp)
|
||||
if (!fp)
|
||||
break;
|
||||
|
||||
while ((rc_getline(&line, &len, fp))) {
|
||||
p = line;
|
||||
if ((token = strsep(&p, "=")) == NULL || ! p)
|
||||
if ((token = strsep(&p, "=")) == NULL || !p)
|
||||
continue;
|
||||
|
||||
if (! *p)
|
||||
if (!*p)
|
||||
continue;
|
||||
|
||||
if (strncmp(token, "argv_", 5) == 0) {
|
||||
if (! list)
|
||||
list = rc_stringlist_new();
|
||||
rc_stringlist_add(list, p);
|
||||
} else if (strcmp(token, "exec") == 0) {
|
||||
if (strcmp(token, "exec") == 0) {
|
||||
if (exec)
|
||||
free(exec);
|
||||
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) {
|
||||
if (name)
|
||||
free(name);
|
||||
@@ -543,14 +534,16 @@ bool rc_service_daemons_crashed(const char *service)
|
||||
free(pidfile);
|
||||
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);
|
||||
name = NULL;
|
||||
} else {
|
||||
if (exec) {
|
||||
if (! list)
|
||||
if (!list)
|
||||
list = rc_stringlist_new();
|
||||
if (! TAILQ_FIRST(list))
|
||||
if (!TAILQ_FIRST(list))
|
||||
rc_stringlist_add(list, exec);
|
||||
|
||||
free(exec);
|
||||
@@ -570,9 +563,10 @@ bool rc_service_daemons_crashed(const char *service)
|
||||
}
|
||||
}
|
||||
|
||||
if (! retval) {
|
||||
if ((pids = rc_find_pids((const char *const *)argv,
|
||||
name, 0, pid)))
|
||||
if (!retval) {
|
||||
if ((pids = rc_find_pids(exec,
|
||||
(const char *const *)argv,
|
||||
0, pid)))
|
||||
{
|
||||
p1 = LIST_FIRST(pids);
|
||||
while (p1) {
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
|
||||
static const char *bootlevel = NULL;
|
||||
|
||||
static char *get_shell_value(char *string)
|
||||
static char *
|
||||
get_shell_value(char *string)
|
||||
{
|
||||
char *p = string;
|
||||
char *e;
|
||||
@@ -60,24 +61,23 @@ static char *get_shell_value(char *string)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rc_deptree_free(RC_DEPTREE *deptree)
|
||||
void
|
||||
rc_deptree_free(RC_DEPTREE *deptree)
|
||||
{
|
||||
RC_DEPINFO *di;
|
||||
RC_DEPINFO *di2;
|
||||
RC_DEPTYPE *dt;
|
||||
RC_DEPTYPE *dt2;
|
||||
|
||||
if (! deptree)
|
||||
if (!deptree)
|
||||
return;
|
||||
|
||||
di = STAILQ_FIRST(deptree);
|
||||
while (di)
|
||||
{
|
||||
di2 = STAILQ_NEXT(di, entries);
|
||||
dt = STAILQ_FIRST(&di->depends);
|
||||
while (dt)
|
||||
{
|
||||
dt2 = STAILQ_NEXT(dt, entries);
|
||||
di = TAILQ_FIRST(deptree);
|
||||
while (di) {
|
||||
di2 = TAILQ_NEXT(di, entries);
|
||||
dt = TAILQ_FIRST(&di->depends);
|
||||
while (dt) {
|
||||
dt2 = TAILQ_NEXT(dt, entries);
|
||||
rc_stringlist_free(dt->services);
|
||||
free(dt->type);
|
||||
free(dt);
|
||||
@@ -91,31 +91,30 @@ void rc_deptree_free(RC_DEPTREE *deptree)
|
||||
}
|
||||
librc_hidden_def(rc_deptree_free)
|
||||
|
||||
static RC_DEPINFO *get_depinfo(const RC_DEPTREE *deptree,
|
||||
const char *service)
|
||||
static RC_DEPINFO *
|
||||
get_depinfo(const RC_DEPTREE *deptree, const char *service)
|
||||
{
|
||||
RC_DEPINFO *di;
|
||||
|
||||
STAILQ_FOREACH(di, deptree, entries)
|
||||
TAILQ_FOREACH(di, deptree, entries)
|
||||
if (strcmp(di->service, service) == 0)
|
||||
return di;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static RC_DEPTYPE *get_deptype(const RC_DEPINFO *depinfo,
|
||||
const char *type)
|
||||
static RC_DEPTYPE *
|
||||
get_deptype(const RC_DEPINFO *depinfo, const char *type)
|
||||
{
|
||||
RC_DEPTYPE *dt;
|
||||
|
||||
STAILQ_FOREACH(dt, &depinfo->depends, entries)
|
||||
TAILQ_FOREACH(dt, &depinfo->depends, entries)
|
||||
if (strcmp(dt->type, type) == 0)
|
||||
return dt;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RC_DEPTREE *rc_deptree_load(void)
|
||||
RC_DEPTREE *
|
||||
rc_deptree_load(void)
|
||||
{
|
||||
FILE *fp;
|
||||
RC_DEPTREE *deptree;
|
||||
@@ -132,53 +131,43 @@ RC_DEPTREE *rc_deptree_load(void)
|
||||
return NULL;
|
||||
|
||||
deptree = xmalloc(sizeof(*deptree));
|
||||
STAILQ_INIT(deptree);
|
||||
|
||||
TAILQ_INIT(deptree);
|
||||
while ((rc_getline(&line, &len, fp)))
|
||||
{
|
||||
p = line;
|
||||
e = strsep(&p, "_");
|
||||
if (! e || strcmp(e, "depinfo") != 0)
|
||||
if (!e || strcmp(e, "depinfo") != 0)
|
||||
continue;
|
||||
|
||||
e = strsep (&p, "_");
|
||||
if (! e || sscanf(e, "%d", &i) != 1)
|
||||
if (!e || sscanf(e, "%d", &i) != 1)
|
||||
continue;
|
||||
|
||||
if (! (type = strsep(&p, "_=")))
|
||||
if (!(type = strsep(&p, "_=")))
|
||||
continue;
|
||||
|
||||
if (strcmp(type, "service") == 0)
|
||||
{
|
||||
if (strcmp(type, "service") == 0) {
|
||||
/* Sanity */
|
||||
e = get_shell_value(p);
|
||||
if (! e || *e == '\0')
|
||||
continue;
|
||||
|
||||
depinfo = xmalloc(sizeof(*depinfo));
|
||||
STAILQ_INIT(&depinfo->depends);
|
||||
TAILQ_INIT(&depinfo->depends);
|
||||
depinfo->service = xstrdup(e);
|
||||
STAILQ_INSERT_TAIL(deptree, depinfo, entries);
|
||||
TAILQ_INSERT_TAIL(deptree, depinfo, entries);
|
||||
deptype = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
e = strsep(&p, "=");
|
||||
if (! e || sscanf(e, "%d", &i) != 1)
|
||||
if (!e || sscanf(e, "%d", &i) != 1)
|
||||
continue;
|
||||
|
||||
/* Sanity */
|
||||
e = get_shell_value(p);
|
||||
if (! e || *e == '\0')
|
||||
if (!e || *e == '\0')
|
||||
continue;
|
||||
|
||||
if (! deptype || strcmp(deptype->type, type) != 0) {
|
||||
if (!deptype || strcmp(deptype->type, type) != 0) {
|
||||
deptype = xmalloc(sizeof(*deptype));
|
||||
deptype->services = rc_stringlist_new();
|
||||
deptype->type = xstrdup (type);
|
||||
STAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
|
||||
deptype->type = xstrdup(type);
|
||||
TAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
|
||||
}
|
||||
|
||||
rc_stringlist_add(deptype->services, e);
|
||||
}
|
||||
fclose(fp);
|
||||
@@ -188,21 +177,28 @@ RC_DEPTREE *rc_deptree_load(void)
|
||||
}
|
||||
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;
|
||||
|
||||
if (!runlevel ||
|
||||
strcmp(type, "ineed") == 0 ||
|
||||
strcmp(type, "needsme") == 0)
|
||||
return true;
|
||||
|
||||
return ((strcmp (runlevel, bootlevel) != 0 &&
|
||||
state = rc_service_state(service);
|
||||
return ((strcmp(runlevel, bootlevel) != 0 &&
|
||||
rc_service_in_runlevel(service, bootlevel)) ||
|
||||
rc_service_in_runlevel(service, runlevel) ||
|
||||
state & RC_SERVICE_COLDPLUGGED ||
|
||||
state & RC_SERVICE_STARTED);
|
||||
}
|
||||
|
||||
static bool get_provided1(const char *runlevel, RC_STRINGLIST *providers,
|
||||
RC_DEPTYPE *deptype,
|
||||
const char *level, bool coldplugged,
|
||||
RC_SERVICE state)
|
||||
static bool
|
||||
get_provided1(const char *runlevel, RC_STRINGLIST *providers,
|
||||
RC_DEPTYPE *deptype, const char *level,
|
||||
bool coldplugged, RC_SERVICE state)
|
||||
{
|
||||
RC_STRING *service;
|
||||
RC_SERVICE st;
|
||||
@@ -219,12 +215,10 @@ static bool get_provided1(const char *runlevel, RC_STRINGLIST *providers,
|
||||
ok = rc_service_in_runlevel(svc, level);
|
||||
else if (coldplugged)
|
||||
ok = (st & RC_SERVICE_COLDPLUGGED &&
|
||||
! rc_service_in_runlevel(svc, runlevel) &&
|
||||
! rc_service_in_runlevel(svc, bootlevel));
|
||||
|
||||
if (! ok)
|
||||
!rc_service_in_runlevel(svc, runlevel) &&
|
||||
!rc_service_in_runlevel(svc, bootlevel));
|
||||
if (!ok)
|
||||
continue;
|
||||
|
||||
switch (state) {
|
||||
case RC_SERVICE_STARTED:
|
||||
ok = (st & RC_SERVICE_STARTED);
|
||||
@@ -239,10 +233,8 @@ static bool get_provided1(const char *runlevel, RC_STRINGLIST *providers,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (! ok)
|
||||
if (!ok)
|
||||
continue;
|
||||
|
||||
retval = true;
|
||||
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
|
||||
provided dependancy can change depending on runlevel state.
|
||||
*/
|
||||
static RC_STRINGLIST *get_provided (const RC_DEPINFO *depinfo,
|
||||
const char *runlevel, int options)
|
||||
static RC_STRINGLIST *
|
||||
get_provided(const RC_DEPINFO *depinfo, const char *runlevel, int options)
|
||||
{
|
||||
RC_DEPTYPE *dt;
|
||||
RC_STRINGLIST *providers = rc_stringlist_new();
|
||||
RC_STRING *service;
|
||||
|
||||
dt = get_deptype(depinfo, "providedby");
|
||||
if (! dt)
|
||||
if (!dt)
|
||||
return providers;
|
||||
|
||||
/* 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
|
||||
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)
|
||||
rc_stringlist_add(providers, service->value);
|
||||
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. */
|
||||
if (options & RC_DEP_STRICT || options & RC_DEP_START)
|
||||
{
|
||||
|
||||
if (options & RC_DEP_STRICT || options & RC_DEP_START) {
|
||||
TAILQ_FOREACH(service, dt->services, entries)
|
||||
if (rc_service_in_runlevel(service->value, runlevel) ||
|
||||
rc_service_in_runlevel(service->value, bootlevel) ||
|
||||
(options & RC_DEP_START &&
|
||||
rc_service_state(service->value) & RC_SERVICE_COLDPLUGGED))
|
||||
rc_stringlist_add(providers, service->value);
|
||||
|
||||
if (TAILQ_FIRST(providers))
|
||||
return providers;
|
||||
}
|
||||
|
||||
/* OK, we're not strict or there were no services in our runlevel.
|
||||
This is now where the logic gets a little fuzzy :)
|
||||
If there is >1 running service then we return NULL.
|
||||
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.
|
||||
We apply this to our runlevel, coldplugged services, then bootlevel
|
||||
and finally any running.*/
|
||||
* This is now where the logic gets a little fuzzy :)
|
||||
* If there is >1 running service then we return NULL.
|
||||
* 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.
|
||||
* We apply this to these states in order:-
|
||||
* started, starting | stopping | inactive, stopped
|
||||
* Our sub preference in each of these is in order:-
|
||||
* runlevel, coldplugged, bootlevel, any
|
||||
*/
|
||||
#define DO \
|
||||
if (TAILQ_FIRST(providers)) { \
|
||||
if (TAILQ_NEXT(TAILQ_FIRST(providers), entries)) { \
|
||||
@@ -312,45 +303,35 @@ static RC_STRINGLIST *get_provided (const RC_DEPINFO *depinfo,
|
||||
return providers; \
|
||||
}
|
||||
|
||||
/* Anything in the runlevel has to come first */
|
||||
if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTED))
|
||||
/* Anything running has to come first */
|
||||
if (get_provided1(runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTED))
|
||||
{ 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;
|
||||
if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STOPPED))
|
||||
if (get_provided1(runlevel, providers, dt, NULL, true, RC_SERVICE_STARTING))
|
||||
return providers;
|
||||
|
||||
/* Check coldplugged services */
|
||||
if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STARTED))
|
||||
{ DO }
|
||||
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))
|
||||
if (bootlevel && strcmp(runlevel, bootlevel) != 0 &&
|
||||
get_provided1(runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTING))
|
||||
return providers;
|
||||
if (get_provided1(runlevel, providers, dt, NULL, false, RC_SERVICE_STARTING))
|
||||
return providers;
|
||||
|
||||
/* 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;
|
||||
|
||||
if (bootlevel && (strcmp (runlevel, bootlevel) != 0)
|
||||
&& (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STOPPED)))
|
||||
if (get_provided1(runlevel, providers, dt, NULL, true, RC_SERVICE_STOPPED))
|
||||
{ DO }
|
||||
if (bootlevel && (strcmp(runlevel, bootlevel) != 0) &&
|
||||
get_provided1(runlevel, providers, dt, bootlevel, false, RC_SERVICE_STOPPED))
|
||||
return providers;
|
||||
|
||||
/* Still nothing? OK, list all services */
|
||||
@@ -360,12 +341,13 @@ static RC_STRINGLIST *get_provided (const RC_DEPINFO *depinfo,
|
||||
return providers;
|
||||
}
|
||||
|
||||
static void visit_service(const RC_DEPTREE *deptree,
|
||||
const RC_STRINGLIST *types,
|
||||
RC_STRINGLIST **sorted,
|
||||
RC_STRINGLIST *visited,
|
||||
const RC_DEPINFO *depinfo,
|
||||
const char *runlevel, int options)
|
||||
static void
|
||||
visit_service(const RC_DEPTREE *deptree,
|
||||
const RC_STRINGLIST *types,
|
||||
RC_STRINGLIST **sorted,
|
||||
RC_STRINGLIST *visited,
|
||||
const RC_DEPINFO *depinfo,
|
||||
const char *runlevel, int options)
|
||||
{
|
||||
RC_STRING *type;
|
||||
RC_STRING *service;
|
||||
@@ -379,7 +361,6 @@ static void visit_service(const RC_DEPTREE *deptree,
|
||||
TAILQ_FOREACH(type, visited, entries)
|
||||
if (strcmp(type->value, depinfo->service) == 0)
|
||||
return;
|
||||
|
||||
/* Add ourselves as a visited service */
|
||||
rc_stringlist_add(visited, depinfo->service);
|
||||
|
||||
@@ -389,10 +370,10 @@ static void visit_service(const RC_DEPTREE *deptree,
|
||||
continue;
|
||||
|
||||
TAILQ_FOREACH(service, dt->services, entries) {
|
||||
if (! options & RC_DEP_TRACE ||
|
||||
if (!(options & RC_DEP_TRACE) ||
|
||||
strcmp(type->value, "iprovide") == 0)
|
||||
{
|
||||
if (! *sorted)
|
||||
if (!*sorted)
|
||||
*sorted = rc_stringlist_new();
|
||||
rc_stringlist_add(*sorted, service->value);
|
||||
continue;
|
||||
@@ -405,18 +386,12 @@ static void visit_service(const RC_DEPTREE *deptree,
|
||||
if (TAILQ_FIRST(provided)) {
|
||||
TAILQ_FOREACH(p, provided, entries) {
|
||||
di = get_depinfo(deptree, p->value);
|
||||
if (di &&
|
||||
(strcmp(type->value, "ineed") == 0 ||
|
||||
strcmp(type->value, "needsme") == 0 ||
|
||||
valid_service(runlevel, di->service)))
|
||||
if (di && valid_service(runlevel, di->service, type->value))
|
||||
visit_service(deptree, types, sorted, visited, di,
|
||||
runlevel, options | RC_DEP_TRACE);
|
||||
}
|
||||
}
|
||||
else if (di &&
|
||||
(strcmp(type->value, "ineed") == 0 ||
|
||||
strcmp(type->value, "needsme") == 0 ||
|
||||
valid_service(runlevel, service->value)))
|
||||
else if (di && valid_service(runlevel, service->value, type->value))
|
||||
visit_service(deptree, types, sorted, visited, di,
|
||||
runlevel, options | RC_DEP_TRACE);
|
||||
|
||||
@@ -445,16 +420,17 @@ static void visit_service(const RC_DEPTREE *deptree,
|
||||
/* We've visited everything we need, so add ourselves unless we
|
||||
are also the service calling us or we are provided by something */
|
||||
svcname = getenv("RC_SVCNAME");
|
||||
if (! svcname || strcmp(svcname, depinfo->service) != 0)
|
||||
if (! get_deptype(depinfo, "providedby")) {
|
||||
if (! *sorted)
|
||||
if (!svcname || strcmp(svcname, depinfo->service) != 0)
|
||||
if (!get_deptype(depinfo, "providedby")) {
|
||||
if (!*sorted)
|
||||
*sorted = rc_stringlist_new();
|
||||
rc_stringlist_add(*sorted, depinfo->service);
|
||||
}
|
||||
}
|
||||
|
||||
RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *deptree,
|
||||
const char *service, const char *type)
|
||||
RC_STRINGLIST *
|
||||
rc_deptree_depend(const RC_DEPTREE *deptree,
|
||||
const char *service, const char *type)
|
||||
{
|
||||
RC_DEPINFO *di;
|
||||
RC_DEPTYPE *dt;
|
||||
@@ -462,7 +438,7 @@ RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *deptree,
|
||||
RC_STRING *svc;
|
||||
|
||||
if (!(di = get_depinfo(deptree, service)) ||
|
||||
! (dt = get_deptype(di, type)))
|
||||
!(dt = get_deptype(di, type)))
|
||||
{
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
@@ -472,15 +448,15 @@ RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *deptree,
|
||||
svcs = rc_stringlist_new();
|
||||
TAILQ_FOREACH(svc, dt->services, entries)
|
||||
rc_stringlist_add(svcs, svc->value);
|
||||
|
||||
return svcs;
|
||||
}
|
||||
librc_hidden_def(rc_deptree_depend)
|
||||
|
||||
RC_STRINGLIST *rc_deptree_depends(const RC_DEPTREE *deptree,
|
||||
const RC_STRINGLIST *types,
|
||||
const RC_STRINGLIST *services,
|
||||
const char *runlevel, int options)
|
||||
RC_STRINGLIST *
|
||||
rc_deptree_depends(const RC_DEPTREE *deptree,
|
||||
const RC_STRINGLIST *types,
|
||||
const RC_STRINGLIST *services,
|
||||
const char *runlevel, int options)
|
||||
{
|
||||
RC_STRINGLIST *sorted = NULL;
|
||||
RC_STRINGLIST *visited = rc_stringlist_new();
|
||||
@@ -488,11 +464,10 @@ RC_STRINGLIST *rc_deptree_depends(const RC_DEPTREE *deptree,
|
||||
const RC_STRING *service;
|
||||
|
||||
bootlevel = getenv("RC_BOOTLEVEL");
|
||||
if (! bootlevel)
|
||||
if (!bootlevel)
|
||||
bootlevel = RC_LEVEL_BOOT;
|
||||
|
||||
TAILQ_FOREACH(service, services, entries) {
|
||||
if (! (di = get_depinfo(deptree, service->value))) {
|
||||
if (!(di = get_depinfo(deptree, service->value))) {
|
||||
errno = ENOENT;
|
||||
continue;
|
||||
}
|
||||
@@ -500,14 +475,13 @@ RC_STRINGLIST *rc_deptree_depends(const RC_DEPTREE *deptree,
|
||||
visit_service(deptree, types, &sorted, visited,
|
||||
di, runlevel, options);
|
||||
}
|
||||
|
||||
rc_stringlist_free(visited);
|
||||
return sorted;
|
||||
}
|
||||
librc_hidden_def(rc_deptree_depends)
|
||||
|
||||
RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
|
||||
const char *runlevel, int options)
|
||||
RC_STRINGLIST *
|
||||
rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
|
||||
{
|
||||
RC_STRINGLIST *list;
|
||||
RC_STRINGLIST *list2;
|
||||
@@ -519,9 +493,9 @@ RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
|
||||
bootlevel = RC_LEVEL_BOOT;
|
||||
|
||||
/* When shutting down, list all running services */
|
||||
if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
|
||||
strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
|
||||
strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
|
||||
if (strcmp(runlevel, RC_LEVEL_SINGLE) == 0 ||
|
||||
strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
|
||||
strcmp(runlevel, RC_LEVEL_REBOOT) == 0)
|
||||
{
|
||||
list = rc_services_in_state(RC_SERVICE_STARTED);
|
||||
list2 = rc_services_in_state(RC_SERVICE_INACTIVE);
|
||||
@@ -553,7 +527,7 @@ RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (list2) {
|
||||
if (list) {
|
||||
@@ -571,21 +545,20 @@ RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
|
||||
rc_stringlist_add(types, "ineed");
|
||||
rc_stringlist_add(types, "iuse");
|
||||
rc_stringlist_add(types, "iafter");
|
||||
|
||||
services = rc_deptree_depends(deptree, types, list, runlevel,
|
||||
RC_DEP_STRICT | RC_DEP_TRACE | options);
|
||||
rc_stringlist_free(list);
|
||||
rc_stringlist_free(types);
|
||||
|
||||
return services;
|
||||
}
|
||||
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;
|
||||
time_t mtime;
|
||||
bool newer = true;
|
||||
bool retval = true;
|
||||
DIR *dp;
|
||||
struct dirent *d;
|
||||
char path[PATH_MAX];
|
||||
@@ -596,36 +569,52 @@ bool rc_newer_than(const char *source, const char *target)
|
||||
return false;
|
||||
mtime = buf.st_mtime;
|
||||
|
||||
/* Of course we are newer than targets that don't exist
|
||||
such as broken symlinks */
|
||||
/* If target does not exist, return true to mimic shell test */
|
||||
if (stat(target, &buf) != 0)
|
||||
return true;
|
||||
|
||||
if (mtime < buf.st_mtime)
|
||||
return false;
|
||||
if (newer) {
|
||||
if (mtime < buf.st_mtime)
|
||||
return false;
|
||||
} else {
|
||||
if (mtime > buf.st_mtime)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If not a dir then reset errno */
|
||||
if (! (dp = opendir(target))) {
|
||||
if (!(dp = opendir(target))) {
|
||||
errno = serrno;
|
||||
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))) {
|
||||
if (d->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
|
||||
newer = rc_newer_than(source, path);
|
||||
if (! newer)
|
||||
retval = mtime_check(source, path, newer);
|
||||
if (!retval)
|
||||
break;
|
||||
}
|
||||
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)
|
||||
|
||||
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
|
||||
{
|
||||
const char *depend;
|
||||
@@ -658,7 +647,8 @@ static const char *const depdirs[] =
|
||||
NULL
|
||||
};
|
||||
|
||||
bool rc_deptree_update_needed(void)
|
||||
bool
|
||||
rc_deptree_update_needed(void)
|
||||
{
|
||||
bool newer = false;
|
||||
RC_STRINGLIST *config;
|
||||
@@ -672,22 +662,22 @@ bool rc_deptree_update_needed(void)
|
||||
|
||||
/* Quick test to see if anything we use has changed and we have
|
||||
* data in our deptree */
|
||||
if (! existss(RC_DEPTREE_CACHE) ||
|
||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR) ||
|
||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR) ||
|
||||
if (!existss(RC_DEPTREE_CACHE) ||
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR) ||
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR) ||
|
||||
#ifdef RC_PKG_INITDIR
|
||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR) ||
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR) ||
|
||||
#endif
|
||||
#ifdef RC_PKG_CONFDIR
|
||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR) ||
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR) ||
|
||||
#endif
|
||||
#ifdef RC_LOCAL_INITDIR
|
||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR) ||
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR) ||
|
||||
#endif
|
||||
#ifdef RC_LOCAL_CONFDIR
|
||||
! rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR) ||
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR) ||
|
||||
#endif
|
||||
! rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf"))
|
||||
!rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf"))
|
||||
return true;
|
||||
|
||||
/* Some init scripts dependencies change depending on config files
|
||||
@@ -695,100 +685,86 @@ bool rc_deptree_update_needed(void)
|
||||
config = rc_config_list(RC_DEPCONFIG);
|
||||
if (config) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rc_stringlist_free(config);
|
||||
}
|
||||
|
||||
return newer;
|
||||
}
|
||||
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
|
||||
and echos their dependency info to stdout
|
||||
Phase 2 takes that and populates a depinfo object with that data
|
||||
Phase 3 adds any provided services to the depinfo object
|
||||
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;
|
||||
RC_DEPTREE *deptree;
|
||||
RC_DEPTREE *providers;
|
||||
RC_DEPINFO *depinfo = NULL;
|
||||
RC_DEPINFO *depinfo_np;
|
||||
RC_DEPINFO *di;
|
||||
RC_DEPTYPE *deptype = NULL;
|
||||
RC_DEPTYPE *dt;
|
||||
RC_DEPTYPE *dt_np;
|
||||
RC_STRINGLIST *config;
|
||||
RC_STRING *s;
|
||||
RC_STRING *s2;
|
||||
RC_DEPTYPE *provide;
|
||||
RC_DEPTREE *deptree, *providers;
|
||||
RC_DEPINFO *depinfo = NULL, *depinfo_np, *di;
|
||||
RC_DEPTYPE *deptype = NULL, *dt_np, *dt, *provide;
|
||||
RC_STRINGLIST *config, *types, *sorted, *visited;
|
||||
RC_STRING *s, *s2, *s2_np, *s3, *s4;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
char *depend;
|
||||
char *depends;
|
||||
char *service;
|
||||
char *type;
|
||||
size_t i;
|
||||
size_t k;
|
||||
size_t l;
|
||||
int retval = true;
|
||||
char *depend, *depends, *service, *type, *nosys;
|
||||
size_t i, k, l;
|
||||
bool retval = true;
|
||||
const char *sys = rc_sys();
|
||||
char *nosys;
|
||||
|
||||
/* Some init scripts need RC_LIBDIR to source stuff
|
||||
Ideally we should be setting our full env instead */
|
||||
if (! getenv("RC_LIBDIR"))
|
||||
if (!getenv("RC_LIBDIR"))
|
||||
setenv("RC_LIBDIR", RC_LIBDIR, 0);
|
||||
|
||||
/* Phase 1 - source all init scripts and print dependencies */
|
||||
if (! (fp = popen(GENDEP, "r")))
|
||||
if (!(fp = popen(GENDEP, "r")))
|
||||
return false;
|
||||
|
||||
deptree = xmalloc(sizeof(*deptree));
|
||||
STAILQ_INIT(deptree);
|
||||
|
||||
TAILQ_INIT(deptree);
|
||||
config = rc_stringlist_new();
|
||||
|
||||
while ((rc_getline(&line, &len, fp)))
|
||||
{
|
||||
depends = line;
|
||||
service = strsep(&depends, " ");
|
||||
if (! service || ! *service)
|
||||
if (!service || !*service)
|
||||
continue;
|
||||
|
||||
type = strsep(&depends, " ");
|
||||
if (! depinfo || strcmp(depinfo->service, service) != 0) {
|
||||
if (!depinfo || strcmp(depinfo->service, service) != 0) {
|
||||
deptype = NULL;
|
||||
depinfo = get_depinfo(deptree, service);
|
||||
if (! depinfo) {
|
||||
if (!depinfo) {
|
||||
depinfo = xmalloc(sizeof(*depinfo));
|
||||
STAILQ_INIT(&depinfo->depends);
|
||||
TAILQ_INIT(&depinfo->depends);
|
||||
depinfo->service = xstrdup(service);
|
||||
STAILQ_INSERT_TAIL(deptree, depinfo, entries);
|
||||
TAILQ_INSERT_TAIL(deptree, depinfo, entries);
|
||||
}
|
||||
}
|
||||
|
||||
/* We may not have any depends */
|
||||
if (! type || ! depends)
|
||||
if (!type || !depends)
|
||||
continue;
|
||||
|
||||
/* Get the type */
|
||||
if (strcmp(type, "config") != 0) {
|
||||
if (! deptype || strcmp (deptype->type, type) != 0)
|
||||
if (!deptype || strcmp(deptype->type, type) != 0)
|
||||
deptype = get_deptype(depinfo, type);
|
||||
if (! deptype) {
|
||||
if (!deptype) {
|
||||
deptype = xmalloc(sizeof(*deptype));
|
||||
deptype->type = xstrdup(type);
|
||||
deptype->services = rc_stringlist_new();
|
||||
STAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
|
||||
TAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -800,7 +776,7 @@ bool rc_deptree_update(void)
|
||||
continue;
|
||||
|
||||
if (strcmp(type, "config") == 0) {
|
||||
rc_stringlist_add(config, depend);
|
||||
rc_stringlist_addu(config, depend);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -828,9 +804,9 @@ bool rc_deptree_update(void)
|
||||
rc_stringlist_delete(dt->services, depend);
|
||||
}
|
||||
/* If we're after something, remove us from the before list */
|
||||
if (strcmp (type, "iafter") == 0 ||
|
||||
strcmp (type, "ineed") == 0 ||
|
||||
strcmp (type, "iuse") == 0) {
|
||||
if (strcmp(type, "iafter") == 0 ||
|
||||
strcmp(type, "ineed") == 0 ||
|
||||
strcmp(type, "iuse") == 0) {
|
||||
if ((dt = get_deptype(depinfo, "ibefore")))
|
||||
rc_stringlist_delete(dt->services, depend);
|
||||
}
|
||||
@@ -850,20 +826,20 @@ bool rc_deptree_update(void)
|
||||
nosys[i + 2] = (char)tolower((unsigned char)sys[i]);
|
||||
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")))
|
||||
TAILQ_FOREACH(s, deptype->services, entries)
|
||||
if (strcmp (s->value, nosys) == 0) {
|
||||
if (strcmp(s->value, nosys) == 0) {
|
||||
provide = get_deptype(depinfo, "iprovide");
|
||||
STAILQ_REMOVE(deptree, depinfo, rc_depinfo, entries);
|
||||
STAILQ_FOREACH(di, deptree, entries) {
|
||||
STAILQ_FOREACH_SAFE(dt, &di->depends, entries, dt_np) {
|
||||
TAILQ_REMOVE(deptree, depinfo, entries);
|
||||
TAILQ_FOREACH(di, deptree, entries) {
|
||||
TAILQ_FOREACH_SAFE(dt, &di->depends, entries, dt_np) {
|
||||
rc_stringlist_delete(dt->services, depinfo->service);
|
||||
if (provide)
|
||||
TAILQ_FOREACH(s2, provide->services, entries)
|
||||
rc_stringlist_delete(dt->services, s2->value);
|
||||
if (! TAILQ_FIRST(dt->services)) {
|
||||
STAILQ_REMOVE(&di->depends, dt, rc_deptype, entries);
|
||||
if (!TAILQ_FIRST(dt->services)) {
|
||||
TAILQ_REMOVE(&di->depends, dt, entries);
|
||||
free(dt->type);
|
||||
free(dt->services);
|
||||
free(dt);
|
||||
@@ -871,38 +847,38 @@ bool rc_deptree_update(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
free (nosys);
|
||||
free(nosys);
|
||||
}
|
||||
|
||||
/* Phase 3 - add our providers to the tree */
|
||||
providers = xmalloc(sizeof(*providers));
|
||||
STAILQ_INIT(providers);
|
||||
STAILQ_FOREACH(depinfo, deptree, entries)
|
||||
TAILQ_INIT(providers);
|
||||
TAILQ_FOREACH(depinfo, deptree, entries)
|
||||
if ((deptype = get_deptype(depinfo, "iprovide")))
|
||||
TAILQ_FOREACH(s, deptype->services, entries) {
|
||||
STAILQ_FOREACH(di, providers, entries)
|
||||
TAILQ_FOREACH(di, providers, entries)
|
||||
if (strcmp(di->service, s->value) == 0)
|
||||
break;
|
||||
if (! di) {
|
||||
if (!di) {
|
||||
di = xmalloc(sizeof(*di));
|
||||
STAILQ_INIT(&di->depends);
|
||||
TAILQ_INIT(&di->depends);
|
||||
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);
|
||||
|
||||
/* Phase 4 - backreference our depends */
|
||||
STAILQ_FOREACH(depinfo, deptree, entries)
|
||||
TAILQ_FOREACH(depinfo, deptree, entries)
|
||||
for (i = 0; deppairs[i].depend; i++) {
|
||||
deptype = get_deptype(depinfo, deppairs[i].depend);
|
||||
if (! deptype)
|
||||
if (!deptype)
|
||||
continue;
|
||||
TAILQ_FOREACH(s, deptype->services, entries) {
|
||||
di = get_depinfo(deptree, s->value);
|
||||
if (! di) {
|
||||
if (strcmp (deptype->type, "ineed") == 0)
|
||||
if (!di) {
|
||||
if (strcmp(deptype->type, "ineed") == 0)
|
||||
fprintf (stderr,
|
||||
"Service `%s' needs non"
|
||||
" existant service `%s'\n",
|
||||
@@ -911,28 +887,80 @@ bool rc_deptree_update(void)
|
||||
}
|
||||
|
||||
dt = get_deptype(di, deppairs[i].addto);
|
||||
if (! dt) {
|
||||
if (!dt) {
|
||||
dt = xmalloc(sizeof(*dt));
|
||||
dt->type = xstrdup(deppairs[i].addto);
|
||||
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?
|
||||
I think yes as then it stays human readable
|
||||
This works and should be entirely shell parseable provided that depend
|
||||
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;
|
||||
STAILQ_FOREACH(depinfo, deptree, entries) {
|
||||
TAILQ_FOREACH(depinfo, deptree, entries) {
|
||||
fprintf(fp, "depinfo_%zu_service='%s'\n",
|
||||
i, depinfo->service);
|
||||
STAILQ_FOREACH(deptype, &depinfo->depends, entries) {
|
||||
TAILQ_FOREACH(deptype, &depinfo->depends, entries) {
|
||||
k = 0;
|
||||
TAILQ_FOREACH(s, deptype->services, entries) {
|
||||
fprintf(fp,
|
||||
@@ -961,13 +989,12 @@ bool rc_deptree_update(void)
|
||||
RC_DEPCONFIG, strerror(errno));
|
||||
retval = false;
|
||||
}
|
||||
rc_stringlist_free (config);
|
||||
} else {
|
||||
unlink(RC_DEPCONFIG);
|
||||
}
|
||||
|
||||
rc_stringlist_free(config);
|
||||
rc_deptree_free(deptree);
|
||||
|
||||
return retval;
|
||||
}
|
||||
librc_hidden_def(rc_deptree_update)
|
||||
|
||||
@@ -138,10 +138,14 @@ RC_STRINGLIST *rc_config_load(const char *file)
|
||||
TAILQ_FOREACH(line, list, entries) {
|
||||
/* Get entry */
|
||||
p = line->value;
|
||||
if (! p)
|
||||
continue;
|
||||
if (strncmp(p, "export ", 7) == 0)
|
||||
p += 7;
|
||||
if (! (token = strsep(&p, "=")))
|
||||
continue;
|
||||
|
||||
entry = xstrdup (token);
|
||||
entry = xstrdup(token);
|
||||
/* Preserve shell coloring */
|
||||
if (*p == '$')
|
||||
token = line->value;
|
||||
|
||||
@@ -80,6 +80,33 @@ bool rc_stringlist_delete(RC_STRINGLIST *list, const char *value)
|
||||
}
|
||||
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)
|
||||
{
|
||||
RC_STRINGLIST *l = *list;
|
||||
|
||||
@@ -35,7 +35,6 @@ const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
|
||||
#define RC_RUNLEVEL RC_SVCDIR "/softlevel"
|
||||
|
||||
@@ -231,9 +230,11 @@ const char *rc_sys(void)
|
||||
else if (file_regex("/proc/self/status",
|
||||
"(s_context|VxID):[[:space:]]*[1-9]"))
|
||||
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",
|
||||
"envID:[[:space:]]*[1-9]"))
|
||||
return RC_SYS_OPENVZ;
|
||||
return RC_SYS_OPENVZ; /* old test */
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -86,6 +86,7 @@ librc_hidden_proto(rc_deptree_update_needed)
|
||||
librc_hidden_proto(rc_find_pids)
|
||||
librc_hidden_proto(rc_getline)
|
||||
librc_hidden_proto(rc_newer_than)
|
||||
librc_hidden_proto(rc_older_than)
|
||||
librc_hidden_proto(rc_runlevel_exists)
|
||||
librc_hidden_proto(rc_runlevel_get)
|
||||
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_addu)
|
||||
librc_hidden_proto(rc_stringlist_delete)
|
||||
librc_hidden_proto(rc_stringlist_find)
|
||||
librc_hidden_proto(rc_stringlist_free)
|
||||
librc_hidden_proto(rc_stringlist_new)
|
||||
librc_hidden_proto(rc_stringlist_split)
|
||||
librc_hidden_proto(rc_stringlist_sort)
|
||||
librc_hidden_proto(rc_sys)
|
||||
librc_hidden_proto(rc_yesno)
|
||||
|
||||
@@ -142,7 +142,7 @@ bool rc_service_delete(const char *, const char *);
|
||||
* @param name of the process (optional)
|
||||
* @param pidfile of the process (optional)
|
||||
* @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);
|
||||
|
||||
/*! 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
|
||||
* @param service to check
|
||||
* @param exec to check
|
||||
* @param argv to check
|
||||
* @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc)
|
||||
* @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
|
||||
* @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
|
||||
* rc_get_depends functions. */
|
||||
/*! Trace provided services */
|
||||
#define RC_DEP_TRACE 0x01
|
||||
#define RC_DEP_TRACE (1<<0)
|
||||
/*! Only use services added to runlevels */
|
||||
#define RC_DEP_STRICT 0x02
|
||||
#define RC_DEP_STRICT (1<<1)
|
||||
/*! Runlevel is starting */
|
||||
#define RC_DEP_START 0x04
|
||||
#define RC_DEP_START (1<<2)
|
||||
/*! Runlevel is stopping */
|
||||
#define RC_DEP_STOP 0x08
|
||||
#define RC_DEP_STOP (1<<3)
|
||||
|
||||
/*! @name Dependencies
|
||||
* We analyse each init script and cache the resultant dependency tree.
|
||||
@@ -281,7 +283,7 @@ typedef struct rc_deptype
|
||||
/*! list of services */
|
||||
RC_STRINGLIST *services;
|
||||
/*! list of types */
|
||||
STAILQ_ENTRY(rc_deptype) entries;
|
||||
TAILQ_ENTRY(rc_deptype) entries;
|
||||
} RC_DEPTYPE;
|
||||
|
||||
/*! Singly linked list of services and their dependencies */
|
||||
@@ -290,12 +292,12 @@ typedef struct rc_depinfo
|
||||
/*! Name of service */
|
||||
char *service;
|
||||
/*! Dependencies */
|
||||
STAILQ_HEAD(, rc_deptype) depends;
|
||||
TAILQ_HEAD(, rc_deptype) depends;
|
||||
/*! List of entries */
|
||||
STAILQ_ENTRY(rc_depinfo) entries;
|
||||
TAILQ_ENTRY(rc_depinfo) entries;
|
||||
} RC_DEPINFO;
|
||||
|
||||
typedef STAILQ_HEAD(,rc_depinfo) RC_DEPTREE;
|
||||
typedef TAILQ_HEAD(,rc_depinfo) RC_DEPTREE;
|
||||
#else
|
||||
/* Handles to internal structures */
|
||||
typedef void *RC_DEPTREE;
|
||||
@@ -306,6 +308,11 @@ typedef void *RC_DEPTREE;
|
||||
* @return true if source is newer than target, otherwise false */
|
||||
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,
|
||||
* its configuration file or an external configuration file the init script
|
||||
* has specified.
|
||||
@@ -438,6 +445,19 @@ RC_STRING *rc_stringlist_addu(RC_STRINGLIST *, const char *);
|
||||
* @return true on success, otherwise false */
|
||||
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
|
||||
* @param list to sort */
|
||||
void rc_stringlist_sort(RC_STRINGLIST **);
|
||||
@@ -458,11 +478,11 @@ typedef LIST_HEAD(rc_pidlist, rc_pid) RC_PIDLIST;
|
||||
* pid overrides anything else.
|
||||
* If both exec and cmd are given then we ignore exec.
|
||||
* @param exec to check for
|
||||
* @param cmd to check for
|
||||
* @param argv to check for
|
||||
* @param uid to check for
|
||||
* @param pid to check for
|
||||
* @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
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,7 @@ global:
|
||||
rc_environ_fd;
|
||||
rc_find_pids;
|
||||
rc_newer_than;
|
||||
rc_older_than;
|
||||
rc_runlevel_exists;
|
||||
rc_runlevel_get;
|
||||
rc_runlevel_list;
|
||||
@@ -43,6 +44,8 @@ global:
|
||||
rc_stringlist_add;
|
||||
rc_stringlist_addu;
|
||||
rc_stringlist_delete;
|
||||
rc_stringlist_find;
|
||||
rc_stringlist_split;
|
||||
rc_stringlist_new;
|
||||
rc_stringlist_sort;
|
||||
rc_stringlist_free;
|
||||
|
||||
2
src/rc/.gitignore
vendored
2
src/rc/.gitignore
vendored
@@ -13,6 +13,7 @@ eerrorn
|
||||
eerror
|
||||
ebegin
|
||||
eend
|
||||
ewaitfile
|
||||
ewend
|
||||
eindent
|
||||
eoutdent
|
||||
@@ -67,5 +68,6 @@ rc-status.o
|
||||
rc-update.o
|
||||
runscript.o
|
||||
rc.o
|
||||
rc.core
|
||||
rc
|
||||
.depend
|
||||
|
||||
@@ -13,7 +13,7 @@ LINKDIR= ${PREFIX}/${LIBNAME}/${PROG}
|
||||
BINLINKS= rc-status
|
||||
SBINLINKS= rc-service rc-update runscript start-stop-daemon
|
||||
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 \
|
||||
service_starting service_started \
|
||||
service_stopping service_stopped \
|
||||
@@ -30,15 +30,14 @@ RC_SBINLINKS= mark_service_starting mark_service_started \
|
||||
ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
|
||||
CLEANFILES+= ${ALL_LINKS}
|
||||
|
||||
CPPFLAGS+= -I../includes -I../librc -I../libeinfo
|
||||
LDFLAGS+= -L../librc -L../libeinfo
|
||||
LDADD+= -lutil -lrc -leinfo
|
||||
|
||||
MK= ../../mk
|
||||
include ${MK}/debug.mk
|
||||
include ${MK}/prog.mk
|
||||
include ${MK}/cc.mk
|
||||
include ${MK}/debug.mk
|
||||
|
||||
CFLAGS+= -I../includes -I../librc -I../libeinfo
|
||||
|
||||
include ${MK}/${MKTERMCAP}.mk
|
||||
LDADD+= ${LIBDL} ${LIBKVM}
|
||||
|
||||
@@ -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 (file) {
|
||||
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));
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
const char *owner)
|
||||
{
|
||||
@@ -228,6 +208,5 @@ int checkpath(int argc, char **argv)
|
||||
optind++;
|
||||
}
|
||||
|
||||
exit(retval);
|
||||
/* NOTREACHED */
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -98,10 +98,10 @@ static int do_mount(struct ENT *ent)
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
argv[0] = (char *) "mount";
|
||||
argv[1] = (char *) "-o";
|
||||
argv[0] = UNCONST("mount");
|
||||
argv[1] = UNCONST("-o");
|
||||
argv[2] = ENT_OPTS(*ent);
|
||||
argv[3] = (char *) "-t";
|
||||
argv[3] = UNCONST("-t");
|
||||
argv[4] = ENT_TYPE(*ent);
|
||||
argv[5] = ENT_BLOCKDEVICE(*ent);
|
||||
argv[6] = ENT_FILE(*ent);
|
||||
@@ -163,7 +163,7 @@ int fstabinfo(int argc, char **argv)
|
||||
int opt;
|
||||
int output = OUTPUT_FILE;
|
||||
RC_STRINGLIST *files = rc_stringlist_new();
|
||||
RC_STRING *file;
|
||||
RC_STRING *file, *file_np;
|
||||
bool filtered = false;
|
||||
|
||||
#ifdef HAVE_GETMNTENT
|
||||
@@ -238,8 +238,18 @@ int fstabinfo(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
while (optind < argc)
|
||||
rc_stringlist_add(files, argv[optind++]);
|
||||
if (files) {
|
||||
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) {
|
||||
START_ENT;
|
||||
while ((ent = GET_ENT))
|
||||
@@ -250,6 +260,11 @@ int fstabinfo(int argc, char **argv)
|
||||
eerrorx("%s: emtpy fstab", argv[0]);
|
||||
}
|
||||
|
||||
if (!files || !TAILQ_FIRST(files)) {
|
||||
rc_stringlist_free(files);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Ensure we always display something */
|
||||
START_ENT;
|
||||
TAILQ_FOREACH(file, files, entries) {
|
||||
|
||||
@@ -481,6 +481,5 @@ int mountinfo(int argc, char **argv)
|
||||
REG_FREE(point_regex);
|
||||
REG_FREE(skip_point_regex);
|
||||
|
||||
exit(result);
|
||||
/* NOTREACHED */
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#define SYSLOG_NAMES
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
@@ -45,12 +46,17 @@
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "einfo.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 */
|
||||
extern const char *applet;
|
||||
|
||||
@@ -76,7 +82,10 @@ static int do_e(int argc, char **argv)
|
||||
char *message = NULL;
|
||||
char *p;
|
||||
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 */
|
||||
argc--;
|
||||
@@ -97,11 +106,14 @@ static int do_e(int argc, char **argv)
|
||||
if (strcmp(applet, "eend") == 0 ||
|
||||
strcmp(applet, "ewend") == 0 ||
|
||||
strcmp(applet, "veend") == 0 ||
|
||||
strcmp(applet, "vweend") == 0)
|
||||
strcmp(applet, "vweend") == 0 ||
|
||||
strcmp(applet, "ewaitfile") == 0)
|
||||
{
|
||||
errno = 0;
|
||||
retval = (int) strtoimax(argv[0], NULL, 0);
|
||||
if (errno != 0)
|
||||
retval = (int)strtoimax(argv[0], &p, 0);
|
||||
if (!p || *p != '\0')
|
||||
errno = EINVAL;
|
||||
if (errno)
|
||||
retval = EXIT_FAILURE;
|
||||
else {
|
||||
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) {
|
||||
for (i = 0; i < argc; i++)
|
||||
l += strlen(argv[i]) + 1;
|
||||
@@ -141,45 +185,42 @@ static int do_e(int argc, char **argv)
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
if (! message)
|
||||
fmt = "";
|
||||
|
||||
if (strcmp(applet, "einfo") == 0)
|
||||
einfo(fmt, message);
|
||||
e = einfo;
|
||||
else if (strcmp(applet, "einfon") == 0)
|
||||
einfon(fmt, message);
|
||||
e = einfon;
|
||||
else if (strcmp(applet, "ewarn") == 0)
|
||||
ewarn(fmt, message);
|
||||
e = ewarn;
|
||||
else if (strcmp(applet, "ewarnn") == 0)
|
||||
ewarnn(fmt, message);
|
||||
e = ewarnn;
|
||||
else if (strcmp(applet, "eerror") == 0) {
|
||||
eerror(fmt, message);
|
||||
e = eerror;
|
||||
retval = 1;
|
||||
} else if (strcmp(applet, "eerrorn") == 0) {
|
||||
eerrorn(fmt, message);
|
||||
e = eerrorn;
|
||||
retval = 1;
|
||||
} else if (strcmp(applet, "ebegin") == 0)
|
||||
ebegin(fmt, message);
|
||||
e = ebegin;
|
||||
else if (strcmp(applet, "eend") == 0)
|
||||
eend(retval, fmt, message);
|
||||
ee = eend;
|
||||
else if (strcmp(applet, "ewend") == 0)
|
||||
ewend(retval, fmt, message);
|
||||
ee = ewend;
|
||||
else if (strcmp(applet, "esyslog") == 0)
|
||||
elog(level, fmt, message);
|
||||
ee = elog;
|
||||
else if (strcmp(applet, "veinfo") == 0)
|
||||
einfov(fmt, message);
|
||||
e = einfov;
|
||||
else if (strcmp(applet, "veinfon") == 0)
|
||||
einfovn(fmt, message);
|
||||
e = einfovn;
|
||||
else if (strcmp(applet, "vewarn") == 0)
|
||||
ewarnv(fmt, message);
|
||||
e = ewarnv;
|
||||
else if (strcmp(applet, "vewarnn") == 0)
|
||||
ewarnvn(fmt, message);
|
||||
e = ewarnvn;
|
||||
else if (strcmp(applet, "vebegin") == 0)
|
||||
ebeginv(fmt, message);
|
||||
e = ebeginv;
|
||||
else if (strcmp(applet, "veend") == 0)
|
||||
eendv(retval, fmt, message);
|
||||
ee = eendv;
|
||||
else if (strcmp(applet, "vewend") == 0)
|
||||
ewendv(retval, fmt, message);
|
||||
ee = ewendv;
|
||||
else if (strcmp(applet, "eindent") == 0)
|
||||
eindent();
|
||||
else if (strcmp(applet, "eoutdent") == 0)
|
||||
@@ -193,6 +234,18 @@ static int do_e(int argc, char **argv)
|
||||
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);
|
||||
return retval;
|
||||
}
|
||||
@@ -200,9 +253,9 @@ static int do_e(int argc, char **argv)
|
||||
static int do_service(int argc, char **argv)
|
||||
{
|
||||
bool ok = false;
|
||||
char *service = NULL;
|
||||
char *service;
|
||||
char *exec;
|
||||
int idx = 0;
|
||||
char *d[] = { NULL, NULL };
|
||||
|
||||
if (argc > 1)
|
||||
service = argv[1];
|
||||
@@ -227,21 +280,19 @@ static int do_service(int argc, char **argv)
|
||||
else if (strcmp(applet, "service_wasinactive") == 0)
|
||||
ok = (rc_service_state(service) & RC_SERVICE_WASINACTIVE);
|
||||
else if (strcmp(applet, "service_started_daemon") == 0) {
|
||||
d[0] = argv[1];
|
||||
|
||||
service = getenv("RC_SVCNAME");
|
||||
exec = argv[1];
|
||||
if (argc > 3) {
|
||||
service = argv[1];
|
||||
d[0] = argv[2];
|
||||
exec = argv[2];
|
||||
sscanf(argv[3], "%d", &idx);
|
||||
} else if (argc == 3) {
|
||||
if (sscanf(argv[2], "%d", &idx) != 1) {
|
||||
service = argv[1];
|
||||
d[0] = argv[2];
|
||||
exec = argv[2];
|
||||
}
|
||||
}
|
||||
ok = rc_service_started_daemon(service,
|
||||
(const char * const *)d, idx);
|
||||
ok = rc_service_started_daemon(service, exec, NULL, idx);
|
||||
|
||||
} else
|
||||
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)
|
||||
{
|
||||
int i = 2;
|
||||
bool match = false;
|
||||
char *p;
|
||||
pid_t pid = 0;
|
||||
|
||||
@@ -394,16 +444,24 @@ void run_applets(int argc, char **argv)
|
||||
if (strcmp(applet, "shell_var") == 0)
|
||||
exit(do_shell_var(argc, argv));
|
||||
|
||||
if (strcmp(applet, "is_newer_than") == 0 ||
|
||||
strcmp(applet, "is_older_than") == 0)
|
||||
{
|
||||
/* This test is perverted - historically the baselayout function
|
||||
* returns 0 on *failure*, which is plain wrong */
|
||||
if (strcmp(applet, "is_older_than") == 0) {
|
||||
if (argc < 3)
|
||||
exit (EXIT_FAILURE);
|
||||
if (strcmp(applet, "is_newer_than") == 0)
|
||||
match = true;
|
||||
while (i < argc) {
|
||||
if (rc_newer_than(argv[1], argv[i++]) != match)
|
||||
exit (EXIT_FAILURE);
|
||||
if (!rc_newer_than(argv[1], argv[i++]))
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
|
||||
#include "einfo.h"
|
||||
#include "rc-logger.h"
|
||||
#include "rc-misc.h"
|
||||
#include "rc.h"
|
||||
#include "rc-misc.h"
|
||||
|
||||
#define LOGFILE RC_SVCDIR "/rc.log"
|
||||
#define PERMLOG "/var/log/rc.log"
|
||||
|
||||
@@ -24,9 +24,14 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RC_LOGGER_H
|
||||
#define RC_LOGGER_H
|
||||
|
||||
pid_t rc_logger_pid;
|
||||
int rc_logger_tty;
|
||||
extern bool rc_in_logger;
|
||||
|
||||
void rc_logger_open (const char *runlevel);
|
||||
void rc_logger_close ();
|
||||
void rc_logger_open(const char *runlevel);
|
||||
void rc_logger_close(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -124,57 +124,49 @@ void env_filter(void)
|
||||
RC_STRINGLIST *profile = NULL;
|
||||
RC_STRINGLIST *env_list;
|
||||
RC_STRING *env;
|
||||
RC_STRING *s;
|
||||
char *env_name;
|
||||
char *e;
|
||||
char *token;
|
||||
size_t i = 0;
|
||||
|
||||
/* Add the user defined list of vars */
|
||||
env_allow = rc_stringlist_new();
|
||||
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);
|
||||
|
||||
env_allow = rc_stringlist_split(rc_conf_value ("rc_env_allow"), " ");
|
||||
if (exists(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();
|
||||
while (environ[i])
|
||||
rc_stringlist_add(env_list, environ[i++]);
|
||||
while (environ[i]) {
|
||||
env = rc_stringlist_add(env_list, environ[i++]);
|
||||
e = strchr(env->value, '=');
|
||||
if (e)
|
||||
*e = '\0';
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(env, env_list, entries) {
|
||||
/* Check the whitelist */
|
||||
i = 0;
|
||||
while (env_whitelist[i]) {
|
||||
if (strcmp(env_whitelist[i++], env->value))
|
||||
for (i = 0; env_whitelist[i]; i++) {
|
||||
if (strcmp(env_whitelist[i], env->value) == 0)
|
||||
break;
|
||||
}
|
||||
if (env_whitelist[i])
|
||||
continue;
|
||||
|
||||
/* Check our user defined list */
|
||||
TAILQ_FOREACH(s, env_allow, entries)
|
||||
if (strcmp(s->value, env->value) == 0)
|
||||
break;
|
||||
if (s)
|
||||
if (rc_stringlist_find(env_allow, env->value))
|
||||
continue;
|
||||
|
||||
/* Now check our profile */
|
||||
|
||||
/* OK, not allowed! */
|
||||
e = strchr(env->value, '=');
|
||||
*e = '\0';
|
||||
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_allow);
|
||||
rc_stringlist_free(profile);
|
||||
@@ -374,3 +366,25 @@ pid_t exec_service(const char *service, const char *arg)
|
||||
|
||||
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;
|
||||
void *handle;
|
||||
int (*hook)(RC_HOOK, const char *);
|
||||
STAILQ_ENTRY(plugin) entries;
|
||||
TAILQ_ENTRY(plugin) entries;
|
||||
} PLUGIN;
|
||||
STAILQ_HEAD(, plugin) plugins;
|
||||
TAILQ_HEAD(, plugin) plugins;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
dlfunc_t dlfunc(void * __restrict handle, const char * __restrict symbol)
|
||||
@@ -87,7 +87,7 @@ void rc_plugin_load(void)
|
||||
if (rc_in_plugin)
|
||||
return;
|
||||
|
||||
STAILQ_INIT(&plugins);
|
||||
TAILQ_INIT(&plugins);
|
||||
|
||||
if (! (dp = opendir(RC_PLUGINDIR)))
|
||||
return;
|
||||
@@ -112,7 +112,7 @@ void rc_plugin_load(void)
|
||||
plugin->name = xstrdup(d->d_name);
|
||||
plugin->handle = h;
|
||||
plugin->hook = fptr;
|
||||
STAILQ_INSERT_TAIL(&plugins, plugin, entries);
|
||||
TAILQ_INSERT_TAIL(&plugins, plugin, entries);
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
@@ -159,7 +159,7 @@ void rc_plugin_run(RC_HOOK hook, const char *value)
|
||||
sigemptyset(&empty);
|
||||
sigfillset(&full);
|
||||
|
||||
STAILQ_FOREACH(plugin, &plugins, entries) {
|
||||
TAILQ_FOREACH(plugin, &plugins, entries) {
|
||||
/* We create a pipe so that plugins can affect our environment
|
||||
* vars, which in turn influence our scripts. */
|
||||
if (pipe(pfd) == -1) {
|
||||
@@ -236,15 +236,15 @@ void rc_plugin_run(RC_HOOK hook, const char *value)
|
||||
|
||||
void rc_plugin_unload(void)
|
||||
{
|
||||
PLUGIN *plugin = STAILQ_FIRST(&plugins);
|
||||
PLUGIN *plugin = TAILQ_FIRST(&plugins);
|
||||
PLUGIN *next;
|
||||
|
||||
while (plugin) {
|
||||
next = STAILQ_NEXT(plugin, entries);
|
||||
next = TAILQ_NEXT(plugin, entries);
|
||||
dlclose(plugin->handle);
|
||||
free(plugin->name);
|
||||
free(plugin);
|
||||
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)
|
||||
{
|
||||
RC_STRINGLIST *l = NULL;
|
||||
RC_STRING *s, *t;
|
||||
RC_STRING *s;
|
||||
char *r = NULL;
|
||||
|
||||
if (! services)
|
||||
@@ -156,10 +156,7 @@ static void print_services(const char *runlevel, RC_STRINGLIST *services)
|
||||
if (!l)
|
||||
return;
|
||||
TAILQ_FOREACH(s, l, entries) {
|
||||
TAILQ_FOREACH(t, services, entries)
|
||||
if (strcmp(t->value, s->value) == 0)
|
||||
break;
|
||||
if (!t)
|
||||
if (!rc_stringlist_find(services, s->value))
|
||||
continue;
|
||||
if (!runlevel || rc_service_in_runlevel(s->value, runlevel))
|
||||
print_service(s->value);
|
||||
@@ -289,6 +286,5 @@ exit:
|
||||
rc_stringlist_free(levels);
|
||||
rc_deptree_free(deptree);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
/* NOTREACHED */
|
||||
return(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
30
src/rc/rc.c
30
src/rc/rc.c
@@ -354,7 +354,7 @@ static void sulogin(bool cont)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void single_user(void)
|
||||
_dead static void single_user(void)
|
||||
{
|
||||
rc_logger_close();
|
||||
|
||||
@@ -756,6 +756,7 @@ static void do_stop_services(const char *newlevel, bool going_down, bool paralle
|
||||
RC_STRING *service, *svc1, *svc2;
|
||||
RC_STRINGLIST *deporder, *tmplist;
|
||||
RC_SERVICE state;
|
||||
RC_STRINGLIST *nostop = rc_stringlist_split(rc_conf_value("rc_nostop"), " ");
|
||||
|
||||
if (! types_n) {
|
||||
types_n = rc_stringlist_new();
|
||||
@@ -768,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)
|
||||
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 */
|
||||
if (going_down || ! start_services) {
|
||||
pid = service_stop(service->value);
|
||||
@@ -777,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 */
|
||||
TAILQ_FOREACH(svc1, start_services, entries)
|
||||
if (strcmp (svc1->value, service->value) == 0)
|
||||
break;
|
||||
|
||||
svc1 = rc_stringlist_find(start_services, service->value);
|
||||
if (svc1) {
|
||||
if (newlevel && strcmp(runlevel, newlevel) != 0) {
|
||||
/* So we're in the start list. But we should
|
||||
@@ -801,14 +805,12 @@ static void do_stop_services(const char *newlevel, bool going_down, bool paralle
|
||||
tmplist = rc_stringlist_new();
|
||||
rc_stringlist_add(tmplist, service->value);
|
||||
deporder = rc_deptree_depends(deptree, types_n, tmplist,
|
||||
runlevel,
|
||||
newlevel ? newlevel : runlevel,
|
||||
RC_DEP_STRICT | RC_DEP_TRACE);
|
||||
rc_stringlist_free(tmplist);
|
||||
svc2 = NULL;
|
||||
TAILQ_FOREACH (svc1, deporder, entries) {
|
||||
TAILQ_FOREACH(svc2, start_services, entries)
|
||||
if (strcmp (svc1->value, svc2->value) == 0)
|
||||
break;
|
||||
svc2 = rc_stringlist_find(start_services, svc1->value);
|
||||
if (svc2)
|
||||
break;
|
||||
}
|
||||
@@ -828,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)
|
||||
@@ -1088,6 +1092,7 @@ int main(int argc, char **argv)
|
||||
going_down = true;
|
||||
rc_runlevel_set(newlevel);
|
||||
setenv("RC_RUNLEVEL", newlevel, 1);
|
||||
setenv("RC_GOINGDOWN", "YES", 1);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* FIXME: we shouldn't have todo this */
|
||||
@@ -1184,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");
|
||||
|
||||
/* Now stop the services that shouldn't be running */
|
||||
@@ -1198,7 +1199,8 @@ int main(int argc, char **argv)
|
||||
wait_for_services();
|
||||
|
||||
/* 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;
|
||||
|
||||
rmdir(RC_STOPPING);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -93,7 +94,6 @@ static bool in_background = false;
|
||||
static RC_HOOK hook_out = 0;
|
||||
static pid_t service_pid = 0;
|
||||
static char *prefix = NULL;
|
||||
static bool prefix_locked = false;
|
||||
static int signal_pipe[2] = { -1, -1 };
|
||||
static int master_tty = -1;
|
||||
|
||||
@@ -315,8 +315,6 @@ static void cleanup(void)
|
||||
restore_state();
|
||||
|
||||
if (! rc_in_plugin) {
|
||||
if (prefix_locked)
|
||||
unlink(PREFIX_LOCK);
|
||||
if (hook_out) {
|
||||
rc_plugin_run(hook_out, applet);
|
||||
if (hook_out == RC_HOOK_SERVICE_START_DONE)
|
||||
@@ -359,7 +357,16 @@ static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) {
|
||||
const char *ec = ecolor(ECOLOR_HILITE);
|
||||
const char *ec_normal = ecolor(ECOLOR_NORMAL);
|
||||
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++) {
|
||||
/* We don't prefix escape codes, like eend */
|
||||
@@ -379,6 +386,9 @@ static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) {
|
||||
ret += write(fd, buffer + i, 1);
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
close(lock_fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -503,22 +513,16 @@ static bool svc_wait(const char *svc)
|
||||
char fifo[PATH_MAX];
|
||||
struct timespec ts;
|
||||
int nloops = WAIT_MAX * (ONE_SECOND / WAIT_INTERVAL);
|
||||
int sloops = (ONE_SECOND / WAIT_INTERVAL) * 5;
|
||||
bool retval = false;
|
||||
bool forever = false;
|
||||
RC_STRINGLIST *keywords;
|
||||
RC_STRING *s;
|
||||
|
||||
/* Some services don't have a timeout, like fsck */
|
||||
keywords = rc_deptree_depend(deptree, svc, "keyword");
|
||||
if (keywords) {
|
||||
TAILQ_FOREACH(s, keywords, entries) {
|
||||
if (strcmp (s->value, "notimeout") == 0) {
|
||||
forever = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rc_stringlist_free (keywords);
|
||||
}
|
||||
if (rc_stringlist_find(keywords, "notimeout"))
|
||||
forever = true;
|
||||
rc_stringlist_free(keywords);
|
||||
|
||||
snprintf(fifo, sizeof(fifo), RC_SVCDIR "/exclusive/%s", basename_c(svc));
|
||||
ts.tv_sec = 0;
|
||||
@@ -537,6 +541,11 @@ static bool svc_wait(const char *svc)
|
||||
|
||||
if (! forever)
|
||||
nloops --;
|
||||
|
||||
if (--sloops == 0) {
|
||||
ewarn("%s: waiting for %s", applet, svc);
|
||||
sloops = (ONE_SECOND / WAIT_INTERVAL) * 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (! exists(fifo))
|
||||
@@ -547,18 +556,18 @@ static bool svc_wait(const char *svc)
|
||||
static RC_SERVICE svc_status(void)
|
||||
{
|
||||
char status[10];
|
||||
int (*e) (const char *fmt, ...) = &einfo;
|
||||
int (*e) (const char *fmt, ...) __EINFO_PRINTF = einfo;
|
||||
RC_SERVICE state = rc_service_state(service);
|
||||
|
||||
if (state & RC_SERVICE_STOPPING) {
|
||||
snprintf(status, sizeof(status), "stopping");
|
||||
e = &ewarn;
|
||||
e = ewarn;
|
||||
} else if (state & RC_SERVICE_STARTING) {
|
||||
snprintf(status, sizeof(status), "starting");
|
||||
e = &ewarn;
|
||||
e = ewarn;
|
||||
} else if (state & RC_SERVICE_INACTIVE) {
|
||||
snprintf(status, sizeof(status), "inactive");
|
||||
e = &ewarn;
|
||||
e = ewarn;
|
||||
} else if (state & RC_SERVICE_STARTED) {
|
||||
errno = 0;
|
||||
if (_rc_can_find_pids() &&
|
||||
@@ -566,7 +575,7 @@ static RC_SERVICE svc_status(void)
|
||||
errno != EACCES)
|
||||
{
|
||||
snprintf(status, sizeof(status), "crashed");
|
||||
e = &eerror;
|
||||
e = eerror;
|
||||
} else
|
||||
snprintf(status, sizeof(status), "started");
|
||||
} else
|
||||
@@ -651,19 +660,6 @@ static void setup_types(void)
|
||||
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)
|
||||
{
|
||||
bool started;
|
||||
@@ -774,8 +770,8 @@ static void svc_start(bool deps)
|
||||
if (state & RC_SERVICE_STARTING &&
|
||||
state & RC_SERVICE_WASINACTIVE)
|
||||
{
|
||||
if (!in_list(need_services, svc->value) &&
|
||||
!in_list(use_services, svc->value))
|
||||
if (!rc_stringlist_find(need_services, svc->value) &&
|
||||
!rc_stringlist_find(use_services, svc->value))
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -785,14 +781,14 @@ static void svc_start(bool deps)
|
||||
state = rc_service_state(svc->value);
|
||||
if (state & RC_SERVICE_STARTED)
|
||||
continue;
|
||||
if (in_list(need_services, svc->value)) {
|
||||
if (rc_stringlist_find(need_services, svc->value)) {
|
||||
if (state & RC_SERVICE_INACTIVE ||
|
||||
state & RC_SERVICE_WASINACTIVE)
|
||||
{
|
||||
if (! tmplist)
|
||||
tmplist = rc_stringlist_new();
|
||||
rc_stringlist_add(tmplist, svc->value);
|
||||
} else
|
||||
} else if (!tmplist)
|
||||
eerrorx("ERROR: cannot start %s as"
|
||||
" %s would not start",
|
||||
applet, svc->value);
|
||||
@@ -1013,7 +1009,7 @@ static void svc_stop(bool deps)
|
||||
continue;
|
||||
svc_wait(svc->value);
|
||||
}
|
||||
rc_stringlist_free (services);
|
||||
rc_stringlist_free(services);
|
||||
services = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
/* nano seconds */
|
||||
#define POLL_INTERVAL 20000000
|
||||
#define WAIT_PIDFILE 500000000
|
||||
#define START_WAIT 100000000
|
||||
#define ONE_SECOND 1000000000
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -94,32 +93,33 @@ typedef struct scheduleitem
|
||||
} type;
|
||||
int value;
|
||||
struct scheduleitem *gotoitem;
|
||||
STAILQ_ENTRY(scheduleitem) entries;
|
||||
TAILQ_ENTRY(scheduleitem) entries;
|
||||
} SCHEDULEITEM;
|
||||
STAILQ_HEAD(, scheduleitem) schedule;
|
||||
TAILQ_HEAD(, scheduleitem) schedule;
|
||||
static char **nav = NULL;
|
||||
|
||||
extern const char *applet;
|
||||
static char *changeuser;
|
||||
static char *changeuser = NULL;
|
||||
|
||||
extern char **environ;
|
||||
|
||||
static void free_schedulelist(void)
|
||||
{
|
||||
SCHEDULEITEM *s1 = STAILQ_FIRST(&schedule);
|
||||
SCHEDULEITEM *s1 = TAILQ_FIRST(&schedule);
|
||||
SCHEDULEITEM *s2;
|
||||
|
||||
while (s1) {
|
||||
s2 = STAILQ_NEXT(s1, entries);
|
||||
s2 = TAILQ_NEXT(s1, entries);
|
||||
free(s1);
|
||||
s1 = s2;
|
||||
}
|
||||
STAILQ_INIT(&schedule);
|
||||
TAILQ_INIT(&schedule);
|
||||
}
|
||||
|
||||
static void cleanup(void)
|
||||
{
|
||||
if (changeuser)
|
||||
free(changeuser);
|
||||
free(changeuser);
|
||||
free(nav);
|
||||
|
||||
free_schedulelist();
|
||||
}
|
||||
@@ -157,7 +157,7 @@ static int parse_signal(const char *sig)
|
||||
unsigned int i = 0;
|
||||
const char *s;
|
||||
|
||||
if (! sig || *sig == '\0')
|
||||
if (!sig || *sig == '\0')
|
||||
return -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->value = timeout;
|
||||
item->gotoitem = NULL;
|
||||
STAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
|
||||
item = xmalloc(sizeof(*item));
|
||||
item->type = SC_TIMEOUT;
|
||||
item->gotoitem = NULL;
|
||||
STAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
if (string) {
|
||||
if (sscanf(string, "%d", &item->value) != 1)
|
||||
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;
|
||||
|
||||
item = parse_schedule_item(buffer);
|
||||
STAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
if (item->type == SC_FOREVER) {
|
||||
if (repeatat)
|
||||
eerrorx("%s: invalid schedule, `forever' "
|
||||
@@ -274,7 +274,7 @@ static void parse_schedule(const char *string, int timeout)
|
||||
item->type = SC_GOTO;
|
||||
item->value = 0;
|
||||
item->gotoitem = repeatat;
|
||||
STAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -289,13 +289,13 @@ static pid_t get_pid(const char *pidfile, bool quiet)
|
||||
return -1;
|
||||
|
||||
if ((fp = fopen(pidfile, "r")) == NULL) {
|
||||
if (! quiet)
|
||||
if (!quiet)
|
||||
eerror("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fscanf(fp, "%d", &pid) != 1) {
|
||||
if (! quiet)
|
||||
if (!quiet)
|
||||
eerror("%s: no pid found in `%s'", applet, pidfile);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
@@ -307,7 +307,7 @@ static pid_t get_pid(const char *pidfile, bool quiet)
|
||||
}
|
||||
|
||||
/* 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,
|
||||
pid_t pid, uid_t uid,int sig,
|
||||
bool quiet, bool verbose, bool test)
|
||||
{
|
||||
@@ -320,14 +320,14 @@ static int do_stop(const char *const *argv, const char *cmd,
|
||||
if (pid)
|
||||
pids = rc_find_pids(NULL, NULL, 0, pid);
|
||||
else
|
||||
pids = rc_find_pids(argv, cmd, uid, pid);
|
||||
pids = rc_find_pids(exec, argv, uid, pid);
|
||||
|
||||
if (! pids)
|
||||
if (!pids)
|
||||
return 0;
|
||||
|
||||
LIST_FOREACH_SAFE(pi, pids, entries, np) {
|
||||
if (test) {
|
||||
if (! quiet)
|
||||
if (!quiet)
|
||||
einfo("Would send signal %d to PID %d",
|
||||
sig, pi->pid);
|
||||
nkilled++;
|
||||
@@ -342,7 +342,7 @@ static int do_stop(const char *const *argv, const char *cmd,
|
||||
eend(killed ? 0 : 1,
|
||||
"%s: failed to send signal %d to PID %d: %s",
|
||||
applet, sig, pi->pid, strerror(errno));
|
||||
if (! killed) {
|
||||
if (!killed) {
|
||||
nkilled = -1;
|
||||
} else {
|
||||
if (nkilled != -1)
|
||||
@@ -356,11 +356,11 @@ static int do_stop(const char *const *argv, const char *cmd,
|
||||
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,
|
||||
bool quiet, bool verbose, bool test)
|
||||
{
|
||||
SCHEDULEITEM *item = STAILQ_FIRST(&schedule);
|
||||
SCHEDULEITEM *item = TAILQ_FIRST(&schedule);
|
||||
int nkilled = 0;
|
||||
int tkilled = 0;
|
||||
int nrunning = 0;
|
||||
@@ -369,14 +369,14 @@ static int run_stop_schedule(const char *const *argv, const char *cmd,
|
||||
pid_t pid = 0;
|
||||
|
||||
if (verbose) {
|
||||
if (exec)
|
||||
einfo ("Will stop %s\n", exec);
|
||||
if (pidfile)
|
||||
einfo("Will stop PID in pidfile `%s'", pidfile);
|
||||
if (uid)
|
||||
einfo("Will stop processes owned by UID %d", uid);
|
||||
if (argv && *argv)
|
||||
einfo("Will stop processes of `%s'", *argv);
|
||||
if (cmd)
|
||||
einfo("Will stop processes called `%s'", cmd);
|
||||
}
|
||||
|
||||
if (pidfile) {
|
||||
@@ -393,7 +393,7 @@ static int run_stop_schedule(const char *const *argv, const char *cmd,
|
||||
|
||||
case SC_SIGNAL:
|
||||
nrunning = 0;
|
||||
nkilled = do_stop(argv, cmd, pid, uid, item->value,
|
||||
nkilled = do_stop(exec, argv, pid, uid, item->value,
|
||||
quiet, verbose, test);
|
||||
if (nkilled == 0) {
|
||||
if (tkilled == 0) {
|
||||
@@ -419,7 +419,7 @@ static int run_stop_schedule(const char *const *argv, const char *cmd,
|
||||
ts.tv_nsec = POLL_INTERVAL;
|
||||
|
||||
while (nloops) {
|
||||
if ((nrunning = do_stop(argv, cmd, pid,
|
||||
if ((nrunning = do_stop(exec, argv, pid,
|
||||
uid, 0, true, false, true)) == 0)
|
||||
return 0;
|
||||
|
||||
@@ -442,7 +442,7 @@ static int run_stop_schedule(const char *const *argv, const char *cmd,
|
||||
}
|
||||
|
||||
if (item)
|
||||
item = STAILQ_NEXT(item, entries);
|
||||
item = TAILQ_NEXT(item, entries);
|
||||
}
|
||||
|
||||
if (test || (tkilled > 0 && nrunning == 0))
|
||||
@@ -466,15 +466,15 @@ static void handle_signal(int sig)
|
||||
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
if (! signame[0])
|
||||
if (!signame[0])
|
||||
snprintf(signame, sizeof(signame), "SIGINT");
|
||||
/* FALLTHROUGH */
|
||||
case SIGTERM:
|
||||
if (! signame[0])
|
||||
if (!signame[0])
|
||||
snprintf(signame, sizeof(signame), "SIGTERM");
|
||||
/* FALLTHROUGH */
|
||||
case SIGQUIT:
|
||||
if (! signame[0])
|
||||
if (!signame[0])
|
||||
snprintf(signame, sizeof(signame), "SIGQUIT");
|
||||
eerrorx("%s: caught %s, aborting", applet, signame);
|
||||
/* NOTREACHED */
|
||||
@@ -499,7 +499,7 @@ static void handle_signal(int sig)
|
||||
|
||||
|
||||
#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[] = {
|
||||
{ "stop", 0, NULL, 'K'},
|
||||
{ "nicelevel", 1, NULL, 'N'},
|
||||
@@ -510,6 +510,7 @@ static const struct option longopts[] = {
|
||||
{ "chuid", 1, NULL, 'c'},
|
||||
{ "chdir", 1, NULL, 'd'},
|
||||
{ "env", 1, NULL, 'e'},
|
||||
{ "umask", 1, NULL, 'k'},
|
||||
{ "group", 1, NULL, 'g'},
|
||||
{ "make-pidfile", 0, NULL, 'm'},
|
||||
{ "name", 1, NULL, 'n'},
|
||||
@@ -529,11 +530,12 @@ static const char * const longopts_help[] = {
|
||||
"Set a nicelevel when starting",
|
||||
"Retry schedule to use when stopping",
|
||||
"Start daemon",
|
||||
"deprecated, use --exec",
|
||||
"deprecated, use --exec or --name",
|
||||
"Force daemon to background",
|
||||
"deprecated, use --user",
|
||||
"Change the PWD",
|
||||
"Set an environment string",
|
||||
"Set the umask for the daemon",
|
||||
"Change the process group",
|
||||
"Create a pidfile",
|
||||
"Match process name",
|
||||
@@ -563,14 +565,14 @@ int start_stop_daemon(int argc, char **argv)
|
||||
#endif
|
||||
|
||||
int opt;
|
||||
bool start = false;
|
||||
bool stop = false;
|
||||
bool start = true;
|
||||
bool oknodo = false;
|
||||
bool test = false;
|
||||
bool quiet;
|
||||
bool verbose = false;
|
||||
char *exec = NULL;
|
||||
char *cmd = NULL;
|
||||
char *startas = NULL;
|
||||
char *name = NULL;
|
||||
char *pidfile = NULL;
|
||||
int sig = SIGTERM;
|
||||
int nicelevel = 0;
|
||||
@@ -585,40 +587,44 @@ int start_stop_daemon(int argc, char **argv)
|
||||
char *redirect_stdout = NULL;
|
||||
int stdout_fd;
|
||||
int stderr_fd;
|
||||
pid_t pid;
|
||||
pid_t pid, spid;
|
||||
int i;
|
||||
char *svcname = getenv("RC_SVCNAME");
|
||||
RC_STRINGLIST *env_list;
|
||||
RC_STRING *env;
|
||||
char *path;
|
||||
char *tmp, *newpath, *np;
|
||||
bool sethome = false;
|
||||
bool setuser = false;
|
||||
char *p;
|
||||
char *tmp;
|
||||
char *token;
|
||||
char exec_file[PATH_MAX];
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
char line[130];
|
||||
FILE *fp;
|
||||
size_t len;
|
||||
bool setumask = false;
|
||||
mode_t numask;
|
||||
char **margv;
|
||||
unsigned int start_wait = 0;
|
||||
|
||||
STAILQ_INIT(&schedule);
|
||||
TAILQ_INIT(&schedule);
|
||||
atexit(cleanup);
|
||||
|
||||
signal_setup(SIGINT, handle_signal);
|
||||
signal_setup(SIGQUIT, handle_signal);
|
||||
signal_setup(SIGTERM, handle_signal);
|
||||
|
||||
if ((path = getenv("SSD_NICELEVEL")))
|
||||
if (sscanf(path, "%d", &nicelevel) != 1)
|
||||
if ((tmp = getenv("SSD_NICELEVEL")))
|
||||
if (sscanf(tmp, "%d", &nicelevel) != 1)
|
||||
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)
|
||||
switch (opt) {
|
||||
case 'K': /* --stop */
|
||||
stop = true;
|
||||
start = false;
|
||||
break;
|
||||
|
||||
case 'N': /* --nice */
|
||||
@@ -696,12 +702,19 @@ int start_stop_daemon(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
if (parse_mode(&numask, optarg))
|
||||
eerrorx("%s: invalid mode `%s'",
|
||||
applet, optarg);
|
||||
setumask = true;
|
||||
break;
|
||||
|
||||
case 'm': /* --make-pidfile */
|
||||
makepidfile = true;
|
||||
break;
|
||||
|
||||
case 'n': /* --name <process-name> */
|
||||
cmd = optarg;
|
||||
name = optarg;
|
||||
break;
|
||||
|
||||
case 'o': /* --oknodo */
|
||||
@@ -724,7 +737,9 @@ int start_stop_daemon(int argc, char **argv)
|
||||
ch_root = optarg;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'a': /* --startas <name> */
|
||||
startas = optarg;
|
||||
break;
|
||||
case 'x': /* --exec <executable> */
|
||||
exec = optarg;
|
||||
break;
|
||||
@@ -740,106 +755,67 @@ int start_stop_daemon(int argc, char **argv)
|
||||
case_RC_COMMON_GETOPT
|
||||
}
|
||||
|
||||
endpwent();
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
quiet = rc_yesno(getenv("EINFO_QUIET"));
|
||||
verbose = rc_yesno(getenv("EINFO_VERBOSE"));
|
||||
|
||||
/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq
|
||||
* instead of forcing --stop --oknodo as well */
|
||||
if (! start && ! stop)
|
||||
if (sig != SIGINT &&
|
||||
sig != SIGTERM &&
|
||||
sig != SIGQUIT &&
|
||||
sig != SIGKILL)
|
||||
{
|
||||
oknodo = true;
|
||||
stop = true;
|
||||
}
|
||||
if (!start &&
|
||||
sig != SIGINT &&
|
||||
sig != SIGTERM &&
|
||||
sig != SIGQUIT &&
|
||||
sig != SIGKILL)
|
||||
oknodo = true;
|
||||
|
||||
if (start == stop)
|
||||
eerrorx("%s: need one of --start or --stop", applet);
|
||||
if (!exec)
|
||||
exec = startas;
|
||||
else if (!name)
|
||||
name = startas;
|
||||
|
||||
if (start && ! exec)
|
||||
eerrorx("%s: --start needs --exec", applet);
|
||||
if (!exec) {
|
||||
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);
|
||||
|
||||
if (makepidfile && ! pidfile)
|
||||
if (makepidfile && !pidfile)
|
||||
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);
|
||||
|
||||
if ((redirect_stdout || redirect_stderr) && ! background)
|
||||
if ((redirect_stdout || redirect_stderr) && !background)
|
||||
eerrorx("%s: --stdout and --stderr are only relevant with --background",
|
||||
applet);
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* 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 (!start) {
|
||||
if (!TAILQ_FIRST(&schedule)) {
|
||||
if (test || oknodo)
|
||||
parse_schedule("0", sig);
|
||||
else
|
||||
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,
|
||||
pidfile, uid, quiet, verbose, test);
|
||||
|
||||
if (result < 0)
|
||||
if (i < 0)
|
||||
/* We failed to stop something */
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
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
|
||||
* remove information about it as it may have unexpectedly
|
||||
@@ -847,21 +823,83 @@ int start_stop_daemon(int argc, char **argv)
|
||||
* result would be the same. */
|
||||
if (pidfile && exists(pidfile))
|
||||
unlink(pidfile);
|
||||
|
||||
if (svcname)
|
||||
rc_service_daemon_set(svcname,
|
||||
rc_service_daemon_set(svcname, exec,
|
||||
(const char *const *)argv,
|
||||
cmd, pidfile, false);
|
||||
|
||||
pidfile, false);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (pidfile) {
|
||||
/* 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
|
||||
else
|
||||
pid = 0;
|
||||
|
||||
if (do_stop((const char * const *)argv, cmd, pid, uid,
|
||||
if (do_stop(exec, (const char * const *)margv, pid, uid,
|
||||
0, true, false, true) > 0)
|
||||
eerrorx("%s: %s is already running", applet, exec);
|
||||
|
||||
@@ -884,6 +922,8 @@ int start_stop_daemon(int argc, char **argv)
|
||||
einfo("in dir `%s'", ch_dir);
|
||||
if (nicelevel != 0)
|
||||
einfo("with a priority of %d", nicelevel);
|
||||
if (name)
|
||||
einfo ("with a process name of %s", name);
|
||||
eoutdent();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@@ -902,6 +942,8 @@ int start_stop_daemon(int argc, char **argv)
|
||||
/* Child process - lets go! */
|
||||
if (pid == 0) {
|
||||
pid_t mypid = getpid();
|
||||
if (setumask)
|
||||
umask(numask);
|
||||
|
||||
#ifdef TIOCNOTTY
|
||||
tty_fd = open("/dev/tty", O_RDWR);
|
||||
@@ -918,7 +960,7 @@ int start_stop_daemon(int argc, char **argv)
|
||||
if (ch_root && chroot(ch_root) < 0)
|
||||
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));
|
||||
|
||||
if (makepidfile && pidfile) {
|
||||
@@ -955,12 +997,12 @@ int start_stop_daemon(int argc, char **argv)
|
||||
else {
|
||||
pw = getpwuid(uid);
|
||||
if (pw) {
|
||||
if (! sethome) {
|
||||
if (!sethome) {
|
||||
unsetenv("HOME");
|
||||
if (pw->pw_dir)
|
||||
setenv("HOME", pw->pw_dir, 1);
|
||||
}
|
||||
if (! setuser) {
|
||||
if (!setuser) {
|
||||
unsetenv("USER");
|
||||
if (pw->pw_name)
|
||||
setenv("USER", pw->pw_name, 1);
|
||||
@@ -996,26 +1038,22 @@ int start_stop_daemon(int argc, char **argv)
|
||||
rc_stringlist_free(env_list);
|
||||
|
||||
/* For the path, remove the rcscript bin dir from it */
|
||||
if ((path = getenv("PATH"))) {
|
||||
size_t mx = strlen(path);
|
||||
char *newpath = xmalloc(mx);
|
||||
char *token;
|
||||
char *np = newpath;
|
||||
size_t l;
|
||||
|
||||
p = path;
|
||||
while ((token = strsep (&p, ":"))) {
|
||||
if (strcmp (token, RC_LIBDIR "/bin") == 0 ||
|
||||
strcmp (token, RC_LIBDIR "/sbin") == 0)
|
||||
if ((tmp = xstrdup(getenv("PATH")))) {
|
||||
len = strlen(tmp);
|
||||
newpath = np = xmalloc(len);
|
||||
p = tmp;
|
||||
while ((token = strsep(&p, ":"))) {
|
||||
if (strcmp(token, RC_LIBDIR "/bin") == 0 ||
|
||||
strcmp(token, RC_LIBDIR "/sbin") == 0)
|
||||
continue;
|
||||
|
||||
l = strlen (token);
|
||||
len = strlen(token);
|
||||
if (np != newpath)
|
||||
*np++ = ':';
|
||||
memcpy (np, token, l);
|
||||
np += l;
|
||||
memcpy(np, token, len);
|
||||
np += len;
|
||||
*np = '\0';
|
||||
}
|
||||
free(tmp);
|
||||
unsetenv("PATH");
|
||||
setenv("PATH", newpath, 1);
|
||||
}
|
||||
@@ -1047,43 +1085,51 @@ int start_stop_daemon(int argc, char **argv)
|
||||
close(i);
|
||||
|
||||
setsid();
|
||||
execv(exec, argv);
|
||||
execvp(exec, argv);
|
||||
#ifdef HAVE_PAM
|
||||
if (pamr == PAM_SUCCESS)
|
||||
pam_close_session(pamh, PAM_SILENT);
|
||||
#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 */
|
||||
if (! background) {
|
||||
/* As we're not backgrounding the process, wait for our pid to return */
|
||||
int status = 0;
|
||||
int savepid = pid;
|
||||
if (!background) {
|
||||
/* As we're not backgrounding the process, wait for our pid
|
||||
* to return */
|
||||
i = 0;
|
||||
spid = pid;
|
||||
|
||||
errno = 0;
|
||||
do {
|
||||
pid = waitpid(savepid, &status, 0);
|
||||
pid = waitpid(spid, &i, 0);
|
||||
if (pid < 1) {
|
||||
eerror("waitpid %d: %s", savepid, strerror(errno));
|
||||
eerror("waitpid %d: %s", spid, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} while (! WIFEXITED(status) && ! WIFSIGNALED(status));
|
||||
|
||||
if (! WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||
if (! quiet)
|
||||
} while (!WIFEXITED(i) && !WIFSIGNALED(i));
|
||||
if (!WIFEXITED(i) || WEXITSTATUS(i) != 0) {
|
||||
if (!quiet)
|
||||
eerrorx("%s: failed to start `%s'", applet, exec);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pid = savepid;
|
||||
pid = spid;
|
||||
}
|
||||
|
||||
/* Wait a little bit and check that process is still running
|
||||
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;
|
||||
int nloops = START_WAIT / POLL_INTERVAL;
|
||||
int nloops = start_wait / POLL_INTERVAL;
|
||||
int nloopsp = WAIT_PIDFILE / POLL_INTERVAL;
|
||||
bool alive = false;
|
||||
|
||||
@@ -1100,30 +1146,35 @@ int start_stop_daemon(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* We wait for a specific amount of time for a pidfile to be
|
||||
* created. Once everything is in place we then wait some more
|
||||
* to ensure that the daemon really is running and won't abort due
|
||||
* to a config error. */
|
||||
if (! background && pidfile && nloopsp)
|
||||
nloopsp --;
|
||||
/* We wait for a specific amount of time for a pidfile
|
||||
* to be created.
|
||||
* Once everything is in place we then wait some more
|
||||
* to ensure that the daemon really is running and won't
|
||||
* abort due to a config error. */
|
||||
if (!background && pidfile && nloopsp)
|
||||
nloopsp--;
|
||||
else
|
||||
nloops --;
|
||||
nloops--;
|
||||
|
||||
/* This is knarly.
|
||||
If we backgrounded then we know the exact pid.
|
||||
Otherwise if we have a pidfile then it *may* know the exact pid.
|
||||
Failing that, we'll have to query processes.
|
||||
We sleep first as some programs like ntp like to fork, and write
|
||||
their pidfile a LONG time later. */
|
||||
* If we backgrounded then we know the exact pid.
|
||||
* Otherwise if we have a pidfile then it *may* know
|
||||
* the exact pid.
|
||||
* Failing that, we'll have to query processes.
|
||||
* We sleep first as some programs like ntp like to
|
||||
* fork, and write their pidfile a LONG time later. */
|
||||
if (background) {
|
||||
if (kill (pid, 0) == 0)
|
||||
alive = true;
|
||||
} else {
|
||||
if (pidfile) {
|
||||
/* The pidfile may not have been written yet - give it some time */
|
||||
/* The pidfile may not have been
|
||||
* written yet - give it some time */
|
||||
if ((pid = get_pid(pidfile, true)) == -1) {
|
||||
if (! nloopsp)
|
||||
eerrorx("%s: did not create a valid pid in `%s'",
|
||||
eerrorx("%s: did not "
|
||||
"create a valid"
|
||||
" pid in `%s'",
|
||||
applet, pidfile);
|
||||
alive = true;
|
||||
pid = 0;
|
||||
@@ -1131,19 +1182,19 @@ int start_stop_daemon(int argc, char **argv)
|
||||
nloopsp = 0;
|
||||
} else
|
||||
pid = 0;
|
||||
if (do_stop((const char *const *)argv, cmd,
|
||||
if (do_stop(exec, (const char *const *)margv,
|
||||
pid, uid, 0, true, false, true) > 0)
|
||||
alive = true;
|
||||
}
|
||||
|
||||
if (! alive)
|
||||
if (!alive)
|
||||
eerrorx("%s: %s died", applet, exec);
|
||||
}
|
||||
}
|
||||
|
||||
if (svcname)
|
||||
rc_service_daemon_set(svcname, (const char *const *)argv,
|
||||
cmd, pidfile, true);
|
||||
rc_service_daemon_set(svcname, exec, (const char *const *)margv,
|
||||
pidfile, true);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
/* NOTREACHED */
|
||||
|
||||
1
src/test/.gitignore
vendored
1
src/test/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
/*.out
|
||||
tmp-*
|
||||
|
||||
@@ -7,5 +7,8 @@ gitignore:
|
||||
check test::
|
||||
./runtests.sh
|
||||
|
||||
verbose-test:
|
||||
VERBOSE=yes ./runtests.sh
|
||||
|
||||
clean:
|
||||
rm -f *.out
|
||||
rm -rf *.out tmp-*
|
||||
|
||||
@@ -11,6 +11,7 @@ rc_deptree_update_needed
|
||||
rc_find_pids
|
||||
rc_getline
|
||||
rc_newer_than
|
||||
rc_older_than
|
||||
rc_runlevel_exists
|
||||
rc_runlevel_get
|
||||
rc_runlevel_list
|
||||
|
||||
@@ -22,6 +22,8 @@ rc_find_pids
|
||||
rc_find_pids@@RC_1.0
|
||||
rc_newer_than
|
||||
rc_newer_than@@RC_1.0
|
||||
rc_older_than
|
||||
rc_older_than@@RC_1.0
|
||||
rc_runlevel_exists
|
||||
rc_runlevel_exists@@RC_1.0
|
||||
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}"
|
||||
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}
|
||||
|
||||
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
|
||||
@@ -9,6 +9,11 @@ srcdir=${srcdir:-.}
|
||||
top_builddir=${top_builddir:-${top_srcdir}}
|
||||
builddir=${builddir:-${srcdir}}
|
||||
|
||||
if ! . ${top_srcdir}/sh/functions.sh; then
|
||||
echo "Sourcing functions.sh failed !?" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH=${top_builddir}/src/libeinfo:${top_builddir}/src/librc:${LD_LIBRARY_PATH}
|
||||
export PATH=${top_builddir}/src/rc:${PATH}
|
||||
|
||||
@@ -16,9 +21,3 @@ cd ${top_srcdir}/src/rc
|
||||
${MAKE:-make} links >/dev/null
|
||||
cd -
|
||||
|
||||
. ${top_srcdir}/sh/functions.sh
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Sourcing functions.sh failed !?" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user