core: add the splashy2fbsplash theme converter
[fbsplash.git] / core / scripts / splash-functions.sh.in
blob4eda445dd546fb85c99c192621460641b9c66c87
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="@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:
36 # svc_start <name>
37 # svc_stop <name>
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'
43 # rc_exit
44 # critical
45 splash() {
46 local event="$1"
47 shift
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
53 splash_setup "force"
54 else
55 splash_setup
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
73 local args=""
75 if [ "${event}" = "rc_init" -o "${event}" = "rc_exit" ]; then
76 args="$* ${RUNLEVEL}"
77 else
78 args="$*"
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}
88 case "$event" in
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;;
98 esac
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}
107 return 0
110 splash_setup() {
111 # If it's already set up, let's not waste time on parsing the config
112 # files again
113 if [ "${SPLASH_THEME}" != "" -a "${SPLASH_TTY}" != "" -a "$1" != "force" ]; then
114 return 0
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
139 options=${opt#*=}
141 for i in $(echo "${options}" | sed -e 's/,/ /g') ; do
142 case ${i%:*} in
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" ;;
150 esac
151 done
152 done
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}"
161 else
162 echo "${SPLASH_BOOT_MESSAGE}"
166 splash_start() {
167 if [ "${SPLASH_MODE_REQ}" = "verbose" ]; then
168 ${spl_decor} -c on 2>/dev/null
169 return 0
170 elif [ "${SPLASH_MODE_REQ}" != "silent" ]; then
171 return 0
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
180 clear
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."
190 return 1
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."
200 return 1
202 umount -n ${spl_tmpdir}
205 rm -f "${spl_pidfile}"
207 # Prepare the communications FIFO
208 rm -f "${spl_fifo}" 2>/dev/null
209 mkfifo "${spl_fifo}"
211 local options=""
212 [ "${SPLASH_KDMODE}" = "GRAPHICS" ] && options="--kdgraphics"
213 [ -n "${SPLASH_EFFECTS}" ] && options="${options} --effects=${SPLASH_EFFECTS}"
215 local ttype="bootup"
216 if [ "${RUNLEVEL}" = "6" ]; then
217 ttype="reboot"
218 elif [ "${RUNLEVEL}" = "0" ]; then
219 ttype="shutdown"
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
234 splash_set_event_dev
236 return 0
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
248 retval="$?"
250 if [ ${retval} -ne 0 ]; then
251 splash_err "Unable to create splash cache - switching to verbose."
252 splash_verbose
253 return "${retval}"
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
272 sleep 1
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).
278 local mntopt=""
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
291 shift
292 done
294 umount -l "${spl_tmpdir}" 2>/dev/null
297 ###########################################################################
298 # Common functions
299 ###########################################################################
301 # Sends data to the splash FIFO after making sure there's someone
302 # alive on the other end to receive it.
303 splash_comm_send() {
304 if [ -z "`pidof $(basename ${spl_daemon})`" ]; then
305 return 1
306 else
307 splash_profile "comm $*"
308 echo "$*" > "${spl_fifo}" &
312 # Returns the current splash mode.
313 splash_get_mode() {
314 local ctty="${spl_bindir}/fgconsole"
315 local mode="$(${spl_util})"
317 if [ "${mode}" = "silent" ]; then
318 echo "silent"
319 else
320 if [ -z "$(${spl_decor} -c getstate --tty=${ctty} 2>/dev/null | grep off)" ]; then
321 echo "verbose"
322 else
323 echo "off"
328 # chvt <n>
329 # --------
330 # Switches to the n-th tty.
331 chvt() {
332 local ntty=$1
334 if [ -x /usr/bin/chvt ] ; then
335 /usr/bin/chvt ${ntty}
336 else
337 printf "\e[12;${ntty}]"
341 # Switches to verbose mode.
342 splash_verbose() {
343 chvt 1
346 # Switches to silent mode.
347 splash_silent() {
348 splash_comm_send "set mode silent"
351 # Saves profiling information
352 splash_profile() {
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#')"
369 done
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 ###########################################################################
383 # Service
384 ###########################################################################
386 # args: <svc> <error-code> <action>
387 splash_svc() {
388 local srv="$1"
389 local err="$2"
390 local act="$3"
392 if [ ${err} -ne 0 -a "${SPLASH_VERBOSE_ON_ERRORS}" = "yes" ]; then
393 splash_verbose
394 return 1
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."
405 else
406 splash_svc_update "${srv}" "svc_start_failed"
407 splash_comm_send "log Service '${srv}' failed to start."
409 else
410 if [ ${err} -eq 0 ]; then
411 splash_svc_update "${srv}" "svc_stopped"
412 splash_comm_send "log Service '${srv}' stopped."
413 else
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"
429 # args: <svc>
430 splash_svc_start() {
431 local svc="$1"
433 splash_svc_update "${svc}" "svc_start"
434 splash_comm_send "paint"
437 # args: <svc>
438 splash_svc_stop() {
439 local svc="$1"
441 splash_svc_update "${svc}" "svc_stop"
442 splash_comm_send "paint"
445 # args: <svc>
446 splash_input_begin() {
447 local svc="$1"
449 if [ "$(splash_get_mode)" = "silent" ]; then
450 splash_verbose
451 export SPL_SVC_INPUT_SILENT="${svc}"
455 # args: <svc>
456 splash_input_end() {
457 local svc="$1"
459 if [ "${SPL_SVC_INPUT_SILENT}" = "${svc}" ]; then
460 splash_silent
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()
477 local theme=$1
478 local tty=$2
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 ###########################################################################
488 # Service list
489 ###########################################################################
491 # splash_svclist_get <type>
492 # -------------------------
493 # type:
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"
504 splash_warn() {
505 echo "$*"
508 splash_err() {
509 echo "$*"
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
524 # runlevels.
526 # Note that the splash cache is already intialized when this
527 # function is called.
528 splash_init() {
529 if [ "$2" = "6" -o "$2" = "0" -o "$2" = "S" -a "$1" = "sysinit" ]; then
530 splash_start
534 # args: <runlevel>
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.
538 splash_exit() {
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"
543 splash_cache_cleanup
546 # args: <svc>
548 # This function is called whenever the progress variable should be
549 # updated. It should recalculate the progress and send it to the
550 # splash daemon.
551 splash_update_progress() {
552 # splash_comm_send "progress ${progress}"
553 # splash_comm_send "paint"
554 return
557 # Export functions if we're running bash.
558 if [ -n "${BASH}" ]; then
559 export -f splash
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
567 export -f chvt
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}"
578 done
580 splash_setup
582 # vim:ts=4