1 # Distributed under the terms of the GNU General Public License v2
3 # Author: Michal Januszewski <spock@gentoo.org>
4 # Maintainer: Michal Januszewski <spock@gentoo.org>
6 # This file is a part of splashutils. The functions contained in this
7 # file are meant to be used by hook scripts in splash themes or by
8 # initscript systems. The code will be kept distro-agnostic to facilitate
9 # portability. It should also contain POSIX compatible code. No bashisms
12 # ####################################################################
13 # Change any settings ONLY if you are sure what you're doing.
14 # Don't cry if it breaks afterwards.
15 # ####################################################################
17 # The splash scripts need a cache which can be guaranteed to be
18 # both readable and writable at all times, even when the root fs
19 # is mounted read-only. To that end, an in-RAM fs is used. Valid
20 # values for spl_cachetype are 'tmpfs' and 'ramfs'. spl_cachesize
21 # is a size limit in KB, and it should probably be left with the
23 export spl_cachesize
="4096"
24 export spl_cachetype
="tmpfs"
25 export spl_cachedir
="@libdir@/splash/cache"
26 export spl_tmpdir
="@libdir@/splash/tmp"
27 export spl_fifo
="${spl_cachedir}/.splash"
28 export spl_pidfile
="${spl_cachedir}/daemon.pid"
29 export spl_util
="@sbindir@/splash_util.static"
30 export spl_daemon
="@sbindir@/fbsplashd.static"
31 export spl_decor
="@sbindir@/fbcondecor_ctl.static"
32 export spl_bindir
="@libdir@/splash/bin"
34 # This is the main function which handles all events.
35 # Accepted parameters:
40 # svc_start_failed <name>
41 # svc_stop_failed <name>
42 # svc_input_begin <name>
43 # svc_input_end <name>
44 # rc_init <internal_runlevel> - used to distinguish between 'boot' and 'sysinit'
51 # Reload the splash settings in rc_init. We could have set them wrong the
52 # first time splash_setup was called (when splash-functions.sh was first
53 # sourced) if /proc wasn't mounted.
54 if [ "${event}" = "rc_init" ]; then
60 [ "${SPLASH_MODE_REQ}" = "off" ] && return
62 # Prepare the cache here -- rc_init-pre might want to use it
63 if [ "${event}" = "rc_init" ]; then
64 if [ "${RUNLEVEL}" = "S" -a "$1" = "sysinit" ]; then
65 splash_cache_prep
'start' ||
return
66 elif [ "${RUNLEVEL}" = "6" -o "${RUNLEVEL}" = "0" ]; then
67 # Check if the splash cachedir is mounted readonly. If it is,
68 # we need to mount a tmpfs over it.
69 if ! touch "${spl_cachedir}/message" 2>/dev
/null
; then
70 splash_cache_prep
'stop' ||
return
77 if [ "${event}" = "rc_init" -o "${event}" = "rc_exit" ]; then
79 elif [ "${event}" = "svc_started" -o "${event}" = "svc_stopped" ]; then
81 # Backwards compatibility hack. Add a 0 to the arguments to simulate
87 # Backwards compatibility: translate an error condition (non-zero
88 # error code) into an appropriate event.
89 if [ "$2" != "0" ]; then
90 if [ "${event}" = "svc_started" ]; then
91 event
="svc_start_failed"
93 event
="svc_stop_failed"
101 splash_profile
"pre ${event} ${args}"
103 # Handle -pre event hooks
104 if [ -x "@sysconfdir@/splash/${SPLASH_THEME}/scripts/${event}-pre" ]; then
105 @sysconfdir@
/splash
/"${SPLASH_THEME}"/scripts/${event}-pre ${args}
109 svc_start) splash_svc_start "$1";;
110 svc_stop) splash_svc_stop "$1";;
111 svc_started) splash_svc "$1" "start
";;
112 svc_stopped) splash_svc "$1" "stop
";;
113 svc_start_failed) splash_svc_fail "$1" "start
";;
114 svc_stop_failed) splash_svc_fail "$1" "stop
";;
115 svc_input_begin) splash_input_begin "$1";;
116 svc_input_end) splash_input_end "$1";;
117 rc_init) splash_init "$1" "${RUNLEVEL}";;
118 rc_exit) splash_exit "${RUNLEVEL}";;
119 critical) splash_verbose;;
122 splash_profile "post
${event} ${args}"
124 # Handle -post event hooks
125 if [ -x "@sysconfdir@
/splash
/${SPLASH_THEME}/scripts
/${event}-post" ]; then
126 @sysconfdir@/splash/"${SPLASH_THEME}"/scripts/${event}-post ${args}
133 # If it's already set up, let's not waste time on parsing the config
135 if [ "${SPLASH_THEME}" != "" -a "${SPLASH_TTY}" != "" -a "$1" != "force" ]; then
139 export SPLASH_EFFECTS
=""
140 export SPLASH_SANITY
=""
141 export SPLASH_TEXTBOX
="no"
142 export SPLASH_MODE_REQ
="off"
143 export SPLASH_PROFILE
="off"
144 export SPLASH_THEME
="default"
145 export SPLASH_TTY
="16"
146 export SPLASH_KDMODE
="TEXT"
147 export SPLASH_AUTOVERBOSE
="0"
148 export SPLASH_BOOT_MESSAGE
="Booting the system (\$progress%)... Press F2 for verbose mode."
149 export SPLASH_SHUTDOWN_MESSAGE
="Shutting down the system (\$progress%)... Press F2 for verbose mode."
150 export SPLASH_REBOOT_MESSAGE
="Rebooting the system (\$progress%)... Press F2 for verbose mode."
151 export SPLASH_XSERVICE
="xdm"
153 [ -f @sysconfdir@
/splash
/splash
] && . @sysconfdir@
/splash
/splash
154 [ -f @sysconfdir@
/conf.d
/splash
] && . @sysconfdir@
/conf.d
/splash
155 [ -f @sysconfdir@
/conf.d
/fbcondecor
] && . @sysconfdir@
/conf.d
/fbcondecor
157 if [ -f /proc
/cmdline
]; then
158 options
=$
(grep -o 'splash=[^ ]*' /proc
/cmdline
)
160 # Execute this loop over $options so that we can process multiple
161 # splash= arguments on the kernel command line. Useful for adjusting
162 # splash parameters from ISOLINUX.
163 for opt
in ${options} ; do
166 for i
in $
(echo "${options}" |
sed -e 's/,/ /g') ; do
168 theme
) SPLASH_THEME
=${i#*:} ;;
169 tty
) SPLASH_TTY
=${i#*:} ;;
170 verbose
) SPLASH_MODE_REQ
="verbose" ;;
171 silent
) SPLASH_MODE_REQ
="silent" ;;
172 kdgraphics
) SPLASH_KDMODE
="GRAPHICS" ;;
173 profile
) SPLASH_PROFILE
="on" ;;
174 insane
) SPLASH_SANITY
="insane" ;;
181 splash_get_boot_message
() {
182 if [ "${RUNLEVEL}" = "6" ]; then
183 echo "${SPLASH_REBOOT_MESSAGE}"
184 elif [ "${RUNLEVEL}" = "0" ]; then
185 echo "${SPLASH_SHUTDOWN_MESSAGE}"
187 echo "${SPLASH_BOOT_MESSAGE}"
192 if [ "${SPLASH_MODE_REQ}" = "verbose" ]; then
193 ${spl_decor} -c on
2>/dev
/null
195 elif [ "${SPLASH_MODE_REQ}" != "silent" ]; then
199 # Display a warning if the system is not configured to display init messages
200 # on tty1. This can cause a lot of problems if it's not handled correctly, so
201 # we don't allow silent splash to run on incorrectly configured systems.
202 if [ "${SPLASH_MODE_REQ}" = "silent" -a "${SPLASH_SANITY}" != "insane" ]; then
203 if [ -z "$(grep -E '(^| )CONSOLE=/dev/tty1( |$)' /proc/cmdline)" -a \
204 -z "$(grep -E '(^| )console=tty1( |$)' /proc/cmdline)" ]; then
206 splash_warn
"You don't appear to have a correct console= setting on your kernel"
207 splash_warn
"command line. Silent splash will not be enabled. Please add"
208 splash_warn
"console=tty1 or CONSOLE=/dev/tty1 to your kernel command line"
209 splash_warn
"to avoid this message."
210 if [ -n "$(grep 'CONSOLE=/dev/tty1' /proc/cmdline)" -o \
211 -n "$(grep 'console=tty1' /proc/cmdline)" ]; then
212 splash_warn
"Note that CONSOLE=/dev/tty1 and console=tty1 are general parameters and"
213 splash_warn
"not splash= settings."
218 if [ -n "$(grep -E '(^| )CONSOLE=/dev/tty1( |$)' /proc/cmdline)" ]; then
219 mount
-n --bind / ${spl_tmpdir}
220 if [ ! -c "${spl_tmpdir}/dev/tty1" ]; then
221 umount
-n ${spl_tmpdir}
222 splash_warn
"The filesystem mounted on / doesn't contain the /dev/tty1 device"
223 splash_warn
"which is required for the silent splash to function properly."
224 splash_warn
"Silent splash will not be enabled. Please create the appropriate"
225 splash_warn
"device node to avoid this message."
228 umount
-n ${spl_tmpdir}
232 rm -f "${spl_pidfile}"
234 # Prepare the communications FIFO
235 rm -f "${spl_fifo}" 2>/dev
/null
239 [ "${SPLASH_KDMODE}" = "GRAPHICS" ] && options
="--kdgraphics"
240 [ -n "${SPLASH_EFFECTS}" ] && options="${options} --effects=${SPLASH_EFFECTS}"
241 [ "${SPLASH_TEXTBOX}" = "yes" ] && options
="${options} --textbox"
244 if [ "${RUNLEVEL}" = "6" ]; then
246 elif [ "${RUNLEVEL}" = "0" ]; then
250 # Start the splash daemon
251 BOOT_MSG
="$(splash_get_boot_message)" ${spl_daemon} --theme="${SPLASH_THEME}" --pidfile="${spl_pidfile}" --type=${ttype} ${options}
253 # Set the silent TTY and boot message
254 splash_comm_send
"set tty silent ${SPLASH_TTY}"
256 if [ "${SPLASH_MODE_REQ}" = "silent" ]; then
257 splash_comm_send
"set mode silent"
258 splash_comm_send
"repaint"
259 ${spl_decor} -c on
2>/dev
/null
262 splash_comm_send
"set autoverbose ${SPLASH_AUTOVERBOSE}"
269 ###########################################################################
270 # Cache-related functions
271 ###########################################################################
273 splash_cache_prep
() {
274 # Mount an in-RAM filesystem at spl_cachedir
275 mount
-ns -t "${spl_cachetype}" cachedir
"${spl_cachedir}" \
276 -o rw
,mode
=0755,noexec
,nosuid
,nodev
,size
="${spl_cachesize}"k
280 if [ ${retval} -ne 0 ]; then
281 splash_err
"Unable to create splash cache - switching to verbose."
287 # args: list of files to save when the cache is umounted
288 # Note that the 'profile' file is already handled and thus shouldn't
289 # be included in the list.
290 splash_cache_cleanup
() {
291 # Don't try to clean anything up if the cachedir is not mounted.
292 [ -z "$(grep ${spl_cachedir} /proc/mounts)" ] && return;
294 # Create the temp dir if necessary.
295 if [ ! -d "${spl_tmpdir}" ]; then
296 mkdir
-p "${spl_tmpdir}" 2>/dev
/null
297 [ "$?" != "0" ] && return
300 # Make sure the splash daemon is dead.
301 if [ -n "$(pgrep fbsplashd)" ]; then
303 killall
-9 "${spl_daemon##*/}" 2>/dev
/null
306 # If /etc is not writable, don't update /etc/mtab. If it is
307 # writable, update it to avoid stale mtab entries (bug #121827).
309 [ -w /etc
/mtab
] || mntopt
="-n"
310 mount
${mntopt} --move "${spl_cachedir}" "${spl_tmpdir}" 2>/dev/null
312 # Don't try to copy anything if the cachedir is not writable.
313 [ -w "${spl_cachedir}" ] || return
315 if [ "${SPLASH_PROFILE}" != "off
" ]; then
316 cp -a "${spl_tmpdir}/profile
" "${spl_cachedir}" 2>/dev/null
319 while [ -n "$1" ]; do
320 cp -a "${spl_tmpdir}/$1" "${spl_cachedir}" 2>/dev/null
324 umount -l "${spl_tmpdir}" 2>/dev/null
327 ###########################################################################
329 ###########################################################################
331 # Sends data to the splash FIFO after making sure there's someone
332 # alive on the other end to receive it.
334 if [ -z "`pidof $(basename ${spl_daemon})`" ]; then
337 splash_profile "comm $
*"
338 echo "$
*" > "${spl_fifo}" &
342 # Returns the current splash mode.
344 local ctty="$
(${spl_bindir}/fgconsole
)"
345 local mode="$
(${spl_util} -c getmode
)"
347 if [ "${mode}" = "silent
" ]; then
350 if [ -z "$
(${spl_decor} -c getstate
--tty=${ctty} 2>/dev
/null |
grep off
)" ]; then
360 # Switches to the n-th tty.
364 if [ -x /usr/bin/chvt ] ; then
365 /usr/bin/chvt ${ntty}
367 printf "\e
[12;${ntty}]"
371 # Switches to verbose mode.
376 # Switches to silent mode.
378 splash_comm_send "set mode silent
"
381 # Saves profiling information
383 if [ "${SPLASH_PROFILE}" = "on
" ]; then
384 echo "$
(cat /proc
/uptime | cut
-f1 -d' '): $
*" >> "${spl_cachedir}/profile
"
388 # Set the input device if it exists. This will make it possible to use F2 to
389 # switch from verbose to silent.
390 splash_set_event_dev() {
391 local t="$
(grep -Hsi keyboard
/sys
/class
/input
/input
*/name |
sed -e 's#.*input\([0-9]*\)/name.*#event\1#')"
392 if [ -z "${t}" ]; then
393 t="$
(grep -Hsi keyboard
/sys
/class
/input
/event
*/device
/driver
/description |
grep -o 'event[0-9]\+')"
394 if [ -z "${t}" ]; then
395 for i in /sys/class/input/input* ; do
396 if [ "$
((0x$
(cat $i/capabilities
/ev
) & 0x100002))" = "1048578" ]; then
397 t="$
(echo $i |
sed -e 's#.*input\([0-9]*\)#event\1#')"
401 if [ -z "${t}" ]; then
402 # Try an alternative method of finding the event device. The idea comes
403 # from Bombadil <bombadil(at)h3c.de>. We're couting on the keyboard controller
404 # being the first device handled by kbd listed in input/devices.
405 t="$
(/bin
/grep -s -m 1 '^H: Handlers=kbd' /proc
/bus
/input
/devices |
grep -o 'event[0-9]*')"
409 [ -n "${t}" ] && splash_comm_send "set event dev
/dev
/input
/${t}"
412 ###########################################################################
414 ###########################################################################
416 # args: <svc> <action>
421 if [ "${act}" = "start
" ]; then
422 splash_svc_update "${srv}" "svc_started
"
423 if [ "${srv}" = "gpm
" ]; then
424 splash_comm_send "set gpm
"
425 splash_comm_send "repaint
"
427 splash_comm_send "log Service
'${srv}' started.
"
429 splash_svc_update "${srv}" "svc_stopped
"
430 splash_comm_send "log Service
'${srv}' stopped.
"
433 splash_update_progress "${srv}"
436 # args: <svc> <action>
441 if [ "${SPLASH_VERBOSE_ON_ERRORS}" = "yes" ]; then
446 if [ "${act}" = "start
" ]; then
447 splash_svc_update "${srv}" "svc_start_failed
"
448 splash_comm_send "log Service
'${srv}' failed to start.
"
450 splash_svc_update "${srv}" "svc_stop_failed
"
451 splash_comm_send "log Service
'${srv}' failed to stop.
"
454 splash_update_progress "${srv}"
457 # args: <svc> <state>
459 # Inform the splash daemon about service status changes.
460 splash_svc_update() {
461 splash_comm_send "update_svc
$1 $2"
468 splash_svc_update "${svc}" "svc_start
"
469 splash_comm_send "paint
"
476 splash_svc_update "${svc}" "svc_stop
"
477 splash_comm_send "paint
"
481 splash_input_begin() {
484 if [ "$
(splash_get_mode
)" = "silent
" ]; then
486 export SPL_SVC_INPUT_SILENT="${svc}"
494 if [ "${SPL_SVC_INPUT_SILENT}" = "${svc}" ]; then
496 unset SPL_SVC_INPUT_SILENT
500 ###########################################################################
501 # Framebuffer Console Decorations functions
502 ###########################################################################
504 fbcondecor_supported()
506 [ -e /dev/fbsplash -o -e /dev/fbcondecor ]
509 # args: <theme> <tty>
510 fbcondecor_set_theme()
515 [ -x ${spl_decor} ] || return 1
517 ${spl_decor} --tty="${tty}" -t "${theme}" -c setcfg ||
return 1
518 ${spl_decor} --tty="${tty}" -t "${theme}" -c setpic -q
519 ${spl_decor} --tty="${tty}" -c on
522 ###########################################################################
524 ###########################################################################
526 # splash_svclist_get <type>
527 # -------------------------
529 # - start - to get a list of services to be started during bootup
530 # - stop - to get a list of services to be stopped during shutdown/reboot
531 splash_svclist_get() {
532 if [ "$1" = "start
" -a -r "${spl_cachedir}/svcs_start
" ]; then
533 cat "${spl_cachedir}/svcs_start
"
534 elif [ "$1" = "stop
" -a -r "${spl_cachedir}/svcs_stop
" ]; then
535 cat "${spl_cachedir}/svcs_stop
"
547 ############################################################################
548 # Functions to be overridden by distro-specific code
549 ###########################################################################
551 # args: <internal_runlevel> <runlevel>
553 # This function is called when an 'rc_init' event takes place,
554 # i.e. when the runlevel is changed.
556 # It is normally used to initialize any internal splash-related
557 # variables (e.g. ones used to track the boot progress), calculate
558 # and save the service list and call `splash_start` in appropriate
561 # Note that the splash cache is already intialized when this
562 # function is called.
564 if [ "$2" = "6" -o "$2" = "0" -o "$2" = "S
" -a "$1" = "sysinit
" ]; then
571 # This function is called when an 'rc_exit' event takes place,
572 # i.e. at the end of processes all initscript from a runlevel.
574 # If we're in sysinit or rebooting, do nothing.
575 [ "$1" = "S
" -o "$1" = "6" -o "$1" = "0" ] && return 0
577 splash_comm_send "exit"
583 # This function is called whenever the progress variable should be
584 # updated. It should recalculate the progress and send it to the
586 splash_update_progress() {
587 # splash_comm_send "progress
${progress}"
588 # splash_comm_send "paint
"
592 # Export functions if we're running bash.
593 if [ -n "${BASH}" ]; then
595 export -f splash_setup
596 export -f splash_get_boot_message
597 export -f splash_start
598 export -f splash_cache_prep
599 export -f splash_cache_cleanup
600 export -f splash_comm_send
601 export -f splash_get_mode
603 export -f splash_verbose
604 export -f splash_silent
605 export -f splash_profile
606 export -f splash_set_event_dev
607 export -f splash_svclist_get
610 # Load any supplementary splash functions.
611 for i in /sbin/splash-functions-*.sh ; do
612 [ -r "${i}" ] && . "${i}"