Compare commits

...

88 Commits

Author SHA1 Message Date
Roy Marples
84f6bf4bff Release 0.3 2008-10-02 16:14:13 +00:00
Roy Marples
5f76c1121a Clean stale sockets. 2008-10-01 21:12:54 +00:00
Roy Marples
41c1e170d6 Add an env var so plugins know when leaving single means the end, or start the default level. 2008-10-01 08:46:53 +00:00
Roy Marples
f53197818b Correcly call the right runlevel for plugins when shutting down. 2008-10-01 06:10:34 +00:00
Roy Marples
bb41d2cc80 Use flock to lock PREFIX_LOCK so that multiple processes can cleanly write to the same tty. 2008-09-27 18:50:21 +00:00
Roy Marples
4291b9140e Warn when waiting for a service every few seconds. 2008-09-27 17:17:15 +00:00
Roy Marples
28d7fb9430 When stopping services, check the newlevel if given otherwise the current runlevel. Fixes #100. 2008-09-27 16:56:03 +00:00
Roy Marples
abe94bec6f Load rtc-cmos if needed, Gentoo #235647 thanks to Robin Johnson. 2008-09-27 06:48:21 +00:00
Roy Marples
c3e192a834 Stop ssd from waiting by default - most daemons are good now. 2008-09-26 23:58:57 +00:00
Roy Marples
13d88731b7 We don't check exec when starting, so don't when testing for crashed. 2008-09-22 20:07:14 +00:00
Roy Marples
ffc79a50c2 Style 2008-09-22 19:49:16 +00:00
Roy Marples
6748c0e04e Allow forcefsck instead of gentoo=forcefsck on the kernel command line. 2008-09-22 12:32:35 +00:00
Roy Marples
27805de20a Allow forcefsck on the kernel command line, Gentoo #218431 2008-09-22 12:32:11 +00:00
Roy Marples
53693367df Our match arguments could be different from the exec arguments, as only the kernel should set script arguments. 2008-09-22 12:14:47 +00:00
Roy Marples
554d2fea19 Allow interpreted daemons to detect interperter options. 2008-09-22 10:45:01 +00:00
Roy Marples
a63303971a Document the --verbose option. 2008-09-22 09:37:28 +00:00
Roy Marples
5610c8560c s-s-d now handles interpreted daemons more easily. 2008-09-22 09:34:51 +00:00
Roy Marples
2c62d095c8 Typo. 2008-09-21 09:53:48 +00:00
Roy Marples
a72dc1194a Style. 2008-09-19 11:34:35 +00:00
Roy Marples
dcc4aa131c Document the limitation of symlinking services outside of the service directory, Gentoo #237263. 2008-09-19 11:32:24 +00:00
Roy Marples
6b3d8cf598 Fix stopping wpa_supplicant incorrectly, #107 2008-09-19 11:24:21 +00:00
Roy Marples
600d1f62fb Allow configuration of bond via extra sysfs entries, #105. 2008-09-19 09:32:24 +00:00
Roy Marples
2de401bca1 Enable bonding via sysfs, #104 thanks to Wolfram Schlich 2008-09-18 22:24:58 +00:00
Roy Marples
e368a4b4f8 Add missing profile bits to env, #72. 2008-09-18 19:46:10 +00:00
Roy Marples
354fb96ee9 Use the new rc_stringlist_find function. 2008-09-18 15:36:22 +00:00
Roy Marples
312d6f3e57 Work with NULL lists. 2008-09-18 15:32:57 +00:00
Roy Marples
39ea0cb84d Use the new rc_stringlist_find function. 2008-09-18 15:28:20 +00:00
Roy Marples
17bf78a539 Use the new rc_stringlist_find function. 2008-09-18 15:20:57 +00:00
Roy Marples
072328ff60 rc_nostop now lists services we should not stop on shutdown. 2008-09-18 15:13:53 +00:00
Roy Marples
e0dfa472d1 Add new functions, rc_stringlist_find and rc_stringlist_split. 2008-09-18 15:12:43 +00:00
Roy Marples
ccc24d1086 Add a config file for ipfw, #110 2008-09-18 14:25:23 +00:00
Roy Marples
c4c024fc9d Allow an empty bridge with no options, Gentoo #237485. 2008-09-18 14:13:33 +00:00
Roy Marples
223015920c Warn about parallel still locking the system. 2008-09-18 13:59:05 +00:00
Roy Marples
aa02a5516a Use better CFLAGS - some new warnings will need to be fixed. 2008-09-18 13:49:58 +00:00
Roy Marples
80a17eb596 Clean up some compile warnings. 2008-09-18 13:09:51 +00:00
Roy Marples
39304745d4 Allow interpreted daemons to use s-s-d a little easier. 2008-09-17 16:56:23 +00:00
Roy Marples
93a3b2dd02 Fix iwconfig parsing on Linux, #111 thanks to Andrew Gaffney. 2008-09-04 14:54:56 +00:00
Roy Marples
00d010fbe0 Work without IP6 kernels, #108 2008-08-29 06:43:54 +00:00
Roy Marples
01de348ede Add rpc.lockd to netmount.in for BSD 2008-08-27 16:06:01 +00:00
Roy Marples
fabee4dc2d Actually set the umask. 2008-08-20 10:19:03 +00:00
Roy Marples
1ab1e9328a Add -k,--umask option, Gentoo #232455. 2008-08-20 10:02:11 +00:00
Roy Marples
a9f7d2d5e5 Allow dhcpcd to use global dhcpcd variable for commandline options. 2008-08-19 22:30:59 +00:00
Roy Marples
a3c8706618 Allow OpenVZ to mount /sys and device managers, #102 2008-08-19 15:27:15 +00:00
Roy Marples
1f227d62bf Allow renaming of modules, #103 thanks to Sven. 2008-08-19 15:25:06 +00:00
Roy Marples
cdace75539 OpenVZ can mount NFS shares. 2008-08-19 06:44:47 +00:00
Roy Marples
15678263d5 Add new OpenVZ detection code 2008-08-19 06:36:43 +00:00
Roy Marples
cea206014d Attempt to make s-s-d simpler by not enforcing the need for a full path and maybe working better with interpreted scripts. 2008-07-27 11:30:49 +00:00
Roy Marples
46a74f244e Typo 2008-07-24 19:02:28 +00:00
Roy Marples
c67233f15c Don't set silly defaults that may brake users. 2008-07-09 18:28:45 +00:00
Roy Marples
b15c4758f8 We should unmount / here. 2008-07-09 18:28:14 +00:00
Roy Marples
289889ebf0 Fix unmounting some more. 2008-07-09 17:05:10 +00:00
Roy Marples
7183cb1b18 Fix last commit 2008-07-09 16:20:48 +00:00
Roy Marples
b83108cd2e Add a knob to avoid the unmounting of some points. 2008-07-09 16:08:38 +00:00
Roy Marples
1ca63447c9 Hide mkdir error's 2008-07-09 15:22:15 +00:00
Roy Marples
c2781c209e Really test if we can write to RC_LIBDIR or not. 2008-07-09 15:12:56 +00:00
Roy Marples
5983add0f2 No point in re-mounting ro filesystems that are already ro. 2008-07-09 14:24:48 +00:00
Roy Marples
a566493eb8 Ignore core files 2008-07-09 14:04:40 +00:00
Roy Marples
bdd8b150cd Fix return display. 2008-07-09 13:36:37 +00:00
Roy Marples
53401cd35f STAILQ -> TAILQ 2008-07-08 10:48:21 +00:00
Roy Marples
7a6112d3b0 Punt STAILQ and just use TAILQ so we're a bit more portable. 2008-07-07 14:16:46 +00:00
Roy Marples
157db50df7 Fix is_older_than a little better, and make is_newer_than correct. 2008-07-03 13:30:17 +00:00
Roy Marples
a88a177f99 Add older_than function to complement newer_than function. Also make the userland instance reversed to be compatable with current baselayout, which truely does suck. 2008-07-03 13:11:47 +00:00
Roy Marples
d61f831896 More unit fixes. 2008-07-03 13:09:24 +00:00
Roy Marples
28a65393ca More unit fixes. 2008-07-03 13:09:10 +00:00
Roy Marples
aa57dd1ff6 More unit fixes. 2008-07-03 12:33:42 +00:00
Roy Marples
e0968a1c2e Fix test. 2008-07-03 12:20:32 +00:00
Roy Marples
2f5d2855ba Add an is_older_than unit test, thanks to zzam 2008-07-03 12:07:46 +00:00
Roy Marples
db9bf18587 Fix compile with pcc. 2008-07-02 23:20:04 +00:00
Roy Marples
feac5ea1d5 Ignore ewaitfile. 2008-06-30 13:36:59 +00:00
Roy Marples
64dbae7f61 If filtering fstab, only match additional mounts asked for. 2008-06-30 13:33:42 +00:00
Roy Marples
11e4059b05 Set the default RC_SVCDIR higher up. 2008-06-21 15:31:04 +00:00
Roy Marples
5510451bac We need to replace @LIB@ here. 2008-06-21 14:10:59 +00:00
Roy Marples
11acce3c7d Use CPPFLAGS so we work with -combine in CFLAGS. 2008-06-19 23:12:00 +00:00
Roy Marples
4f2bb5ceaf open should use 3 args when using O_CREAT. 2008-06-17 15:14:33 +00:00
Roy Marples
bf8f0da921 fuzzy dependency ordering should be started, starting, stopped whilst checking runlevel, bootlevel, any at each stage. 2008-06-10 15:19:46 +00:00
Roy Marples
9b1cb4e246 When we have dependant scheduled services, don't error if a need is stopped. 2008-06-10 15:04:29 +00:00
Roy Marples
2adc99a8f5 No need to include this. 2008-06-05 12:26:53 +00:00
Roy Marples
fc747f9894 Remove the macro ;) 2008-06-05 12:19:49 +00:00
Roy Marples
76063daee5 Update style to more BSDish and replace the big macro with a function. 2008-06-05 12:17:41 +00:00
Roy Marples
dc891b0647 Remove broken before dependencies, Gentoo #224171. 2008-06-05 10:14:11 +00:00
Roy Marples
3525e602d6 Use addu instead of another loop. 2008-06-04 19:07:09 +00:00
Roy Marples
79ebd89d19 Only add a backreference if it doesn't already exist. 2008-06-04 19:00:46 +00:00
Roy Marples
ba8008fb05 Include time headers for ewaitfile. 2008-06-04 14:09:25 +00:00
Roy Marples
5e2c3fb5fe Merge branch 'master' of git@git.overlays.gentoo.org:proj/openrc 2008-06-04 12:58:05 +00:00
Roy Marples
e6aed12328 No need to check type twice like this. 2008-06-04 12:47:06 +00:00
Roy Marples
83ade5b701 Style. 2008-06-04 12:44:45 +00:00
Roy Marples
587051ec67 Add the ewaitfile function so init scripts can wait until sockts are created, Gentoo #175783. 2008-06-03 11:57:15 +00:00
Roy Marples
f2ea7ca514 Let ifdown control all interfaces. 2008-06-03 11:51:36 +00:00
84 changed files with 1399 additions and 1006 deletions

