/[splashy]/trunk/scripts/splashy-init
ViewVC logotype

Contents of /trunk/scripts/splashy-init

Parent Directory Parent Directory | Revision Log Revision Log


Revision 858 - (show annotations) (download)
Wed May 31 17:29:11 2006 UTC (6 years, 11 months ago) by jacobo221-guest
File size: 54752 byte(s)
updating splashy-init to curent splashy_update return codes
1 #!/bin/sh
2
3 # /etc/init.d/splashy-init
4
5 # Copyright 2005, 2006 Splashy Project http://alioth.debian.org/projects/splashy
6 # Copyright 2005, 2006 Jacobo Vilella (aka Jacobo221) <jacobo221@gmail.com>
7 #
8 # This file is part of Splashy.
9 #
10 # Splashy is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU General Public
12 # License as published by the Free Software Foundation;
13 # either version 2 of the License, or (at your option) any
14 # later version.
15 #
16 # Splashy is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty
18 # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 # See the GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public
22 # License along with Splashy; if not, write to the Free
23 # Software Foundation, Inc., 51 Franklin St, Fifth Floor,
24 # Boston, MA 02110-1301 USA
25
26 # init script for the service splashy
27 # Read details about this script in the Readme.txt file
28
29 ### BEGIN INIT INFO
30 # Provides: splashy
31 # Required-Start:
32 # Should-Start: mountvirtfs
33 # Required-Stop:
34 # Should-Stop:
35 # Default-Start: S 2 3 4 5
36 # Default-Stop: 0 2 3 4 5 6
37 # Short-Description: splashy daemon used for presenting a boot splash for Linux
38 # Description: The splashy service is used for starting a user-space boot
39 # splash utility that draws an image and a progress bar while the system
40 # is booting.
41 # X-UnitedLinux-Default-Enabled: yes
42 ### END INIT INFO
43
44 # COMMENTS:
45 # - Debug lines easily removable: delete all lines containing "DEBUG" or "debug"
46 #
47 # TODO:
48 # - splashy_pgrep... must go away :)
49 # - Support fsck
50 #
51 # NOT TODO:
52 # - The script does not support filenames with spaces in /etc/rc?.d/*, but
53 # supporting it would add too much mess to the script and no one really
54 # has that
55 # - Determine the scripts that will be run more acuratelly by not including
56 # those that will not be started/stopped by an optimized rc(S) script,
57 # because:
58 # * There is no way to be sure that the optimization will happen
59 # * It is too CPU expensive
60 ### END NOTES INFO
61
62 SC_NAME="${0##*/}"
63 NAME="splashy"
64 DESC="Splashy client"
65
66 # Script-only options. Do not touch unless you know what you are doing
67 CONFIG="/etc/default/splashy"
68 #CHANGE: Once splashy_config --check works, return code should tell also if the
69 # file does not exist, thus the $XML_CONFIG variable will be useless
70 XML_CONFIG="/etc/splashy/config.xml"
71 SC_SLEEP="0.5"
72 #CHANGE: Make it into config.xml? Anyway, check in config_parse
73 CONSOLE="/dev/vcs1"
74
75 # LSB strongly recommends not to trust $PATH
76 PATH=/bin:/sbin
77
78 ### BEGIN MAIN FUNCTIONS
79 # Load LSB's functions
80 # Why adding this here instead of only where it is needed? LSB's init-functions
81 # file could run some inline commands which should be run on all init scripts
82 if test -r /lib/lsb/init-functions; then
83 . /lib/lsb/init-functions
84 else
85 # Simulate LSB functions if the real ones are not available
86 echo "Please install LSB init-funcitons!"
87 log_begin_msg() { echo $@; }
88 log_end_msg() { if test $1 -eq 0; then echo done; else echo failed; fi;}
89 log_succees_msg() { echo $@; }
90 log_warning_msg() { echo $@; }
91 log_failure_msg() { echo $@; }
92 fi
93
94 # Provide an interface to be able to silent commands not bothering if
95 # If -2 is first argument, only stderr is silenced
96 # If -S is first argument, command will be silenced even when /dev/null doesn't
97 # exist and will return true if the command had no output and false otherwise
98 # This only applies to the cases when no /dev/null exists
99 # If -s is first argument, same as when -S, but returns true/false inveresly
100 # Options -S and -s imply -2
101 # Since debug() already calls silent() do not use debug in this function
102 silent() {
103 if test "$1" = -2; then
104 smode=2
105 shift
106 elif test "$1" = -S; then
107 smode=S
108 shift
109 elif test "$1" = -s; then
110 smode=s
111 shift
112 fi
113 if test -c /dev/null; then
114 if test "$smode" = 2; then
115 "$@" 2>/dev/null
116 else
117 "$@" >/dev/null 2>&1
118 fi
119 else
120 if test "$smode" = S; then
121 "$@" 2>&1 | if read i; then false; else true; fi
122 elif test "$smode" = s; then
123 "$@" 2>&1 | if read i; then true; else false; fi
124 else
125 # Cannot silence it
126 "$@"
127 fi
128 fi
129 }
130 # Output debug info passed as arguments when $DEBUG is enabled
131 # Return 0 when debug mode is set. Return 1 otherwise
132 # When -S is set, it only have effect when DEBUG=2, return 1 otherwise
133 debug() {
134 debugnull=""
135 is_enabled $DEBUG || return 1
136 test "$1" = -S && if test "$DEBUG" = 2; then shift; else return 1; fi
137 test -w /dev/null || debugnull=" (/dev/null doesn't exist)"
138 if test $# -gt 0 && is_enabled "$LOG"; then # debug log
139 # On boot fs is ro. Buffer until it is writtable # debug log
140 # we cannot trust test -w # debug log
141 # Also, touching the file makes sure the file exists by the time
142 # echo >> $LOG is executed
143 if silent -S touch "$LOG"; then # debug log
144 test -n "$LOGBUFF" && # debug log
145 echo -e "$LOGBUFF" >> "$LOG" && # debug log
146 unset LOGBUFF # debug log
147 echo -e "$$: $*$debugnull" >> "$LOG" # debug log
148 else # debug log
149 LOGBUFF="$(echo $LOGBUFF"\n"$$: $*$debugnull)" # debug log
150 fi # debug log
151 fi # debug log
152 test $# -gt 0 && echo -e "=Splashy debug ($$)=: $*$debugnull"; return 0; }
153 export LOGBUFF # Must be exported so daemon gets the debug log from Start
154
155 # Check if $1 is a number
156 # It requires another number as $2 to check this. Some number which $1 can
157 # never be
158 is_number() {
159 silent -S test "$1" -ne "$2"
160 }
161
162 # Return true when $1 is an 'enable value'
163 is_enabled() {
164 local value
165 test $# -lt 1 && return 1
166 for value in "" 0 no No NO disable Disable DISABLE false False FALSE \
167 disabled Disabled DISABLED; do
168 test "$1" = "$value" && return 1
169 done
170 return 0
171 }
172
173 # This function shows the error message <msg> and exists with code <code>
174 # By default, code is 1
175 # error <msg> [code]
176 # error <code>
177 error() {
178 is_enabled "$initmsg_call" && log_end_msg 1
179 debug "Error(): $2"
180 if test $# -gt 1; then
181 if test $2 -eq 0; then
182 log_warning_msg "$1"
183 else
184 log_failure_msg "$1"
185 fi
186 exit $2
187 else
188 log_failure_msg "$1"
189 exit 1
190 fi
191 }
192
193 # This function just checks if, given a path patter, at least one file exists
194 # matching that pattern
195 # This is useful because ls might file in many circumstances (for example, with
196 # deep linked symbolic links) and test only allows a single file to be checked
197 file_exists() {
198 local file
199 for file in $1; do
200 test -e "$file" && return 0
201 done
202 return 1
203 }
204
205 #CHANGE: delete once --check is implemented in /sbin/splashy_config
206 splashy_config() {
207 case "$1" in
208 --check)
209 if test -r "$XML_CONFIG"; then
210 return 0
211 else
212 return 1
213 fi
214 ;;
215 *)
216 /sbin/splashy_config "$@"
217 ;;
218 esac
219 }
220
221 is_enabled "$EXTERN_PROGRESS" ||
222 # See if the current theme in the current runlevel must have a progress bar
223 # The result is returned in $SET_PROGRESS and the return value is that of
224 # the splashy_config command
225 get_set_progress() {
226 if test "$RUNLEVEL" = 0 -o "$RUNLEVEL" = 6; then
227 SET_PROGRESS="$("$CONFIG_READER" --get-key \
228 /splashy/progressbaronshutdown)"
229 else
230 SET_PROGRESS="$("$CONFIG_READER" --get-key \
231 /splashy/progressbaronboot)"
232 fi
233 }
234
235 # Load options
236 # Export them so that subshells can read them too
237 config_parse() {
238 debug "Config parse: Starting"
239 # Unset all variables so that in a USR2 signal, the are all rechecked
240 # Do not unset FRAMEBUFFER, RUNLEVEL nor PREVLEVEL since they could be
241 # taken from environment variable and the script would loose their value
242 # Do not unset DEBUG either since some effects are unrevertable once
243 # the scripts started, such as server startup when DEBUG=2
244 unset ENABLE SERVER UPDATE_CMD CONFIG_READER SLEEP_TIME CHVT_TTY \
245 PIDFILE CLIENT_PIDFILE END_MATCHES LEVEL_MATCH SET_PROGRESS \
246 EXTERN_PROGRESS POST_EXEC_SERVICES ENABLE_INITRAMFS
247 # INVERT_DOWN FIFO_FILE
248 # Unset $prctg in case after a USR2 signal there has to be no progress
249 unset prctg
250 # If the script is run manually, get the current runlevel or exit
251 # Another chance that $RUNLEVEL might not be defined is in old
252 # init binnaries, but anyway splashy will only work on 2.6 linux
253 # kernels, which should be installed along with newer init versions
254 if test -z "$RUNLEVEL"; then
255 RUNLEVEL="$(silent -2 runlevel)"
256 test "$RUNLEVEL" = unknown &&
257 error "Splashy: No priviledges to determine runlevel"
258 # Use dd instead of cut since cut is in /usr/bin. dd spits
259 # stats. attempt to filter them. No matter if that filtering
260 # generates an error: return code is not checked and dd will
261 # spit messages if /dev/null doesn't exist anyway
262 RUNLEVEL="$(echo "$RUNLEVEL" |
263 dd skip=2 count=1 bs=1 2>/dev/null)"
264 test -z "$RUNLEVEL" &&
265 error "Splashy: No priviledges to determine runlevel"
266 fi
267 if test -z "$PREVLEVEL"; then
268 # See comment above about why using dd here
269 PREVLEVEL="$(silent -2 runlevel |
270 dd count=1 bs=1 2>/dev/null)"
271 test -z "$PREVLEVEL" && PREVLEVEL=N
272 fi
273 debug "Config parse: Parsing file"
274 # Load script configuration file
275 if test -r "$CONFIG"; then
276 . $CONFIG
277 else
278 log_warning_msg "Splashy: Missing $CONFIG. Using defaults"
279 fi
280 debug "Config parse: Config reader execution"
281 # Load XML configuration file
282 test -z "$CONFIG_READER" && CONFIG_READER="/sbin/splashy_config"
283 test -x "$CONFIG_READER" ||
284 error "Splashy: $CONFIG_READER cannot be executed"
285 CONFIG_READER="${CONFIG_READER##*/}" #CHANGE: delete
286 "$CONFIG_READER" --check ||
287 error "Splashy: $XML_CONFIG config file is broken"
288 # FIFO_FILE="$("$CONFIG_READER" --get-key /splashy/fifo)"
289 PIDFILE="$("$CONFIG_READER" --get-key /splashy/pid)"
290 get_set_progress || SET_PROGRESS=yes
291 debug "Config parse: Reading vars"
292 # Default user options
293 test -z "$ENABLE" && ENABLE=1
294 test -z "$SERVER" && SERVER="/sbin/splashy"
295 test -z "$UPDATE_CMD" && UPDATE_CMD="/sbin/splashy_update"
296 test -x "$UPDATE_CMD" || error "Splashy: $UPDATE_CMD cannot be executed"
297 test -z "$POST_EXEC_SERVICES" &&
298 POST_EXEC_SERVICES="keymap.sh console-screen.sh"
299 test -z "$END_MATCHES" &&
300 # do not include "halt reboot" since they should hold the image
301 END_MATCHES="^[Ss]top[Ss]plashy$ ^S[Ss]plashy[Ss]top$
302 ^gdm$ ^kdm$ ^wdm$ ^xdm$ ^3xdm$ ^startx$"
303 test -z "$FRAMEBUFFER" && FRAMEBUFFER="/dev/fb0"
304 test -z "$SLEEP_TIME" && SLEEP_TIME=1
305 # test -z "$INVERT_DOWN" && INVERT_DOWN=0
306 # INVERT_DOWN=0 # Disable always since it is not usable (on server side)
307 # Support old variable names
308 # test -n "$spl_fifo" -a -z "$FIFO_FILE" && FIFO_FILE="$spl_fifo"
309 test -n "$spl_tty" -a -z "$CHVT_TTY" && CHVT_TTY="$spl_tty"
310 # Check configuration values
311 test -x "$SERVER" || error "Splashy: $SERVER cannot be executed"
312 # If it is a number, just detect level. But make sure it is _just_ a
313 # number, with no spaces
314 echo "$END_MATCHES" | grep '^[0-9]\+$' -q &&
315 test $END_MATCHES -lt 100 && LEVEL_MATCH=y
316 # Do not check $SLEEP_TIME with is_number(): It could be a decimal
317 echo "$SLEEP_TIME" | grep -E '^[0-9]+\.*[0-9]*$|[0-9]*\.*[0-9]+' -q ||
318 error "Splashy: Wrong SLEEP_TIME value $SLEEP_TIME"
319 # Check $CHVT_TTY value
320 if test -z "$CHVT_TTY"; then
321 CHVT_TTY=auto
322 elif ! is_number "$CHVT_TTY" -1 &&
323 test "$CHVT_TTY" != auto -a "$CHVT_TTY" != none; then
324 error "Splashy: Invalid CHVT_TTY value ($CHVT_TTY)"
325 fi
326 test "${LOG%/*}" != "$LOG" -a ! -w "${LOG%/*}" &&
327 error "Splashy: Cannot log to $LOG"
328 # Get other settings
329 CLIENT_PIDFILE="$PIDFILE.client"
330 # Don't check the existence of the PID file. It might not
331 # yet exist, but check that it is set
332 # # Same goes for the FIFO file
333 # test -z "$FIFO_FILE" &&
334 # error "Splashy: No fifo file set in $XML_CONFIG"
335 test -z "$PIDFILE" && error "Splashy: No pid file set in $XML_CONFIG"
336 # Everything was successfull, so export them and set $CONFIG_PARSED
337 export ENABLE SERVER UPDATE_CMD CONFIG_READER SLEEP_TIME CHVT_TTY \
338 PIDFILE CLIENT_PIDFILE END_MATCHES FRAMEBUFFER LEVEL_MATCH \
339 SET_PROGRESS RUNLEVEL PREVLEVEL EXTERN_PROGRESS LOG \
340 POST_EXEC_SERVICES ENABLE_INITRAMFS CONFIG_PARSED=yes \
341 DEBUG
342 # INVERT_DOWN FIFO_FILE
343 debug "Config parse: Done"
344 }
345
346 # Detect if this script is already running
347 # Arguments correspond to PIDs that will be ignored
348 # Must be called _after_ calling config_parse()
349 # It returns the PID(s) in variable $pid if successfull
350 # Beware it could return duplicate PIDs
351 is_client_running() {
352 debug "Client_run(): Parent script PIDs: $SCRIPTSPIDS"
353 # The sorting of the matches is from least CPU heavy to most heavy
354 if test -e "$CLIENT_PIDFILE"; then
355 pid=`cat "$CLIENT_PIDFILE"`
356 silent -S kill -0 $pid &&
357 # Make sure that it is actually splashy. On init scripts, it
358 # is very easy for another process to have the same pid that
359 # a splashy process on an earlier boot
360 grep -i splashy -q /proc/$pid/cmdline &&
361 return 0
362 fi
363 local file files ipid npid tpid
364 for file in "$0" /etc/rc?.d/[SK][0-9][0-9]splashy* \
365 /etc/init.d/*splashy*; do
366 files="$files $file"
367 done
368 pid="$(pidof -x $files)"
369 # Do not use pidof's -o option. It is broken: it will fail
370 # to work when the results have duplicate pids and it only
371 # accepts 4 -o pids
372 # Therefore, here is an independent and good implementation
373 for ipid in $pid; do
374 for npid in $SCRIPTSPIDS; do
375 test $npid -eq $ipid && continue 2
376 done
377 tpid="$tpid $ipid"
378 done
379 test -n "$tpid" && pid="$tpid"
380 }
381
382 # Detect if the splashy server is already running
383 # Must be called _after_ calling config_parse()
384 # It returns the PID in variable $pid if successfull. Be aware that more than
385 # one PID could be returned in $pid
386 # It uses $SERVER_PID to remember the pid (and check it) across calls
387 is_server_running() {
388 # The sorting of the matches is from least CPU heavy to most heavy
389 if test -n "$SERVER_PID"; then
390 silent -S kill -0 $SERVER_PID &&
391 pid="$SERVER_PID" && return 0
392 fi
393 if test -e "$PIDFILE"; then
394 pid=`cat "$PIDFILE"`
395 silent -S kill -0 $pid &&
396 # Update SERVER_PID so next time it is faster to check
397 SERVER_PID="$pid" && return 0
398 fi
399 pid="$(pidof "${SERVER##*/}")" &&
400 # Update SERVER_PID so next time it is faster to check
401 SERVER_PID="$pid" && return 0
402 unset pid SERVER_PID
403 return 1
404 }
405
406 # Remove the PID file and close splashy server before exitting
407 # This does not close the server, since that would run into a race condition
408 # (clean_exit calls send_command which calls clean_exit...)
409 clean_exit() {
410 is_enabled "$EXTERN_PROGRESS" ||
411 silent -S rm -f "$CLIENT_PIDFILE"
412 debug "Clean_exit(): $1"
413 exit $1
414 }
415
416 is_enabled "$EXTERN_PROGRESS" ||
417 # Sends commands to Splashy
418 # In case of error, exit
419 send_command() {
420 debug "send_command(): Called as $*"
421 # test ! -p "$FIFO_FILE" &&
422 # error "Splashy: FIFO file $FIFO_FILE no longer exists!"
423 if is_server_running; then
424 debug "send_command(): Sending '$*'"
425 # # Do not run in the background! This will wait until
426 # # splashy-server reads the command, so no bottle-necks
427 # # will happen. Also, if it is run while udev is
428 # # remounting /dev, running in background would fail
429 # # since /dev/null might not exist (and '&' needs
430 # # /dev/null)
431 # echo $* > "$FIFO_FILE" ||
432 # error "Splashy: Unable to send '$*' to Splashy"
433 # Luis Mondesi <lemsx1@gmail.com>
434 # We use splashy_update to send our commands to Splashy's fifo
435 # This command allows us to write to the FIFO without blocking
436 # this script (non-io block). splashy_update will report
437 # error codes according to the error that was encountered. If
438 # we encounter a recoverable error, we try at least 10 times
439 # before we give up on the command
440 #CHANGE: Is there any sense in retrying??
441 for i in 1 2 3 4 5 6 7 8 9 0; do
442 upout="$("$UPDATE_CMD" "$*" 2>&1)"
443 upcode="$?"
444 debug "splashy_update code: $upcode"
445 case "$upcode" in
446 0) break
447 ;;
448 1|4) sleep 0.5
449 debug "FIFO failure. Delayed 0.5s"
450 test -n "$upout" && debug "Reason: $upout"
451 ;;
452 2) debug "FIFO failure. Reason: $upout" ;;
453 3) debug "Update_cmd: args failure!" ;;
454 esac
455 done
456 else
457 # The server is not running anymore (user closed it)
458 debug "send_command(): No server"
459 debug ||
460 clean_exit 0
461 fi
462 }
463
464 is_enabled "$EXTERN_PROGRESS" ||
465 # This is a hack I've come up with to see if X is running
466 # since there is no 'official way' of getting this information
467 # If there is an X running, provide the tty number of the first X screen
468 # It returns the result in $X_tty. If no X or no valid result is found,
469 # $X_tty is either unset or set to "" and return code is 1. Otherwise, return
470 # code is 0
471 get_X_tty() {
472 debug "get_X(): Running"
473 local f X_sc X_sc_lowest X_pid
474 # See if an X is running and, if so, get the lockfile of the
475 # lowest X screen
476 for f in /tmp/.X*-lock; do
477 X_sc="$(echo ${f##*/} | sed 's/\.X\([0-9]*\)-lock/\1/')"
478 # If the $X_sc's value is the filename, then the
479 # pattern wasn't found
480 test "${f##*/}" = "$X_sc" && unset X_sc &&
481 continue
482 # If $X_sc_lowest isn't yet set, just set it and
483 # continue (do not compare)
484 test -z "$X_sc_lowest" && X_sc_lowest=$X_sc &&
485 continue
486 test $X_sc -lt $X_sc_lowest && X_sc_lowest=$X_sc
487 done
488 # If an X was found running get it's PID
489 if test $X_sc_lowest; then
490 debug "get_X(): Xnum: $X_sc_lowest"
491 X_pid=`sed 's/[^0-9]*\([0-9]*\).*/\1/' \
492 /tmp/.X"$X_sc_lowest"-lock`
493 # Make sure we are getting a number. Comparing a pid
494 # against 0 is a safe check
495 if is_number "$X_pid" 0; then
496 # This is the most precise way, but requires
497 # root priviledge
498 if test -r /proc/$X_pid/fd; then
499 debug "get_X: Root"
500 for f in /proc/$X_pid/fd/*; do
501 # Search for a /dev/tty* file
502 # being used by the X server
503 X_tty="$(readlink "$f" |
504 grep "^/dev/tty")" &&
505 break
506 done
507 # See if a device was found. If so, get
508 # its number
509 if test -n "$X_tty"; then
510 X_tty="$(echo "$X_tty" |
511 sed 's/[^0-9]*\([0-9]*\)/\1/')"
512 # Make sure we are getting a
513 # number. Comparing a tty
514 # against a nevative number is a
515 # safe check
516 is_number "$X_tty" -1 ||
517 unset X_tty
518 fi
519 fi
520 # This method similar to `ps -aux | grep X |
521 # grep vt7`, but more precise (though more CPU
522 # expensive)
523 # It should be available for any user, even
524 # non-priviledged
525 # Priviledged uers may also come here if the
526 # other method failed
527 if test -z "$X_tty"; then
528 debug "get_X(): NoRoot"
529 # The reason for using "echo `cat ...` |
530 # tr ... | sed ...", instead of passing
531 # the file directly as an argument is
532 # that sed doesn't hande files with NULL
533 # characters, and cmdline has some
534 X_tty="$(cat /proc/$X_pid/cmdline |
535 tr '\000' ' ' |
536 sed 's/.*\ vt\([0-9]*\)[\ \x0$].*/\1/')"
537 # Make sure we are getting a number
538 # Comparing a tty against a nevative
539 # number is a safe check
540 is_number "$X_tty" -1 || unset X_tty
541 fi
542 fi
543 fi
544 debug "get_X(): X_tty: $X_tty"
545 test -n "$X_tty" || return 1
546 }
547
548 is_enabled "$EXTERN_PROGRESS" ||
549 # Complete the progress bar
550 # $prctg is global in case a USR2 signal happened
551 perform_complete() {
552 debug "Complete: $atempts=$succeeded+$repeats/$failed"
553 # The progress has been completed. Complete progress and exit
554 if is_enabled "$SET_PROGRESS"; then
555 # if test "$RUNLEVEL" = 6 -o "$RUNLEVEL" = 0 &&
556 # is_enabled "$INVERT_DOWN"; then
557 # prctg=0
558 # else
559 prctg=100
560 # fi
561 # Do not update progress if it is already set to that percentage
562 if test "$oldprctg" != "$prctg"; then
563 # debug "Complete: Sending 100%: $prctg - $oldprctg"
564 # send_command "progress $(($prctg - $oldprctg))"
565 # debug && i=$(($prctg - $oldprctg))
566 # debug "FINAL INCREMENT: $inc_count + $i"
567 debug "Complete: Sending 100%: $prctg"
568 send_command "progress $prctg"
569 fi
570 fi
571
572 # Switch to X's terminal when not shutting down
573 if test "$RUNLEVEL" != 6 -a "$RUNLEVEL" != 0; then
574 # If a tty was set to switch in config, switch to it
575 # Otherwise, try to determine where X is running, or
576 # don't switch
577 if test "$CHVT_TTY" = auto; then
578 debug "Get tty: yes"
579 if get_X_tty; then
580 switch_tty="$X_tty"
581 else
582 debug "Get tty: no. Defaulting to 1"
583 switch_tty=1 # Fallback to tty1
584 fi
585 else
586 switch_tty="$CHVT_TTY"
587 fi
588 debug "Switch X initialized"
589 # If a tty is set, switch to it
590 # Don't use 'chvt' command: It is not a base distro command
591 if [ "$switch_tty" != none ]; then
592 debug "Switch to $switch_tty tty"
593 # Allow Splashy to change vt
594 send_command "allowchvt"
595 # Tell Splashy to switch vt
596 send_command "chvt $switch_tty"
597 fi
598 debug "Server: Exitting"
599 send_command "exit"
600 fi
601 # If Splashy is supposed to be running from initramfs, so any init script
602 # running unicode{start|stop} will be patched and must be rerun now
603 # Do not use "is_enabled $ENABLE_INITRAMFS" but instead check if it is
604 # enabled using the same check used in initramfs/hooks/splashy
605 if test "$ENABLE_INITRAMFS" = 1; then
606 debug "Initramfs enabled"
607 # Timeout after 10 seconds
608 for i in 1 2 3 4 5 6 7 8 9 0; do
609 # Do the same check that the init scripts do when patched
610 silent pidof splashy || break
611 done
612 debug "Server died"
613 # Even if splashy is still running, start the services. In the
614 # worst case it will halt the system until splashy server
615 # timesout which is what would have happened anyway if this code
616 # wasn't here
617 # Execute the services in the same order they should
618 if test "$POST_EXEC_SERVICES" = auto; then
619 debug "Autodetecting services to rerun"
620 if test "PREVLEVEL" = N; then
621 runlevels="S $RUNLEVEL"
622 else
623 runlevels="$RUNLEVEL"
624 fi
625 for rl in runlevels; do
626 for file in \
627 `grep -i unicode_ /etc/rc"$rl"/* -m1 | \
628 cut -f1 -d:`; do
629 debug "Rerunning $file"
630 test -x "$file" && "$file"
631 done
632 done
633 else
634 for file in $POST_EXEC_SERVICES; do
635 debug "Rerunning service $file"
636 test -r "/etc/init.d/$file" || continue
637 case "$file" in
638 *.sh) sh "/etc/init.d/$file" start
639 debug "Shell service rerun successfully"
640 ;;
641 *) test -x "/etc/init.d/$file" || continue
642 /etc/init.d/"$file" start
643 debug "Binary service rerun successfully"
644 ;;
645 esac
646 done
647 fi
648 fi
649 debug "Client: Exitting"
650 clean_exit 0
651 }
652
653 is_enabled "$EXTERN_PROGRESS" ||
654 # Get the aproximate list of scripts that will be run for the passed
655 # as argument runlevel
656 # The list of scripts is appended to $scripts and the amount of scripts
657 # is summed to $nscripts
658 get_scripts() {
659 local file
660 # Ignore K scripts in first runlevel since boot
661 # Also note that $END_MATCHES applies only for start scripts
662 # This is because a runlevel might have a name twice (as a K and an S
663 # script) and it would make no sense to stop splashy at K level. Same
664 # would happen in name collision between runlevels S and 2 for example
665 if test "$PREVLEVEL" != N; then
666 # Make sure that at least such a file exists, otherwise we
667 # would get the exact literal string
668 file_exists "/etc/rc$1.d/K[0-9][0-9]*" &&
669 for file in /etc/rc"$1".d/K[0-9][0-9]*; do
670 scripts="$scripts$1${file##*/} "
671 nscripts=$(($nscripts + 1))
672 done
673 fi
674 # Make sure that at least such a file exists, otherwise we
675 # would get the exact literal string
676 file_exists "/etc/rc$1.d/S[0-9][0-9]*" &&
677 if test "$1" != S -a "$1" != s; then
678 local done oldlevel count var newlevel
679 for file in /etc/rc"$1".d/S[0-9][0-9]*; do
680 file="${file##*/}"
681 newlevel="$(printf "%.3s" "$file")"
682 scripts="$scripts$1$file "
683 if test -z "$done"; then
684 if test "$oldlevel" = $newlevel; then
685 count=$(($count + 1))
686 else
687 oldlevel=$newlevel
688 count=0
689 fi
690 for match in $END_MATCHES; do
691 test -z "$match" && continue
692 if is_enabled $LEVEL_MATCH; then
693 match="S$match*"
694 else
695 test -n "${match#*\$}" &&
696 match="$match*"
697 if test -n "${match%%^*}"; then
698 match="*$match"
699 else
700 match="S[0-9][0-9]$match"
701 fi
702 fi
703 case "$file" in
704 $match)
705 done=1
706 var=$(($var - $count))
707 debug "Get_scripts(): M: $file"
708 break
709 ;;
710 esac
711 done
712 # Even when done, +1, because when a matching
713 # script is reached, it is that script that
714 # ends, not the one right before it
715 #J221: Any system wide option to check?
716 # Notice that this is optimized for parallel
717 # booting scripts. It will not be all that good
718 # in serial scripts booting, since all $oldlevel
719 # scripts are disconted and then +1, so if the
720 # matched script wasn't the first one, it might
721 # stop before it is reached
722 var=$(($var + 1))
723 fi
724 done
725 nscripts=$(($nscripts + $var))
726 else
727 for file in /etc/rc"$1".d/S[0-9][0-9]*; do
728 scripts="$scripts$1${file##*/} "
729 nscripts=$(($nscripts + 1))
730 done
731 fi
732 }
733
734 is_enabled "$EXTERN_PROGRESS" ||
735 # Get the aproximate list of scripts that will be run in the given runlevel
736 # This wrapper simple adds the ability to include post-S scripts
737 # Notice that this will never be exact since rc(S) scripts tend to optimize
738 # performance by not stopping or running those services which are kept or
739 # or not restarted along runlevels
740 # The script names are returned along with the runlevel in $scripts
741 # The amount of scripts returned is returned in $nscripts
742 # It sets $target_rl when in booting S runlevel and the next runlevel is known
743 # It uses $target_rl_was_set to remember if $target_rl has already been set
744 get_scripts_wrapper() {
745 unset scripts nscripts
746 get_scripts "$1"
747 debug "Wrapper(): $1 = $nscripts"
748 # Export them now since the function might be left due to
749 # errors at any moment. They must be exported to be usable
750 # across shells
751 export scripts nscripts target_rl
752 if test "$1" = S -o "$1" = s; then
753 # Notice that /proc could not yet be mounted
754 test ! -e /proc/1 && return
755 # Only set it the first time we enter runlevel S
756 if ! is_enabled "$target_rl_was_set" &&
757 test "$PREVLEVEL" = N; then
758 target_rl="$(sed 's/init\ \[\([Ss0-9AaBbCc]\)\].*/\1/' \
759 /proc/1/cmdline)"
760 test "$target_rl" = "$(cat /proc/1/cmdline)" -o \
761 "$target_rl" = S -o "$target_rl" = s -o \
762 -z "$target_rl" &&
763 unset target_rl && return
764 get_scripts "$target_rl"
765 debug "Wrapper(): S + $target_rl = $nscripts"
766 fi
767 fi
768 }
769
770 # Start the splashy server accordingly to the runlevel we are in or going to
771 # It accepts "-s" as its only argument. When passed, it will not show errors nor
772 # exit if failure happens
773 # $vga will never vary during a system session so it is safe keeping it through
774 # USR2 signals and overwritting it
775 # Returns true on success
776 start_server() {
777 local server_code=0 command
778 if test "$RUNLEVEL" = 0 -o "$RUNLEVEL" = 6; then
779 debug "Server(): Run: shutdown"
780 command=shutdown
781 else
782 debug "Server(): Run: boot"
783 command=boot
784 fi
785 # # When debug option is enabled in splashy server, uncomment line below
786 # debug && command="--debug $command"
787 # We cannot rely on splashy-server writting the pid, since the
788 # filesystem might not be writable yet
789 # Notice that splashy server is silenced, so all errors must be handled
790 # by the script
791 ! debug -S &&
792 if silent "$SERVER" $command &&
793 # Make sure there is only one instance running
794 is_server_running && is_number "$pid" 0; then
795 # # With incremental progress commands it is not possible to
796 # # restore the progress bar
797 # server_code=0
798 # Try to restore previous progress bar status if there was
799 if test -n "$prctg"; then
800 send_command "progress $prctg" || server_code=1
801 fi
802 else
803 server_code=1
804 fi
805 # See if the server was successfuly initiated
806 if test $server_code -ne 0 -a "$1" != "-s"; then
807 # Let's now determine the exact reason for the failure and tell
808 # it
809 echo "Splashy failed because of the following reason(s):"
810 test ! -e /proc/fb &&
811 echo " - No framebuffer kernel support is available"
812 ! test -w "$FRAMEBUFFER" &&
813 echo " - Framebuffer device unwrittable ($FRAMEBUFFER)"
814 # # rc scripts get kernel foo=bar arguments as environment
815 # # variables. So check if vga= is set (this is an alternate way
816 # # of checking /proc/cmdline, since /proc could not yet be
817 # # mounted) or try to find it out
818 # # Grub method
819 # test -z "$vga" &&
820 # # Lilo (kernel docs) method
821 # vga="$(silent -2 dd count=1 bs=2 skip=295165 if=/dev/mem |
822 # silent -2 od -d - | head -n 1 | tr -s \ | cut -f 2 -d \ )"
823 # ! silent -S test "$vga" -ge 769 -a "$vga" -le 799 &&
824 # # Desperate detection
825 # # It is practically impossible to detect all possible values,
826 # # just run and take a look at:
827 # # egrep '(fix(\.|->)id.*\"|\.id[[:space:]]*=[[:space:]]*\")' \
828 # # -R /usr/src/linux/drivers/video/ | \
829 # # sed 's/.*\"\([^\"]*\)\".*/\1/'
830 # # ...and that's just some (most) of them
831 # ! silent -S grep 'VESA VGA' /proc/fb -q &&
832 # echo " - Kernel parameter vga= not set"
833 # To see if Framebuffer is usable just check that /proc/fb
834 # contains data (framebuffer's identification string)
835 # If it does, it is usable (/proc/fb never contains error
836 # messages, etc), if it doesn't, it is not (all framebuffer
837 # devices _must_ define a 'char id[16]' string
838 test -z "$(cat /proc/fb)" &&
839 echo " - Framebuffer disabled. Set vga= value in kernel"
840 is_server_running &&
841 if ! is_number "$pid" 0; then
842 echo " - There is more than one Splashy server running!"
843 else
844 echo " - Another Splashy server is already running"
845 fi
846 test ! -p "$("$CONFIG_READER" --get-key /splashy/fifo)" &&
847 echo " - FIFO file doesn't exist"
848 debug || # Do not fail on debug mode. Keep going
849 error "Failed to start Splashy server"
850 fi
851 return $server_code
852 }
853 ### END MAIN FUNCTIONS
854
855 ### BEGIN COMMON STUFF
856 # Add this pid to the list of PIDS is_client_running() should ignore and export
857 # it so it is readable from subshells
858 export SCRIPTSPIDS="$SCRIPTSPIDS $$"
859
860 # Parse the config files. Only if not parsed already
861 is_enabled "$CONFIG_PARSED" || config_parse
862
863 debug "Starting client: $0 ($SC_NAME)"
864 debug "Runlevel: $RUNLEVEL"
865
866 # This is the only way possible to have it behave appropiately in some
867 # circumstances, although breaking LSB
868 case "$SC_NAME" in
869 [KS][0-9][0-9][Ss]top[Ss]plashy | [KS][0-9][0-9][Ss]plashy[Ss]top)
870 # The capital 'S' is on purpose to know it is an init script
871 mode=Stop
872 ;;
873 [KS][0-9][0-9]*)
874 if ! is_enabled "$START_RUN" && test "$1" = start -o "$1" = stop; then
875 # The capital 'S' is on purpose to know it is an init script
876 mode=Start
877 else
878 mode="$1"
879 fi
880 ;;
881 *) mode="$1"
882 ;;
883 esac
884
885 # This script should be run in start mode from a K call in all runlevels but S.
886 # If this is not the case, assume it is already running from a K script. It is
887 # necessary to run the script in all runlevels as both K and S script because
888 # of the reason explained in the README file under section "USER NOTES"
889 # Also, remove the splashy server pid file when booting the system
890 test "$mode" = Start && test "$RUNLEVEL" = S -o "$RUNLEVEL" = s &&
891 case "$SC_NAME" in
892 K*) error "Please do not run Splashy as a K script from runlevel S"
893 ;;
894 S*) silent -S rm "$PIDFILE"
895 ;;
896 esac
897
898 debug "Mode: $mode. $$"
899 ### END COMMON STUFF
900
901 ### BEGIN ACTIONS
902 # Behave appropiately to the command
903 case "$mode" in
904 # The start mode does initial checks before running the daemon and sets
905 # everything up so that the daemon can run in background as lightly as
906 # possible
907 [Ss]tart)
908 # We are using the initrc messages here instead of using them in the
909 # daemon (where they should be) because the init-functions currently
910 # do not support parallel running
911 # log_begin_msg is available since LSB 2.0, while log_daemon_msg is new
912 # in LSB 3.0. But we will simulate log_daemon_msg through log_begin_msg
913 log_begin_msg "Starting $DESC: $NAME"
914 # Under certain circumstances (such as when exitting) it is necessary
915 # to know if the log_begin_msg function was called and is waiting
916 # for a log_end_msg call
917 initmsg_call=yes
918 # Do not run on RUNLEVEL 1. Don't bother disabling this:
919 # The splashy-server checks this too and will not run on runlevel 1
920 test "$RUNLEVEL" = 1 && error "Splashy: Will not run in runlevel 1" 0
921 # Since init scripts are config files, they might be left after an
922 # uninstall. Check whether the binary is still present:
923 test ! -x "$SERVER" &&
924 error "Splashy: $SERVER not installed. Purge Splashy" 5
925 # Do not start if disabled and called as init script
926 ! is_enabled "$ENABLE" && test "$mode" = Start &&
927 error "Splashy is disabled in $CONFIG" 0
928 # Do not run if this script is already running
929 # This must obviously be checked before the pid file is rewritten
930 # Return successful as described in LSB
931 is_client_running &&
932 # This script is run twice during almost all runlevels to avoid
933 # the rc script optimizations (see USER NOTES in the Readme.txt
934 # file), so try to give an apropiate output for each case
935 if test $mode = Start; then
936 debug "Splashy client already running"
937 echo " status is \"running\"."
938 exit 0
939 else
940 error "Splashy: Already running" 0
941 fi
942 # Perform some operations with the script name that may be necessary
943 # later
944 test $mode = Start && export NAME_FULL="$0"
945 debug "Start: NameFull: $NAME_FULL"
946 # Get the scripts here so it is done when entering daemon mode
947 is_enabled "$EXTERN_PROGRESS" ||
948 get_scripts_wrapper "$RUNLEVEL"
949 # Be able to know if the script was run with start initially
950 export START_RUN=yes
951 # Try to run the server, if possible. If it fails, just ignore
952 # This will make splashy appear from the very first moment, with no
953 # scrolling text at all (almost). Thus the importance of suggestion to
954 # be launched after mountvirtfs
955 test -e /proc/1 -a -e /dev/fb0 &&
956 #CHANGE: Do not check for /dev/vcs1. Splashy could just be showing a
957 # static image while on initramfs
958 if test "$PREVLEVEL" = N; then
959 # If the system is booting, just try to start it, but don't care
960 # if it fails: it will be started again later
961 #CHANGE: When the server handles its launching errors
962 # correctly, remove this check and launch without -s. Otherwise
963 # it might be correctly launched twice (if user entered verbose)
964 # # Luis Mondesi <lemsx1@gmail.com>
965 # # When using initramfs, splashy will be running with no ability
966 # # to read our named pipe (fifo). We must kill it first and then
967 # # start it properly
968 # debug "PidOf says $(pidof -s splashy)."
969 # silent -S kill -9 $(pidof -s splashy)
970 # sleep 1
971 start_server -s
972 else
973 start_server
974 fi
975 if test $? -eq 0; then
976 debug "Client: Started server"
977 export SERVER_RUNNING=y &&
978 # If in extern_progress mode, splashy server started, so exit
979 is_enabled "$EXTERN_PROGRESS" &&
980 clean_exit 0
981 fi
982 # Start in background
983 # We assume that /dev/null exists, since this part should be run
984 # asynchronously
985 debug "Calling daemon mode"
986 "$0" daemon &
987 # If we got here, the process was successfull as far as we can report
988 # up to the moment
989 log_end_msg 0
990 # This isn't necessary. It is just in case someday something is added
991 # below, so we don't forget
992 unset initmsg_call
993 ;;
994 # NEVER call this script in "daemon" mode directly! Let "start" call it
995 daemon)
996 is_enabled "$START_RUN" || error "Daemon mode cannot be called directly"
997 debug "Entering daemon mode"
998 ### BEGIN FUNCTIONS EXCLUSIVE FOR THIS MODE
999 is_enabled "$EXTERN_PROGRESS" ||
1000 # Set the pid file, if possible
1001 # It uses $pidmark_done to know if the pid file has been successfully
1002 # and definitely written
1003 set_pid_file() {
1004 # Don't write PID when shutting down, otherwise it would be
1005 # there when booting back again
1006 test -n "$pidmark_done" -o \
1007 "$RUNLEVEL" = 0 -o "$RUNLEVEL" = 6 &&
1008 return
1009 # We cannot trust in /dev/null existing
1010 if test -e /dev/null; then
1011 ( echo $$ > "$CLIENT_PIDFILE" ) 2>/dev/null
1012 else
1013 echo $$ > "$CLIENT_PIDFILE"
1014 fi &&
1015 # We cannot assume that the filesystem is correctly set
1016 # and that it will not be remounted until runlevel S
1017 # has been passed
1018 # Notice that the order in the check below does matter
1019 # This function is always called after
1020 # progress2percentage() so it is safe to assume that if
1021 # $target_rl is blank, this is not first runlevel S
1022 if test -z "$target_rl"; then
1023 pidmark_done=yes
1024 debug "PID(): done"
1025 else debug "PID(): written"
1026 fi
1027 }
1028
1029 is_enabled "$EXTERN_PROGRESS" ||
1030 # Get the $level (s, S or 0-9), $mode (S or K), $progress (rc
1031 # step) and $name (script name) currently running. Also $script is
1032 # the whole script's name plus it's runlevel
1033 # Note that the variables' values may be empty when the progress status
1034 # cannot be detected
1035 # Return true when the progress is complete. Otherwise, return false
1036 # It updates $RUNLEVEL acording to the runlevel it has detected
1037 # It uses $oldscript to remember the previous script across calls
1038 get_status() {
1039 local line
1040 unset script
1041 debug "Get_status(): oldscript: $oldscript"
1042 debug && atempts="$(($atempts + 1))"
1043 # There are two characteristics which should be studied:
1044 # 1. CPU usage: We don't want splashy to harm boot time too
1045 # much
1046 # 2. (Most important) Atomic: It is extremely important that
1047 # the delay between the /proc/*/exe listing and the reading of
1048 # the links is as short as possible (explained later in point
1049 # 4 about why can no init script be detected)
1050 # We can almost assure that this following command is the real
1051 # core of this script, so making it's CPU usage low, makes the
1052 # sholw script fast
1053 # Only search for the newest process since we are only
1054 # interested in processes newer than this script. If no such
1055 # process is found, then this script will appear, which
1056 # we'll ignore
1057 line="$(splashy_pgrep -f -n -l \
1058 "/rc[sS0-9AaBbCc\].d/[KS][0-9][0-9]")" &&
1059 test "${line%% *}" -ne $$ && script="${line#* }"
1060 # How to get sourced scripts progress too?
1061 # TheBonsai: "redefine "source" ["."] as a function" "read
1062 # INVOCATION section in [bash] manpage" "i mean the ENV hack"
1063 # Jacobo221: "reading kernel docs" "Note that [...] a trailing =
1064 # on the name of any parameter states that that parameter will
1065 # be entered as an environment variable"
1066 # twkm: "it is not exported, it is merely in pid 1's env"
1067 # (and init passes it to rc/rcS)
1068 #test -n "$script" && debug "Get_status(): script: $script"
1069 # It can happen that no rc script is detected to be running in
1070 # the following cases:
1071 # 1. /etc/boot.rc/ scripts (deprecated, but still supported) are
1072 # being run
1073 # 2. All rc scripts have been run. The stop script should have
1074 # been run by this time
1075 # 3. The status check was performed while the rc script itself
1076 # was iterating into another init script
1077 # 4. The init script that was being run while the /proc/*/exe
1078 # listing was performed, died before its link was read
1079 # No init script has been detected to be running
1080 if test -z "$script"; then
1081 debug "Get_status(): No script"
1082 unset progress mode level
1083 # See if rc scripts are being run still
1084 # It could happen that it was switching from
1085 # runlevel S to another runlevel such as 2, so it
1086 # would not detect any /etc/init.d/rc(S) script
1087 # To avoid the switching from S to X runlevel bug,
1088 # see if runlevel command is set. This command
1089 # reads the utmp file, which is set by init not
1090 # before switching from runlevel S. Also notice
1091 # it cannot be trusted much since the utmp could be
1092 # from a previous session or just not exist yet
1093 # But, this doesn't save much, since init sets utmp
1094 # _during_ the runlevel switching process, so the bug
1095 # is still there, just more difficult to suffer it
1096 # Notice that if /proc is unmounted _during_ the
1097 # script, it will complete the progress bar
1098 if ! silent -s splashy_pgrep -f -o "/etc/init.d/rc" &&
1099 test "$(silent -2 runlevel)" != unknown; then
1100 debug "Get_status(): No rc(S)"
1101 succeeded=$(($succeeded + 1))
1102 return 0
1103 else
1104 if test -z "$oldscript"; then
1105 # At least, we are at the progress were
1106 # this script is called from, if this is
1107 # an init script
1108 test -n "$NAME_FULL" &&
1109 script="$NAME_FULL"
1110 if test -z "$script"; then
1111 debug "Get_status(): No 1st" &&
1112 failed="$(($failed +1))"
1113 return 1
1114 fi
1115 debug "Get_status(): script1: $script"
1116 else
1117 debug "Get_status(): Not detected" &&
1118 failed="$(($failed + 1))"
1119 return 1
1120 fi
1121 fi
1122 fi
1123 progress=$(echo $script | sed 's/.*\/[KS]\([0-9][0-9]\).*/\1/')
1124 level=$(echo $script | sed 's/.*\/rc\([sS0-9AaBbCc]\).*/\1/')
1125 mode=$(echo $script | sed 's/.*\/\([KS]\).*/\1/')
1126 name="$(echo $script |
1127 sed 's/.*\/[KS][0-9][0-9]\([^[:space:]]*\).*/\1/')"
1128 script="$level$mode$progress$name"
1129 debug "Get_status(): Progress: $script ($level$mode$progress)"
1130 # If we are at the same progress that we were before, skip. We
1131 # avoid writting to the fifo and loosing cpu cycles in
1132 # framebuffer drawing
1133 if test "$script" = "$oldscript"; then
1134 unset progress mode level
1135 debug "Get_status(): Repeat ($oldscript)" &&
1136 repeats="$(($repeats + 1))"
1137 else
1138 # Update the $oldscript variable to check against it
1139 # on next iteration
1140 oldscript="$script"
1141 fi
1142 # Do not check here if the progress is complete
1143 # If there is no stop script, this script will detect this later
1144 debug "Get_status(): oldscript2: $oldscript"
1145 # Update runlevel
1146 test -n "$level" && RUNLEVEL="$level"
1147 return 1
1148 }
1149
1150 is_enabled "$EXTERN_PROGRESS" ||
1151 # Convert the progress status into a percentage number to reflect in the
1152 # progress bar. Leave the result in the $prctg variable
1153 # Returns true when the progress is complete
1154 # Unsets $prctg if it couldn't be detected
1155 # It updates $PREVLEVEL when the detected level has changed
1156 # It uses $prevcyclerl to remember the runlevel that was used in the
1157 # last iteration. It also uses $oldprctg to remember the $prctg value
1158 # in the last call
1159 # When it detects the $target_rl runlevel has been passed, it unsets the
1160 # variable
1161 # It may also set target_rl_was_set when get_scripts_wrapper() failed to
1162 # set $target_rl
1163 # Notice $RUNLEVEL and $level are equivalent here (except when $level is
1164 # not set)
1165 progress2percent() {
1166 debug "Progress: Non-complete"
1167 # Set the $oldprctg now before it is modified
1168 oldprctg="$prctg"
1169 # Check if the variables have been set by get_status
1170 # If the variables are not set that is because the
1171 # percentage should not be updated
1172 # If only one variable is set, the others are too
1173 test -z "$level" && return 1
1174 local xscript var file
1175 debug "Progress: Exists"
1176 debug && succeeded="$(($succeeded + 1))"
1177 # This is the first iteration
1178 if test -z "$prevcyclerl"; then
1179 prevcyclerl="$level"
1180 # $target_rl_was_set is very often used in this script
1181 # to know when we have passed the first S runlevel. So
1182 # since this is the first iteration, if it isn't S, say
1183 # so
1184 test "$PREVLEVEL" != N && target_rl_was_set=yes
1185 fi
1186 # See if the runlevel changed in the last iteration. If it did,
1187 # update the variables
1188 if test "$prevcyclerl" != "$level"; then
1189 debug "Progress(): Runlevel $prevcyclerl -> $level"
1190 debug "Progress(): Target Runlevel1: $target_rl"
1191 debug "Progress(): Target RL set1: $target_rl_was_set"
1192 # Set $PREVLEVEL. Only set it when this is not a change
1193 # from initial S to X
1194 if test -n "$target_rl_was_set" -a -z "$target_rl"; then
1195 PREVLEVEL="$prevcyclerl"
1196 debug "Progress(): PREVLEVEL changed"
1197 # If the runlevel that goes after S has not been
1198 # detected, we can assume it is this one
1199 # Also assume it is this one whe, although $target_rl is
1200 # set, this other runlevel has taken its place
1201 elif test -z "$target_rl" -a -z "$target_rl_was_set" ||
1202 test -n "$target_rl" -a "$target_rl" != "$level"; then
1203 debug "Progress(): Hard target_rl detection"
1204 target_rl="$level"
1205 # get_scripts_wrapper() also sets $scripts and
1206 # other variables when it detects $target_rl
1207 # Since this cannot be done here, set it to
1208 # value 'half' so it is known later
1209 target_rl_was_set=half
1210 # Check if we have just finished running the target
1211 # runlevel, and if so, set things up
1212 elif test "$prevcyclerl" = "$target_rl"; then
1213 unset target_rl
1214 fi
1215 debug "Progress(): Target Runlevel2: $target_rl"
1216 debug "Progress(): Target RL set2: $target_rl_was_set"
1217 # Update the variables for the new runlevel unless they
1218 # are already set
1219 if test "$target_rl" != "$level" -o \
1220 "$target_rl_was_set" = half; then
1221 debug "Progress(): Regetting scripts"
1222 get_scripts_wrapper "$level"
1223 # Only do this operations when this is not the
1224 # post S runlevel
1225 if test "$target_rl_was_set" != half; then
1226 debug "Progress(): Redoing thingies"
1227 get_set_progress
1228 #CHANGE: Restart server (since it
1229 # does not support downgrading the
1230 # progress) and set apropiate command
1231 # (boot, shutdown) and check
1232 # progressbaron*. This should be removed
1233 # when it does
1234 send_command "exit"
1235 start_server
1236 fi
1237 # If it was 'half', it is completly set now
1238 test "$target_rl_was_set" = half &&
1239 target_rl_was_set=yes
1240 fi
1241 debug "Progress(): Target Runlevel3: $target_rl"
1242 debug "Progress(): Target RL set3: $target_rl_was_set"
1243 fi
1244 # Unset $prctg so that if unknown, it is not set. It cannot be
1245 # unset earlier since start_server() might need it
1246 unset prctg
1247 debug "Progress(): script=$script, scripts=$scripts"
1248 # Note that $script might be something like
1249 # "/bin/sh /etc/rcS.d/S01splashy"
1250 for file in $scripts; do
1251 var=$(($var + 1))
1252 test $file = "$script" && xscript=$var && break
1253 done
1254 if test -z "$xscript"; then
1255 # If the script wasn't found, ignore it. Maybe a
1256 # K script in runlevel S
1257 debug "Progress: NOT FOUND!!: $script,$scripts"
1258 return 1
1259 elif test 0"$xscript" -gt 0"$nscripts"; then
1260 # If we are here it is because we passed the
1261 # last step, so complete at once
1262 debug "Progress: Overflowed"
1263 return 0
1264 fi
1265 # Don't calculate progress if it is not going to be used
1266 if is_enabled "$SET_PROGRESS"; then
1267 # If no scripts were detected, return and keep looping
1268 # Do not return true (break main loop) since this could
1269 # be runlevel S, so there could be scripts in next
1270 # runlevel
1271 # The script is already prepared to detect when no
1272 # scripts are left to run, even when $nscript == 0
1273 # Anyway, this should never happen. If it did, it is
1274 # most probably a bug in the get_scripts() function
1275 if [ $nscripts = 0 ]; then
1276 debug "Progress: No scripts detected!"
1277 return 1
1278 fi
1279 # Notice that the calculations are all in a single
1280 # command and with a single division so that there is
1281 # little loss in integer division
1282 # If the next runlevel cannot be handled now (when in
1283 # first runlevel S), suppose S will take 75% of the time
1284 if test -z "$target_rl_was_set" ||
1285 test -n "$target_rl" -a "$target_rl" != "$level"
1286 then
1287 prctg="$(($xscript * 100 * 3 /(4 * $nscripts)))"
1288 debug "Progress: PrctgAlgo: S"
1289 # Previously the booting runlevel wasn't know but it is
1290 # now known, so resume from the suppose 75% progress
1291 elif test "$target_rl" = "$level"; then
1292 prctg="$(($xscript * 100 /(4 * $nscripts) +75))"
1293 debug "Progress: PrctgAlgo: !S"
1294 # Default behaviour
1295 else
1296 prctg="$(($xscript * 100 / $nscripts))"
1297 debug "Progress: PrctgAlgo: Other"
1298 fi
1299 # # When going down, if set in configuration, invert
1300 # # percentage
1301 # if test $RUNLEVEL = 0 -o $RUNLEVEL = 6; then
1302 # #debug "Progress: Now: 0 or 6"
1303 # if is_enabled "$INVERT_DOWN"; then
1304 # prctg="$((100 - $prctg))"
1305 # debug "Progress: Down: Inverse"
1306 # fi
1307 # fi
1308 fi
1309 test "$prevcyclerl" != "$level" && prevcyclerl="$level"
1310 return 1
1311 }
1312
1313 is_enabled "$EXTERN_PROGRESS" ||
1314 # This function performs signals handling
1315 signal_handler() {
1316 debug "Signal Handler: $1"
1317 case $1 in
1318 ABRT)
1319 clean_exit 0
1320 ;;
1321 TERM)
1322 send_command exit
1323 clean_exit 0
1324 ;;
1325 USR1)
1326 perform_complete
1327 ;;
1328 USR2)
1329 config_parse
1330 start_server
1331 ;;
1332 *)
1333 error "Signal Handler: Invalid signal $1"
1334 ;;
1335 esac
1336 }
1337 ### END FUNCTIONS EXCLUSIVE FOR THIS MODE
1338
1339 # If the server was already set to run (in start mode), don't attempt to
1340 # start it now. Otherwise, if the user had been fast enough to enter
1341 # verbose mode, it would splash again
1342 if test -z "$SERVER_RUNNING"; then
1343 # See if proc fs is mounted. If it isn't sleep until it is
1344 # Since it should be mounted pretty soon, we can safely set it
1345 # to wake up in very low frequencies
1346 # Even if we already checked if it exists, it does noharm to
1347 # check again
1348 while test ! -e /proc/1; do sleep -- $SC_SLEEP; done
1349 # Check also that the framebuffer device exists or wait for it
1350 # to be created, since some systems may rely on udev creating
1351 # it. But before, make sure that udev is going to run, otherwise
1352 # just go on and report the failure when splashy server fails
1353 if test ! -e "$CONSOLE" -o ! -e "$FRAMEBUFFER"; then
1354 # Only wait if udev is launched. Otherwise just fail
1355 if file_exists "/etc/rcS.d/*udev"; then
1356 i=0
1357 debug "Waiting framebuffer or console devices"
1358 # Cycle 90 times maximum
1359 while test "$i" -lt 90; do
1360 sleep -- $SC_SLEEP
1361 if test -e "$FRAMEBUFFER" -a \
1362 -e "$CONSOLE"; then
1363 fbdev_found=1
1364 break
1365 fi
1366 i=$(($i + 1))
1367 done
1368 fi
1369 test 0$fbdev_found -eq 0 && clean_exit 0
1370 fi
1371 # Run splashy-server daemon
1372 is_server_running
1373 server_status=$?
1374 if test $server_status -eq 0 &&
1375 test $RUNLEVEL != 0 -a $RUNLEVEL != 6 &&
1376 is_number "$pid" 0; then
1377 # If it is already running, we are not going down and
1378 # there is only one instance running, use it
1379 # Notice it MUST be restarted when going down. Read few
1380 # lines below the reason
1381 debug "Server: Running already"
1382 true
1383 else
1384 debug "Server: Not running (or nevermind)"
1385 # If it is already running but level is 0 or 6, or there
1386 # is more than one instance running, kill it (them) and
1387 # run it again. In the case of going down it would get
1388 # killed by runlevel shutdown scripts otherwise
1389 test $server_status -eq 0 && silent -S kill $pid
1390 start_server
1391 fi
1392 else debug "Client: Server was started already"
1393 fi
1394 # In extern_progress mode Splashy server must be running now, so exit
1395 is_enabled "$EXTERN_PROGRESS" && clean_exit 0
1396 # Set $prctg and $oldprctg to the initial progress value
1397 is_enabled "$SET_PROGRESS" && test -z "$prctg" &&
1398 # if test "$tlevel" = 0 -o "$tlevel" = 6 &&
1399 # is_enabled "$INVERT_DOWN"; then
1400 # prctg=100
1401 # # If in inverse mode, set bar to 100 from the very start since
1402 # # Splashy initializes it to 0%
1403 # send_command "progress $prctg"
1404 # else
1405 prctg=0
1406 # fi
1407 # Do not assume $oldprctg will be set later: if the process is complete
1408 # before it hits progress2percent(), it will never be set
1409 oldprctg="$prctg"
1410
1411 # Trap signals to control remotely a running instance of this script
1412 # There is no need to trap them before this point
1413 # SIGINT and SIGQUIT cannot be handled (at least by bash) here
1414 #LM: man bash and look for SIGNALS
1415 trap "signal_handler ABRT" ABRT # ctrl+c
1416 trap "signal_handler TERM" TERM # kill
1417 trap "signal_handler USR1" USR1
1418 trap "signal_handler USR2" USR2
1419
1420 # Now go drawing the percentage in frequencies of $SLEEP_TIME seconds
1421 # By the time we get here, we can expect some progress has been done
1422 # (otherwise /proc would not be mounted), so don't sleep initially
1423 debug "Progress: Start (sleep: $SLEEP_TIME)"
1424 until get_status || progress2percent; do
1425 # Write down the PID. This must be done every time it is
1426 # possible, since it may be deleted during the client's
1427 # execution (see the boot notes in the comment at the beginning
1428 # of the script
1429 # When runlevel S finishes, all mounts should be correctly done,
1430 # so we can assume that the pidfile is not correctly set
1431 set_pid_file
1432 if test -n "$prctg" -a "$oldprctg" != "$prctg"; then
1433 # # Send Splashy the percentage to increment the bar
1434 # i=$(($prctg - $oldprctg));debug S: $prctg-$oldprctg=$i
1435 # test $i -lt 0 && debug "GOSH!!!!"
1436 # debug && inc_count="$((${inc_count:-0} + $i))"
1437 # debug "Current count goes up to $inc_count"
1438 # send_command "progress $(($prctg - $oldprctg))"
1439 # Send Splashy the percentage to display
1440 debug "S: $prctg"
1441 send_command "progress $prctg"
1442 else debug "Progress: no progress update reported"
1443 fi
1444 debug "Progress: Next iteration"
1445 sleep -- $SLEEP_TIME
1446 done
1447 trap - INT USR1 USR2
1448 perform_complete
1449 ;;
1450
1451 [Ss]top)
1452 # In extern_progress mode, just stop server
1453 if ! is_enabled "$EXTERN_PROGRESS" && is_client_running; then
1454 debug "Stop: Client $pid"
1455 silent -S kill -USR1 $pid
1456 else
1457 # Stop server. Only when it was impossible to stop signal the
1458 # client
1459 if is_server_running; then
1460 debug "Stop: Server"
1461 # Notice that if the config file path changed, this
1462 # may fail
1463 send_command "exit"
1464 else
1465 false
1466 fi
1467 fi
1468 test $? -ne 0 -a $mode = stop &&
1469 error "Unable to stop Splashy. Most probably it isn't running" 0
1470 ;;
1471
1472 restart)
1473 # If in extern_progress mode, just restart server
1474 if is_enabled "$EXTERN_PROGRESS"; then
1475 splashy_update exit
1476 sleep 1
1477 if is_server_running; then
1478 for proc in $pid; do
1479 kill -9 $proc
1480 done
1481 fi
1482 start_server
1483 elif is_client_running; then
1484 debug "Restart: Client: Running"
1485 "$0" stop && "$0" start
1486 else
1487 debug "Restart: Server: Not running"
1488 "$0" start
1489 fi
1490 ;;
1491
1492 try-restart | force-reload)
1493 # If in extern_progress mode, just restart server
1494 if is_enabled "$EXTERN_PROGRESS"; then
1495 "$0" restart
1496 elif is_client_running; then
1497 debug "Try-Restart: Yes"
1498 "$0" stop && "$0" start
1499 else
1500 debug "Try-Restart: No"
1501 exit 1
1502 fi
1503 ;;
1504
1505 reload)
1506 # If in extern_progress mode, just restart server
1507 if is_enabled "$EXTERN_PROGRESS"; then
1508 "$0" restart
1509 exit 0
1510 fi
1511 # Read config again and restart server at the same point it was (since
1512 # this is the only way to make the server read the theme again)
1513 is_client_running && silent -S kill -USR2 $pid
1514 ;;
1515
1516 status)
1517
1518 # If in extern_progress mode, just show server status
1519 if is_enabled "$EXTERN_PROGRESS"; then
1520 if is_server_running; then
1521 echo Running
1522 exit 0
1523 elif test -e "$PIDFILE"; then
1524 echo "Not running, but pid file exists"
1525 exit 1
1526 else
1527 echo "Not running"
1528 exit 3
1529 fi
1530 # Report client status only. Client should die once server dies
1531 elif is_client_running; then
1532 echo Running
1533 exit 0
1534 elif test -e "$CLIENT_PIDFILE"; then
1535 # Do not use error() function: this is not an error
1536 echo "Not running, but pid file exists"
1537 exit 1
1538 else
1539 # Do not use error() function: this is not an error
1540 echo "Not running"
1541 exit 3
1542 fi
1543 ;;
1544
1545 *)
1546 # This is not an init error message, so do not use error() funciton
1547 echo "Usage: start|stop|status|restart|try-restart|reload|force-reload"
1548 test "$mode" = help && exit 0
1549 exit 1
1550 ;;
1551 esac
1552 ### END ACTIONS

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.5