From 0af7d5bc204cd6b7d03f22aacf4072c5f526c0ee Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 3 Nov 2008 15:31:01 +0000 Subject: Add a new shutdown runlevel, Gentoo #224537. Split halt.sh into halt, killprocs, romount and savecache services. The reboot runlevel is removed but mapped to shutdown. The halt script should be moved to the sysvinit package. --- etc/Makefile | 2 + init.d/.gitignore | 5 ++- init.d/Makefile | 4 +- init.d/Makefile.Linux | 8 +++- init.d/halt.in | 23 ++++++++++ init.d/halt.sh.in | 112 ---------------------------------------------- init.d/killprocs.in | 15 +++++++ init.d/romount.in | 43 ++++++++++++++++++ init.d/savecache.in | 25 +++++++++++ man/rc.8 | 4 +- runlevels/Makefile | 10 +++++ runlevels/Makefile.Linux | 4 ++ sh/init-common-post.sh.in | 12 +++-- sh/init.sh.BSD.in | 21 --------- sh/init.sh.Linux.in | 30 +++---------- src/librc/librc-depend.c | 6 +-- src/librc/rc.h.in | 1 - src/rc/rc.c | 79 +++++++++++++++++++------------- src/rc/runscript.c | 5 ++- 19 files changed, 199 insertions(+), 210 deletions(-) create mode 100644 init.d/halt.in delete mode 100644 init.d/halt.sh.in create mode 100644 init.d/killprocs.in create mode 100644 init.d/romount.in create mode 100644 init.d/savecache.in diff --git a/etc/Makefile b/etc/Makefile index 8b43544..ee1642e 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -1,6 +1,8 @@ DIR= ${SYSCONFDIR} CONF= rc.conf +CLEANFILES+= rc.conf + MK= ../mk include ${MK}/os.mk include Makefile.${OS} diff --git a/init.d/.gitignore b/init.d/.gitignore index d7322d6..dace4de 100644 --- a/init.d/.gitignore +++ b/init.d/.gitignore @@ -2,12 +2,15 @@ bootmisc devfs dmesg fsck -halt.sh +halt hostname +killprocs local localmount netmount +romount root +savecache swap sysctl urandom diff --git a/init.d/Makefile b/init.d/Makefile index 07d41a1..fd2c87d 100644 --- a/init.d/Makefile +++ b/init.d/Makefile @@ -1,6 +1,6 @@ DIR= ${INITDIR} -SRCS= bootmisc.in fsck.in halt.sh.in hostname.in local.in localmount.in \ - netmount.in root.in swap.in sysctl.in urandom.in +SRCS= bootmisc.in fsck.in hostname.in local.in localmount.in \ + netmount.in root.in savecache.in swap.in sysctl.in urandom.in BIN= ${OBJS} INSTALLAFTER= _installafter diff --git a/init.d/Makefile.Linux b/init.d/Makefile.Linux index be519c8..1bf3fe7 100644 --- a/init.d/Makefile.Linux +++ b/init.d/Makefile.Linux @@ -1,7 +1,11 @@ NET_LO= net.lo -SRCS+= devfs.in dmesg.in hwclock.in consolefont.in keymaps.in modules.in \ - mtab.in numlock.in procfs.in sysfs.in termencoding.in +SRCS+= devfs.in dmesg.in hwclock.in consolefont.in keymaps.in killprocs.in \ + modules.in mtab.in numlock.in procfs.in romount.in sysfs.in \ + termencoding.in + +# This really belongs with sysvinit +SRCS+= halt.in .SUFFIXES: .Linux.in .Linux.in: diff --git a/init.d/halt.in b/init.d/halt.in new file mode 100644 index 0000000..b8f9ed9 --- /dev/null +++ b/init.d/halt.in @@ -0,0 +1,23 @@ +#!@PREFIX@/sbin/runscript +# Copyright 2007-2008 Roy Marples +# All rights reserved. Released under the 2-clause BSD license. + +# This script really belongs with the Linux sysvinit package + +depend() +{ + after * + use romount +} + +start() +{ + case "${RUNLEVEL}" in + 0) runlevel=shutdown;; + 6) runlevel=reboot;; + *) eerror "Unknown runlevel ${RUNLEVEL}"; return 1 + esac + + . /etc/init.d/"${runlevel}".sh + return 0 +} diff --git a/init.d/halt.sh.in b/init.d/halt.sh.in deleted file mode 100644 index ab73d8d..0000000 --- a/init.d/halt.sh.in +++ /dev/null @@ -1,112 +0,0 @@ -#!@SHELL@ -# Copyright 2007-2008 Roy Marples -# All rights reserved. Released under the 2-clause BSD license. - -. @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 - -# Really kill things off before unmounting -if [ -x /sbin/killall5 ]; then - killall5 -15 - killall5 -9 -fi - -# Flush all pending disk writes now -sync; sync - -# If we are in a VPS, we don't need anything below here, because -# 1) we don't need (and by default can't) umount anything (VServer) or -# 2) the host utils take care of all umounting stuff (OpenVZ) -if [ "${RC_SYS}" = "VSERVER" -o "${RC_SYS}" = "OPENVZ" ]; then - [ "${RC_SYS}" = "OPENVZ" -a "$1" = "reboot" ] && echo "" > /reboot - if [ -e @SYSCONFDIR@/init.d/"$1".sh ]; then - . @SYSCONFDIR@/init.d/"$1".sh - else - exit 0 - fi -fi - -# If $svcdir is still mounted, preserve it if we can -mnt=$(mountinfo --node "${RC_SVCDIR}") -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 - if [ -n "$(fuser ${f_opts} "${svcdir}" 2>/dev/null)" ]; then - fuser -k ${f_opts} "${svcdir}" >/dev/null 2>&1 - sleep 2 - fi - fi - cp -p "${RC_SVCDIR}"/deptree "${RC_SVCDIR}"/depconfig \ - "${RC_SVCDIR}"/softlevel "${RC_SVCDIR}"/nettree \ - "${RC_SVCDIR}"/rc.log \ - "${RC_LIBDIR}" 2>/dev/null - umount "${RC_SVCDIR}" - rm -rf "${RC_SVCDIR}"/* - # Pipe errors to /dev/null as we may have future timestamps - cp -p "${RC_LIBDIR}"/deptree "${RC_LIBDIR}"/depconfig \ - "${RC_LIBDIR}"/softlevel "${RC_LIBDIR}"/nettree \ - "${RC_LIBDIR}"/rc.log \ - "${RC_SVCDIR}" 2>/dev/null - rm -f "${RC_LIBDIR}"/deptree "${RC_LIBDIR}"/depconfig \ - "${RC_LIBDIR}"/softlevel "${RC_LIBDIR}"/nettree \ - "${RC_LIBDIR}"/rc.log - # Release the memory disk if we used it - case "${mnt}" in - "/dev/md"[0-9]*) mdconfig -d -u "${mnt#/dev/md*}";; - esac -fi - -unmounted=0 -# Remount the remaining filesystems read-only -# Most BSD's don't need this as the kernel handles it nicely -if [ "${RC_UNAME}" = "Linux" ]; then - ebegin "Remounting remaining filesystems read-only" - # 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 "${no_umounts_r}" \ - ${fs:+--skip-fstype-regex} ${fs} --nonetdev - eoutdent - eend $? - unmounted=$? -fi - -if [ ${unmounted} -ne 0 ]; then - if [ -x /sbin/sulogin ]; then - ewarn "$1 timeout in 30 seconds" - sulogin -t 30 /dev/console - fi -fi - -# Load the final script - not needed on BSD so they should not exist -[ -e @SYSCONFDIR@/init.d/"$1".sh ] && . @SYSCONFDIR@/init.d/"$1".sh - -# Always exit 0 here -exit 0 diff --git a/init.d/killprocs.in b/init.d/killprocs.in new file mode 100644 index 0000000..a969d52 --- /dev/null +++ b/init.d/killprocs.in @@ -0,0 +1,15 @@ +#!@PREFIX@/sbin/runscript +# Copyright 2007-2008 Roy Marples +# All rights reserved. Released under the 2-clause BSD license. + +start() +{ + ebegin "Terminating remaining processes" + killall5 -15 + sleep 1 + eend 0 + ebegin "Killing remaining processes" + killall5 -9 + sleep 1 + eend 0 +} diff --git a/init.d/romount.in b/init.d/romount.in new file mode 100644 index 0000000..d1adaad --- /dev/null +++ b/init.d/romount.in @@ -0,0 +1,43 @@ +#!@PREFIX@/sbin/runscript +# Copyright 2007-2008 Roy Marples +# All rights reserved. Released under the 2-clause BSD license. + +depend() +{ + need killprocs savecache + keywords noopenvz novserver +} + +start() +{ + # Flush all pending disk writes now + sync; sync + + ebegin "Remounting remaining filesystems read-only" + # We need the do_unmount function + . "${RC_LIBDIR}"/sh/rc-mount.sh + eindent + local m="/dev|/dev/.*|/proc|/proc.*|/sys|/sys/.*|${RC_SVCDIR}" x= fs= + # RC_NO_UMOUNTS is an env var that can be set by plugins + local OIFS=$IFS SIFS=${IFS-y} IFS=$IFS + IFS=$IFS: + for x in ${no_umounts} ${RC_NO_UMOUNTS}; do + m="${m}|${x}" + done + if [ "${SIFS}" = y ]; then + IFS=$OIFS + else + unset IFS + fi + m="^(${m})$" + 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 "${m}" \ + ${fs:+--skip-fstype-regex} ${fs} --nonetdev + eoutdent + eend $? +} diff --git a/init.d/savecache.in b/init.d/savecache.in new file mode 100644 index 0000000..57ed50c --- /dev/null +++ b/init.d/savecache.in @@ -0,0 +1,25 @@ +#!@PREFIX@/sbin/runscript +# Copyright 2007-2008 Roy Marples +# All rights reserved. Released under the 2-clause BSD license. + +description="Saves the caches OpenRC uses to non volatile storage" + +start() +{ + ebegin "Saving dependency cache" + if [ ! -d "${RC_LIBDIR}"/cache ]; then + rm -rf "${RC_LIBDIR}"/cache + if ! mkdir "${RC_LIBDIR}"/cache; then + eend $? + return $? + fi + fi + local save= + for x in deptree depconfig softlevel nettree rc.log; do + [ -e "${RC_SVCDIR}/${x}" ] && save="${save} ${RC_SVCDIR}/${x}" + done + if [ -n "${save}" ]; then + cp -p ${save} "${RC_LIBDIR}"/cache 2>/devnull + fi + eend $? +} diff --git a/man/rc.8 b/man/rc.8 index e0e3198..d4609ee 100644 --- a/man/rc.8 +++ b/man/rc.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 27, 2008 +.Dd November 03, 2008 .Dt RC 8 SMM .Os OpenRC .Sh NAME @@ -65,8 +65,6 @@ All services in the boot and sysinit runlevels are automatically included in all other runlevels except for those listed here. .It Ar single Stops all services except for those in the sysinit runlevel. -.It Ar reboot -Changes to the single runlevel and then reboots the host. .It Ar shutdown Changes to the single runlevel and then halts the host. .El diff --git a/runlevels/Makefile b/runlevels/Makefile index 9e3131a..b8a830a 100644 --- a/runlevels/Makefile +++ b/runlevels/Makefile @@ -1,11 +1,13 @@ BOOT= bootmisc fsck hostname localmount \ root swap sysctl urandom DEFAULT= local netmount +SHUTDOWN= savecache LEVELDIR= ${DESTDIR}/${SYSCONFDIR}/runlevels SYSINITDIR= ${LEVELDIR}/sysinit BOOTDIR= ${LEVELDIR}/boot DEFAULTDIR= ${LEVELDIR}/default +SHUTDOWNDIR= ${LEVELDIR}/shutdown INITDIR= ../init.d @@ -44,6 +46,14 @@ install: fi; \ ln -snf ${PREFIX}/etc/init.d/"$$x" ${DEFAULTDIR}/"$$x" || exit $$?; done \ fi + if ! test -d "${SHUTDOWNDIR}"; then \ + ${INSTALL} -d ${SHUTDOWNDIR} || exit $$?; \ + for x in ${SHUTDOWN}; do \ + if test -n "${PREFIX}"; then \ + grep -q "keyword .*noprefix" ${INITDIR}/"$$x" && continue; \ + fi; \ + ln -snf ${PREFIX}/etc/init.d/"$$x" ${SHUTDOWNDIR}/"$$x" || exit $$?; done \ + fi check test:: diff --git a/runlevels/Makefile.Linux b/runlevels/Makefile.Linux index c5649b2..8e086aa 100644 --- a/runlevels/Makefile.Linux +++ b/runlevels/Makefile.Linux @@ -1,2 +1,6 @@ SYSINIT+= devfs dmesg BOOT+= hwclock keymaps modules mtab net.lo procfs termencoding +SHUTDOWN+= killprocs romount + +# This really belongs with sysvinit +SHUTDOWN+= halt diff --git a/sh/init-common-post.sh.in b/sh/init-common-post.sh.in index 2b1641d..aa264aa 100644 --- a/sh/init-common-post.sh.in +++ b/sh/init-common-post.sh.in @@ -9,17 +9,15 @@ retval=0 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}/*; do - [ -e "${x}" ] || continue - case ${x##*/} in - depconfig|deptree|ksoftlevel|rc.log);; - *) rm -rf "${x}";; - esac - done + rm -rf "${RC_SVCDIR}"/* else mount_svcdir retval=$? fi +if [ -e "${RC_LIBDIR}"/cache/deptree ]; then + cp -p "${RC_LIBDIR}"/cache/* "${RC_SVCDIR}" 2>/dev/null +fi + echo "sysinit" > "${RC_SVCDIR}/softlevel" exit ${retval} diff --git a/sh/init.sh.BSD.in b/sh/init.sh.BSD.in index dbff736..652a3de 100644 --- a/sh/init.sh.BSD.in +++ b/sh/init.sh.BSD.in @@ -10,18 +10,6 @@ # FreeBSD-7 supports tmpfs now :) mount_svcdir() { - local dotmp=false release=false retval=0 - if [ -e "${RC_SVCDIR}"/deptree ]; then - dotmp=true - if ! mount -t tmpfs none "${RC_LIBDIR}"/tmp 2>/dev/null; then - mdconfig -a -t malloc -s 1m -u 1 - newfs /dev/md1 - mount /dev/md1 "${RC_LIBDIR}"/tmp - release=true - fi - cp -p "${RC_SVCDIR}"/deptree "${RC_SVCDIR}"/depconfig \ - "${RC_SVCDIR}"/nettree "${RC_LIBDIR}"/tmp 2>/dev/null - fi if ! fstabinfo --mount "${RC_SVCDIR}"; then if ! mount -t tmpfs -o rw,noexec,nosuid none "${RC_SVCDIR}" 2>/dev/null; then mdconfig -a -t malloc -s "${rc_svcsize:-1024}"k -u 0 @@ -29,15 +17,6 @@ mount_svcdir() mount -o rw,noexec,nosuid /dev/md0 "${RC_SVCDIR}" fi fi - retval=$? - if ${dotmp}; then - cp -p "${RC_LIBDIR}"/tmp/deptree "${RC_LIBDIR}"/tmp/depconfig \ - "${RC_LIBDIR}"/tmp/nettree "${RC_SVCDIR}" 2>/dev/null - umount "${RC_LIBDIR}"/tmp - ${release} && mdconfig -d -u 1 - fi - - return ${retval} } . "${RC_LIBDIR}"/sh/functions.sh diff --git a/sh/init.sh.Linux.in b/sh/init.sh.Linux.in index 6d99d49..f38fe4e 100644 --- a/sh/init.sh.Linux.in +++ b/sh/init.sh.Linux.in @@ -3,14 +3,13 @@ # Copyright 2007-2008 Roy Marples # All rights reserved. Released under the 2-clause BSD license. -# This basically mounts $RC_SVCDIR as a ramdisk, but preserving its content -# which allows us to store service state and generate dependencies if needed. +# This basically mounts $RC_SVCDIR as a ramdisk. # The tricky part is finding something our kernel supports # tmpfs and ramfs are easy, so force one or the other. mount_svcdir() { local fs= fsopts="-o rw,noexec,nodev,nosuid" - local devdir="rc-svcdir" devtmp="none" x= + local devdir="rc-svcdir" x= local svcsize=${rc_svcsize:-1024} if grep -Eq "[[:space:]]+tmpfs$" /proc/filesystems; then @@ -19,41 +18,24 @@ mount_svcdir() elif grep -Eq "[[:space:]]+ramfs$" /proc/filesystems; then fs="ramfs" # ramfs has no special options - elif [ -e /dev/ram0 -a -e /dev/ram1 ] \ + elif [ -e /dev/ram0 ] \ && grep -Eq "[[:space:]]+ext2$" /proc/filesystems; then devdir="/dev/ram0" - devtmp="/dev/ram1" fs="ext2" - for x in ${devdir} ${devtmp}; do - dd if=/dev/zero of="${x}" bs=1k count="${svcsize}" - mkfs -t "${fs}" -i 1024 -vm0 "${x}" "${svcsize}" - done + dd if=/dev/zero of="${devdir}" bs=1k count="${svcsize}" + mkfs -t "${fs}" -i 1024 -vm0 "${devdir}" "${svcsize}" else echo - eerror "OpenRC requires tmpfs, ramfs or 2 ramdisks + ext2" + eerror "OpenRC requires tmpfs, ramfs or a ramdisk + ext2" eerror "compiled into the kernel" echo return 1 fi - local dotmp=false - if [ -e "${RC_SVCDIR}"/deptree ]; then - dotmp=true - mount -n -t "${fs}" -o rw "${devtmp}" "${RC_LIBDIR}"/tmp - cp -p "${RC_SVCDIR}"/deptree "${RC_SVCDIR}"/depconfig \ - "${RC_SVCDIR}"/nettree "${RC_LIBDIR}"/tmp 2>/dev/null - fi - # If we have no entry in fstab for $RC_SVCDIR, provide our own if ! fstabinfo --mount "${RC_SVCDIR}"; then mount -n -t "${fs}" ${fsopts} "${devdir}" "${RC_SVCDIR}" fi - - if ${dotmp}; then - cp -p "${RC_LIBDIR}"/tmp/deptree "${RC_LIBDIR}"/tmp/depconfig \ - "${RC_LIBDIR}"/tmp/nettree "${RC_SVCDIR}" 2>/dev/null - umount -n "${RC_LIBDIR}"/tmp - fi } . /etc/init.d/functions.sh diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c index 739e6fc..2c05ea1 100644 --- a/src/librc/librc-depend.c +++ b/src/librc/librc-depend.c @@ -189,7 +189,8 @@ valid_service(const char *runlevel, const char *service, const char *type) if (rc_service_in_runlevel(service, runlevel)) return true; - if (strcmp(runlevel, RC_LEVEL_SYSINIT) != 0 && + if (strcmp(runlevel, RC_LEVEL_SHUTDOWN) != 0 && + strcmp(runlevel, RC_LEVEL_SYSINIT) != 0 && strcmp(runlevel, bootlevel) != 0) { if (rc_service_in_runlevel(service, bootlevel)) @@ -499,8 +500,7 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options) /* 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) + strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0) { list = rc_services_in_state(RC_SERVICE_STARTED); list2 = rc_services_in_state(RC_SERVICE_INACTIVE); diff --git a/src/librc/rc.h.in b/src/librc/rc.h.in index 92fb19c..6f7c64e 100644 --- a/src/librc/rc.h.in +++ b/src/librc/rc.h.in @@ -70,7 +70,6 @@ typedef TAILQ_HEAD(rc_stringlist, rc_string) RC_STRINGLIST; #define RC_LEVEL_SYSINIT "sysinit" #define RC_LEVEL_SINGLE "single" #define RC_LEVEL_SHUTDOWN "shutdown" -#define RC_LEVEL_REBOOT "reboot" /*! Return the current runlevel. * @return the current runlevel */ diff --git a/src/rc/rc.c b/src/rc/rc.c index a6cde11..995cc91 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -831,6 +831,11 @@ main(int argc, char **argv) } newlevel = argv[optind++]; + /* For compat with old system */ + if (newlevel) { + if (strcmp(newlevel, "reboot") == 0) + newlevel = UNCONST(RC_LEVEL_SHUTDOWN); + } /* Enable logging */ setenv("EINFO_LOG", "rc", 1); @@ -875,8 +880,7 @@ main(int argc, char **argv) set_krunlevel(NULL); if (newlevel && - (strcmp(newlevel, RC_LEVEL_REBOOT) == 0 || - strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 || + (strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 || strcmp(newlevel, RC_LEVEL_SINGLE) == 0)) { going_down = true; @@ -887,9 +891,9 @@ main(int argc, char **argv) #ifdef __FreeBSD__ /* FIXME: we shouldn't have todo this */ - /* For some reason, wait_for_services waits for the logger proccess - * to finish as well, but only on FreeBSD. We cannot allow this so - * we stop logging now. */ + /* For some reason, wait_for_services waits for the logger + * proccess to finish as well, but only on FreeBSD. + * We cannot allow this so we stop logging now. */ rc_logger_close(); #endif @@ -944,29 +948,30 @@ main(int argc, char **argv) } /* Load our list of hotplugged services */ - hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED); - if (!going_down || - strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) == 0) - start_services = rc_services_in_runlevel(RC_LEVEL_SYSINIT); - if (!going_down && + start_services = rc_services_in_runlevel(newlevel ? + newlevel : runlevel); + if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0) { - /* We need to include the boot runlevel services */ - tmplist = rc_services_in_runlevel(bootlevel); + tmplist = rc_services_in_runlevel(RC_LEVEL_SYSINIT); TAILQ_CONCAT(start_services, tmplist, entries); free(tmplist); - if (strcmp (newlevel ? newlevel : runlevel, bootlevel) != 0) { - tmplist = rc_services_in_runlevel(newlevel ? - newlevel : runlevel); - TAILQ_CONCAT(start_services, tmplist, entries); - free(tmplist); - } - - if (hotplugged_services) { - if (!start_services) - start_services = rc_stringlist_new(); - TAILQ_FOREACH(service, hotplugged_services, entries) - rc_stringlist_addu(start_services, service->value); + if (strcmp(newlevel ? runlevel : runlevel, + RC_LEVEL_SINGLE) != 0) + { + if (strcmp(newlevel ? newlevel : runlevel, + bootlevel) != 0) + { + tmplist = rc_services_in_runlevel(bootlevel); + TAILQ_CONCAT(start_services, tmplist, entries); + free(tmplist); + } + if (hotplugged_services) { + TAILQ_FOREACH(service, hotplugged_services, + entries) + rc_stringlist_addu(start_services, + service->value); + } } } @@ -994,15 +999,12 @@ main(int argc, char **argv) setenv("RC_RUNLEVEL", runlevel, 1); } - /* Run the halt script if needed */ - if (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 || - strcmp(runlevel, RC_LEVEL_REBOOT) == 0) - { +#ifdef __linux__ + /* We can't log beyond this point as the shutdown runlevel + * will mount / readonly. */ + if (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0) rc_logger_close(); - execl(HALTSH, HALTSH, runlevel, (char *) NULL); - eerrorx("%s: unable to exec `%s': %s", - applet, HALTSH, strerror(errno)); - } +#endif mkdir(RC_STARTING, 0755); rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, runlevel); @@ -1064,5 +1066,18 @@ main(int argc, char **argv) if (regen && strcmp(runlevel, bootlevel) == 0) unlink(RC_DEPTREE_CACHE); +#ifdef __linux__ + /* Run our halt script if it exists + * We only do this for compat with Gentoo sysvinit which + * should run halt.sh itself. */ + if (exists(HALTSH)) { + if (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0) { + execl(HALTSH, HALTSH, (char *) NULL); + eerrorx("%s: unable to exec `%s': %s", + applet, HALTSH, strerror(errno)); + } + } +#endif + return EXIT_SUCCESS; } diff --git a/src/rc/runscript.c b/src/rc/runscript.c index 4fc12bf..d055730 100644 --- a/src/rc/runscript.c +++ b/src/rc/runscript.c @@ -519,6 +519,9 @@ svc_exec(const char *arg1, const char *arg2) } execok = rc_waitpid(service_pid) == 0 ? true : false; + if (!execok && errno == ECHILD) + /* killall5 -9 could cause this */ + execok = true; service_pid = 0; return execok; @@ -1008,8 +1011,6 @@ svc_stop(bool deps) if (runlevel && (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 || - strcmp(runlevel, - RC_LEVEL_REBOOT) == 0 || strcmp(runlevel, RC_LEVEL_SINGLE) == 0)) continue; -- cgit v1.2.3