updated on Wed Jan 25 20:08:56 UTC 2012
[aur-mirror.git] / fbsplash-extras / fbsplash-controld
blob1627ad1349640a1e62ec5cf4de9953dbdf03a264
1 #!/bin/bash
3 # fbsplash-controld #
5 # Daemon for controlling the Fbsplash daemon #
6 # #
7 # Author: Kurt J. Bosch <kjb-temp-2009 at alpenjodel.de> #
8 # Based on the work of: Michal Januszewski <spock at gentoo.org> #
9 # and others #
10 # #
11 # Distributed under the terms of the GNU General Public License (GPL) #
13 # Features and Tweaks
15 # * Replace splash main event shell-function by a process maintaining state
16 # * Provide smooth animation like progress (self learning, time based)
17 # * Support filesystem check progress (via status message text)
18 # * Provide a general failure status (dummy service event)
19 # * Support splash daemon started in initcpio
20 # * Wait until fbcondecor_helper fadein done before starting the daemon
21 # * Prevent auto-verbose timeout as long as message is updated
22 # * Support random splash log messages instead of writing ugly generic ones
23 # * Update splash even on 'verbose error'
24 # * On gpm start, wait until socket ready before using
25 # * Reserve some progress for late stuff to avoid looking freezed
26 # * Avoid adding to profile (splash_manager replay log) after splash exit
27 # * If in configuration, make the splash daemon fade in even on shutdown
28 # * If not available, provide a fake SysV-Init environment for theme hooks
30 # Usage
32 # 'start' 'early' [<mountpoint> [svcs-fg-file]] Start control daemon for a bootup splash daemon started in initrd
33 # 'start' 'bootup'|'shutdown'|'reboot' [svcs-fg-file [svcs-start-file [svcs-stop-file]]]
34 # Start control daemon and splash daemon
35 # mountpoint is the directory where the splash cache tmpfs was mounted by the initrd.
36 # svcs-fg-file services started (stopped if reboot/shutdown) in foreground (those relevant for progress) - one per line.
37 # (Current working directory when reading is the splash cache tmpfs root.)
38 # svcs-start-file and svcs-stop-file
39 # are copied to svcs_start and svcs_stop in the splash cache tmpfs for theme hooks using splash_svclist_get().
40 # 'stop' ['force'] Stop (or abort) splash and control daemons (if running) and wait until gone
41 # 'comms' <splash-daemon-command>... Send one or more commands to the splash daemon (if running)
42 # 'ping' Returns a zero exit-code if control daemon is running
43 # 'fsckd' 'start'|'stop' Start/stop a daemon for pushing filesystem check progress info to the splash
44 # status message line ( {FSCK_FD}>/run/fbsplash-fsckd.fifo; fsck -C$FSCK_FD )
45 # <command>|<splash-event> Send a command or event to the control daemon FIFO (non blocking)
47 # FIFO Commands:
49 # 'comm' <splash-daemon-command> Send a command to the splash daemon
50 # 'message <text>' Update the main status message and reset the auto verbose timeout
51 # 'push-message <text>' Like message if SPLASH_PUSH_MESSAGES="yes" in configuration
52 # 'default-message' Reset message to default
53 # 'log <text>' Send a message to the log textbox
54 # 'svc-error' Set general failure service 'fbsplash-dummy' to failed (w/o a splash event)
55 # 'store' Save messured services start/stop time values to the disk
57 # FIFO Events - similar as for /sbin/splash-function.sh splash():
59 # 'critical' Change to console (Virtual Terminal # 1)
60 # '<svc-event> <service-name>' Update splash (and run theme hooks)
61 # Special case: 'svc_start'|'svc_started'|'svc_start_failed' 'fbsplash-boot-dummy'
62 # Pseudo service for SysV-Init 'boot' stage and
63 # running theme hooks for sysinit end as well as entering multi-user
66 # Runtime Interface
67 PID_FILE=/run/fbsplash-controld.pid
68 FIFO=/run/fbsplash-controld.fifo
69 PID_LINK=/run/fbsplashd.pid
71 # Internal Persistent Data Cache
72 CACHE_DIR=/lib/fbsplash-controld/cache
74 # Fade takes 2 sec. normally, but some machines are broken
75 SPLASH_FADE_WAIT=10 # seconds
77 . /sbin/fbsplash-control-functions.bash
79 # Wait until given processes die or return 1 if timeout
80 # args: <seconds> [<pid>...]
81 splash_wait() {
82 local t=$(( $1 * 10 ))
83 shift
84 while kill -0 -- $* &>/dev/null; do
85 (( -- t >= 0 )) && sleep .1 && continue
86 echo "Timeout waiting for processes to die: $*" >&2
87 return 1
88 done
91 case $1
92 in ping | stop )
93 pid=""
94 pids=""
95 error=0
96 [[ -f $PID_FILE ]] && read pid pids <"$PID_FILE" && (( pid )) && kill -0 -- $pid || error=1
97 ;;& ping )
98 [[ -p $FIFO ]] || error=1
99 exit $error
100 ;;& stop )
101 splash_control "$@"
102 splash_wait "$(( SPLASH_FADE_WAIT + 2 ))" $pid $pids || exit 1 # wait a bit longer than for splash exit
103 # Never error if no daemon running, except for ping
104 exit 0
105 ;; start )
107 ;; fsckd )
108 # Daemon for pushing progress info from 'fsck -C$FSCK_FD' to the splash status message line
109 pid_file="/run/fbsplash-fsckd.pid"
110 fifo="/run/fbsplash-fsckd.fifo"
111 case $2
112 in start )
113 # Avoid starting multiple instances
114 [[ ! -e $pid_file ]] && mkfifo -m 600 "$fifo" || exit 1
116 trap "rm -f '$pid_file' '$fifo'" EXIT
117 trap 'exit 0' TERM # avoid terminated message
118 fsck_progress=-1
119 while read phase step total fs; do
120 new_pgr=$(( 100 * step / total ))
121 (( fsck_progress == new_pgr )) && continue
122 fsck_progress=$new_pgr
123 printf -v fsck_msg '[ %s phase %s %2i%% ]' "$fs" "$phase" $fsck_progress
124 splash_control progress-message "Checking Filesystems ${fsck_msg}"
125 done
126 ) &>/dev/null <"$fifo" &
127 echo $! >|"$pid_file"
128 ;; stop )
129 [[ -f "$pid_file" ]] || exit 0
130 read pid <"$pid_file" && kill $pid &>/dev/null && splash_wait 5 $pid
131 splash_control progress-message # restore message
132 esac
133 exit $?
134 ;; * )
135 splash_control "$@"
136 exit 0
137 esac
139 ## Set up environment, splash-functions and configuration
141 # Allow to start splash w/o SysV-Init, in custom pm-utils scripts, for testing ...
142 # RUNLEVEL is needed for hooks, splash_start() and splash_get_boot_message()
143 # (export to be save in case hooks use it directly)
144 export PREVLEVEL RUNLEVEL
145 [[ $PREVLEVEL = ? ]] || PREVLEVEL=5
146 case $2
147 in early | bootup )
148 PREVLEVEL="N"
149 RUNLEVEL="S"
150 ;; reboot )
151 RUNLEVEL=6
152 ;; shutdown )
153 RUNLEVEL=0
154 ;; * )
155 echo "Usage: ${0##*/} start bootup|early|shutdown|reboot [arg]..." >&2
156 exit 1
157 esac
159 # Note: /proc needs to be mounted at this point!
160 # /etc/conf.d/splash is also sourced by this
161 . /sbin/splash-functions.sh || exit 1
162 # Eliminate some non local splash_setup variables ## FIXME ##
163 unset -v options opt i
164 # Add path for miscsplashutils fgconsole (needed in case /usr not mounted)
165 [[ -d $spl_bindir ]] && PATH+=":${spl_bindir}"
166 # Resolution variables (might also be required by some themes)
167 res=$( "$spl_util" -c getres -t "$SPLASH_THEME" )
168 export SPLASH_XRES=${res%x*} SPLASH_YRES=${res#*x}
170 # Defaults, Configuration
171 SPLASH_SMOOTH_PROGRESS="yes"
172 . /etc/conf.d/splash-extras
174 # If already started, don't allow to override splash mode
175 [[ $2 = early ]] && SPLASH_MODE_REQ="silent"
177 # Sleep interval for progress updates
178 ms_tick=33 # milliseconds
180 # If verbose mode, just change to console
181 [[ $SPLASH_MODE_REQ = verbose && $PREVLEVEL != N ]] && splash_verbose
182 # If off, do nothing
183 [[ $SPLASH_MODE_REQ = silent ]] || exit 0
185 ## Overrides (exported for theme hooks and used by upstream functions)
187 splash_get_boot_message() {
188 # Use a space instead of an empty message to avoid tonns of 'Text has zero width.' ## FIXME ##
189 case $RUNLEVEL
190 in 6 ) echo "${SPLASH_REBOOT_MESSAGE:- }"
191 ;; 0 ) echo "${SPLASH_SHUTDOWN_MESSAGE:- }"
192 ;; * ) echo "${SPLASH_BOOT_MESSAGE:- }"
193 esac
196 # Send a command to the (non blocking) splash daemon fifo w/o forking
197 splash_comm_send() {
198 # Avoid using SysV-Init pidof
199 pgrep -x -f "$spl_daemon .*" >/dev/null || return 1
200 splash_fifo_send "$*"
203 # Write a line to the splash profile log file
204 splash_profile() {
205 splash_profile_write "$*"
208 # Open a non blocking file descriptor for the splash daemon fifo
209 # Send zero ore more commands
210 export splash_fifo_fd=""
211 splash_fifo_send() {
212 if [[ -z $splash_fifo_fd ]]; then
213 [[ -p $spl_fifo ]] && exec {splash_fifo_fd}<>"$spl_fifo" || return 0
215 (( $# )) || return 0
216 splash_profile_write comm "$@"
217 printf '%s\n' "$@" >&$splash_fifo_fd
219 export -f splash_fifo_send
221 # Open a file descriptor for the splash profile log file
222 # Write zero or more lines
223 # args: [<prefix> <text>...]
224 export splash_profile_fd=""
225 splash_profile_write() {
226 [[ $SPLASH_PROFILE = on ]] || return 0
227 if [[ -z $splash_profile_fd ]]; then
228 # Avoid read-only filesystem error on shutdown
229 # Append to contents written in initcpio
230 [[ -w $spl_cachedir ]] && exec {splash_profile_fd}>>$spl_cachedir/profile || return 0
232 (( $# )) || return 0
233 local uptime rest
234 read uptime rest </proc/uptime
235 printf "$uptime: ${1} %s\n" "${@:2}" >&$splash_profile_fd
238 ## Prepare for starting
240 unset -v ticker_pid
241 cleanup() {
242 [[ $ticker_pid ]] && kill -- $ticker_pid
243 # Send SIGKILL to any stale splash daemon and unmount the tmpfs copying
244 # the profile log file to the disk for splash_manager replay and debugging
245 # Note: If no tmpfs is mounted, this does nothing at all.
246 cd /
247 splash_cache_cleanup
248 rm -f "$PID_FILE" "$PID_LINK" "$FIFO"
251 trap cleanup EXIT
253 silent_err() {
254 # If silent splash VT active, change to console
255 [[ $( fgconsole ) = "$SPLASH_TTY" ]] && splash_verbose
256 (( $# )) || return 0
257 echo "ERROR: $*" >&2
260 cache_check() {
261 findmnt -n -r -t "$spl_cachetype" -T "$1" >/dev/null && return 0
262 silent_err "Unable to find the splash cache filesystem at: '${1/#./$PWD}'"
263 return 1
266 if [[ $2 = early ]]; then
267 cachedir=${3:-$spl_cachedir}
268 cache_check "$cachedir" || exit 1
269 [[ $cachedir = "$spl_cachedir" ]] || mount --move "$cachedir" "$spl_cachedir" || exit 1
270 set -- "$1" "$2" "$4"
271 else
272 # On shutdown we might already have some control/ticker/splash daemons
273 # running (if splash_manager is in use etc.)
274 pids=" "$( pgrep -d " " -x -f "($BASH ${0}|${spl_daemon})( .*)?" )" "
275 pids=${pids// $$ /}
276 # Kill daemons to allow starting
277 kill -- $pids &>/dev/null
278 # No fadeout should happen when killed
279 splash_wait 5 $pids || exit 1
280 # Make sure the splash cache tmpfs is gone
281 SPLASH_PROFILE="off" splash_cache_cleanup
282 # Mount a new empty splash cache tmpfs
283 ( splash_cache_prep ) || exit 1
286 case $2
287 in reboot | shutdown )
288 softlevel="shutdown"
289 action="stop"
290 action_done="stopped"
291 ;; * )
292 softlevel="sysinit"
293 action="start"
294 action_done="started"
295 esac
297 svcs_fg_file=$3
298 svcs_start=$4
299 svcs_stop=$5
301 # Avoid loosing the splash cache tmpfs (on shutdown) and writing to the harddisk
302 cd "$spl_cachedir" && cache_check . || exit 1
304 ## Create and open the control daemon fifo non blocking and hold it to avoid loosing input or getting eof
305 mkfifo -m 600 "$FIFO" && exec {control_fifo_fd}<>"$FIFO" || exit 1
307 # Run theme hook script (if any)
308 # args: 'pre'|'post' <event> [arg]...
309 run_hook() {
310 local pre_post=$1 event=$2 args=( "${@:3}" )
311 local hook_name=${event}-${pre_post}
312 local hook_script=/etc/splash/$SPLASH_THEME/scripts/$hook_name
313 # Profile might be reused by splash_manager replay with different theme,
314 # so this is added even if hook isn't there.
315 splash_profile_write "$pre_post" "$event ${args[*]}"
316 # source is faster, but not supported by old/foreign themes
317 if [[ -r ${hook_script}.sh ]]; then
318 # Export hook name to support symlinked generic scripts
319 ( SPLASH_HOOK=$hook_name source "${hook_script}.sh" "${args[@]}" )
320 elif [[ -x $hook_script ]]; then
321 "$hook_script" "${args[@]}"
325 # Wrapper for updating the splash main status message (if needed)
326 splash_set_message() {
327 local msg=$1
328 # Send a NBSP instead of an empty/space string to avoid splash daemon crash ## FIXME ##
329 [[ $msg =~ ^[[:space:]]*$ ]] && msg=$'\xC2\xA0'
330 [[ $splash_message = $msg ]] && return 0
331 splash_message=$msg
332 # Reset autoverbose timeout (but only if needed to keep the profile clean)
333 (( SPLASH_AUTOVERBOSE > 0 )) && splash_fifo_send "progress $progress_elapsed"
334 # 'repaint' needed at least for 'set message' if daemon not started with '--type=bootup'
335 splash_fifo_send "set message $splash_message" "repaint"
338 ## Start splash daemon and/or open splash daemon fifo
340 if [[ $2 = early ]]; then
341 # Override (unknown) initcpio boot message
342 splash_message="$SPLASH_BOOT_MESSAGE -- invalid --"
343 splash_set_message "$SPLASH_BOOT_MESSAGE"
344 else
345 # Copy services list files into the splash cache for hooks using splash_svclist_get()
346 [[ $svcs_start ]] && echo "$( <"$svcs_start" )" >|"svcs_start"
347 [[ $svcs_stop ]] && echo "$( <"$svcs_stop" )" >|"svcs_stop"
348 # Wait for initcpio helper fadein
349 if ! splash_wait "$SPLASH_FADE_WAIT" $( pgrep fbcondecor_helper ); then
350 silent_err "Your framebuffer seems to be to slow. Please disable splash fade effects!"
351 exit 1
353 # Run any pre rc_init hook
354 # Note: For splash_manager replay, pre rc_init needs to be the first line in the profile
355 run_hook pre rc_init $softlevel $RUNLEVEL
356 # Enable shutdown fadein hack
357 [[ $PREVLEVEL != N && ,$SPLASH_EFFECTS, = *,fadein,* && $( fgconsole ) = "$SPLASH_TTY" ]] && chvt 63
358 # Start the splash daemon or (on boot) let the user read the error message on the splash VT
359 splash_start || exit 1
360 splash_message=$( splash_get_boot_message )
361 # Prevent gpm from garbling the splash
362 [[ -S /dev/gpmctl ]] && splash_control comms "set gpm" "repaint"
365 # Symlink splash daemon PID file
366 ln -sfT "$spl_pidfile" "$PID_LINK"
368 # Run any post rc_init hook
369 run_hook post rc_init $softlevel $RUNLEVEL
371 # Avoid blackscreen (in spite of splash daemon running) or stale fbcondecor helper splash
372 # if theme is missing or video mode and theme do not match
373 # Give some error infos additional to those of the daemon to direct users in the right direction
374 # Unfortunately we can't check a theme loaded in the initcpio, so just hope there is no difference.
375 file=/etc/splash/$SPLASH_THEME/${SPLASH_XRES}x${SPLASH_YRES}.cfg
376 pic="silentpic"
377 if ! [[ -f $file ]]; then
378 silent_err "File not found: '$file'" >&2
379 elif ! [[ $( <"$file" ) =~ (^|$'\n')[[:blank:]]*${pic}(256)?=[^[:space:]] ]]; then
380 silent_err "Silent splash mode not supported in: '$file'"
381 elif
382 read bpp </sys/class/graphics/fb0/bits_per_pixel && [[ $bpp = 8 ]] && pic+="256"
383 ! [[ $( <"$file" ) =~ (^|$'\n')[[:blank:]]*${pic}=[^[:space:]] ]]; then
384 silent_err "Splash theme / video mode bit depth mismatch."
387 ## Ticker daemon
389 trap cleanup EXIT
390 trap 'exit 0' TERM
391 printf -v sleep '.%03i' $ms_tick
392 while :; do
393 sleep $sleep
394 echo tick >"${FIFO}"
395 done
396 ) </dev/null &>/dev/null &
397 ticker_pid=$!
399 # Run half way bootup hooks once in order to make sure any extra voodoo is done
400 splash_rc_exit_sysinit() {
401 [[ $softlevel = "sysinit" ]] || return 0
402 run_hook pre rc_exit "S"
403 run_hook post rc_exit "S"
404 softlevel="boot"
407 splash_rc_init_boot() {
408 splash_rc_exit_sysinit
409 [[ $softlevel = "boot" ]] || return 0
410 read PREVLEVEL RUNLEVEL < <( runlevel 2>/dev/null )
411 [[ $PREVLEVEL = ? ]] || PREVLEVEL="N"
412 [[ $RUNLEVEL = [^Ss] ]] || RUNLEVEL=5
413 run_hook pre rc_init boot $RUNLEVEL
414 run_hook post rc_init boot $RUNLEVEL
415 softlevel=""
418 ## Control daemon
420 # Stop ticker and remove pid file no matter how we exit
421 trap cleanup EXIT
422 # Abort avoiding terminated message
423 trap 'exit 0' TERM
424 # Names of progress (foreground) services (those done until splash stopped)
425 declare -a SPLASH_SVCS_FG=( )
426 # Avarage services start times in ms
427 declare -A SPLASH_SVC_TIMES_MS=( )
428 # Weighted count of starts * 100
429 declare -A SPLASH_SVC_TIMES_N100=( )
430 # New services start times in ms
431 declare -A SPLASH_SVC_TIMES_MS_NEW=( )
433 times_file=${CACHE_DIR}/svc_${action}_times
435 # Read in stored times
436 if [[ -f $times_file ]]; then
437 while read line; do
438 # Ignore garbled and empty lines to be save
439 [[ $line =~ ^(.+)" "([0-9]+)" "([0-9]+)[[:blank:]]*$ ]] || continue
440 SPLASH_SVC_TIMES_MS["${BASH_REMATCH[1]}"]=${BASH_REMATCH[2]}
441 SPLASH_SVC_TIMES_N100["${BASH_REMATCH[1]}"]=${BASH_REMATCH[3]}
442 done <"$times_file"
445 ms_elapsed_add() {
446 local ms=${SPLASH_SVC_TIMES_MS["$1"]}
447 # Fall back to one tick per foreground service run
448 if [[ $SPLASH_SMOOTH_PROGRESS = yes && $ms ]]
449 then (( ms_elapsed += ms ))
450 else (( ms_elapsed += ms_tick ))
453 # Read in foreground daemons and sum up relevant services times for progress
454 ms_elapsed=0
455 if [[ $svcs_fg_file ]]; then
456 while read -r svc; do
457 [[ $svc ]] || continue
458 SPLASH_SVCS_FG+=( "$svc" )
459 ms_elapsed_add "$svc"
460 done <"$svcs_fg_file"
462 ms_total=$ms_elapsed
463 ms_elapsed=0
464 # If in environment, start at PROGRESS as the splash daemon does
465 progress_elapsed=${PROGRESS:-0}
466 # Reserve some progress at the end and only let 'stop' do 100%
467 progress_max=$(( 65535 - 65535 / 100 )) # assume 100 pixel minimum progress bar length
468 # Update progress per tick to avoid jumping in favour of accelleration in case services skipped
469 progress_tick_set() {
470 local ms_remain=$1
471 if (( ms_remain > 0 && progress_max > progress_elapsed ))
472 then progress_tick=$(( ( progress_max - progress_elapsed ) * ms_tick / ms_remain ))
473 else progress_tick=0
476 progress_tick_set $(( ms_total - ms_elapsed ))
478 svc_fg=""
479 # Disable progress until first foreground service event
480 svc_fg_ticks=0
481 svc_fg_ticks_elapsed=0
483 # Normal status message
484 normal_message() {
485 (( $# )) && message_normal=$1
486 splash_set_message "$message_normal"
487 # Cancel any previous text progress message
488 message_progress=""
489 message_progress_ticks=0
490 message_push=""
491 message_push_ticks=0
493 normal_message "$( splash_get_boot_message )"
495 while read -r cmd args <"${FIFO}"; do
496 event=""; svc=""
497 case $cmd
498 in tick )
499 (( svc_fg_ticks_elapsed ++ ))
500 # Text progress - Override status message for some time
501 if [[ $message_progress ]]; then
502 splash_set_message "$message_progress"
503 message_progress=""
504 message_progress_ticks=$(( 3000 / ms_tick ))
505 elif (( message_progress_ticks > 0 )); then
506 # On timeout, fallback to push-message or restore
507 if (( -- message_progress_ticks == 0 )); then
508 SPLASH_AUTOVERBOSE=0 splash_set_message "${message_push:-$message_normal}"
509 message_push_ticks=0
511 # Graphical progress
512 elif [[ $SPLASH_SMOOTH_PROGRESS = yes ]] &&
513 (( svc_fg_ticks_elapsed <= svc_fg_ticks && progress_elapsed < progress_max )); then
514 (( progress_elapsed += progress_tick ))
515 splash_fifo_send "progress $progress_elapsed" "paint"
516 # No progress - Override status message after timeout
517 elif (( message_push_ticks > 0 )); then
518 (( -- message_push_ticks == 0 )) && splash_set_message "$message_push"
520 ;; comm ) splash_fifo_send "$args"
521 ;; log )
522 # Ignore empty messages to avoid splash daemon crash ## FIXME ##
523 # 'repaint' needed at least for 'set message' if daemon not started with '--type=bootup'
524 [[ $args ]] && splash_fifo_send "log ${args}" "repaint"
525 ;; progress-message )
526 if [[ $args ]]; then
527 message_progress=$args
528 # Cancel graphical progress for current service
529 svc_fg_ticks=0
530 elif [[ $message_progress ]] || (( message_progress_ticks )); then
531 # Restore message
532 normal_message
534 ;; push-message )
535 # Temporary override after progress timeout
536 if [[ $SPLASH_PUSH_DELAY = yes ]]; then
537 message_push=$args
538 message_push_ticks=$(( 1000 / ms_tick ))
539 # Simple old mode: Just change it until next or exit
540 elif [[ $SPLASH_PUSH_MESSAGES = yes ]]; then
541 normal_message "$args"
543 ;; message )
544 normal_message "$args"
545 ;; default-message )
546 normal_message "$( splash_get_boot_message )"
547 ;; stop )
548 splash_rc_init_boot
549 run_hook pre rc_exit $RUNLEVEL
550 # Reset status message
551 splash_set_message "$( splash_get_boot_message )"
552 # If not aborting, set 100% progress now because we reserved some
553 [[ $args = force ]] || splash_fifo_send "progress 65535" "paint"
554 splash_fifo_send "exit staysilent"
555 splash_wait "$SPLASH_FADE_WAIT" $( pgrep -x -f "$spl_daemon .*" )
556 trap - EXIT
557 cleanup
558 # Reopen moved profile for post rc_exit
559 # Note: If not bootup, the post rc_exit hook shouldn't try to write anything to the filesystem.
560 [[ $splash_profile_fd ]] && exec {splash_profile_fd}<&-
561 unset -v splash_profile_fd
562 run_hook post rc_exit $RUNLEVEL
563 exit 0
564 ;; store )
565 [[ -d ${CACHE_DIR} ]] || mkdir -p "${CACHE_DIR}"
566 for svc in "${!SPLASH_SVC_TIMES_MS[@]}"; do
567 # Lower weight of old values by factor 0.98 on each boot - 0.98^34 = 0.5
568 n_100=$(( ${SPLASH_SVC_TIMES_N100["$svc"]:-0} * 98 / 100 ))
569 ms_avg=${SPLASH_SVC_TIMES_MS["$svc"]:-0}
570 ms_new=${SPLASH_SVC_TIMES_MS_NEW["$svc"]}
571 if [[ $ms_new ]]; then
572 echo $svc $(( ( 100 * ms_new + n_100 * ms_avg )/( 100 + n_100 ) )) $(( 100 + n_100 ))
573 elif (( n_100 > 0 )); then
574 echo $svc $ms_avg $n_100
576 done >|"$times_file"
577 ;; svc-error )
578 # Allow to set the general failure status explicitely (w/o a splash event)
579 splash_fifo_send "update_svc fbsplash-dummy ${action}_failed" "paint"
580 ;; critical )
581 event=$cmd
582 hook_args=( )
583 ;; svc_* )
584 # Avoid null/blank string crashing the splash daemon ## FIXME ##
585 [[ $args =~ ^\ *$ ]] && continue
586 event=$cmd
587 svc=$args
588 hook_args=( "$svc" )
589 ;;& svc_started | svc_stopped )
590 # Backwards compatibility: Add 0 exit code to hook args.
591 hook_args+=( 0 )
592 esac # Ignore any garbage
594 [[ $event ]] || continue
596 case $event
597 in svc_started | svc_start_failed )
598 [[ $svc = fbsplash-boot-dummy ]] && splash_rc_init_boot
599 esac
600 run_hook pre "$event" "${hook_args[@]}"
601 case $event
602 in critical )
603 splash_verbose
604 ;; svc_input_begin )
605 # Cancel graphical progress for current service
606 svc_fg_ticks=0
607 splash_input_begin "$svc"
608 ;; svc_input_end )
609 splash_input_end "$svc"
610 # Service update events
611 ;; svc_started )
612 if [[ $1 = gpm ]]; then
613 # This loop shouldn't be needed as newer gpm puts itself in the background
614 # after started (like a daemon), but splashutils-gentoo does this also.
615 for i in {1..10}; do
616 [[ -S /dev/gpmctl ]] && break
617 sleep .1
618 done
619 splash_fifo_send "set gpm" "repaint"
621 ;;& svc_$action )
622 ifs=$IFS
623 IFS=$'\n'
624 if [[ ${IFS}${SPLASH_SVCS_FG[*]}${IFS} = *"${IFS}${svc}${IFS}"* ]]; then
625 svc_fg=$svc
626 svc_fg_ms=${SPLASH_SVC_TIMES_MS["$svc"]}
627 if [[ $SPLASH_SMOOTH_PROGRESS = yes && $svc_fg_ms ]]
628 # Allow one more tick than calculated to avoid jumpiness
629 then svc_fg_ticks=$(( svc_fg_ms / ms_tick + 1 ))
630 else svc_fg_ticks=1
632 # Silent step skipping
633 for i in "${!SPLASH_SVCS_FG[@]}"; do
634 svc_i=${SPLASH_SVCS_FG[i]}
635 [[ $svc_i = "$svc_fg" ]] && break
636 unset -v SPLASH_SVCS_FG[i]
637 ms_elapsed_add "$svc_i"
638 done
639 progress_tick_set $(( ms_total - ms_elapsed ))
641 IFS=$ifs
642 ;;& svc_${action_done} )
643 # Save new time value (taking the first one in case of repeat)
644 if [[ $svc_fg = "$svc" ]] && (( svc_fg_ticks > 0 )) &&
645 [[ $SPLASH_SMOOTH_PROGRESS = yes && -z ${SPLASH_SVC_TIMES_MS_NEW["$svc"]} ]]; then
646 SPLASH_SVC_TIMES_MS_NEW["$svc"]=$(( svc_fg_ticks_elapsed * ms_tick ))
647 SPLASH_SVC_TIMES_MS["$svc"]+=""
649 ;;& svc_${action_done} | svc_${action}_failed )
650 if [[ $svc_fg = "$svc" ]]; then
651 # One tick per service mode
652 if [[ $SPLASH_SMOOTH_PROGRESS != yes ]]; then
653 (( progress_elapsed += progress_tick ))
654 splash_fifo_send "progress $progress_elapsed"
656 svc_fg=""
657 svc_fg_ticks=1
658 svc_fg_ticks_elapsed=0
659 # Restore message
660 normal_message
662 ;;& svc_start_failed | svc_stop_failed )
663 # Provide a general failure status
664 splash_fifo_send "update_svc fbsplash-dummy $event"
665 # Simple/upstream way of error handling
666 # Assume error messages are shown on console even if background service
667 [[ $SPLASH_VERBOSE_ON_ERRORS = yes ]] && splash_verbose
668 ;;& svc_* )
669 splash_fifo_send "update_svc $svc $event" "paint"
670 esac
671 run_hook post "$event" "${hook_args[@]}"
672 [[ $event = svc_start && $svc = fbsplash-boot-dummy ]] && splash_rc_exit_sysinit
673 done
675 echo $! $ticker_pid >>"$PID_FILE"
676 trap - EXIT
677 exit 0
679 # EOF #