If you followed all the instructions correctly, you now can restart and enjoy your new and fresh boot splash. But, what wrong?, there wasn't any progress bar! Documents found in Internet explain how to do it in SuSE, Mandrake, Gentoo and LFS, but not in Debian. I tried it with many examples and animations with mng, but none of them works. Eventually, I got to do it, but this method was not tested intensely as I have only tried it in my Debian/Sarge. It should work fine in Woody as well, but do it at your own risk.
First we need to know how to use the progress utility (remember it was compiled and copied together with splash). Progress just draws a quadrilateral in any framebuffer device (/dev/fb0 by default). If you run it without any argument you will get a list with all the available options. The only parameters we are interested in are:
- x: The quadrilateral origin for the x coordenate
- y: The quadrilateral origin for the y coordenate
- dx: Quadrilateral width
- dy: Quadrilateral height
- color: Quadrilateral color. This is a hexadecimal number. This colors work the same as for web pages, in case you are familiar with them.
For example:
progress 0 0 512 384 FFFFFF
will draw a white quadrilateral with the origin on the superior left corner of the screen, and it will cover a fourth of it.
progress 256 192 521 384 FCD192
will draw a yellow quadrilateral right in the middle of the screen.
This examples must be tried in a tty (preferely in tty1) and not in a Konsole or xterm window.
Ok, now we need to put the drawing program and the boot together. I studied Mandrake's boot and realized that its boot scripts use this program to draw a quadrilateral in a given position and with a given size every time a new service is started (xfs, cron, samba or any other it has installed). In Mandrake, this is achieved through the /etc/rc.d/rc script, but in Debian there's two: /etc/init.d/rcS is executed in first place and then /etc/init.d/rc (I won't explain how it works for every other distro as it's not the goal of this article).
Now it's time to take a look at the /etc/init.d/rcS code. Note that this script calls all the scripts on every runlevel in order, we insert our code
marked as bold for drawing our progress bar. It should look like this:
# Initialize j variable
# j is the progress bar width
j=20
for i in /etc/rcS.d/S??*
do
# Ignore dangling symlinks for now.
[ ! -f "$i" ] && continue
# Start progress bar
#
# This is for not escape from established bar progress width
if ((j < 616))
then
# With this, we call progress to draw a bar wider than
# the previous one, exactly 15 pixels wider (j=dx)
# x y dx dy color
/usr/local/bin/progress 204 667 $j 21 FCD123
let j=j+15
fi
# End progress bar
case "$i" in
*.sh)
# Source shell script for speed.
(
trap - INT QUIT TSTP
set start
. $i
)
;;
*)
# No sh extension, so fork subprocess.
$i start
;;
esac
done
This code will draw the first part of the bar, but now we have to draw the second part with /etc/init.d/rc. In order to do this, we need to know exactly in what position did the drawing process stop so we can go on with the second smoothing.
# Explained below
danger_var=395
j=danger_var
for i in /etc/rc$runlevel.d/S*
do
[ ! -f $i ] && continue
if [ $previous != N ] && [ $previous != S ]
then
#
# Find start script in previous runlevel and
# stop script in this runlevel.
#
suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9]}
stop=/etc/rc$runlevel.d/K[0-9][0-9]$suffix
previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix
#
# If there is a start script in the previous level
# and _no_ stop script in this level, we don't
# have to re-start the service.
#
[ -f $previous_start ] && [ ! -f $stop ] && continue
fi
#This is to not escape from established bar progress width
if ((j < 616))
then
/usr/local/bin/progress 204 666 $j 21 FCD123
let j=j+15
fi
#End progress bar
case "$runlevel" in
0|6)
startup $i stop
;;
*)
startup $i start
;;
esac
done
The code is clear. Proceeding the same way, it draws the progress bar. But what is danger_var?. We'll go little by little. I said before that we need to know in what posicion did the first part of the bar drawing process stop so it could continue with the second smoothing. This posicion is signaled by danger_var. As I can't pass it like a local variable with export or environment variable, I had to get creative to do it. It's coarse and even dangerous if it isn't done right. The following code must be inserted at the end of /etc/init.d/rcS :
sed 's/danger_var=[0-9]*/danger_var='$j'/g' /etc/init.d/rc > /tmp/boots
mv /tmp/boots /etc/init.d/rc
chmod 755 /etc/init.d/rc
It couldn't be any easier: get j value, search the string
danger_var=any_number in rc file and modify like this:
danger_var=last_value_of_j. Save as /tmp/boots, rename then in /etc/init.d/rc and change its permissions. If you choose the name danger_var, you're not very likely to have name coincidence problems with any of the other boot scripts..
If you restart the computer now, you will be able to enjoy a beautiful progress bar, but you'll realize that when you halt or reboot the computer, the splash screen won't have a progress bar like it did before. This is solved with the following code (in bold), which must be added in /etc/init.d/rc
# First, run the KILL scripts.
if [ $previous != N ]
then
k=20
for i in /etc/rc$runlevel.d/K[0-9][0-9]*
do
# Check if the script is there.
[ ! -f $i ] && continue
# Stop the service.
#This is to not escape from established bar progress width
if ((k < 616))
then
/usr/local/bin/progress 204 666 $k 21 FCD123
let k=k+25
fi
# Fin barra proceso
startup $i stop
done
fi
I don't need to explain what does the k variable do and why is it there, do I? ;-)
Now we can enjoy our graphical boot with progress bar and graphical halt.