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
="@bindir@/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:
38 # svc_started <name> <errcode>
39 # svc_stopped <name> <errcode>
40 # svc_input_begin <name>
41 # svc_input_end <name>
42 # rc_init <internal_runlevel> - used to distinguish between 'boot' and 'sysinit'
49 # Reload the splash settings in rc_init. We could have set them wrong the
50 # first time splash_setup was called (when splash-functions.sh was first
51 # sourced) if /proc wasn't mounted.
52 if [ "${event}" = "rc_init" ]; then
58 [ "${SPLASH_MODE_REQ}" = "off" ] && return
60 # Prepare the cache here -- rc_init-pre might want to use it
61 if [ "${event}" = "rc_init" ]; then
62 if [ "${RUNLEVEL}" = "S" -a "$1" = "sysinit" ]; then
63 splash_cache_prep
'start' ||
return
64 elif [ "${RUNLEVEL}" = "6" -o "${RUNLEVEL}" = "0" ]; then
65 # Check if the splash cachedir is mounted readonly. If it is,
66 # we need to mount a tmpfs over it.
67 if ! touch "${spl_cachedir}/message" 2>/dev
/null
; then
68 splash_cache_prep
'stop' ||
return
75 if [ "${event}" = "rc_init" -o "${event}" = "rc_exit" ]; then
81 splash_profile
"pre ${event} ${args}"
83 # Handle -pre event hooks
84 if [ -x "@sysconfdir@/splash/${SPLASH_THEME}/scripts/${event}-pre" ]; then
85 @sysconfdir@
/splash
/"${SPLASH_THEME}"/scripts/${event}-pre ${args}
89 svc_start) splash_svc_start "$1";;
90 svc_stop) splash_svc_stop "$1";;
91 svc_started) splash_svc "$1" "$2" "start
";;
92 svc_stopped) splash_svc "$1" "$2" "stop
";;
93 svc_input_begin) splash_input_begin "$1";;
94 svc_input_end) splash_input_end "$1";;
95 rc_init) splash_init "$1" "${RUNLEVEL}";;
96 rc_exit) splash_exit "${RUNLEVEL}";;
97 critical) splash_verbose;;
100 splash_profile "post
${event} ${args}"
102 # Handle -post event hooks
103 if [ -x "@sysconfdir@
/splash
/${SPLASH_THEME}/scripts
/${event}-post" ]; then
104 @sysconfdir@/splash/"${SPLASH_THEME}"/scripts/${event}-post ${args}
111 # If it's already set up, let's not waste time on parsing the config
113 if [ "${SPLASH_THEME}" != "" -a "${SPLASH_TTY}" != "" -a "$1" != "force" ]; then
117 export SPLASH_EFFECTS
=""
118 export SPLASH_SANITY
=""
119 export SPLASH_MODE_REQ
="off"
120 export SPLASH_PROFILE
="off"
121 export SPLASH_THEME
="default"
122 export SPLASH_TTY
="16"
123 export SPLASH_KDMODE
="TEXT"
124 export SPLASH_BOOT_MESSAGE
="Booting the system (\$progress%)... Press F2 for verbose mode."
125 export SPLASH_SHUTDOWN_MESSAGE
="Shutting down the system (\$progress%)... Press F2 for verbose mode."
126 export SPLASH_REBOOT_MESSAGE
="Rebooting the system (\$progress%)... Press F2 for verbose mode."
128 [ -f @sysconfdir@
/splash
/splash
] && . @sysconfdir@
/splash
/splash
129 [ -f @sysconfdir@
/conf.d
/splash
] && . @sysconfdir@
/conf.d
/splash
130 [ -f @sysconfdir@
/conf.d
/fbcondecor
] && . @sysconfdir@
/conf.d
/fbcondecor
132 if [ -f /proc
/cmdline
]; then
133 options
=$
(grep -o 'splash=[^ ]*' /proc
/cmdline
)
135 # Execute this loop over $options so that we can process multiple
136 # splash= arguments on the kernel command line. Useful for adjusting
137 # splash parameters from ISOLINUX.
138 for opt
in ${options} ; do
141 for i
in $
(echo "${options}" |
sed -e 's/,/ /g') ; do
143 theme
) SPLASH_THEME
=${i#*:} ;;
144 tty
) SPLASH_TTY
=${i#*:} ;;
145 verbose
) SPLASH_MODE_REQ
="verbose" ;;
146 silent
) SPLASH_MODE_REQ
="silent" ;;
147 kdgraphics
) SPLASH_KDMODE
="GRAPHICS" ;;
148 profile
) SPLASH_PROFILE
="on" ;;
149 insane
) SPLASH_SANITY
="insane" ;;
156 splash_get_boot_message
() {
157 if [ "${RUNLEVEL}" = "6" ]; then
158 echo "${SPLASH_REBOOT_MESSAGE}"
159 elif [ "${RUNLEVEL}" = "0" ]; then
160 echo "${SPLASH_SHUTDOWN_MESSAGE}"
162 echo "${SPLASH_BOOT_MESSAGE}"
167 if [ "${SPLASH_MODE_REQ}" = "verbose" ]; then
168 ${spl_decor} -c on
2>/dev
/null
170 elif [ "${SPLASH_MODE_REQ}" != "silent" ]; then
174 # Display a warning if the system is not configured to display init messages
175 # on tty1. This can cause a lot of problems if it's not handled correctly, so
176 # we don't allow silent splash to run on incorrectly configured systems.
177 if [ "${SPLASH_MODE_REQ}" = "silent" -a "${SPLASH_SANITY}" != "insane" ]; then
178 if [ -z "$(grep -E '(^| )CONSOLE=/dev/tty1( |$)' /proc/cmdline)" -a \
179 -z "$(grep -E '(^| )console=tty1( |$)' /proc/cmdline)" ]; then
181 splash_warn
"You don't appear to have a correct console= setting on your kernel"
182 splash_warn
"command line. Silent splash will not be enabled. Please add"
183 splash_warn
"console=tty1 or CONSOLE=/dev/tty1 to your kernel command line"
184 splash_warn
"to avoid this message."
185 if [ -n "$(grep 'CONSOLE=/dev/tty1' /proc/cmdline)" -o \
186 -n "$(grep 'console=tty1' /proc/cmdline)" ]; then
187 splash_warn
"Note that CONSOLE=/dev/tty1 and console=tty1 are general parameters and"
188 splash_warn
"not splash= settings."
193 mount
-n --bind / ${spl_tmpdir}
194 if [ ! -c "${spl_tmpdir}/dev/tty1" ]; then
195 umount
-n ${spl_tmpdir}
196 splash_warn
"The filesystem mounted on / doesn't contain the /dev/tty1 device"
197 splash_warn
"which is required for the silent splash to function properly."
198 splash_warn
"Silent splash will not be enabled. Please create the appropriate"
199 splash_warn
"device node to avoid this message."
202 umount
-n ${spl_tmpdir}
205 rm -f "${spl_pidfile}"
207 # Prepare the communications FIFO
208 rm -f "${spl_fifo}" 2>/dev
/null
212 [ "${SPLASH_KDMODE}" = "GRAPHICS" ] && options
="--kdgraphics"
213 [ -n "${SPLASH_EFFECTS}" ] && options="${options} --effects=${SPLASH_EFFECTS}"
216 if [ "${RUNLEVEL}" = "6" ]; then
218 elif [ "${RUNLEVEL}" = "0" ]; then
222 # Start the splash daemon
223 BOOT_MSG
="$(splash_get_boot_message)" ${spl_daemon} --theme="${SPLASH_THEME}" --pidfile="${spl_pidfile}" --type=${ttype} ${options}
225 # Set the silent TTY and boot message
226 splash_comm_send
"set tty silent ${SPLASH_TTY}"
228 if [ "${SPLASH_MODE_REQ}" = "silent" ]; then
229 splash_comm_send
"set mode silent"
230 splash_comm_send
"repaint"
231 ${spl_decor} -c on
2>/dev
/null
239 ###########################################################################
240 # Cache-related functions
241 ###########################################################################
243 splash_cache_prep
() {
244 # Mount an in-RAM filesystem at spl_cachedir
245 mount
-ns -t "${spl_cachetype}" cachedir
"${spl_cachedir}" \
246 -o rw
,mode
=0644,size
="${spl_cachesize}"k
250 if [ ${retval} -ne 0 ]; then
251 splash_err
"Unable to create splash cache - switching to verbose."
257 # args: list of files to save when the cache is umounted
258 # Note that the 'profile' file is already handled and thus shouldn't
259 # be included in the list.
260 splash_cache_cleanup
() {
261 # Don't try to clean anything up if the cachedir is not mounted.
262 [ -z "$(grep ${spl_cachedir} /proc/mounts)" ] && return;
264 # Create the temp dir if necessary.
265 if [ ! -d "${spl_tmpdir}" ]; then
266 mkdir
-p "${spl_tmpdir}" 2>/dev
/null
267 [ "$?" != "0" ] && return
270 # Make sure the splash daemon is dead.
271 if [ -n "$(pgrep fbsplashd)" ]; then
273 killall
-9 "${spl_daemon##*/}" 2>/dev
/null
276 # If /etc is not writable, don't update /etc/mtab. If it is
277 # writable, update it to avoid stale mtab entries (bug #121827).
279 [ -w /etc
/mtab
] || mntopt
="-n"
280 mount
${mntopt} --move "${spl_cachedir}" "${spl_tmpdir}" 2>/dev/null
282 # Don't try to copy anything if the cachedir is not writable.
283 [ -w "${spl_cachedir}" ] || return
285 if [ "${SPLASH_PROFILE}" != "off
" ]; then
286 cp -a "${spl_tmpdir}/profile
" "${spl_cachedir}" 2>/dev/null
289 while [ -n "$1" ]; do
290 cp -a "${spl_tmpdir}/$1" "${spl_cachedir}" 2>/dev/null
294 umount -l "${spl_tmpdir}" 2>/dev/null
297 ###########################################################################
299 ###########################################################################
301 # Sends data to the splash FIFO after making sure there's someone
302 # alive on the other end to receive it.
304 if [ -z "`pidof $(basename ${spl_daemon})`" ]; then
307 splash_profile "comm $
*"
308 echo "$
*" > "${spl_fifo}" &
312 # Returns the current splash mode.
314 local ctty="${spl_bindir}/fgconsole
"
315 local mode="$
(${spl_util})"
317 if [ "${mode}" = "silent
" ]; then
320 if [ -z "$
(${spl_decor} -c getstate
--tty=${ctty} 2>/dev
/null |
grep off
)" ]; then
330 # Switches to the n-th tty.
334 if [ -x /usr/bin/chvt ] ; then
335 /usr/bin/chvt ${ntty}
337 printf "\e
[12;${ntty}]"
341 # Switches to verbose mode.
346 # Switches to silent mode.
348 splash_comm_send "set mode silent
"
351 # Saves profiling information
353 if [ "${SPLASH_PROFILE}" = "on
" ]; then
354 echo "$
(cat /proc
/uptime | cut
-f1 -d' '): $
*" >> "${spl_cachedir}/profile
"
358 # Set the input device if it exists. This will make it possible to use F2 to
359 # switch from verbose to silent.
360 splash_set_event_dev() {
361 local t="$
(grep -Hsi keyboard
/sys
/class
/input
/input
*/name |
sed -e 's#.*input\([0-9]*\)/name.*#event\1#')"
362 if [ -z "${t}" ]; then
363 t="$
(grep -Hsi keyboard
/sys
/class
/input
/event
*/device
/driver
/description |
grep -o 'event[0-9]\+')"
364 if [ -z "${t}" ]; then
365 for i in /sys/class/input/input* ; do
366 if [ "$
((0x$
(cat $i/capabilities
/ev
) & 0x100002))" = "1048578" ]; then
367 t="$
(echo $i |
sed -e 's#.*input\([0-9]*\)#event\1#')"
371 if [ -z "${t}" ]; then
372 # Try an alternative method of finding the event device. The idea comes
373 # from Bombadil <bombadil(at)h3c.de>. We're couting on the keyboard controller
374 # being the first device handled by kbd listed in input/devices.
375 t="$
(/bin
/grep -s -m 1 '^H: Handlers=kbd' /proc
/bus
/input
/devices |
grep -o 'event[0-9]*')"
379 [ -n "${t}" ] && splash_comm_send "set event dev
/dev
/input
/${t}"
382 ###########################################################################
384 ###########################################################################
386 # args: <svc> <error-code> <action>
392 if [ ${err} -ne 0 -a "${SPLASH_VERBOSE_ON_ERRORS}" = "yes" ]; then
397 if [ "${act}" = "start
" ]; then
398 if [ ${err} -eq 0 ]; then
399 splash_svc_update "${srv}" "svc_started
"
400 if [ "${srv}" = "gpm
" ]; then
401 splash_comm_send "set gpm
"
402 splash_comm_send "repaint
"
404 splash_comm_send "log Service
'${srv}' started.
"
406 splash_svc_update "${srv}" "svc_start_failed
"
407 splash_comm_send "log Service
'${srv}' failed to start.
"
410 if [ ${err} -eq 0 ]; then
411 splash_svc_update "${srv}" "svc_stopped
"
412 splash_comm_send "log Service
'${srv}' stopped.
"
414 splash_svc_update "${srv}" "svc_stop_failed
"
415 splash_comm_send "log Service
'${srv}' failed to stop.
"
419 splash_update_progress "${srv}"
422 # args: <svc> <state>
424 # Inform the splash daemon about service status changes.
425 splash_svc_update() {
426 splash_comm_send "update_svc
$1 $2"
433 splash_svc_update "${svc}" "svc_start
"
434 splash_comm_send "paint
"
441 splash_svc_update "${svc}" "svc_stop
"
442 splash_comm_send "paint
"
446 splash_input_begin() {
449 if [ "$
(splash_get_mode
)" = "silent
" ]; then
451 export SPL_SVC_INPUT_SILENT="${svc}"
459 if [ "${SPL_SVC_INPUT_SILENT}" = "${svc}" ]; then
461 unset SPL_SVC_INPUT_SILENT
465 ###########################################################################
466 # Framebuffer Console Decorations functions
467 ###########################################################################
469 fbcondecor_supported()
471 [ -e /dev/fbsplash -o -e /dev/fbcondecor ]
474 # args: <theme> <tty>
475 fbcondecor_set_theme()
480 [ -x ${spl_decor} ] || return 1
482 ${spl_decor} --tty="${tty}" -t "${theme}" -c setcfg ||
return 1
483 ${spl_decor} --tty="${tty}" -t "${theme}" -c setpic -q
484 ${spl_decor} --tty="${tty}" -c on
487 ###########################################################################
489 ###########################################################################
491 # splash_svclist_get <type>
492 # -------------------------
494 # - start - to get a list of services to be started during bootup
495 # - stop - to get a list of services to be stopped during shutdown/reboot
496 splash_svclist_get() {
497 if [ "$1" = "start
" -a -r "${spl_cachedir}/svcs_start
" ]; then
498 cat "${spl_cachedir}/svcs_start
"
499 elif [ "$1" = "stop
" -a -r "${spl_cachedir}/svcs_stop
" ]; then
500 cat "${spl_cachedir}/svcs_stop
"
512 ############################################################################
513 # Functions to be overridden by distro-specific code
514 ###########################################################################
516 # args: <internal_runlevel> <runlevel>
518 # This function is called when an 'rc_init' event takes place,
519 # i.e. when the runlevel is changed.
521 # It is normally used to initialize any internal splash-related
522 # variables (e.g. ones used to track the boot progress), calculate
523 # and save the service list and call `splash_start` in appropriate
526 # Note that the splash cache is already intialized when this
527 # function is called.
529 if [ "$2" = "6" -o "$2" = "0" -o "$2" = "S
" -a "$1" = "sysinit
" ]; then
536 # This function is called when an 'rc_exit' event takes place,
537 # i.e. at the end of processes all initscript from a runlevel.
539 # If we're in sysinit or rebooting, do nothing.
540 [ "$1" = "S
" -o "$1" = "6" -o "$1" = "0" ] && return 0
542 splash_comm_send "exit"
548 # This function is called whenever the progress variable should be
549 # updated. It should recalculate the progress and send it to the
551 splash_update_progress() {
552 # splash_comm_send "progress
${progress}"
553 # splash_comm_send "paint
"
557 # Export functions if we're running bash.
558 if [ -n "${BASH}" ]; then
560 export -f splash_setup
561 export -f splash_get_boot_message
562 export -f splash_start
563 export -f splash_cache_prep
564 export -f splash_cache_cleanup
565 export -f splash_comm_send
566 export -f splash_get_mode
568 export -f splash_verbose
569 export -f splash_silent
570 export -f splash_profile
571 export -f splash_set_event_dev
572 export -f splash_svclist_get
575 # Load any supplemental splash functions.
576 for i in /sbin/splash-functions-*.sh ; do
577 [ -r "${i}" ] && . "${i}"