Fix typo in the Gentoo initscript.
[fbsplash.git] / core / scripts / splash-functions.sh.in
blob03f6bfe5943a40a9f88fe5256ee02c40f65a450f
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
10 # allowed!
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
22 # default value.
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:
36 # svc_start <name>
37 # svc_stop <name>
38 # svc_started <name>
39 # svc_stopped <name>
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'
45 # rc_exit
46 # critical
47 splash() {
48 local event="$1"
49 shift
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
55 splash_setup "force"
56 else
57 splash_setup
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
75 local args=""
77 if [ "${event}" = "rc_init" -o "${event}" = "rc_exit" ]; then
78 args="$* ${RUNLEVEL}"
79 elif [ "${event}" = "svc_started" -o "${event}" = "svc_stopped" ]; then
80 if [ -z "$2" ]; then
81 # Backwards compatibility hack. Add a 0 to the arguments to simulate
82 # an error code.
83 args="$* 0"
84 else
85 args="$*"
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"
92 else
93 event="svc_stop_failed"
97 else
98 args="$*"
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}
108 case "$event" in
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;;
120 esac
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}
129 return 0
132 splash_setup() {
133 # If it's already set up, let's not waste time on parsing the config
134 # files again
135 if [ "${SPLASH_THEME}" != "" -a "${SPLASH_TTY}" != "" -a "$1" != "force" ]; then
136 return 0
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
164 options=${opt#*=}
166 for i in $(echo "${options}" | sed -e 's/,/ /g') ; do
167 case ${i%:*} in
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" ;;
175 esac
176 done
177 done
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}"
186 else
187 echo "${SPLASH_BOOT_MESSAGE}"
191 splash_start() {
192 if [ "${SPLASH_MODE_REQ}" = "verbose" ]; then
193 ${spl_decor} -c on 2>/dev/null
194 return 0
195 elif [ "${SPLASH_MODE_REQ}" != "silent" ]; then
196 return 0
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
205 clear
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."
215 return 1
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."
226 return 1
228 umount -n ${spl_tmpdir}
232 rm -f "${spl_pidfile}"
234 # Prepare the communications FIFO
235 rm -f "${spl_fifo}" 2>/dev/null
236 mkfifo "${spl_fifo}"
238 local options=""
239 [ "${SPLASH_KDMODE}" = "GRAPHICS" ] && options="--kdgraphics"
240 [ -n "${SPLASH_EFFECTS}" ] && options="${options} --effects=${SPLASH_EFFECTS}"
241 [ "${SPLASH_TEXTBOX}" = "yes" ] && options="${options} --textbox"
243 local ttype="bootup"
244 if [ "${RUNLEVEL}" = "6" ]; then
245 ttype="reboot"
246 elif [ "${RUNLEVEL}" = "0" ]; then
247 ttype="shutdown"
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}"
264 splash_set_event_dev
266 return 0
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
278 retval="$?"
280 if [ ${retval} -ne 0 ]; then
281 splash_err "Unable to create splash cache - switching to verbose."
282 splash_verbose
283 return "${retval}"
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
302 sleep 1
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).
308 local mntopt=""
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
321 shift
322 done
324 umount -l "${spl_tmpdir}" 2>/dev/null
327 ###########################################################################
328 # Common functions
329 ###########################################################################
331 # Sends data to the splash FIFO after making sure there's someone
332 # alive on the other end to receive it.
333 splash_comm_send() {
334 if [ -z "`pidof $(basename ${spl_daemon})`" ]; then
335 return 1
336 else
337 splash_profile "comm $*"
338 echo "$*" > "${spl_fifo}" &
342 # Returns the current splash mode.
343 splash_get_mode() {
344 local ctty="$(${spl_bindir}/fgconsole)"
345 local mode="$(${spl_util} -c getmode)"
347 if [ "${mode}" = "silent" ]; then
348 echo "silent"
349 else
350 if [ -z "$(${spl_decor} -c getstate --tty=${ctty} 2>/dev/null | grep off)" ]; then
351 echo "verbose"
352 else
353 echo "off"
358 # chvt <n>
359 # --------
360 # Switches to the n-th tty.
361 chvt() {
362 local ntty=$1
364 if [ -x /usr/bin/chvt ] ; then
365 /usr/bin/chvt ${ntty}
366 else
367 printf "\e[12;${ntty}]"
371 # Switches to verbose mode.
372 splash_verbose() {
373 chvt 1
376 # Switches to silent mode.
377 splash_silent() {
378 splash_comm_send "set mode silent"
381 # Saves profiling information
382 splash_profile() {
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#')"
399 done
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 ###########################################################################
413 # Service
414 ###########################################################################
416 # args: <svc> <action>
417 splash_svc() {
418 local srv="$1"
419 local act="$2"
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."
428 else
429 splash_svc_update "${srv}" "svc_stopped"
430 splash_comm_send "log Service '${srv}' stopped."
433 splash_update_progress "${srv}"
436 # args: <svc> <action>
437 splash_svc_fail() {
438 local srv="$1"
439 local act="$2"
441 if [ "${SPLASH_VERBOSE_ON_ERRORS}" = "yes" ]; then
442 splash_verbose
443 return 1
446 if [ "${act}" = "start" ]; then
447 splash_svc_update "${srv}" "svc_start_failed"
448 splash_comm_send "log Service '${srv}' failed to start."
449 else
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"
464 # args: <svc>
465 splash_svc_start() {
466 local svc="$1"
468 splash_svc_update "${svc}" "svc_start"
469 splash_comm_send "paint"
472 # args: <svc>
473 splash_svc_stop() {
474 local svc="$1"
476 splash_svc_update "${svc}" "svc_stop"
477 splash_comm_send "paint"
480 # args: <svc>
481 splash_input_begin() {
482 local svc="$1"
484 if [ "$(splash_get_mode)" = "silent" ]; then
485 splash_verbose
486 export SPL_SVC_INPUT_SILENT="${svc}"
490 # args: <svc>
491 splash_input_end() {
492 local svc="$1"
494 if [ "${SPL_SVC_INPUT_SILENT}" = "${svc}" ]; then
495 splash_silent
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()
512 local theme=$1
513 local tty=$2
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 ###########################################################################
523 # Service list
524 ###########################################################################
526 # splash_svclist_get <type>
527 # -------------------------
528 # type:
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"
539 splash_warn() {
540 echo "$*"
543 splash_err() {
544 echo "$*"
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
559 # runlevels.
561 # Note that the splash cache is already intialized when this
562 # function is called.
563 splash_init() {
564 if [ "$2" = "6" -o "$2" = "0" -o "$2" = "S" -a "$1" = "sysinit" ]; then
565 splash_start
569 # args: <runlevel>
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.
573 splash_exit() {
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"
578 splash_cache_cleanup
581 # args: <svc>
583 # This function is called whenever the progress variable should be
584 # updated. It should recalculate the progress and send it to the
585 # splash daemon.
586 splash_update_progress() {
587 # splash_comm_send "progress ${progress}"
588 # splash_comm_send "paint"
589 return
592 # Export functions if we're running bash.
593 if [ -n "${BASH}" ]; then
594 export -f splash
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
602 export -f chvt
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}"
613 done
615 splash_setup
617 # vim:ts=4