3 # splash_manager -- a convenience utility to perform various splash-related
4 # tasks in an easy and user-friendly way
6 # Copyright (C) 2005-2007, Michal Januszewski <spock@gentoo.org>
8 # This file is a part of the splashutils package.
10 # This file is subject to the terms and conditions of the GNU General Public
11 # License v2. See the file COPYING in the main directory of this archive for
16 # - support for icons and scripts in themes
18 # - support for 8bpp modes
21 # - replay won't work correctly when started from a tty with a video mode
22 # different from the one used for the silent tty
24 # System configuration variables
25 spl_util
=splash_util.static
26 spl_daemon
=fbsplashd.static
27 spl_decor
=fbcondecor_ctl
28 spl_dir
="@libdir@/splash"
29 spl_fifo
=${spl_dir}/cache
/.splash
30 spl_pidfile
=${spl_dir}/cache
/daemon.pid
33 spl_daemon_exename
="$(basename ${spl_daemon})"
34 spl_daemon_short
="${spl_daemon:0:9}"
37 killall
${spl_daemon_exename} 2>/dev
/null
43 splash_geninitramfs/splashutils-@PACKAGE_VERSION@
44 Usage: splash_manager [options] -c <command>
48 demo test a splash theme
49 list list available splash themes
50 set set a splash theme on a specific tty
51 shot take a screenshot of a selected splash theme
52 switch switch a splash theme by changing GRUB/LILO config files
53 replay replay a complete boot sequence using splash profile data
56 -c, --cmd=CMD execute CMD
57 -h, --help display this message
58 -t, --theme=THEME [bdehsr] theme name
59 --steps=N [ d ] use N steps when testing the silent splash
60 --delay=N [ d ] delay each step by N seconds
61 -m, --mode=(v|s) [ d h ] specify which mode to use (verbose/silent)
62 --tty=N [bdeh ] set the theme on the Nth tty
63 -e, --exec=CMD [ h ] run CMD on the tty where splash is being tested
64 --progress=N [ h ] set progress to N (0-65535)
65 --msg=MSG [bd h ] set the main system message to MSG
66 --profile=FILE [ r] read splash profile data from FILE
68 The letters in the square brackets indicate the commands with which
69 specific options can be used: b (bechmark) d (demo), e (set), h (shot),
70 s (switch), r (replay).
73 splash_manager -c switch -t livecd-2005.0
74 (switch to the 'livecd-2005.0' theme; the new theme will be used
77 splash_manager -c set -t linux --tty=8
78 (set the 'linux' theme on the 8th tty)
80 splash_manager -c demo -t livecd-2005.0 -m s --steps=100
81 (run a demonstration of the 'livecd-2005.0' theme, silent mode;
82 use 100 steps for the progress bar)
84 splash_manager -c shot -t foobar -m s --progress=32767 --msg='Smile!'
85 (take a screenshot of the 'foobar' theme, silent mode; set progress
86 to 50% and use 'Smile!' as the main system message)
98 # Displays an error message.
100 echo -e "${CBAD}Error:${CNORM} $*" >&2
103 # void einfo(char *msg)
104 # Displays an informational message.
106 echo -e "${CGOOD}*${CNORM} $*"
109 # void ewarn(char *msg0
110 # Display a warning message.
112 echo -e "${CWARN}*${CNORM} $*"
115 # void spl_comm(char *msg)
116 # Sends 'msg' to the splash fifo.
118 if [ ! -e ${spl_pidfile} ]; then
122 if [ "$(pgrep ${spl_daemon_short})" == "$(<${spl_pidfile})" ]; then
123 echo "$*" > ${spl_fifo} &
125 err
"Splash daemon not running!"
126 rm -f "${spl_pidfile}"
131 # Switches to the n-th tty.
135 if [ -x /usr
/bin
/chvt
] ; then
136 /usr
/bin
/chvt
${ntty}
138 echo -en "\e[12;${ntty}]"
143 # void theme_sanity_check(char *theme)
144 # Performs a theme sanity check -- checks whether a theme exists.
145 theme_sanity_check
() {
149 # For verbose mode, we care about the real resolution, not the one
150 # fbsplash would be using for the silent mode.
151 if [ "${mode}" == "v" ]; then
155 if [ -z "${theme}" ]; then
156 err
"You have to specify a theme name."
160 if [ ! -e "${themedir}/${theme}/${t}.cfg" ]; then
161 err
"Theme '${theme}' doesn't seem to provide a config file for the current resolution (${t})."
166 # void set_theme(char *theme, int tty)
167 # Sets a theme on a specific tty.
172 theme_sanity_check
"${theme}"
173 [ -z "${tty}" ] && tty
="${ctty}"
174 ${spl_decor} -c setcfg -t "${theme}" --tty="${tty}"
175 [ "${tty}" == "${ctty}" ] && ${spl_decor} -c setpic -t "${theme}" --tty="${tty}"
176 ${spl_decor} -c on --tty=${tty}
179 # void get_theme(int tty)
180 # Prints the name of the theme that is used on a tty.
183 echo $(${spl_decor} --tty=${ctty} -c getcfg | grep theme | awk '{ print $2 }')
186 # void get_state(int tty)
187 # Prints 'on' or 'off', indicating fbsplash state on a tty.
190 echo $(${spl_decor} --tty=${ctty} -c getstate | cut -f2 -d: | tr -d ' ')
193 # void check_silent(char *theme, char *res, char *action)
194 # Checks whether a theme supports the silent splash mode.
200 if [ -z $(cat "${themedir}/${ctheme}/${cres}.cfg
" 2>/dev/null | egrep "^silent
(pic|jpeg
)=") ]; then
201 [ "${action}" == "test" ] && return 1
202 err "Theme
'${ctheme}' doesn
't support the silent splash mode."
207 # void check_verbose(char *theme, char *res, char *action)
208 # Checks whether a theme supports the verbose splash mode.
214 if [ -z $(cat "${themedir}/${ctheme}/${cres}.cfg" 2>/dev/null | egrep "^(pic|jpeg)=") ]; then
215 [ "${action}" == "test" ] && return 1
216 err "Theme '${ctheme}' doesn't support the silent splash mode.
"
226 # Make sure the splash daemon is not running
227 killall -9 ${spl_daemon_exename} 2>/dev/null
228 ${spl_daemon} -t "${theme}" --pidfile ${spl_pidfile} ${util_params}
229 pid=$(cat ${spl_pidfile})
231 [ -z "${msg}" ] && msg="Testing the
'${theme}' theme
(\
$progress%)...
"
232 spl_comm "set message
${msg}"
233 [ -n "${tty}" ] && spl_comm "set tty silent
${tty}"
234 spl_comm "set mode silent
"
241 while [[ "$
(head -n 1 /proc
/${pid}/status
2>/dev
/null | cut
-f2)" == "${spl_daemon_short}" ]]; do
245 while [ "`fgconsole`" != ${ctty} ] ; do
251 check_silent "${theme}" "${res}"
255 timestart=$(date +"%s.
%N
")
256 for ((i=0;i<65536;i=$i+$step)) ; do
257 echo "progress
$i" > ${spl_fifo}
258 echo "paint
" > ${spl_fifo}
260 timeend=$(date +"%s.
%N
")
263 echo "Test took $
(echo "$timeend - $timestart" |
bc) seconds.
"
266 demo_theme_silent() {
267 check_silent "${theme}" "${res}"
268 if [ -z "$
(echo ${util_params} |
grep -- '--type=')" ]; then
269 export util_params="${util_params} --type=bootup
"
273 # Set the input device if it exists. This will make it possible to use F2 to
274 # switch from verbose to silent.
275 local t=$(grep -Hsi keyboard /sys/class/input/input*/name | sed -e 's#.*input\([0-9]*\)/name.*#event\1#')
276 if [[ -z "${t}" ]]; then
277 t=$(grep -Hsi keyboard /sys/class/input/event*/device/driver/description | grep -o 'event[0-9]\+')
278 if [[ -z "${t}" ]]; then
279 # Try an alternative method of finding the event device. The idea comes
280 # from Bombadil <bombadil(at)h3c.de>. We're couting on the keyboard controller
281 # being the first device handled by kbd listed in input/devices.
282 t=$(/bin/grep -s -m 1 '^H: Handlers=kbd' /proc/bus/input/devices | grep -o 'event[0-9]*')
286 if [[ -n "${t}" ]]; then
287 spl_comm "set event dev
/dev
/input
/${t}"
290 if [[ -n "$
(pgrep gpm
)" ]]; then
294 [ -z "${delay}" ] && delay=0.05
295 step=$((65535/$steps))
297 for ((i=0;i<65536;i=$i+$step)) ; do
298 spl_comm "progress
$i"
302 spl_comm "progress
65535"
308 check_silent "${theme}" "${res}"
310 if [[ -z "${profile}" ]]; then
311 err "You have to specify a splash profile
file.
"
315 if [[ ! -r "${profile}" ]]; then
316 err "Profile
file '${profile}' not found.
"
324 if [[ -e /etc/gentoo-release ]]; then
329 source @sbindir@/splash-functions.sh
332 export SPLASH_XRES="$xres"
333 export SPLASH_YRES="$yres"
334 export SPLASH_THEME=${theme}
338 t=${arr[0]:0:$((${#arr[0]}-1))}
340 utime=$((${t%.*}*1000 + ${tdec#0*}*10))
342 [[ "$ctime" == "0" ]] && ctime=${utime}
344 delay=$((${utime} - ${ctime}))
345 sleep "$
(($delay/1000)).$
(printf '%03d' $
(($delay%1000)))"
348 # Start the splash daemon after rc_init/pre.
349 if [[ -z "${pid}" ]]; then
350 if [[ "${arr[1]}" != "pre
" || "${arr[2]}" != "rc_init
" ]]; then
351 BOOT_MSG="$
(splash_get_boot_message
)" ${spl_daemon} -t ${theme} --pidfile ${spl_pidfile} --type=bootup
352 pid=$(cat ${spl_pidfile})
358 if [[ -x ${themedir}/${theme}/scripts/${arr[2]}-pre ]]; then
359 ${themedir}/${theme}/scripts/${arr[2]}-pre ${arr[*]:3}
364 if [[ -x ${themedir}/${theme}/scripts/${arr[2]}-post ]]; then
365 ${themedir}/${theme}/scripts/${arr[2]}-post ${arr[*]:3}
368 if [[ -e /etc/gentoo-release && ${arr[3]} == 'boot' ]]; then
374 spl_comm "${arr[*]:2}"
381 [ -z "${tty}" ] && tty=${ctty}
383 export cstate=$(get_state ${tty})
384 [ "${cstate}" == "on
" ] && export ctheme=$(get_theme ${tty})
386 set_theme "${theme}" "${tty}"
392 if [ "${cstate}" == "on
" ]; then
393 set_theme "${ctheme}" "${tty}"
395 ${spl_decor} --tty=${tty} -c off
399 demo_theme_verbose() {
400 [ -z "${delay}" ] && delay=5
402 check_verbose "${theme}" "${res}"
405 einfo "Testing the
'${theme}' theme...
" >/dev/tty${tty}
406 for (( i = 0 ; i < ${delay} ; i = i+1 )) ; do
407 echo -n "$i " >/dev/tty${tty}
416 check_silent "${theme}" "${res}"
419 [ -z "${progress}" ] && progress=16384
420 spl_comm "progress
${progress}"
424 fbgrab ${theme}-${res}-silent.png
429 take_shot_verbose() {
430 check_verbose "${theme}" "${res}"
433 if [ -n "${cexec}" ]; then
434 ps -A -o pid,comm,tty > /tmp/spl-shot-$$.pre
435 openvt -f -c ${tty} -- ${cexec}
437 ps -A -o pid,comm,tty > /tmp/spl-shot-$$.post
438 local ce=$(basename "${cexec}")
439 pid=$(diff /tmp/spl-shot-$$.pre /tmp/spl-shot-$$.post | grep "${ce:0:15}" | grep "tty${tty}" | grep '^>' | awk '{ print $2 }')
440 rm -f /tmp/spl-shot-$$.pre /tmp/spl-shot-$$.post
443 fbgrab ${theme}-${res}-verbose.png
445 if [[ -n "${ce}" && -n "${pid}" &&
446 "$(cat /proc/${pid}/status 2>/dev/null | grep 'Name
:' | cut -f2)" == "${ce:0:15}" ]]; then
453 for i in "${themedir}"/* ; do
454 [ ! -d "${i}" ] && continue
455 [ -z "$(ls "${i}"/*.cfg 2>/dev/null)" ] && continue
463 for res in "${i}"/*.cfg ; do
467 [ "$first" != "true" ] && echo -n ","
473 if check_silent "$tn" "$res" "test"; then
479 if check_verbose "$tn" "$res" "test"; then
485 if [[ "$ver" == "true" && "$sil" == "true" ]]; then
487 elif [[ "$sil" == "true" ]]; then
499 detect_bootloader() {
500 if [[ -e /boot/grub/grub.conf && -e /etc/lilo.conf ]]; then
501 ewarn "Both GRUB and LILO seem to be installed and configured. Please"
502 ewarn "select which one should be configured by this script:"
506 echo -n "Your choice [1]: "
508 if [ -z "${choice}" ]; then
511 elif [ "${choice}" == 1 ]; then
514 elif [ "${choice}" == 2 ]; then
518 err "You have chosen an invalid number."
521 elif [[ -e /boot/grub/grub.conf ]]; then
523 elif [[ -e /etc/lilo.conf ]]; then
526 err "It appears that none of the supported bootloaders (GRUB, LILO) is installed"
527 err "on your system. Please install one of these or configure fbsplash/splashutils"
533 # The code of mount_boot_partition() is stolen from Gentoo's mount-boot.eclass.
534 mount_boot_partition
() {
535 # note that /dev/BOOT is in the Gentoo default /etc/fstab file
536 local fstabstate
="$(cat /etc/fstab | awk '!/^#|^[[:blank:]]+#|^\/dev\/BOOT/ {print $2}' | egrep "^
/boot$
" )"
537 local procstate
="$(cat /proc/mounts | awk '{print $2}' | egrep "^
/boot$
" )"
538 local proc_ro
="$(cat /proc/mounts | awk '{ print $2, $4 }' | sed -n '/\/boot/{ /[ ,]\?ro[ ,]\?/p }' )"
540 if [ -n "${fstabstate}" ] && [ -n "${procstate}" ]; then
541 if [ -n "${proc_ro}" ]; then
542 einfo
"Your boot partition, detected as being mounted as /boot, is read-only."
543 einfo
"Remounting it in read-write mode ..."
544 mount
-o remount
,rw
/boot
&>/dev
/null
545 if [ "$?" -ne 0 ]; then
546 err
"Unable to remount in rw mode. Please do it manually!"
550 einfo
"Your boot partition was detected as being mounted as /boot."
552 elif [ -n "${fstabstate}" ] && [ -z "${procstate}" ]; then
553 mount
/boot
-o rw
&>/dev
/null
554 if [ "$?" -eq 0 ]; then
555 einfo
"Your boot partition was not mounted as /boot, but this"
556 einfo
"script was able to mount it without additional intervention."
558 err
"Cannot automatically mount your /boot partition."
559 err
"Your boot partition has to be mounted rw before the splash configuration"
560 err
"can be continued."
564 einfo
"Assuming you do not have a separate /boot partition."
568 # int input_number(int min, int max, int default)
569 # Asks the user to enter a number in the range [min;max].
576 echo -n "Your choice: "
578 while [[ ${done} != "true" ]]; do
582 if [[ -z "${n}" || "${n}" -lt ${min} || "${n}" -gt ${max} ]]; then
583 err "Invalid number. Try again. Enter a number
in the range
: ${min}-${max}}.
"
584 echo -n "Your choice
: "
593 # bool input_bool(bool default)
594 # Asks the user to enter 'y' or 'n'.
599 echo -n "Your choice
"
601 if [[ "${default}" == "y
" ]]; then
609 if [[ "${default}" == "y
" ]]; then
610 if [[ "${choice}" != "n
" && "${choice}" != "N
" ]]; then
616 if [[ "${choice}" != "y
" && "${choice}" != "Y
" ]]; then
624 # void theme_switch_initrd(char *initrd)
625 # Asks the user whether (s)he wants to generate and use a new initrd.
626 theme_switch_initrd() {
631 if [ -z "${initrd}" ]; then
632 einfo "It appears that you are not using an initrd. Do you want this
script"
633 einfo "to automatically generate one
for use with the
'${theme}' theme?
"
634 if input_bool 'y'; then
637 elif [ "${initrd:0:13}" == "/boot
/splash
/" ]; then
641 einfo "It appears that you are already using an initrd
:"
643 einfo "Do you want this
script to automatically generate another initrd
for"
644 einfo "use with the
'${theme}' theme?
"
645 einfo "The new initrd will be used instead of the current one.
"
646 if input_bool 'n'; then
651 if [ ${want_initrd} == "true
" ]; then
652 [ ! -d /boot/splash ] && mkdir /boot/splash
653 newinitrd="/boot
/splash
/initrd-spl-
${theme}-all"
654 splash_geninitramfs -g "${newinitrd}" -v "${theme}"
658 theme_switch_lilo() {
662 local want_name=false
665 # Display a list of entries from lilo.conf and ask the user to select one of them.
666 einfo "Please
select which kernel should be configured
for use with splashutils
:"
669 if [[ ${i:0:5} == "image
" ]]; then
671 lines[$cnt]="$linecnt"
674 if [[ ${want_name} == "true
" && ${i:0:5} == "label
" ]]; then
675 i=$(echo ${i} | cut -d= -f2)
679 printf "%3d
) %s
\n" "$cnt" "$i"
682 linecnt=$(($linecnt+1))
683 done < /etc/lilo.conf
685 input_number 1 ${cnt} 1
687 einfo "Configuring
'${entries[$n]}'..
"
690 cp /etc/lilo.conf /etc/lilo.conf.work.$$
692 initrd="$
(awk "FNR == $line {
694 while(getline > 0 && \$1 != \"image\") {
697 }" /etc
/lilo.conf.work.$$ |
grep "^[[:space:]]*initrd")"
698 initrd=$(echo "$initrd" | cut -f2 -d'=')
700 theme_switch_initrd "${initrd}"
701 cp /etc/lilo.conf /etc/lilo.conf.backup
703 awk "FNR
== $
(($line+1)) {
705 if (\"${newinitrd}\" != \"\") {
710 if (\
$1 ~
/^append
/) {
712 } else if (\
$1 ~
/^image
/ || \
$1 ~
/^other
/) {
713 print
\"\\tappend
= \\\"splash
=silent
,fadein
,theme
:${theme} console
=tty1
\\\"\"
715 print
\"\\\tinitrd
= ${newinitrd}\"
720 if (initrd
== 1 && \
$1 ~
/^initrd
/) {
721 sub
(/initrd.
*/, \"initrd
= ${newinitrd}\", \
$0)
726 } while (getline
> 0)
732 \
$0=gensub
(/.
*\"([^
\"]+)\"/,\"\\\\1\",\"g
\",\
$0)
734 for(i
=1; i
<=NF
+1; i
++) {
735 if (substr
(\
$i,0,6) == \"splash
\") {
737 } else if (\
$i == \"console
=tty1
\") {
742 sub
(/splash
=[^
]+/, \"splash
=silent
,fadein
,theme
:${theme}\", \
$0)
744 \
$0=\
$0 \" splash
=silent
,fadein
,theme
:${theme}\"
746 if (cons
== 0) { \
$0 = \
$0 \" console
=tty1
\" }
748 sub
(/\".
*\"/, \"\\\"\" \
$0 \"\\\"\", full
)
753 while (!(\
$1 ~
/^image
/) && !(\
$1 ~
/^other
/)) {
754 if (\
$1 ~
/^initrd
/) {
755 sub
(/initrd.
*/, \"initrd
= ${newinitrd}\", \
$0)
762 print
\"\\tinitrd
= ${newinitrd}\"
769 FNR
!= $
(($line+1)) { print \
$0 }" /etc/lilo.conf.work.$$ > /etc/lilo.conf.tmp.$$
771 rm /etc/lilo.conf.work.$$
772 mv /etc/lilo.conf.tmp.$$ /etc/lilo.conf
774 einfo "LILO config
file has been updated.
"
777 theme_switch_grub() {
783 # Display a list of entries from grub.conf and ask the user to select one of them.
784 einfo "Please
select which kernel should be configured
for use with splashutils
:"
785 grep -n '^[[:space:]]*title' /boot/grub/grub.conf > /tmp/splash_mngr.$$
787 line=$(echo "${i}" | cut -d: -f1)
788 i=$(echo "${i}" | cut -d: -f2)
793 printf "%3d
) %s
\n" "$cnt" "$i"
794 done < /tmp/splash_mngr.$$
795 rm /tmp/splash_mngr.$$
797 input_number 1 ${cnt} 1
799 einfo "Configuring
'${entries[$n]}'..
"
802 t="$
(sed -e "${line}p" -e 'd' /boot
/grub
/grub.conf
)"
804 if [[ "$
(echo ${t})" != "title
${entries[$n]}" ]]; then
805 err "The GRUB config
file appears to have been modified
while this
script was
"
806 err "working. Please run it again after making sure no one is modifying
"
807 err "/boot
/grub
/grub.conf.
"
811 cp /boot/grub/grub.conf /boot/grub/grub.conf.work.$$
813 initrd="$
(awk "FNR == $line {
815 while(getline > 0 && \$1 != \"title\") {
818 }" /boot
/grub
/grub.conf.work.$$ |
grep "^[[:space:]]*initrd")"
819 initrd=$(echo "$initrd" | cut -f2 -d' ')
821 theme_switch_initrd "${initrd}"
822 cp /boot/grub/grub.conf /boot/grub/grub.conf.backup
826 if (\"${newinitrd}\" != \"\") {
830 while(\
$1 != \"kernel
\") {
831 if (initrd
== 1 && \
$1 == \"initrd
\") {
832 sub
(/initrd .
*/, \"initrd
${newinitrd}\", \
$0)
843 for(i
=1; i
<=NF
+1; i
++) {
844 if (substr
(\
$i,0,6) == \"splash
\") {
846 } else if (\
$i == \"console
=tty1
\") {
851 sub
(/splash
=[^
]+/, \"splash
=silent
,fadein
,theme
:${theme}\", \
$0)
854 printf \"%s splash
=silent
,fadein
,theme
:${theme}\", \
$0
856 if (cons
== 0) { printf \" %s
\", \"console
=tty1
\" }
861 while (\
$1 != \"title
\") {
862 if (\
$1 == \"initrd
\") {
863 sub
(/initrd .
*/, \"initrd
${newinitrd}\", \
$0)
872 print
\"\\tinitrd
${newinitrd}\"
879 FNR
!= $line { print \
$0 }" /boot/grub/grub.conf.work.$$
880 #> /boot/grub/grub.conf.tmp.$$
882 rm /boot/grub/grub.conf.work.$$
883 # mv /boot/grub/grub.conf.tmp.$$ /boot/grub/grub.conf
885 einfo "GRUB config
file has been updated.
"
892 if [[ ${bootloader} == "grub
" ]]; then
899 # Set some useful variables that we'll be using in various places
900 ctty=$(${spl_dir}/bin/fgconsole)
909 profile="${spl_dir}/cache
/profile
"
912 temp=`getopt -l help,cmd:,theme:,steps:,delay:,mode:,msg:,tty:,exec:,progress:,profile: c:m:t:he: "$@
"`
922 -c|--cmd) op="$2"; shift; shift;;
923 -h|--help) usage; exit 0;;
924 -m|--mode) mode="$2"; shift; shift;;
925 -t|--theme) theme="$2"; shift; shift;;
926 -e|--exec) cexec="$2"; shift; shift;;
927 --progress) progress="$2"; shift; shift;;
928 --profile) profile="$2"; shift; shift;;
929 --steps) steps="$2"; shift; shift;;
930 --delay) delay="$2"; shift; shift;;
931 --tty) tty="$2"; shift; shift;;
932 --msg) msg="$2"; shift; shift;;
939 if [ -z "${op}" ]; then
944 rres=$(${spl_dir}/bin/fbres)
945 res=$(${spl_util} -c getres -t ${theme})
952 set_theme "${theme}" "${tty}" ;;
954 theme_sanity_check "${theme}"
955 if [ ${mode} == 's' ]; then
964 if [ -z "$
(which bc)" ]; then
965 err "Benchmarking requires the
'bc' command-line calculator.
"
968 theme_sanity_check "${theme}"
973 theme_sanity_check "${theme}"
974 if [ ! -x /usr/bin/fbgrab ]; then
975 err "Cannot
find /usr
/bin
/fbgrab
"
979 if [ ${mode} == 's' ]; then
987 theme_sanity_check "${theme}"
996 theme_sanity_check "${theme}"
1000 *) err "Unrecognized
command"
1007 # vim: set ts=4 sts=4: