/[baselayout]/trunk/sbin/rc
Gentoo

Contents of /trunk/sbin/rc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 399 - (show annotations) (download)
Mon Aug 4 21:39:17 2003 UTC (15 years, 8 months ago) by azarah
File size: 16288 byte(s)
Last minute fixes

1 #!/bin/bash
2 # Copyright 1999-2003 Gentoo Technologies, Inc.
3 # Distributed under the terms of the GNU General Public License v2
4 # $Header$
5
6
7 trap ":" INT QUIT TSTP
8 source /sbin/functions.sh
9 umask 022
10
11 try() {
12 local errstr=
13 local retval=0
14 # This works fine in test, but real life booting, fails for mounting /proc
15 # if we only check $? for instance ... We thus need to [ -n "${errstr}" ]
16 # as well.
17
18 errstr="$((eval $*) 2>&1 >/dev/null)"
19 retval=$?
20 if [ "${retval}" -ne 0 ] || \
21 ([ "${*/mount/}" != "$*" -a -n "${errstr}" ])
22 then
23 echo -e "${ENDCOL}${NORMAL}[${BAD} oops ${NORMAL}]"
24 echo
25 eerror "The \"${1}\" command failed with error:"
26 echo
27 echo "${errstr#*: }"
28 echo
29 eerror "Since this is a critical task, startup cannot continue."
30 echo
31 /sbin/sulogin ${CONSOLE}
32 einfo "Unmounting filesystems"
33 /bin/mount -a -o remount,ro & >/dev/null
34 einfo "Rebooting"
35 /sbin/reboot -f
36 fi
37
38 return ${retval}
39 }
40
41 # Check that $svcdir exists ...
42 check_statedir() {
43 if [ ! -d "${svcdir}" ]
44 then
45 if ! mkdir -p "${svcdir}" &> /dev/null
46 then
47 echo
48 eerror "For Gentoo Linux to function properly, \"${svcdir}\" need to exist."
49 eerror "Please mount your root partition read/write, and execute:"
50 echo
51 eerror " # mkdir -p ${svcdir}"
52 echo; echo
53 /sbin/sulogin ${CONSOLE}
54 einfo "Unmounting filesystems"
55 /bin/mount -a -o remount,ro & >/dev/null
56 einfo "Rebooting"
57 /sbin/reboot -f
58 fi
59 fi
60
61 return 0
62 }
63
64 get_critical_services() {
65 local x=
66 CRITICAL_SERVICES=
67
68 if [ -f "/etc/runlevels/${BOOTLEVEL}/.critical" ]
69 then
70 for x in $(< /etc/runlevels/${BOOTLEVEL}/.critical)
71 do
72 CRITICAL_SERVICES="${CRITICAL_SERVICES} ${x##*/}"
73 done
74 else
75 CRITICAL_SERVICES="checkroot hostname modules checkfs localmount"
76 fi
77
78 export CRITICAL_SERVICES
79
80 return 0
81 }
82
83 # Save $1
84 argv1="$1"
85
86 # First time boot stuff goes here. Note that 'sysinit' is an internal runlevel
87 # used to bring up local filesystems, and should not be started with /sbin/rc
88 # directly ...
89 if [ "${RUNLEVEL}" = "S" -a "${argv1}" = "sysinit" ]
90 then
91 # Setup initial $PATH just in case
92 PATH="/bin:/sbin:/usr/bin:/usr/sbin:${PATH}"
93
94 echo
95 echo -e "${GOOD}Gentoo Linux${GENTOO_VERS}; ${BRACKET}http://www.gentoo.org/${NORMAL}"
96 echo -e " Copyright 2001-2003 Gentoo Technologies, Inc.; Distributed under the GPL"
97 echo
98
99 ebegin "Mounting proc at /proc"
100 try try mount -n -t proc none /proc
101 eend $?
102
103 if [ -d /sys -a "$(get_KV)" -ge "$(KV_to_int '2.5.0')" ]
104 then
105 ebegin "Mounting sysfs at /sys"
106 mount -t sysfs none /sys
107 eend $?
108
109 elif [ "$(get_KV)" -ge "$(KV_to_int '2.5.0')" ]
110 then
111 ewarn "No /sys to mount sysfs needed in 2.5+ kernels!"
112 fi
113
114 # Check if the user disabled devfs
115 devfs="yes"
116 if get_bootparam "nodevfs"
117 then
118 devfs="no"
119 fi
120
121 # Fix weird bug where there is a /dev/.devfsd in a unmounted /dev
122 mymounts="$(awk '($3 == "devfs") { print "yes"; exit 0 }' /proc/mounts)"
123 if [ -e "/dev/.devfsd" -a "${mymounts}" != "yes" ]
124 then
125 rm -f /dev/.devfsd
126 fi
127
128 # With the new way, /dev can be mounted by the kernel ...
129 if [ "${devfs}" = "yes" -a ! -e "/dev/.devfsd" ]
130 then
131 mymounts="$(awk '($2 == "devfs") { print "yes"; exit 0 }' /proc/filesystems)"
132 # Is devfs support compiled in?
133 if [ "${mymounts}" = "yes" ]
134 then
135 ebegin "Mounting devfs at /dev"
136 try mount -n -t devfs none /dev
137 eend $?
138 else
139 clear
140 echo
141 einfo "The Gentoo Linux system initialization scripts have detected that your"
142 einfo "kernel has been compiled without DEVFS support. Because Gentoo Linux"
143 einfo "has been designed to work with DEVFS, it is required that you compile"
144 einfo "support for it into your kernel. Please read the 'Gentoo Linux from"
145 einfo "source (build) CD Installation Guide' at:"
146 echo
147 einfo " http://www.gentoo.org/doc/build.html"
148 echo
149 einfo "for more information on how to do this."
150 echo
151 read -t 15 -p "(hit Enter to continue or wait 15 seconds...)"
152 fi
153 fi
154
155 # From linux-2.5.68 we need to mount /dev/pts again ...
156 if [ "$(get_KV)" -ge "$(KV_to_int '2.5.68')" ]
157 then
158 have_devpts="$(awk '($2 == "devpts") { print "yes"; exit 0 }' /proc/filesystems)"
159 mymounts="$(awk '($3 == "devfs") { print "yes"; exit 0 }' /proc/mounts)"
160
161 if [ "${have_devpts}" = "yes" ]
162 then
163 # Only try to create /dev/pts if we have /dev mounted as devfs,
164 # else it might fail as / might be still mounted readonly.
165 if [ ! -d /dev/pts -a -e "/dev/.devfsd" -a "${mymounts}" = "yes" ]
166 then
167 # Make sure we have /dev/pts
168 mkdir -p /dev/pts &> /dev/null
169 fi
170
171 if [ -d /dev/pts ]
172 then
173 ebegin "Mounting devpts at /dev/pts"
174 try mount -n -t devpts none /dev/pts
175 eend $?
176 fi
177 fi
178 fi
179
180 # Need devfsd running now so that /dev/ram0 exists if we need it
181 mymounts="$(awk '($3 == "devfs") { print "yes"; exit 0 }' /proc/mounts)"
182 if [ "${devfs}" = "yes" -a -e "/dev/.devfsd" -a \
183 "${mymounts}" = "yes" ]
184 then
185 if [ "${RC_DEVFSD_STARTUP}" != "no" ]
186 then
187 ebegin "Starting devfsd"
188 /sbin/devfsd /dev > /dev/null
189 eend $?
190 fi
191 fi
192
193 if [ -x /sbin/irqbalance -a "$(get_KV)" -ge "$(KV_to_int '2.5.0')" ]
194 then
195 ebegin "Starting irqbalance"
196 /sbin/irqbalance
197 eend $?
198 fi
199
200 # Mount either a ramdisk or tmpfs if requested.
201 # we do this to temp mount, until we can get /var mounted ...
202 tsvcdir="/mnt/.init.d"
203
204 # Should we use tmpfs or a ramdisk for caching dependency and
205 # general initscript data? Note that the 'gentoo=tmpfs' kernel
206 # option should override most settings ...
207 if get_bootparam "tmpfs" || \
208 [ "${svcmount}" = "yes" -a "${svcfstype}" = "tmpfs" ]
209 then
210 mkdir -p "${tsvcdir}" &> /dev/null
211
212 ebegin "Mounting tmpfs at ${tsvcdir}"
213 try mount -n -t tmpfs tmpfs "${tsvcdir}" \
214 -o rw,mode=0644,size="${svcsize}"k
215 eend 0
216
217 elif get_bootparam "ramfs" || \
218 [ "${svcmount}" = "yes" -a "${svcfstype}" = "ramfs" ]
219 then
220 mkdir -p "${tsvcdir}"
221
222 ebegin "Mounting ramdisk 0 at ${tsvcdir}"
223 try dd if=/dev/zero of=/dev/ram0 bs=1k count="${svcsize}"
224 try /sbin/mke2fs -i 1024 -vm0 /dev/ram0 "${svcsize}"
225 try mount -n -t ext2 /dev/ram0 "${tsvcdir}" -o rw
226 eend 0
227 fi
228
229 # Swap needs to be activated *after* devfs has been mounted and *after*
230 # devfsd has been started, so that the fstab can be properly parsed
231 # and only if the server/Gentoo box is initialized ...
232 ebegin "Activating (possible) swap"
233 /sbin/swapon -a &> /dev/null
234 eend 0
235
236 # Set the console loglevel to 1 for a cleaner boot
237 # the logger should anyhow dump the ring-0 buffer at start to the
238 # logs, and that with dmesg can be used to check for problems
239 /bin/dmesg -n 1
240
241 # We set the forced softlevel from the kernel command line
242 # It needs to be run right after proc is mounted for the
243 # boot runlevel
244 setup_defaultlevels
245
246 # $BOOT can be used by rc-scripts to test if it is the first time
247 # the 'boot' runlevel is executed. Now also needed by some stuff in
248 # the 'sysinit' runlevel ...
249 export BOOT="yes"
250
251 start_critical_service() {
252 local retval=
253
254 source "/etc/init.d/${x}" || error "Failed to source /etc/init.d/${x}"
255 retval=$?
256 [ "${retval}" -ne 0 ] && return "${retval}"
257
258 start || eerror "Failed to start /etc/init.d/${x}"
259 retval=$?
260
261 return "${retval}"
262 }
263
264 # We first try to find a locally defined list of critical services
265 # for a particular runlevel. If we cannot find it, we use the
266 # defaults.
267 get_critical_services
268
269 # We do not want to break compadibility, so we do not fully integrate
270 # these into /sbin/rc, but rather start them by hand ...
271 for x in ${CRITICAL_SERVICES}
272 do
273 if ! start_critical_service "${x}"
274 then
275 echo
276 eerror "One of more critical startup scripts failed to start!"
277 eerror "Please correct this, and reboot ..."
278 echo; echo
279 /sbin/sulogin ${CONSOLE}
280 einfo "Unmounting filesystems"
281 /bin/mount -a -o remount,ro & >/dev/null
282 einfo "Rebooting"
283 /sbin/reboot -f
284 fi
285 done
286
287 # Check that $svcdir exists ...
288 check_statedir
289
290 # Since we are using tmpfs or ramfs, just bin to $tsvcdir to $svcdir
291 if get_bootparam "tmpfs" || get_bootparam "ramfs" || [ "${svcmount}" = "yes" ]
292 then
293 mount --bind "${tsvcdir}" "${svcdir}"
294 fi
295
296 # Clear $svcdir from stale entries
297 rm -rf "${svcdir}"/*
298
299 # Update the dependency cache
300 /sbin/depscan.sh
301
302 # Now that the dependency cache are up to date, make sure these
303 # are marked as started ...
304 (
305 # Needed for mark_service_started()
306 source "${svclib}/sh/rc-services.sh"
307
308 for x in ${CRITICAL_SERVICES}
309 do
310 mark_service_started "${x}"
311 done
312 )
313 fi # Sysinit ends here
314
315 if [ "${RUNLEVEL}" = "S" -a "${argv1}" = "sysinit" ]
316 then
317 exit 0
318
319 elif [ "${RUNLEVEL}" = "S" -a "${argv1}" = "boot" ]
320 then
321 setup_defaultlevels
322
323 if [ -n "${DEFAULTLEVEL}" -a "${DEFAULTLEVEL}" != "default" ]
324 then
325 # Setup our default runlevel runlevel that will be run
326 # the first time /sbin/rc is called with argv1 != sysinit|boot
327 echo "${DEFAULTLEVEL}" > "${svcdir}/ksoftlevel"
328 fi
329
330 # $BOOT can be used by rc-scripts to test if it is the first time
331 # the 'boot' runlevel is executed
332 export BOOT="yes"
333
334 # We reset argv1 to the bootlevel given on the kernel command line
335 # if there is one
336 argv1="${BOOTLEVEL}"
337
338 elif [ "${RUNLEVEL}" != "S" -a -e "${svcdir}/ksoftlevel" ]
339 then
340 argv1="$(< ${svcdir}/ksoftlevel)"
341 rm -f "${svcdir}/ksoftlevel"
342 fi
343
344
345 source "${svclib}/sh/rc-services.sh"
346 source "${svclib}/sh/rc-daemon.sh"
347
348 if [ -f "${svcdir}/softlevel" ]
349 then
350 # Set OLDSOFTLEVEL if we had a valid SOFTLEVEL
351 export OLDSOFTLEVEL="$(< ${svcdir}/softlevel)"
352 else
353 export OLDSOFTLEVEL=
354 fi
355
356 if [ -z "${argv1}" ]
357 then
358 if [ -f "${svcdir}/softlevel" ]
359 then
360 export SOFTLEVEL="$(< ${svcdir}/softlevel)"
361 else
362 export SOFTLEVEL="${BOOTLEVEL}"
363 fi
364 else
365 export SOFTLEVEL="${argv1}"
366 fi
367
368 if [ ! -f "${svcdir}/softlevel" ]
369 then
370 echo "${SOFTLEVEL}" > "${svcdir}/softlevel"
371 fi
372
373 # For keeping a list of services that fails during boot/halt
374 if [ ! -d "${svcdir}/failed" ]
375 then
376 install -d -m0755 "${svcdir}/failed"
377 else
378 rm -rf "${svcdir}"/failed/*
379 fi
380
381 if [ "${SOFTLEVEL}" = "reboot" -o "${SOFTLEVEL}" = "shutdown" ]
382 then
383 myscripts=
384
385 elif [ "${SOFTLEVEL}" = "single" ]
386 then
387 get_critical_services
388
389 myscripts="${CRITICAL_SERVICES}"
390
391 elif [ ! -d "/etc/runlevels/${SOFTLEVEL}" ]
392 then
393 eerror "ERROR: runlevel ${SOFTLEVEL} does not exist; exiting..."
394 exit 1
395 else
396 myscripts=
397 if [ "${SOFTLEVEL}" != "${BOOTLEVEL}" ]
398 then
399 # Normal runlevels *include* boot scripts
400 mylevels="$(dolisting "/etc/runlevels/${SOFTLEVEL}/")"
401 mylevels="${mylevels} $(dolisting /etc/runlevels/${BOOTLEVEL}/)"
402 else
403 # Non-normal runlevels don't include boot scripts as default
404 mylevels="$(dolisting "/etc/runlevels/${SOFTLEVEL}/")"
405 fi
406
407 [ "${OLDSOFTLEVEL}" = "${BOOTLEVEL}" -o "${OLDSOFTLEVEL}" = "single" ] \
408 && /bin/dmesg -n 1
409
410 for x in ${mylevels}
411 do
412 [ -L "${x}" ] && myscripts="${myscripts} ${x##*/}"
413 done
414 fi
415
416 # The softscripts dir contains all scripts that belong to the
417 # runlevel specified in ${svcdir}/softlevel
418 # It needs to be a new directory, else when stopping the services
419 # and the old directory is not intact, things get broken
420
421 install -d -m0755 "${svcdir}/softscripts.new"
422
423 for x in ${myscripts}
424 do
425 if [ ! -e "/etc/init.d/${x}" ]
426 then
427 ewarn "WARNING: /etc/init.d/${x} missing; skipping..."
428 continue
429 fi
430 # The -f eliminates a warning if the symlink already exists,
431 # which can happen if a service is in both the boot level and
432 # the current "normal" runlevel
433 ln -snf "/etc/init.d/${x}" "${svcdir}/softscripts.new/${x}"
434 done
435
436 dep_stop() {
437 local x=
438 local dep=
439 local needsme=
440 local myservice="${1##*/}"
441 local depservice=
442
443 if ! service_started "${myservice}"
444 then
445 return 0
446 fi
447
448 # Candidate for zapping
449 if [ ! -L "${svcdir}/softscripts.new/${myservice}" ]
450 then
451 # If this is a 'net' service, we do not want to stop it if it was
452 # not in the previous runlevel, and we are not shutting down,
453 # rebooting or going to single runlevel. This is because the user
454 # might have started it (net.ppp?), or possibly hotplug ...
455 if [ "${myservice%%.*}" = "net" -a \
456 "${myservice##*.}" != "${myservice}" ] && \
457 [ "${SOFTLEVEL}" != "reboot" -a \
458 "${SOFTLEVEL}" != "shutdown" -a \
459 "${SOFTLEVEL}" != "single" ]
460 then
461 if [ -n "${OLDSOFTLEVEL}" ] && \
462 ! in_runlevel "${myservice}" "${OLDSOFTLEVEL}"
463 then
464 # This service is not in the previous runlevel, so
465 # do not stop it ...
466 return 0
467 fi
468 fi
469
470 # Should not work for 'use'
471 if [ -z "$(needsme "${myservice}")" ]
472 then
473 # Nothing depends on me
474 stop_service "${myservice}"
475 else
476 # Something may depend on me
477 needsme=0
478
479 for dep in $(needsme "${myservice}")
480 do
481 if service_started "${dep}" && \
482 [ -L "${svcdir}/softscripts.new/${dep}" ]
483 then
484 # This dep is valid
485 needsme=1
486
487 break
488 fi
489 done
490
491 if [ "${needsme}" -eq 0 ]
492 then
493 stop_service "${myservice}"
494 fi
495 fi
496 fi
497 }
498
499 # Stop services
500 if [ "${SOFTLEVEL}" != "single" -a \
501 "${SOFTLEVEL}" != "reboot" -a \
502 "${SOFTLEVEL}" != "shutdown" ]
503 then
504 for i in $(dolisting "${svcdir}/started/")
505 do
506 dep_stop "${i}"
507 done
508 else
509 get_critical_services
510
511 is_critical_service() {
512 local x=
513 local myservice="${1##*/}"
514
515 for x in ${CRITICAL_SERVICES}
516 do
517 if [ "${myservice}" = "${x}" ]
518 then
519 return 0
520 fi
521 done
522
523 return 1
524 }
525
526 # First stop non critical services
527 for i in $(dolisting "${svcdir}/started/")
528 do
529 if [ -n "${LOGGER_SERVICE}" ]
530 then
531 # Only stop it if the logger do not depends on it
532 if ! query_before "${i##*/}" "${LOGGER_SERVICE}"
533 then
534 continue
535 fi
536 fi
537
538 # Do not stop critical services just yet
539 is_critical_service "${i}" || dep_stop "${i}"
540 done
541
542 # Now stop the logger if running
543 if [ -n "${LOGGER_SERVICE}" ]
544 then
545 dep_stop "${LOGGER_SERVICE}"
546 fi
547
548 # Now stop the rest
549 for i in $(dolisting "${svcdir}/started/")
550 do
551 dep_stop "${i}"
552 done
553 fi
554
555 # Only change softlevel AFTER all the services have been stopped,
556 # else they will not get the depend's right (wrong SOFTLEVEL)
557
558 echo "${SOFTLEVEL}" > "${svcdir}/softlevel"
559
560 if [ "${SOFTLEVEL}" = "reboot" -o "${SOFTLEVEL}" = "shutdown" ]
561 then
562 source /sbin/functions.sh
563
564 # Make sure that our $svcdir are clean for next reboot ...
565 rm -rf "${svcdir}"/*
566
567 source /etc/init.d/halt.sh
568
569 if [ "${SOFTLEVEL}" = "reboot" ]
570 then
571 source /etc/init.d/reboot.sh
572 else
573 source /etc/init.d/shutdown.sh
574 fi
575
576 # Should never get here
577 exit 0
578 fi
579
580 # Move the old softscritps directory to a different one
581 # and make the new softscripts directory the current
582
583 mv -f "${svcdir}/softscripts" "${svcdir}/softscripts.old"
584 mv -f "${svcdir}/softscripts.new" "${svcdir}/softscripts"
585
586 dep_start() {
587 local myservice="${1##*/}"
588
589 [ ! -L "${svcdir}/softscripts/${myservice}" ] && continue
590
591 # Only start a script if it isn't already running
592 service_started "${myservice}" || schedule_service_startup "${myservice}"
593 }
594
595 get_critical_services
596
597 EXTRA_SOFTSCRIPTS="${CRITICAL_SERVICES}"
598
599 if [ -n "${LOGGER_SERVICE}" -a -L "${svcdir}/softscripts/${LOGGER_SERVICE}" ]
600 then
601 service_started "${LOGGER_SERVICE}" || \
602 EXTRA_SOFTSCRIPTS="${EXTRA_SOFTSCRIPTS} ${LOGGER_SERVICE}"
603 fi
604
605 if [ "${SOFTLEVEL}" != "${BOOTLEVEL}" ]
606 then
607 for i in $(dolisting "/etc/runlevels/${BOOTLEVEL}/")
608 do
609 [ -L "${svcdir}/softscripts/${i##*/}" ] && \
610 EXTRA_SOFTSCRIPTS="${EXTRA_SOFTSCRIPTS} ${i##*/}"
611 done
612 fi
613
614 # Start scripts
615 for i in ${EXTRA_SOFTSCRIPTS} $(dolisting "${svcdir}/softscripts/")
616 do
617 dep_start "${i}"
618 done
619
620 # Wait for any services that may still be running ...
621 [ "${RC_PARALLEL_STARTUP}" = "yes" ] && wait
622
623 # Clean the old runlevel
624 rm -rf "${svcdir}/softscripts.old" &> /dev/null
625
626 # Depends gets nuked, so update them
627 # (this problem should be solved now, but i think it will be a good idea
628 # to recreate the deps after a change in runlevel)
629
630 #/sbin/depscan.sh &>/dev/null
631
632 # We want devfsd running after a change of runlevel (this is mostly if we return
633 # from runlevel 'single')
634 if [ -z "`ps --no-heading -C 'devfsd'`" -a \
635 -n "`gawk '/\/dev devfs/ { print }' /proc/mounts 2> /dev/null`" ]
636 then
637 if [ "${RC_DEVFSD_STARTUP}" != "no" ]
638 then
639 /sbin/devfsd /dev &> /dev/null
640 fi
641 fi
642
643 # Runlevel end, so clear stale fail list
644 rm -rf "${svcdir}/failed" &> /dev/null
645
646 # If we were in the boot runlevel, it is done now ...
647 [ -n "${BOOT}" ] && unset BOOT
648
649
650 # 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