summaryrefslogtreecommitdiffstats
path: root/abs/core/fbsplash/splash-functions.sh
diff options
context:
space:
mode:
Diffstat (limited to 'abs/core/fbsplash/splash-functions.sh')
-rw-r--r--abs/core/fbsplash/splash-functions.sh618
1 files changed, 618 insertions, 0 deletions
diff --git a/abs/core/fbsplash/splash-functions.sh b/abs/core/fbsplash/splash-functions.sh
new file mode 100644
index 0000000..1c17663
--- /dev/null
+++ b/abs/core/fbsplash/splash-functions.sh
@@ -0,0 +1,618 @@
+# Distributed under the terms of the GNU General Public License v2
+
+# Author: Michal Januszewski <spock@gentoo.org>
+# Maintainer: Michal Januszewski <spock@gentoo.org>
+
+# This file is a part of splashutils. The functions contained in this
+# file are meant to be used by hook scripts in splash themes or by
+# initscript systems. The code will be kept distro-agnostic to facilitate
+# portability. It should also contain POSIX compatible code. No bashisms
+# allowed!
+
+# ####################################################################
+# Change any settings ONLY if you are sure what you're doing.
+# Don't cry if it breaks afterwards.
+# ####################################################################
+
+# The splash scripts need a cache which can be guaranteed to be
+# both readable and writable at all times, even when the root fs
+# is mounted read-only. To that end, an in-RAM fs is used. Valid
+# values for spl_cachetype are 'tmpfs' and 'ramfs'. spl_cachesize
+# is a size limit in KB, and it should probably be left with the
+# default value.
+export spl_cachesize="4096"
+export spl_cachetype="tmpfs"
+export spl_cachedir="//lib/splash/cache"
+export spl_tmpdir="//lib/splash/tmp"
+export spl_fifo="${spl_cachedir}/.splash"
+export spl_pidfile="${spl_cachedir}/daemon.pid"
+export spl_util="//bin/splash_util.static"
+export spl_daemon="//sbin/fbsplashd.static"
+export spl_decor="//sbin/fbcondecor_ctl.static"
+export spl_bindir="//lib/splash/bin"
+
+# This is the main function which handles all events.
+# Accepted parameters:
+# svc_start <name>
+# svc_stop <name>
+# svc_started <name>
+# svc_stopped <name>
+# svc_start_failed <name>
+# svc_stop_failed <name>
+# svc_input_begin <name>
+# svc_input_end <name>
+# rc_init <internal_runlevel> - used to distinguish between 'boot' and 'sysinit'
+# rc_exit
+# critical
+splash() {
+ local event="$1"
+ shift
+
+ # Reload the splash settings in rc_init. We could have set them wrong the
+ # first time splash_setup was called (when splash-functions.sh was first
+ # sourced) if /proc wasn't mounted.
+ if [ "${event}" = "rc_init" ]; then
+ splash_setup "force"
+ else
+ splash_setup
+ fi
+
+ [ "${SPLASH_MODE_REQ}" = "off" ] && return
+
+ # Prepare the cache here -- rc_init-pre might want to use it
+ if [ "${event}" = "rc_init" ]; then
+ if [ "${RUNLEVEL}" = "S" -a "$1" = "sysinit" ]; then
+ splash_cache_prep 'start' || return
+ elif [ "${RUNLEVEL}" = "6" -o "${RUNLEVEL}" = "0" ]; then
+ # Check if the splash cachedir is mounted readonly. If it is,
+ # we need to mount a tmpfs over it.
+ if ! touch "${spl_cachedir}/message" 2>/dev/null ; then
+ splash_cache_prep 'stop' || return
+ fi
+ fi
+ fi
+
+ local args=""
+
+ if [ "${event}" = "rc_init" -o "${event}" = "rc_exit" ]; then
+ args="$* ${RUNLEVEL}"
+ elif [ "${event}" = "svc_started" -o "${event}" = "svc_stopped" ]; then
+ if [ -z "$2" ]; then
+ # Backwards compatibility hack. Add a 0 to the arguments to simulate
+ # an error code.
+ args="$* 0"
+ else
+ args="$*"
+
+ # Backwards compatibility: translate an error condition (non-zero
+ # error code) into an appropriate event.
+ if [ "$2" != "0" ]; then
+ if [ "${event}" = "svc_started" ]; then
+ event="svc_start_failed"
+ else
+ event="svc_stop_failed"
+ fi
+ fi
+ fi
+ else
+ args="$*"
+ fi
+
+ splash_profile "pre ${event} ${args}"
+
+ # Handle -pre event hooks
+ if [ -x "/etc/splash/${SPLASH_THEME}/scripts/${event}-pre" ]; then
+ /etc/splash/"${SPLASH_THEME}"/scripts/${event}-pre ${args}
+ fi
+
+ case "$event" in
+ svc_start) splash_svc_start "$1";;
+ svc_stop) splash_svc_stop "$1";;
+ svc_started) splash_svc "$1" "start";;
+ svc_stopped) splash_svc "$1" "stop";;
+ svc_start_failed) splash_svc_fail "$1" "start";;
+ svc_stop_failed) splash_svc_fail "$1" "stop";;
+ svc_input_begin) splash_input_begin "$1";;
+ svc_input_end) splash_input_end "$1";;
+ rc_init) splash_init "$1" "${RUNLEVEL}";;
+ rc_exit) splash_exit "${RUNLEVEL}";;
+ critical) splash_verbose;;
+ esac
+
+ splash_profile "post ${event} ${args}"
+
+ # Handle -post event hooks
+ if [ -x "/etc/splash/${SPLASH_THEME}/scripts/${event}-post" ]; then
+ /etc/splash/"${SPLASH_THEME}"/scripts/${event}-post ${args}
+ fi
+
+ return 0
+}
+
+splash_setup() {
+ # If it's already set up, let's not waste time on parsing the config
+ # files again
+ if [ "${SPLASH_THEME}" != "" -a "${SPLASH_TTY}" != "" -a "$1" != "force" ]; then
+ return 0
+ fi
+
+ export SPLASH_EFFECTS=""
+ export SPLASH_SANITY=""
+ export SPLASH_TEXTBOX="no"
+ export SPLASH_MODE_REQ="off"
+ export SPLASH_PROFILE="off"
+ export SPLASH_THEME="default"
+ export SPLASH_TTY="16"
+ export SPLASH_KDMODE="TEXT"
+ export SPLASH_AUTOVERBOSE="0"
+ export SPLASH_BOOT_MESSAGE="Booting the system (\$progress%)... Press F2 for verbose mode."
+ export SPLASH_SHUTDOWN_MESSAGE="Shutting down the system (\$progress%)... Press F2 for verbose mode."
+ export SPLASH_REBOOT_MESSAGE="Rebooting the system (\$progress%)... Press F2 for verbose mode."
+ export SPLASH_XSERVICE="xdm"
+
+ [ -f /etc/splash/splash ] && . /etc/splash/splash
+ [ -f /etc/conf.d/splash ] && . /etc/conf.d/splash
+ [ -f /etc/conf.d/fbcondecor ] && . /etc/conf.d/fbcondecor
+
+ if [ -f /proc/cmdline ]; then
+ options=$(grep -o 'splash=[^ ]*' /proc/cmdline)
+
+ # Execute this loop over $options so that we can process multiple
+ # splash= arguments on the kernel command line. Useful for adjusting
+ # splash parameters from ISOLINUX.
+ for opt in ${options} ; do
+ options=${opt#*=}
+
+ for i in $(echo "${options}" | sed -e 's/,/ /g') ; do
+ case ${i%:*} in
+ theme) SPLASH_THEME=${i#*:} ;;
+ tty) SPLASH_TTY=${i#*:} ;;
+ verbose) SPLASH_MODE_REQ="verbose" ;;
+ silent) SPLASH_MODE_REQ="silent" ;;
+ kdgraphics) SPLASH_KDMODE="GRAPHICS" ;;
+ profile) SPLASH_PROFILE="on" ;;
+ insane) SPLASH_SANITY="insane" ;;
+ esac
+ done
+ done
+ fi
+}
+
+splash_get_boot_message() {
+ if [ "${RUNLEVEL}" = "6" ]; then
+ echo "${SPLASH_REBOOT_MESSAGE}"
+ elif [ "${RUNLEVEL}" = "0" ]; then
+ echo "${SPLASH_SHUTDOWN_MESSAGE}"
+ else
+ echo "${SPLASH_BOOT_MESSAGE}"
+ fi
+}
+
+splash_start() {
+ if [ "${SPLASH_MODE_REQ}" = "verbose" ]; then
+ ${spl_decor} -c on 2>/dev/null
+ return 0
+ elif [ "${SPLASH_MODE_REQ}" != "silent" ]; then
+ return 0
+ fi
+
+ # Display a warning if the system is not configured to display init messages
+ # on tty1. This can cause a lot of problems if it's not handled correctly, so
+ # we don't allow silent splash to run on incorrectly configured systems.
+ if [ "${SPLASH_MODE_REQ}" = "silent" -a "${SPLASH_SANITY}" != "insane" ]; then
+ if [ -z "$(grep -E '(^| )CONSOLE=/dev/tty1( |$)' /proc/cmdline)" -a \
+ -z "$(grep -E '(^| )console=tty1( |$)' /proc/cmdline)" ]; then
+ clear
+ splash_warn "You don't appear to have a correct console= setting on your kernel"
+ splash_warn "command line. Silent splash will not be enabled. Please add"
+ splash_warn "console=tty1 or CONSOLE=/dev/tty1 to your kernel command line"
+ splash_warn "to avoid this message."
+ if [ -n "$(grep 'CONSOLE=/dev/tty1' /proc/cmdline)" -o \
+ -n "$(grep 'console=tty1' /proc/cmdline)" ]; then
+ splash_warn "Note that CONSOLE=/dev/tty1 and console=tty1 are general parameters and"
+ splash_warn "not splash= settings."
+ fi
+ return 1
+ fi
+
+ if [ -n "$(grep -E '(^| )CONSOLE=/dev/tty1( |$)' /proc/cmdline)" ]; then
+ mount -n --bind / ${spl_tmpdir}
+ if [ ! -c "${spl_tmpdir}/dev/tty1" ]; then
+ umount -n ${spl_tmpdir}
+ splash_warn "The filesystem mounted on / doesn't contain the /dev/tty1 device"
+ splash_warn "which is required for the silent splash to function properly."
+ splash_warn "Silent splash will not be enabled. Please create the appropriate"
+ splash_warn "device node to avoid this message."
+ return 1
+ fi
+ umount -n ${spl_tmpdir}
+ fi
+ fi
+
+ rm -f "${spl_pidfile}"
+
+ # Prepare the communications FIFO
+ rm -f "${spl_fifo}" 2>/dev/null
+ mkfifo "${spl_fifo}"
+
+ local options=""
+ [ "${SPLASH_KDMODE}" = "GRAPHICS" ] && options="--kdgraphics"
+ [ -n "${SPLASH_EFFECTS}" ] && options="${options} --effects=${SPLASH_EFFECTS}"
+ [ "${SPLASH_TEXTBOX}" = "yes" ] && options="${options} --textbox"
+
+ local ttype="bootup"
+ if [ "${RUNLEVEL}" = "6" ]; then
+ ttype="reboot"
+ elif [ "${RUNLEVEL}" = "0" ]; then
+ ttype="shutdown"
+ fi
+
+ # Start the splash daemon
+ BOOT_MSG="$(splash_get_boot_message)" ${spl_daemon} --theme="${SPLASH_THEME}" --pidfile="${spl_pidfile}" --type=${ttype} ${options}
+
+ # Set the silent TTY and boot message
+ splash_comm_send "set tty silent ${SPLASH_TTY}"
+
+ if [ "${SPLASH_MODE_REQ}" = "silent" ]; then
+ splash_comm_send "set mode silent"
+ splash_comm_send "repaint"
+ ${spl_decor} -c on 2>/dev/null
+ fi
+
+ splash_comm_send "set autoverbose ${SPLASH_AUTOVERBOSE}"
+
+ splash_set_event_dev
+
+ return 0
+}
+
+###########################################################################
+# Cache-related functions
+###########################################################################
+
+splash_cache_prep() {
+ # Mount an in-RAM filesystem at spl_cachedir
+ mount -ns -t "${spl_cachetype}" cachedir "${spl_cachedir}" \
+ -o rw,mode=0644,size="${spl_cachesize}"k
+
+ retval="$?"
+
+ if [ ${retval} -ne 0 ]; then
+ splash_err "Unable to create splash cache - switching to verbose."
+ splash_verbose
+ return "${retval}"
+ fi
+}
+
+# args: list of files to save when the cache is umounted
+# Note that the 'profile' file is already handled and thus shouldn't
+# be included in the list.
+splash_cache_cleanup() {
+ # Don't try to clean anything up if the cachedir is not mounted.
+ [ -z "$(grep ${spl_cachedir} /proc/mounts)" ] && return;
+
+ # Create the temp dir if necessary.
+ if [ ! -d "${spl_tmpdir}" ]; then
+ mkdir -p "${spl_tmpdir}" 2>/dev/null
+ [ "$?" != "0" ] && return
+ fi
+
+ # Make sure the splash daemon is dead.
+ if [ -n "$(pgrep fbsplashd)" ]; then
+ sleep 1
+ killall -9 "${spl_daemon##*/}" 2>/dev/null
+ fi
+
+ # If /etc is not writable, don't update /etc/mtab. If it is
+ # writable, update it to avoid stale mtab entries (bug #121827).
+ local mntopt=""
+ [ -w /etc/mtab ] || mntopt="-n"
+ mount ${mntopt} --move "${spl_cachedir}" "${spl_tmpdir}" 2>/dev/null
+
+ # Don't try to copy anything if the cachedir is not writable.
+ [ -w "${spl_cachedir}" ] || return
+
+ if [ "${SPLASH_PROFILE}" != "off" ]; then
+ cp -a "${spl_tmpdir}/profile" "${spl_cachedir}" 2>/dev/null
+ fi
+
+ while [ -n "$1" ]; do
+ cp -a "${spl_tmpdir}/$1" "${spl_cachedir}" 2>/dev/null
+ shift
+ done
+
+ umount -l "${spl_tmpdir}" 2>/dev/null
+}
+
+###########################################################################
+# Common functions
+###########################################################################
+
+# Sends data to the splash FIFO after making sure there's someone
+# alive on the other end to receive it.
+splash_comm_send() {
+ if [ -z "`pidof $(basename ${spl_daemon})`" ]; then
+ return 1
+ else
+ splash_profile "comm $*"
+ echo "$*" > "${spl_fifo}" &
+ fi
+}
+
+# Returns the current splash mode.
+splash_get_mode() {
+ local ctty="${spl_bindir}/fgconsole"
+ local mode="$(${spl_util})"
+
+ if [ "${mode}" = "silent" ]; then
+ echo "silent"
+ else
+ if [ -z "$(${spl_decor} -c getstate --tty=${ctty} 2>/dev/null | grep off)" ]; then
+ echo "verbose"
+ else
+ echo "off"
+ fi
+ fi
+}
+
+# chvt <n>
+# --------
+# Switches to the n-th tty.
+chvt() {
+ local ntty=$1
+
+# if [ -x /usr/bin/chvt ] ; then
+# /usr/bin/chvt ${ntty}
+# else
+ printf "\e[12;${ntty}]"
+# fi
+}
+
+# Switches to verbose mode.
+splash_verbose() {
+# chvt 1
+/bin/true
+}
+
+# Switches to silent mode.
+splash_silent() {
+ splash_comm_send "set mode silent"
+}
+
+# Saves profiling information
+splash_profile() {
+ if [ "${SPLASH_PROFILE}" = "on" ]; then
+ echo "$(cat /proc/uptime | cut -f1 -d' '): $*" >> "${spl_cachedir}/profile"
+ fi
+}
+
+# Set the input device if it exists. This will make it possible to use F2 to
+# switch from verbose to silent.
+splash_set_event_dev() {
+ local t="$(grep -Hsi keyboard /sys/class/input/input*/name | sed -e 's#.*input\([0-9]*\)/name.*#event\1#')"
+ if [ -z "${t}" ]; then
+ t="$(grep -Hsi keyboard /sys/class/input/event*/device/driver/description | grep -o 'event[0-9]\+')"
+ if [ -z "${t}" ]; then
+ for i in /sys/class/input/input* ; do
+ if [ "$((0x$(cat $i/capabilities/ev) & 0x100002))" = "1048578" ]; then
+ t="$(echo $i | sed -e 's#.*input\([0-9]*\)#event\1#')"
+ fi
+ done
+
+ if [ -z "${t}" ]; then
+ # Try an alternative method of finding the event device. The idea comes
+ # from Bombadil <bombadil(at)h3c.de>. We're couting on the keyboard controller
+ # being the first device handled by kbd listed in input/devices.
+ t="$(/bin/grep -s -m 1 '^H: Handlers=kbd' /proc/bus/input/devices | grep -o 'event[0-9]*')"
+ fi
+ fi
+ fi
+ [ -n "${t}" ] && splash_comm_send "set event dev /dev/input/${t}"
+}
+
+###########################################################################
+# Service
+###########################################################################
+
+# args: <svc> <action>
+splash_svc() {
+ local srv="$1"
+ local act="$2"
+
+ if [ "${act}" = "start" ]; then
+ splash_svc_update "${srv}" "svc_started"
+ if [ "${srv}" = "gpm" ]; then
+ splash_comm_send "set gpm"
+ splash_comm_send "repaint"
+ fi
+ splash_comm_send "log Service '${srv}' started."
+ else
+ splash_svc_update "${srv}" "svc_stopped"
+ splash_comm_send "log Service '${srv}' stopped."
+ fi
+
+ splash_update_progress "${srv}"
+}
+
+# args: <svc> <action>
+splash_svc_fail() {
+ local srv="$1"
+ local act="$2"
+
+ if [ "${SPLASH_VERBOSE_ON_ERRORS}" = "yes" ]; then
+ splash_verbose
+ return 1
+ fi
+
+ if [ "${act}" = "start" ]; then
+ splash_svc_update "${srv}" "svc_start_failed"
+ splash_comm_send "log Service '${srv}' failed to start."
+ else
+ splash_svc_update "${srv}" "svc_stop_failed"
+ splash_comm_send "log Service '${srv}' failed to stop."
+ fi
+
+ splash_update_progress "${srv}"
+}
+
+# args: <svc> <state>
+#
+# Inform the splash daemon about service status changes.
+splash_svc_update() {
+ splash_comm_send "update_svc $1 $2"
+}
+
+# args: <svc>
+splash_svc_start() {
+ local svc="$1"
+
+ splash_svc_update "${svc}" "svc_start"
+ splash_comm_send "paint"
+}
+
+# args: <svc>
+splash_svc_stop() {
+ local svc="$1"
+
+ splash_svc_update "${svc}" "svc_stop"
+ splash_comm_send "paint"
+}
+
+# args: <svc>
+splash_input_begin() {
+ local svc="$1"
+
+ if [ "$(splash_get_mode)" = "silent" ]; then
+ splash_verbose
+ export SPL_SVC_INPUT_SILENT="${svc}"
+ fi
+}
+
+# args: <svc>
+splash_input_end() {
+ local svc="$1"
+
+ if [ "${SPL_SVC_INPUT_SILENT}" = "${svc}" ]; then
+ splash_silent
+ unset SPL_SVC_INPUT_SILENT
+ fi
+}
+
+###########################################################################
+# Framebuffer Console Decorations functions
+###########################################################################
+
+fbcondecor_supported()
+{
+ [ -e /dev/fbsplash -o -e /dev/fbcondecor ]
+}
+
+# args: <theme> <tty>
+fbcondecor_set_theme()
+{
+ local theme=$1
+ local tty=$2
+
+ [ -x ${spl_decor} ] || return 1
+
+ ${spl_decor} --tty="${tty}" -t "${theme}" -c setcfg || return 1
+ ${spl_decor} --tty="${tty}" -t "${theme}" -c setpic -q
+ ${spl_decor} --tty="${tty}" -c on
+}
+
+###########################################################################
+# Service list
+###########################################################################
+
+# splash_svclist_get <type>
+# -------------------------
+# type:
+# - start - to get a list of services to be started during bootup
+# - stop - to get a list of services to be stopped during shutdown/reboot
+splash_svclist_get() {
+ if [ "$1" = "start" -a -r "${spl_cachedir}/svcs_start" ]; then
+ cat "${spl_cachedir}/svcs_start"
+ elif [ "$1" = "stop" -a -r "${spl_cachedir}/svcs_stop" ]; then
+ cat "${spl_cachedir}/svcs_stop"
+ fi
+}
+
+splash_warn() {
+ echo "$*"
+}
+
+splash_err() {
+ echo "$*"
+}
+
+############################################################################
+# Functions to be overridden by distro-specific code
+###########################################################################
+
+# args: <internal_runlevel> <runlevel>
+#
+# This function is called when an 'rc_init' event takes place,
+# i.e. when the runlevel is changed.
+
+# It is normally used to initialize any internal splash-related
+# variables (e.g. ones used to track the boot progress), calculate
+# and save the service list and call `splash_start` in appropriate
+# runlevels.
+#
+# Note that the splash cache is already intialized when this
+# function is called.
+splash_init() {
+ if [ "$2" = "6" -o "$2" = "0" -o "$2" = "S" -a "$1" = "sysinit" ]; then
+ splash_start
+ fi
+}
+
+# args: <runlevel>
+#
+# This function is called when an 'rc_exit' event takes place,
+# i.e. at the end of processes all initscript from a runlevel.
+splash_exit() {
+ # If we're in sysinit or rebooting, do nothing.
+ [ "$1" = "S" -o "$1" = "6" -o "$1" = "0" ] && return 0
+
+ splash_comm_send "exit"
+ splash_cache_cleanup
+}
+
+# args: <svc>
+#
+# This function is called whenever the progress variable should be
+# updated. It should recalculate the progress and send it to the
+# splash daemon.
+splash_update_progress() {
+ # splash_comm_send "progress ${progress}"
+ # splash_comm_send "paint"
+ return
+}
+
+# Export functions if we're running bash.
+if [ -n "${BASH}" ]; then
+ export -f splash
+ export -f splash_setup
+ export -f splash_get_boot_message
+ export -f splash_start
+ export -f splash_cache_prep
+ export -f splash_cache_cleanup
+ export -f splash_comm_send
+ export -f splash_get_mode
+ export -f chvt
+ export -f splash_verbose
+ export -f splash_silent
+ export -f splash_profile
+ export -f splash_set_event_dev
+ export -f splash_svclist_get
+fi
+
+# Load any supplementary splash functions.
+for i in /sbin/splash-functions-*.sh ; do
+ [ -r "${i}" ] && . "${i}"
+done
+
+splash_setup
+
+# vim:ts=4