View File

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

View File

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

View File

@@ -1 +1 @@
CONF+= moused powerd rarpd savecore syscons
CONF+= ipfw moused powerd rarpd savecore syscons

14
conf.d/ipfw Normal file
View 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
View 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"

View File

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

View File

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

View File

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

View File

@@ -89,6 +89,10 @@ start()
! -name random-seed ! -name dev.db \
! -name ld-elf.so.hints ! -name ld.so.hints);
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -8,6 +8,6 @@ CLEANFILES+= .depend
IGNOREFILES+= .depend
.depend: ${SRCS}
${CC} ${CFLAGS} -MM ${SRCS} > .depend
${CC} ${CPPFLAGS} -MM ${SRCS} > .depend
depend: .depend

View File

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

View File

@@ -1,3 +1,3 @@
LIBTERMCAP?= -lncurses
CFLAGS+= -DHAVE_TERMCAP
CPPFLAGS+= -DHAVE_TERMCAP
LDADD+= ${LIBTERMCAP}

View File

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

View File

@@ -1,5 +1,5 @@
LIBPAM?= -lpam
CFLAGS+= -DHAVE_PAM
CPPFLAGS+= -DHAVE_PAM
LDADD+= ${LIBPAM}
PAMDIR?= /etc/pam.d

View File

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

