/[baselayout]/branches/baselayout-1_12/sbin/rc
Gentoo

Contents of /branches/baselayout-1_12/sbin/rc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2026 - (show annotations) (download)
Fri May 5 15:25:14 2006 UTC (8 years, 5 months ago) by uberlord
File size: 23542 byte(s)
If a device initiated service is in the default runlevel then we no longer start it in the boot runlevel.
1 #!/sbin/runscript
2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4
5 trap ":" INT QUIT TSTP
6 source /sbin/functions.sh
7 # Only source this when this is a livecd booting ...
8 [ -f /sbin/livecd-functions.sh ] && source /sbin/livecd-functions.sh
9 umask 022
10
11 # Quick test to see if we can be interactive or not
12 if [[ ${RC_INTERACTIVE:-yes} == "yes" ]] ; then
13 if tty -s && stty -a | grep -q " icanon" ; then
14 RC_INTERACTIVE="yes"
15 else
16 RC_INTERACTIVE="no"
17 fi
18 fi
19
20 try() {
21 local errstr
22 local retval=0
23
24 if [ -c /dev/null ]; then
25 errstr="$((eval $*) 2>&1 >/dev/null)"
26 else
27 errstr="$((eval $*) 2>&1)"
28 fi
29 retval=$?
30 if [ "${retval}" -ne 0 ]
31 then
32 splash "critical" &
33
34 echo -e "${ENDCOL}${NORMAL}[${BAD} oops ${NORMAL}]"
35 echo
36 eerror "The \"${1}\" command failed with error:"
37 echo
38 echo "${errstr#*: }"
39 echo
40 eerror "Since this is a critical task, startup cannot continue."
41 echo
42 /sbin/sulogin ${CONSOLE}
43 einfo "Unmounting filesystems"
44 if [ -c /dev/null ]; then
45 /bin/mount -a -o remount,ro &>/dev/null
46 else
47 /bin/mount -a -o remount,ro
48 fi
49 einfo "Rebooting"
50 /sbin/reboot -f
51 fi
52
53 return ${retval}
54 }
55
56 # Check that $1 exists ...
57 check_statedir() {
58 [ -z "$1" ] && return 0
59
60 if [ ! -d "$1" ] ; then
61 if ! mkdir -p "$1" &>/dev/null ; then
62 splash "critical" &
63 echo
64 eerror "For Gentoo to function properly, \"$1\" needs to exist."
65 if [[ ${RC_FORCE_AUTO} == "yes" ]] ; then
66 eerror "Attempting to create \"$1\" for you ..."
67 mount -o remount,rw /
68 mkdir -p "$1"
69 else
70 eerror "Please mount your root partition read/write, and execute:"
71 echo
72 eerror " # mkdir -p $1"
73 echo; echo
74 /sbin/sulogin ${CONSOLE}
75 fi
76 einfo "Unmounting filesystems"
77 /bin/mount -a -o remount,ro &>/dev/null
78 einfo "Rebooting"
79 /sbin/reboot -f
80 fi
81 fi
82
83 return 0
84 }
85
86 # void noblock_read(var)
87 #
88 # reads a line of input into var like regular read
89 # but it does not block waiting for input
90 #
91 noblock_read() {
92 local old_tty_settings="$(stty -g)"
93 stty -icanon min 0 time 0
94 read "$@"
95 stty "${old_tty_settings}"
96 }
97
98 # bool user_want_interactive(void)
99 #
100 # return 0 if user wants interactive mode
101 #
102 user_want_interactive() {
103 [[ ${RC_INTERACTIVE} != "yes" ]] && return 1
104
105 local user_input
106 noblock_read user_input
107 [[ ${user_input} == *"I"* || ${user_input} == *"i"* ]]
108 }
109
110 # void do_interactive
111 #
112 # starts, skips, continues or drops to the shell
113 # depending on user selection
114 #
115 do_interactive() {
116 local service="$2"
117
118 user_want_interactive && svcinteractive="yes"
119 if [[ ${svcinteractive} != "yes" || ! -e "/etc/init.d/${service}" ]] ; then
120 "$@"
121 return $?
122 fi
123
124 local start_text="Start service"
125 local skip_text="Skip service"
126 local continue_text="Continue boot process"
127 local shell_text="Exit to shell"
128
129 echo
130 echo "About to start the service ${service}"
131 PS3="Enter your selection: "
132 select action in "${start_text}" "${skip_text}" "${continue_text}" \
133 "${shell_text}"
134 do
135 case ${action} in
136 "${start_text}")
137 "$@"
138 break
139 ;;
140 "${skip_text}")
141 break
142 ;;
143 "${continue_text}")
144 svcinteractive="no"
145 "$@"
146 break
147 ;;
148 "${shell_text}")
149 echo
150 sulogin "${CONSOLE}"
151 ;;
152 esac
153 done
154 }
155
156 get_critical_services() {
157 local x=
158 CRITICAL_SERVICES=
159
160 if [ -f "/etc/runlevels/${BOOTLEVEL}/.critical" ]
161 then
162 for x in $(< /etc/runlevels/${BOOTLEVEL}/.critical)
163 do
164 CRITICAL_SERVICES="${CRITICAL_SERVICES} ${x##*/}"
165 done
166 else
167 CRITICAL_SERVICES="checkroot modules checkfs localmount clock"
168 fi
169
170 export CRITICAL_SERVICES
171
172 return 0
173 }
174
175 check_critical_services() {
176 local x
177
178 # Ensure that critical services are in the boot runlevel
179 for x in ${CRITICAL_SERVICES} ; do
180 if [[ ! -L "/etc/runlevels/${BOOTLEVEL}/${x}" ]] ; then
181 ewarn "WARNING: Adding critical service ${x} to the ${BOOTLEVEL} runlevel"
182 ln -snf "/etc/init.d/${x}" "/etc/runlevels/${BOOTLEVEL}/${x}"
183 fi
184 done
185 }
186
187 # Save $1
188 argv1="$1"
189
190 # First time boot stuff goes here. Note that 'sysinit' is an internal runlevel
191 # used to bring up local filesystems, and should not be started with /sbin/rc
192 # directly ...
193 if [[ ( ${RUNLEVEL} == "S" || ${RUNLEVEL} == "1" ) && ${argv1} = "sysinit" ]]
194 then
195 # Setup initial $PATH just in case
196 PATH="/bin:/sbin:/usr/bin:/usr/sbin:${PATH}"
197
198 # Help users recover their systems incase these go missing
199 [ -c /dev/null ] && dev_null=1 || dev_null=0
200 [ -c /dev/console ] && dev_console=1 || dev_console=0
201
202 echo
203 echo -e "${GOOD}Gentoo Linux${GENTOO_VERS}; ${BRACKET}http://www.gentoo.org/${NORMAL}"
204 echo -e " Copyright 1999-2006 Gentoo Foundation; Distributed under the GPLv2"
205 echo
206 if [[ ${RC_INTERACTIVE} == "yes" ]] ; then
207 echo -e "Press ${GOOD}I${NORMAL} to enter interactive boot mode"
208 echo
209 fi
210 check_statedir /proc
211
212 ebegin "Mounting proc at /proc"
213 if [[ ${RC_USE_FSTAB} = "yes" ]] ; then
214 mntcmd=$(get_mount_fstab /proc)
215 else
216 unset mntcmd
217 fi
218 try mount -n ${mntcmd:--t proc proc /proc}
219 eend $?
220
221 # Read off the kernel commandline to see if there's any special settings
222 # especially check to see if we need to set the CDBOOT environment variable
223 # Note: /proc MUST be mounted
224 [ -f /sbin/livecd-functions.sh ] && livecd_read_commandline
225
226 if [ "$(get_KV)" -ge "$(KV_to_int '2.6.0')" ] ; then
227 if [[ -d /sys ]] ; then
228 ebegin "Mounting sysfs at /sys"
229 if [[ ${RC_USE_FSTAB} = "yes" ]] ; then
230 mntcmd=$(get_mount_fstab /sys)
231 else
232 unset mntcmd
233 fi
234 try mount -n ${mntcmd:--t sysfs sysfs /sys}
235 eend $?
236 else
237 ewarn "No /sys to mount sysfs needed in 2.6 and later kernels!"
238 fi
239 fi
240
241 check_statedir /dev
242
243 # Fix weird bug where there is a /dev/.devfsd in a unmounted /dev
244 devfs_automounted="no"
245 if [ -e "/dev/.devfsd" ]
246 then
247 mymounts="$(awk '($3 == "devfs") { print "yes"; exit 0 }' /proc/mounts)"
248 if [ "${mymounts}" != "yes" ]
249 then
250 rm -f /dev/.devfsd
251 else
252 devfs_automounted="yes"
253 fi
254 fi
255
256 # Try to figure out how the user wants /dev handled
257 # - check $RC_DEVICES from /etc/conf.d/rc
258 # - check boot parameters
259 # - make sure the required binaries exist
260 # - make sure the kernel has support
261 if [ "${RC_DEVICES}" = "static" ]
262 then
263 ebegin "Using existing device nodes in /dev"
264 eend 0
265 else
266 fellback_to_devfs="no"
267 case "${RC_DEVICES}" in
268 devfs) devfs="yes"
269 udev="no"
270 ;;
271 udev) devfs="yes"
272 udev="yes"
273 fellback_to_devfs="yes"
274 ;;
275 auto|*) devfs="yes"
276 udev="yes"
277 ;;
278 esac
279
280 # Check udev prerequisites and kernel params
281 if [ "${udev}" = "yes" ]
282 then
283 if get_bootparam "noudev" || \
284 [ ! -x /sbin/udev -o ${devfs_automounted} = "yes" ] || \
285 [ "$(get_KV)" -lt "$(KV_to_int '2.6.0')" ]
286 then
287 udev="no"
288 fi
289 fi
290
291 # Check devfs prerequisites and kernel params
292 if [ "${devfs}" = "yes" ]
293 then
294 if get_bootparam "nodevfs" || [ "${udev}" = "yes" ]
295 then
296 devfs="no"
297 fi
298 fi
299
300 # Actually start setting up /dev now
301 if [[ ${udev} == "yes" ]] ; then
302 start_addon udev
303
304 # With devfs, /dev can be mounted by the kernel ...
305 elif [[ ${devfs} == "yes" ]] ; then
306 start_addon devfs
307
308 # Did the user want udev in the config file but for
309 # some reason, udev support didnt work out ?
310 if [[ ${fellback_to_devfs} == "yes" ]] ; then
311 ewarn "You wanted udev but support for it was not available!"
312 ewarn "Please review your system after it's booted!"
313 fi
314 fi
315
316 # OK, if we got here, things are probably not right :)
317 if [[ ${devfs} == "no" && ${udev} == "no" ]] ; then
318 clear
319 echo
320 einfo "The Gentoo Linux system initialization scripts have detected that"
321 einfo "your system does not support UDEV. Since Gentoo Linux has been"
322 einfo "designed with dynamic /dev in mind, it is highly suggested that you"
323 einfo "emerge sys-fs/udev and configure your system to use it."
324 einfo "Please read the Gentoo Handbook for more information!"
325 echo
326 einfo " http://www.gentoo.org/doc/en/handbook/"
327 echo
328 einfo "Thanks for using Gentoo! :)"
329 echo
330 read -t 15 -p "(hit Enter to continue or wait 15 seconds ...)"
331 fi
332 fi
333
334 # From linux-2.5.68 we need to mount /dev/pts again ...
335 if [ "$(get_KV)" -ge "$(KV_to_int '2.5.68')" ]
336 then
337 have_devpts="$(awk '($2 == "devpts") { print "yes"; exit 0 }' /proc/filesystems)"
338
339 if [ "${have_devpts}" = "yes" ]
340 then
341 # Only try to create /dev/pts if we have /dev mounted dynamically,
342 # else it might fail as / might be still mounted readonly.
343 if [ ! -d /dev/pts ] && \
344 [ "${devfs}" = "yes" -o "${udev}" = "yes" ]
345 then
346 # Make sure we have /dev/pts
347 mkdir -p /dev/pts &>/dev/null || \
348 ewarn "Could not create /dev/pts!"
349 fi
350
351 if [[ -d /dev/pts ]] ; then
352 ebegin "Mounting devpts at /dev/pts"
353 if [[ ${RC_USE_FSTAB} = "yes" ]] ; then
354 mntcmd=$(get_mount_fstab /dev/pts)
355 else
356 unset mntcmd
357 fi
358 try mount -n ${mntcmd:--t devpts -o gid=5,mode=0620 devpts /dev/pts}
359 eend $?
360 fi
361 fi
362 fi
363
364 # Set the console loglevel to 1 for a cleaner boot
365 # the logger should anyhow dump the ring-0 buffer at start to the
366 # logs, and that with dmesg can be used to check for problems
367 /bin/dmesg -n 1
368
369 # Start logging console output since we have all /dev stuff setup
370 bootlog start
371
372 # Start RAID/LVM/EVMS/DM volumes for /usr, /var, etc.
373 start_volumes
374
375 # Swap needs to be activated *after* /dev has been fully setup so that
376 # the fstab can be properly parsed. This first pass we send to /dev/null
377 # in case the user has swap points setup on different partitions. We
378 # will run swapon again in localmount and that one will report errors.
379 ebegin "Activating (possible) swap"
380 /sbin/swapon -a >& /dev/null
381 eend 0
382
383 # We set the forced softlevel from the kernel command line
384 # It needs to be run right after proc is mounted for the
385 # boot runlevel
386 setup_defaultlevels
387
388 # $BOOT can be used by rc-scripts to test if it is the first time
389 # the 'boot' runlevel is executed. Now also needed by some stuff in
390 # the 'sysinit' runlevel ...
391 export BOOT="yes"
392
393 start_critical_service() {
394 (
395 local retval=
396 local service="$1"
397 # Needed for some addons like dm-crypt that starts in critical services
398 local myservice="$1"
399
400 source "/etc/init.d/${service}"
401 retval=$?
402 if [[ ${retval} -ne 0 ]] ; then
403 eerror "Failed to source /etc/init.d/${service}"
404 return "${retval}"
405 fi
406
407 local conf="$(add_suffix /etc/conf.d/${service})"
408 [[ -e ${conf} ]] && source "${conf}"
409 conf="$(add_suffix /etc/rc.conf)"
410 [[ -e ${conf} ]] && source "${conf}"
411
412 start
413 retval=$?
414 [[ ${retval} -ne 0 ]] && eerror "Failed to start /etc/init.d/${service}"
415
416 return "${retval}"
417 )
418 }
419
420 # We first try to find a locally defined list of critical services
421 # for a particular runlevel. If we cannot find it, we use the
422 # defaults.
423 get_critical_services
424
425 splash "rc_init" "${argv1}"
426
427 export START_CRITICAL="yes"
428
429 # We do not want to break compatibility, so we do not fully integrate
430 # these into /sbin/rc, but rather start them by hand ...
431 for x in ${CRITICAL_SERVICES}
432 do
433 splash "svc_start" "${x}"
434 if ! start_critical_service "${x}" ; then
435 splash "critical" &>/dev/null &
436
437 echo
438 eerror "One of more critical startup scripts failed to start!"
439 eerror "Please correct this, and reboot ..."
440 echo; echo
441 /sbin/sulogin ${CONSOLE}
442 einfo "Unmounting filesystems"
443 /bin/mount -a -o remount,ro &>/dev/null
444 einfo "Rebooting"
445 /sbin/reboot -f
446 fi
447
448 splash "svc_started" "${x}" "0"
449 done
450
451 unset START_CRITICAL
452
453 # /var/log should be writable now, so starting saving the boot output
454 bootlog sync
455
456 # have to run this after /var/run is mounted rw #85304
457 if [ -x /sbin/irqbalance -a "$(get_KV)" -ge "$(KV_to_int '2.5.0')" ]
458 then
459 ebegin "Starting irqbalance"
460 /sbin/irqbalance
461 eend $?
462 fi
463
464 # Check that $svcdir exists ...
465 check_statedir "${svcdir}"
466
467 # Should we use tmpfs/ramfs/ramdisk for caching dependency and
468 # general initscript data? Note that the 'gentoo=<fs>' kernel
469 # option should override any other setting ...
470 for fs in tmpfs ramfs ramdisk
471 do
472 if get_bootparam "${fs}"
473 then
474 svcmount="yes"
475 svcfstype="${fs}"
476 break
477 fi
478 done
479 if [ "${svcmount}" = "yes" ]
480 then
481 ebegin "Mounting ${svcfstype} at ${svcdir}"
482 case "${svcfstype}" in
483 ramfs)
484 try mount -t ramfs svcdir "${svcdir}" \
485 -o rw,mode=0755,size="${svcsize}"k
486 ;;
487 ramdisk)
488 try dd if=/dev/zero of=/dev/ram0 bs=1k count="${svcsize}"
489 try /sbin/mke2fs -i 1024 -vm0 /dev/ram0 "${svcsize}"
490 try mount -t ext2 /dev/ram0 "${svcdir}" -o rw
491 ;;
492 tmpfs|*)
493 try mount -t tmpfs svcdir "${svcdir}" \
494 -o rw,mode=0755,size="${svcsize}"k
495 ;;
496 esac
497 eend 0
498 fi
499
500 # If booting off CD, we want to update inittab before setting the runlevel
501 if [ -f "/sbin/livecd-functions.sh" -a -n "${CDBOOT}" ]
502 then
503 ebegin "Updating inittab"
504 livecd_fix_inittab
505 eend $?
506 /sbin/telinit q &>/dev/null
507 fi
508
509 # Clear $svcdir from stale entries, but leave the caches around, as it
510 # should help speed things up a bit
511 rm -rf $(ls -d1 "${svcdir}/"* 2>/dev/null | \
512 grep -ve '\(depcache\|deptree\|envcache\)')
513
514 echo "sysinit" > "${svcdir}/softlevel"
515
516 # Ensure all critical services have are in the boot runlevel
517 check_critical_services
518
519 # Update the dependency cache
520 /sbin/depscan.sh
521
522 # Now that the dependency cache are up to date, make sure these
523 # are marked as started ...
524 (
525 # Needed for mark_service_started()
526 source "${svclib}/sh/rc-services.sh"
527
528 for x in ${CRITICAL_SERVICES}
529 do
530 mark_service_started "${x}"
531 done
532 )
533
534 # If the user's /dev/null or /dev/console are missing, we
535 # should help them out and explain how to rectify the situation
536 if [ ${dev_null} -eq 0 -o ${dev_console} -eq 0 ] \
537 && [ -e /usr/share/baselayout/issue.devfix ]
538 then
539 # Backup current /etc/issue
540 if [ -e /etc/issue -a ! -e /etc/issue.devfix ]
541 then
542 mv /etc/issue /etc/issue.devfix
543 fi
544
545 cp /usr/share/baselayout/issue.devfix /etc/issue
546 fi
547
548 # Setup login records ... this has to be done here because when
549 # we exit this runlevel, init will write a boot record to utmp
550 # If /var/run is readonly, then print a warning, not errors
551 if touch /var/run/utmp 2>/dev/null
552 then
553 > /var/run/utmp
554 touch /var/log/wtmp
555 chgrp utmp /var/run/utmp /var/log/wtmp
556 chmod 0664 /var/run/utmp /var/log/wtmp
557 # Remove /var/run/utmpx (bug from the past)
558 rm -f /var/run/utmpx
559 else
560 ewarn "Skipping /var/run/utmp initialization (ro root?)"
561 fi
562
563 # Check and save if the user wants interactive
564 user_want_interactive && svcinteractive="yes"
565 echo "${svcinteractive:-no}" > "${svcdir}/interactive"
566
567 # sysinit is now done, so allow init scripts to run normally
568 [[ -e /dev/.rcsysinit ]] && rm -f /dev/.rcsysinit
569
570 # All done logging
571 bootlog quit
572
573 exit 0
574 fi # Sysinit ends here
575
576 if [[ ( ${RUNLEVEL} == "S" || ${RUNLEVEL} == "1" ) && ${argv1} == "boot" ]]
577 then
578 setup_defaultlevels
579
580 if [ -n "${DEFAULTLEVEL}" -a "${DEFAULTLEVEL}" != "default" ]
581 then
582 # Setup our default runlevel runlevel that will be run
583 # the first time /sbin/rc is called with argv1 != sysinit|boot
584 echo "${DEFAULTLEVEL}" > "${svcdir}/ksoftlevel"
585 fi
586
587 # $BOOT can be used by rc-scripts to test if it is the first time
588 # the 'boot' runlevel is executed
589 export BOOT="yes"
590
591 # We reset argv1 to the bootlevel given on the kernel command line
592 # if there is one
593 argv1="${BOOTLEVEL}"
594
595 elif [[ ${RUNLEVEL} != "S" && ${RUNLEVEL} != "1" && -e ${svcdir}/ksoftlevel ]]
596 then
597 argv1="$(< ${svcdir}/ksoftlevel)"
598 rm -f "${svcdir}/ksoftlevel"
599 elif [[ ${RUNLEVEL} != "S" && ${RUNLEVEL} != "1" && ${argv1} == "single" ]]
600 then
601 /sbin/telinit S
602 exit 0
603 elif [[ ( ${RUNLEVEL} == "S" || ${RUNLEVEL} == "1" ) && ${argv1} != "single" ]]
604 then
605 level=$(awk -v level="${argv1}" '
606 $2 == level {
607 split($0, fields, ":")
608 print fields[2]
609 exit
610 }' /etc/inittab 2>/dev/null)
611 [[ -z ${level} ]] && level=3
612 /sbin/telinit "${level}"
613 exit 0
614 fi
615
616 # Ensure that critical services are in the boot runlevel
617 get_critical_services
618 check_critical_services
619
620 source "${svclib}/sh/rc-services.sh"
621 [[ -e "${svcdir}/interactive" ]] \
622 && svcinteractive="$(<${svcdir}/interactive)"
623
624 if [ -f "${svcdir}/softlevel" ]
625 then
626 # Set OLDSOFTLEVEL if we had a valid SOFTLEVEL
627 export OLDSOFTLEVEL="$(< ${svcdir}/softlevel)"
628 else
629 export OLDSOFTLEVEL=
630 fi
631
632 if [ -z "${argv1}" ]
633 then
634 if [ -f "${svcdir}/softlevel" ]
635 then
636 export SOFTLEVEL="$(< ${svcdir}/softlevel)"
637 else
638 export SOFTLEVEL="${BOOTLEVEL}"
639 fi
640 else
641 export SOFTLEVEL="${argv1}"
642 fi
643
644 if [ ! -f "${svcdir}/softlevel" ]
645 then
646 echo "${SOFTLEVEL}" > "${svcdir}/softlevel"
647 fi
648
649 # For keeping a list of services that fails during boot/halt
650 if [ ! -d "${svcdir}/failed" ]
651 then
652 mkdir -p -m 0755 "${svcdir}/failed"
653 else
654 rm -rf "${svcdir}"/failed/*
655 fi
656
657 splash "rc_init" "${argv1}"
658
659
660 if [ "${SOFTLEVEL}" = "reboot" -o "${SOFTLEVEL}" = "shutdown" ]
661 then
662 myscripts=
663
664 elif [ "${SOFTLEVEL}" = "single" ]
665 then
666
667 myscripts="${CRITICAL_SERVICES}"
668
669 elif [ ! -d "/etc/runlevels/${SOFTLEVEL}" ]
670 then
671 eerror "ERROR: runlevel ${SOFTLEVEL} does not exist; exiting ..."
672 exit 1
673 else
674 myscripts=
675 if [ "${SOFTLEVEL}" != "${BOOTLEVEL}" ]
676 then
677 # Normal runlevels *include* boot scripts
678 mylevels="$(dolisting "/etc/runlevels/${SOFTLEVEL}/")"
679 mylevels="${mylevels} $(dolisting /etc/runlevels/${BOOTLEVEL}/)"
680 else
681 # Non-normal runlevels don't include boot scripts as default
682 mylevels="$(dolisting "/etc/runlevels/${SOFTLEVEL}/")"
683
684 # As we're in the bootlevel, add any services that failed due
685 # to /dev/.rcsysinit existing to the list
686 if [[ -d /dev/.rcboot ]] ; then
687 for x in $(dolisting /dev/.rcboot/) ; do
688 [[ -L ${x} && ! -e /etc/runlevels/"${DEFAULTLEVEL}"/"${x##*/}" ]] \
689 && myscripts="${myscripts} ${x##*/}"
690 done
691 einfo "Device initiated services:${HILITE}${myscripts}${NORMAL}"
692 rm -rf /dev/.rcboot
693 fi
694 fi
695
696 [ "${OLDSOFTLEVEL}" = "${BOOTLEVEL}" -o "${OLDSOFTLEVEL}" = "single" ] \
697 && /bin/dmesg -n 1
698
699 for x in ${mylevels}
700 do
701 [ -L "${x}" ] && myscripts="${myscripts} ${x##*/}"
702 done
703 fi
704
705 # The softscripts dir contains all scripts that belong to the
706 # runlevel specified in ${svcdir}/softlevel
707 # It needs to be a new directory, else when stopping the services
708 # and the old directory is not intact, things get broken
709
710 mkdir -p -m 0755 "${svcdir}/softscripts.new"
711
712 for x in ${myscripts} ; do
713 if [[ ! -e /etc/init.d/${x} ]] ; then
714 ewarn "WARNING: /etc/init.d/${x} missing; skipping ..."
715 continue
716 fi
717 # The -f eliminates a warning if the symlink already exists,
718 # which can happen if a service is in both the boot level and
719 # the current "normal" runlevel
720 ln -snf "/etc/init.d/${x}" "${svcdir}/softscripts.new/${x}"
721 done
722
723 get_stop_services() {
724 local x list
725
726 for x in $(dolisting "${svcdir}/inactive/") \
727 $(dolisting "${svcdir}/started/") ; do
728 list="${list} ${x##*/}"
729 done
730
731 reverse_list $(trace_dependencies ${list})
732 }
733
734 dep_stop() {
735 local x dep needsme depservice
736 local service=${1##*/}
737
738 service_stopped "${service}" && return 0
739
740 # Candidate for zapping ?
741 [[ ! -L ${svcdir}/softscripts.new/${service} ]] || \
742 return 0
743
744 # If this is a 'net' service, we do not want to stop it if it was
745 # not in the previous runlevel, and we are not shutting down,
746 # rebooting or going to single runlevel. This is because the user
747 # (or hotplut) might have started it (net.ppp?) ...
748 if net_service "${service}" && \
749 [[ ${SOFTLEVEL} != "reboot" && \
750 ${SOFTLEVEL} != "shutdown" && \
751 ${SOFTLEVEL} != "single" ]] ; then
752 if [[ -z ${OLDSOFTLEVEL} ]] || \
753 ! in_runlevel "${service}" "${OLDSOFTLEVEL}"
754 then
755 # This service is not in the previous runlevel, so
756 # do not stop it ...
757 return 0
758 fi
759 fi
760
761 # Should not work for 'use'
762 if [[ -z $(needsme "${service}") ]] ; then
763 # Nothing depends on me
764 stop_service "${service}"
765 else
766 # Something may depend on me
767 needsme=0
768
769 for dep in $(needsme "${service}") ; do
770 if [[ -L "${svcdir}/softscripts.new/${dep}" ]] ; then
771 # This dep is valid
772 needsme=1
773
774 break
775 fi
776 done
777
778 [[ ${needsme} -eq 0 ]] && stop_service "${service}"
779 fi
780 }
781
782 # Stop services
783 if [[ ${SOFTLEVEL} != "single" && \
784 ${SOFTLEVEL} != "reboot" && \
785 ${SOFTLEVEL} != "shutdown" ]]
786 then
787 for i in $(get_stop_services) ; do
788 dep_stop "${i}"
789 done
790
791 # Wait for any services that may still be stopping ...
792 [ "${RC_PARALLEL_STARTUP}" = "yes" ] && wait
793 else
794 get_critical_services
795
796 is_critical_service() {
797 local x
798 local service=${1##*/}
799
800 for x in ${CRITICAL_SERVICES} ${LOGGER_SERVICE} ; do
801 [[ ${service} == "${x}" ]] && return 0
802 done
803
804 return 1
805 }
806
807 # First stop non critical services
808 for i in $(get_stop_services) ; do
809 is_critical_service "${i}" || dep_stop "${i}"
810 done
811
812 # Wait for any services that may still be stopping ...
813 [ "${RC_PARALLEL_STARTUP}" = "yes" ] && wait
814
815 export STOP_CRITICAL="yes"
816 # Now stop the rest
817 for i in $(get_stop_services) ; do
818 dep_stop "${i}"
819 done
820 unset STOP_CRITICAL
821 fi
822
823 # Only change softlevel AFTER all the services have been stopped,
824 # else they will not get the depend's right (wrong SOFTLEVEL)
825
826 echo "${SOFTLEVEL}" > "${svcdir}/softlevel"
827
828 if [[ ${SOFTLEVEL} == "reboot" || ${SOFTLEVEL} == "shutdown" ]] ; then
829 # Clear $svcdir from stale entries, but leave the caches around, as it
830 # should help speed things up a bit
831 rm -rf $(ls -d1 "${svcdir}/"* 2>/dev/null | \
832 grep -ve '\(depcache\|deptree\|envcache\)')
833
834 source /etc/init.d/halt.sh
835
836 if [[ ${SOFTLEVEL} == "reboot" ]] ; then
837 source /etc/init.d/reboot.sh
838 else
839 source /etc/init.d/shutdown.sh
840 fi
841
842 # Should never get here
843 exit 0
844 fi
845
846 if [[ ${SOFTLEVEL} == "single" ]] ; then
847 /sbin/sulogin ${CONSOLE}
848 exit 0
849 fi
850
851 # Move the old softscritps directory to a different one
852 # and make the new softscripts directory the current
853
854 mv -f "${svcdir}/softscripts" "${svcdir}/softscripts.old"
855 mv -f "${svcdir}/softscripts.new" "${svcdir}/softscripts"
856
857 get_start_services() {
858 local x list
859
860 get_critical_services
861 list=${CRITICAL_SERVICES}
862
863 [[ -n ${LOGGER_SERVICE} && \
864 -L ${svcdir}/softscripts/${LOGGER_SERVICE} ]] && \
865 list="${list} ${LOGGER_SERVICE}"
866
867 for x in $(dolisting "${svcdir}/softscripts/") ; do
868 list="${list} ${x##*/}"
869 done
870
871 trace_dependencies ${list}
872 }
873
874 # Start scripts
875 for i in $(get_start_services) ; do
876 if service_stopped "${i}" ; then
877 do_interactive start_service "${i}"
878 fi
879 done
880
881 # Wait for any services that may still be running ...
882 [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && wait
883
884 # Clean the old runlevel
885 rm -rf "${svcdir}/softscripts.old" &>/dev/null
886
887 # Depends gets nuked, so update them
888 # (this problem should be solved now, but i think it will be a good idea
889 # to recreate the deps after a change in runlevel)
890
891 #/sbin/depscan.sh &>/dev/null
892
893 # We want devfsd running after a change of runlevel (this is mostly if we return
894 # from runlevel 'single')
895 if [ -z "`ps --no-heading -C 'devfsd'`" -a \
896 -n "`gawk '/\/dev devfs/ { print }' /proc/mounts 2>/dev/null`" ]
897 then
898 if [ "${RC_DEVFSD_STARTUP}" != "no" ]
899 then
900 /sbin/devfsd /dev &>/dev/null
901 fi
902 fi
903
904 # Runlevel end, so clear stale fail list
905 rm -rf "${svcdir}/failed" &>/dev/null
906
907 # If we were in the boot runlevel, it is done now ...
908 if [[ -n ${BOOT} ]]; then
909 unset BOOT
910 # Save our interactive mode into the default runlevel
911 user_want_interactive && svcinteractive="yes"
912 echo "${svcinteractive}" > "${svcdir}/interactive"
913 else
914 # As we're not boot, we remove the interactive file
915 [[ -e "${svcdir}/interactive" ]] && rm -f "${svcdir}/interactive"
916 fi
917
918 # Remove the cached CONSOLETYPE
919 unset CONSOLETYPE
920
921 splash "rc_exit"
922
923 # vim:ts=4

Properties

Name Value
svn:eol-style native
svn:executable *
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20