diff --git a/etc/Makefile b/etc/Makefile index 8b43544c..ee1642e8 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 d7322d68..dace4de5 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 07d41a10..fd2c87d1 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 be519c80..1bf3fe70 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 00000000..b8f9ed90 --- /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 ab73d8df..00000000 --- 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 00000000..a969d52a --- /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 00000000..d1adaad2 --- /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 00000000..57ed50ce --- /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 e0e31987..d4609eee 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 9e3131a9..b8a830af 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 c5649b20..8e086aaf 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 2b1641df..aa264aa3 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 dbff7368..652a3de2 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 6d99d49e..f38fe4e0 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 739e6fc1..2c05ea1e 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 92fb19c7..6f7c64e0 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 a6cde112..995cc910 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 4fc12bfe..d0557307 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;