View File

@@ -1,3 +1,3 @@
LIBTERMCAP?= -ltermcap
CFLAGS+= -DHAVE_TERMCAP
CPPFLAGS+= -DHAVE_TERMCAP
LDADD+= ${LIBTERMCAP}

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

@@ -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##*=}"

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,7 @@ VERSION_MAP= rc.map
LDADD+= ${LIBKVM}
CFLAGS+= -I../includes
CPPFLAGS+= -I../includes
MK= ../../mk
include ${MK}/lib.mk

View File

@@ -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,26 +305,26 @@ 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;
while (argv && argv[i]) {
l = strlen(*argv) + strlen("argv_=") + 16;
if (exec) {
l = strlen(exec) + 6;
m = xmalloc(sizeof(char) * l);
snprintf(m, l, "argv_0=%s", argv[i++]);
snprintf(m, l, "exec=%s", exec);
rc_stringlist_add(match, m);
free(m);
}
if (name) {
l = strlen(name) + 6;
m = xmalloc(sizeof (char) * l);
snprintf(m, l, "name=%s", name);
while (argv && argv[i]) {
l = strlen(*argv) + strlen("argv_=") + 16;
m = xmalloc(sizeof(char) * l);
snprintf(m, l, "argv_0=%s", argv[i++]);
rc_stringlist_add(match, m);
free(m);
}
@@ -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) {

View File

@@ -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;
return ((strcmp (runlevel, bootlevel) != 0 &&
if (!runlevel ||
strcmp(type, "ineed") == 0 ||
strcmp(type, "needsme") == 0)
return true;
state = rc_service_state(service);
return ((strcmp(runlevel, bootlevel) != 0 &&
rc_service_in_runlevel(service, bootlevel)) ||
rc_service_in_runlevel(service, 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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

@@ -481,6 +481,5 @@ int mountinfo(int argc, char **argv)
REG_FREE(point_regex);
REG_FREE(skip_point_regex);
exit(result);
/* NOTREACHED */
return result;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

@@ -1 +1,2 @@
/*.out
tmp-*

View File

@@ -7,5 +7,8 @@ gitignore:
check test::
./runtests.sh
verbose-test:
VERBOSE=yes ./runtests.sh
clean:
rm -f *.out
rm -rf *.out tmp-*

View File

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

View File

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

View File

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

@@ -0,0 +1 @@
tmp-*

71
src/test/units/is_older_than Executable file
View 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

View File

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