Rewrite bootscripts and Chaper 7
[linux_from_scratch.git] / bootscripts / lfs / init.d / functions
blobe91ce5b5adf5b9188fec01caa5be51299e5bd147
1 #!/bin/sh
2 ########################################################################
3 # Begin boot functions
5 # Description : Run Level Control Functions
7 # Authors : Gerard Beekmans - gerard@linuxfromscratch.org
8 # Update : Bruce Dubbs - bdubbs@linuxfromscratch.org
10 # Version : LFS 7.0
12 # Notes : With code based on Matthias Benkmann's simpleinit-msb
13 # http://winterdrache.de/linux/newboot/index.html
15 # The file should be located in /lib/boot
17 ########################################################################
19 # Set any needed environment variables e.g. HEADLESS
20 [ -r /etc/sysconfig/init_params ] && . /etc/sysconfig/init_params
22 ## Environmental setup
23 # Setup default values for environment
24 umask 022
25 export PATH="/bin:/usr/bin:/sbin:/usr/sbin"
27 # Signal sent to running processes to refresh their configuration
28 RELOADSIG="HUP"
30 # Number of seconds between STOPSIG and FALLBACK when stopping processes
31 KILLDELAY="3"
33 ## Screen Dimensions
34 # Find current screen size
35 if [ -z "${COLUMNS}" ]; then
36 COLUMNS=$(stty size)
37 COLUMNS=${COLUMNS##* }
40 # When using remote connections, such as a serial port, stty size returns 0
41 if [ "${COLUMNS}" = "0" ]; then
42 COLUMNS=80
45 ## Measurements for positioning result messages
46 COL=$((${COLUMNS} - 8))
47 WCOL=$((${COL} - 2))
49 ## Provide an echo that supports -e and -n
50 # If formatting is needed, $ECHO should be used
51 case "`echo -e -n test`" in
52 -[en]*)
53 ECHO=/bin/echo
56 ECHO=echo
58 esac
60 ## Set Cursor Position Commands, used via $ECHO
61 SET_COL="\\033[${COL}G" # at the $COL char
62 SET_WCOL="\\033[${WCOL}G" # at the $WCOL char
63 CURS_UP="\\033[1A\\033[0G" # Up one line, at the 0'th char
65 ## Set color commands, used via $ECHO
66 # Please consult `man console_codes for more information
67 # under the "ECMA-48 Set Graphics Rendition" section
69 # Warning: when switching from a 8bit to a 9bit font,
70 # the linux console will reinterpret the bold (1;) to
71 # the top 256 glyphs of the 9bit font. This does
72 # not affect framebuffer consoles
73 NORMAL="\\033[0;39m" # Standard console grey
74 SUCCESS="\\033[1;32m" # Success is green
75 WARNING="\\033[1;33m" # Warnings are yellow
76 FAILURE="\\033[1;31m" # Failures are red
77 INFO="\\033[1;36m" # Information is light cyan
78 BRACKET="\\033[1;34m" # Brackets are blue
80 STRING_LENGTH="0" # the length of the current message
82 #*******************************************************************************
83 # Function - boot_mesg()
85 # Purpose: Sending information from bootup scripts to the console
87 # Inputs: $1 is the message
88 # $2 is the colorcode for the console
90 # Outputs: Standard Output
92 # Dependencies: - sed for parsing strings.
93 # - grep for counting string length.
95 # Todo:
96 #*******************************************************************************
97 boot_mesg()
99 local ECHOPARM=""
101 while true
103 case "${1}" in
105 ECHOPARM=" -n "
106 shift 1
109 echo "Unknown Option: ${1}"
110 return 1
113 break
115 esac
116 done
118 ## Figure out the length of what is to be printed to be used
119 ## for warning messages.
120 STRING_LENGTH=$((${#1} + 1))
122 # Print the message to the screen
123 ${ECHO} ${ECHOPARM} -e "${2}${1}"
125 # Log the message
126 ${ECHO} ${ECHOPARM} -e "${2}${1}" >> /run/var/bootlog
129 boot_mesg_flush()
131 # Reset STRING_LENGTH for next message
132 STRING_LENGTH="0"
135 echo_ok()
137 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${SUCCESS} OK ${BRACKET}]"
138 ${ECHO} -e "${NORMAL}"
139 boot_mesg_flush
140 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${SUCCESS} OK ${BRACKET}]" >> /run/var/bootlog
141 ${ECHO} -e "${NORMAL}" >> /run/var/bootlog
144 echo_failure()
146 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${FAILURE} FAIL ${BRACKET}]"
147 ${ECHO} -e "${NORMAL}"
148 boot_mesg_flush
149 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${FAILURE} FAIL ${BRACKET}]" >> /run/var/bootlog
150 ${ECHO} -e "${NORMAL}" >> /run/var/bootlog
153 echo_warning()
155 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${WARNING} WARN ${BRACKET}]"
156 ${ECHO} -e "${NORMAL}"
157 boot_mesg_flush
158 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${WARNING} WARN ${BRACKET}]" >> /run/var/bootlog
159 ${ECHO} -e "${NORMAL}" >> /run/var/bootlog
162 echo_skipped()
164 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${WARNING} SKIP ${BRACKET}]"
165 ${ECHO} -e "${NORMAL}"
166 boot_mesg_flush
167 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${WARNING} SKIP ${BRACKET}]" >> /run/var/bootlog
168 ${ECHO} -e "${NORMAL}" >> /run/var/bootlog
171 wait_for_user()
173 # Wait for the user by default
174 [ "${HEADLESS=0}" = "0" ] && read ENTER
177 evaluate_retval()
179 error_value="${?}"
181 if [ ${error_value} = 0 ]; then
182 echo_ok
183 else
184 echo_failure
187 # This prevents the 'An Unexpected Error Has Occurred' from trivial
188 # errors.
189 return 0
192 print_status()
194 if [ "${#}" = "0" ]; then
195 echo "Usage: ${0} {success|warning|failure}"
196 return 1
199 case "${1}" in
201 success)
202 echo_ok
205 warning)
206 # Leave this extra case in because old scripts
207 # may call it this way.
208 case "${2}" in
209 running)
210 ${ECHO} -e -n "${CURS_UP}"
211 ${ECHO} -e -n "\\033[${STRING_LENGTH}G "
212 boot_mesg "Already running." ${WARNING}
213 echo_warning
215 not_running)
216 ${ECHO} -e -n "${CURS_UP}"
217 ${ECHO} -e -n "\\033[${STRING_LENGTH}G "
218 boot_mesg "Not running." ${WARNING}
219 echo_warning
221 not_available)
222 ${ECHO} -e -n "${CURS_UP}"
223 ${ECHO} -e -n "\\033[${STRING_LENGTH}G "
224 boot_mesg "Not available." ${WARNING}
225 echo_warning
228 # This is how it is supposed to
229 # be called
230 echo_warning
232 esac
235 failure)
236 echo_failure
239 esac
243 reloadproc()
245 local pidfile=""
246 local failure=0
248 while true
250 case "${1}" in
252 pidfile="${2}"
253 shift 2
256 log_failure_msg "Unknown Option: ${1}"
257 return 2
260 break
262 esac
263 done
265 if [ "${#}" -lt "1" ]; then
266 log_failure_msg "Usage: reloadproc [-p pidfile] pathname"
267 return 2
270 # This will ensure compatibility with previous LFS Bootscripts
271 if [ -n "${PIDFILE}" ]; then
272 pidfile="${PIDFILE}"
275 # Is the process running?
276 if [ -z "${pidfile}" ]; then
277 pidofproc -s "${1}"
278 else
279 pidofproc -s -p "${pidfile}" "${1}"
282 # Warn about stale pid file
283 if [ "$?" = 1 ]; then
284 boot_mesg -n "Removing stale pid file: ${pidfile}. " ${WARNING}
285 rm -f "${pidfile}"
288 if [ -n "${pidlist}" ]; then
289 for pid in ${pidlist}
291 kill -"${RELOADSIG}" "${pid}" || failure="1"
292 done
294 (exit ${failure})
295 evaluate_retval
297 else
298 boot_mesg "Process ${1} not running." ${WARNING}
299 echo_warning
303 statusproc()
305 local pidfile=""
306 local base=""
307 local ret=""
309 while true
311 case "${1}" in
313 pidfile="${2}"
314 shift 2
317 log_failure_msg "Unknown Option: ${1}"
318 return 2
321 break
323 esac
324 done
326 if [ "${#}" != "1" ]; then
327 shift 1
328 log_failure_msg "Usage: statusproc [-p pidfile] pathname"
329 return 2
332 # Get the process basename
333 base="${1##*/}"
335 # This will ensure compatibility with previous LFS Bootscripts
336 if [ -n "${PIDFILE}" ]; then
337 pidfile="${PIDFILE}"
340 # Is the process running?
341 if [ -z "${pidfile}" ]; then
342 pidofproc -s "${1}"
343 else
344 pidofproc -s -p "${pidfile}" "${1}"
347 # Store the return status
348 ret=$?
350 if [ -n "${pidlist}" ]; then
351 ${ECHO} -e "${INFO}${base} is running with Process"\
352 "ID(s) ${pidlist}.${NORMAL}"
353 else
354 if [ -n "${base}" -a -e "/var/run/${base}.pid" ]; then
355 ${ECHO} -e "${WARNING}${1} is not running but"\
356 "/var/run/${base}.pid exists.${NORMAL}"
357 else
358 if [ -n "${pidfile}" -a -e "${pidfile}" ]; then
359 ${ECHO} -e "${WARNING}${1} is not running"\
360 "but ${pidfile} exists.${NORMAL}"
361 else
362 ${ECHO} -e "${INFO}${1} is not running.${NORMAL}"
367 # Return the status from pidofproc
368 return $ret
371 # The below functions are documented in the LSB-generic 2.1.0
373 #*******************************************************************************
374 # Function - pidofproc [-s] [-p pidfile] pathname
376 # Purpose: This function returns one or more pid(s) for a particular daemon
378 # Inputs: -p pidfile, use the specified pidfile instead of pidof
379 # pathname, path to the specified program
381 # Outputs: return 0 - Success, pid's in stdout
382 # return 1 - Program is dead, pidfile exists
383 # return 2 - Invalid or excessive number of arguments,
384 # warning in stdout
385 # return 3 - Program is not running
387 # Dependencies: pidof, echo, head
389 # Todo: Remove dependency on head
390 # This replaces getpids
391 # Test changes to pidof
393 #*******************************************************************************
394 pidofproc()
396 local pidfile=""
397 local lpids=""
398 local silent=""
399 pidlist=""
400 while true
402 case "${1}" in
404 pidfile="${2}"
405 shift 2
409 # Added for legacy opperation of getpids
410 # eliminates several '> /dev/null'
411 silent="1"
412 shift 1
415 log_failure_msg "Unknown Option: ${1}"
416 return 2
419 break
421 esac
422 done
424 if [ "${#}" != "1" ]; then
425 shift 1
426 log_failure_msg "Usage: pidofproc [-s] [-p pidfile] pathname"
427 return 2
430 if [ -n "${pidfile}" ]; then
431 if [ ! -r "${pidfile}" ]; then
432 return 3 # Program is not running
435 lpids=`head -n 1 ${pidfile}`
436 for pid in ${lpids}
438 if [ "${pid}" -ne "$$" -a "${pid}" -ne "${PPID}" ]; then
439 kill -0 "${pid}" 2>/dev/null &&
440 pidlist="${pidlist} ${pid}"
443 if [ "${silent}" != "1" ]; then
444 echo "${pidlist}"
447 test -z "${pidlist}" &&
448 # Program is dead, pidfile exists
449 return 1
450 # else
451 return 0
452 done
454 else
455 pidlist=`pidof -o $$ -o $PPID -x "$1"`
456 if [ "${silent}" != "1" ]; then
457 echo "${pidlist}"
460 # Get provide correct running status
461 if [ -n "${pidlist}" ]; then
462 return 0
463 else
464 return 3
469 if [ "$?" != "0" ]; then
470 return 3 # Program is not running
474 #*******************************************************************************
475 # Function - loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]
477 # Purpose: This runs the specified program as a daemon
479 # Inputs: -f, run the program even if it is already running
480 # -n nicelevel, specifies a nice level. See nice(1).
481 # -p pidfile, uses the specified pidfile
482 # pathname, pathname to the specified program
483 # args, arguments to pass to specified program
485 # Outputs: return 0 - Success
486 # return 2 - Invalid of excessive number of arguments,
487 # warning in stdout
488 # return 4 - Program or service status is unknown
490 # Dependencies: nice, rm
492 # Todo: LSB says this should be called start_daemon
493 # LSB does not say that it should call evaluate_retval
494 # It checks for PIDFILE, which is deprecated.
495 # Will be removed after BLFS 6.0
496 # loadproc returns 0 if program is already running, not LSB compliant
498 #*******************************************************************************
499 loadproc()
501 local pidfile=""
502 local forcestart=""
503 local nicelevel="10"
505 # This will ensure compatibility with previous LFS Bootscripts
506 if [ -n "${PIDFILE}" ]; then
507 pidfile="${PIDFILE}"
510 while true
512 case "${1}" in
514 forcestart="1"
515 shift 1
518 nicelevel="${2}"
519 shift 2
522 pidfile="${2}"
523 shift 2
526 log_failure_msg "Unknown Option: ${1}"
527 return 2 #invalid or excess argument(s)
530 break
532 esac
533 done
535 if [ "${#}" = "0" ]; then
536 log_failure_msg "Usage: loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]"
537 return 2 #invalid or excess argument(s)
540 if [ -z "${forcestart}" ]; then
541 if [ -z "${pidfile}" ]; then
542 pidofproc -s "${1}"
543 else
544 pidofproc -s -p "${pidfile}" "${1}"
547 case "${?}" in
549 log_warning_msg "Unable to continue: ${1} is running"
550 return 0 # 4
553 boot_mesg "Removing stale pid file: ${pidfile}" ${WARNING}
554 rm -f "${pidfile}"
559 log_failure_msg "Unknown error code from pidofproc: ${?}"
560 return 4
562 esac
565 nice -n "${nicelevel}" "${@}"
566 evaluate_retval # This is "Probably" not LSB compliant,
567 # but required to be compatible with older bootscripts
568 return 0
571 #*******************************************************************************
572 # Function - killproc [-p pidfile] pathname [signal]
574 # Purpose:
576 # Inputs: -p pidfile, uses the specified pidfile
577 # pathname, pathname to the specified program
578 # signal, send this signal to pathname
580 # Outputs: return 0 - Success
581 # return 2 - Invalid of excessive number of arguments,
582 # warning in stdout
583 # return 4 - Unknown Status
585 # Dependencies: kill, rm
587 # Todo: LSB does not say that it should call evaluate_retval
588 # It checks for PIDFILE, which is deprecated.
589 # Will be removed after BLFS 6.0
591 #*******************************************************************************
592 killproc()
594 local pidfile=""
595 local killsig=TERM # default signal is SIGTERM
596 pidlist=""
598 # This will ensure compatibility with previous LFS Bootscripts
599 if [ -n "${PIDFILE}" ]; then
600 pidfile="${PIDFILE}"
603 while true
605 case "${1}" in
607 pidfile="${2}"
608 shift 2
611 log_failure_msg "Unknown Option: ${1}"
612 return 2
615 break
617 esac
618 done
620 if [ "${#}" = "2" ]; then
621 killsig="${2}"
622 elif [ "${#}" != "1" ]; then
623 shift 2
624 log_failure_msg "Usage: killproc [-p pidfile] pathname [signal]"
625 return 2
628 # Is the process running?
629 if [ -z "${pidfile}" ]; then
630 pidofproc -s "${1}"
631 else
632 pidofproc -s -p "${pidfile}" "${1}"
635 # Remove stale pidfile
636 if [ "$?" = 1 ]; then
637 boot_mesg "Removing stale pid file: ${pidfile}." ${WARNING}
638 rm -f "${pidfile}"
641 # If running, send the signal
642 if [ -n "${pidlist}" ]; then
643 for pid in ${pidlist}
645 kill -${killsig} ${pid} 2>/dev/null
647 # Wait up to 3 seconds, for ${pid} to terminate
648 case "${killsig}" in
649 TERM|SIGTERM|KILL|SIGKILL)
650 # sleep in 1/10ths of seconds and
651 # multiply KILLDELAY by 10
652 local dtime="${KILLDELAY}0"
653 while [ "${dtime}" != "0" ]
655 kill -0 ${pid} 2>/dev/null || break
656 sleep 0.1
657 dtime=$(( ${dtime} - 1))
658 done
659 # If ${pid} is still running, kill it
660 kill -0 ${pid} 2>/dev/null && kill -KILL ${pid} 2>/dev/null
662 esac
663 done
665 # Check if the process is still running if we tried to stop it
666 case "${killsig}" in
667 TERM|SIGTERM|KILL|SIGKILL)
668 if [ -z "${pidfile}" ]; then
669 pidofproc -s "${1}"
670 else
671 pidofproc -s -p "${pidfile}" "${1}"
674 # Program was terminated
675 if [ "$?" != "0" ]; then
676 # Remove the pidfile if necessary
677 if [ -f "${pidfile}" ]; then
678 rm -f "${pidfile}"
680 echo_ok
681 return 0
682 else # Program is still running
683 echo_failure
684 return 4 # Unknown Status
688 # Just see if the kill returned successfully
689 evaluate_retval
691 esac
692 else # process not running
693 print_status warning not_running
698 #*******************************************************************************
699 # Function - log_success_msg "message"
701 # Purpose: Print a success message
703 # Inputs: $@ - Message
705 # Outputs: Text output to screen
707 # Dependencies: echo
709 # Todo: logging
711 #*******************************************************************************
712 log_success_msg()
714 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
715 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${SUCCESS}"" OK ""${BRACKET}""]""${NORMAL}"
716 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}" >> /run/var/bootlog
717 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${SUCCESS}"" OK ""${BRACKET}""]""${NORMAL}" \
718 >> /run/var/bootlog
719 return 0
722 #*******************************************************************************
723 # Function - log_failure_msg "message"
725 # Purpose: Print a failure message
727 # Inputs: $@ - Message
729 # Outputs: Text output to screen
731 # Dependencies: echo
733 # Todo: logging
735 #*******************************************************************************
736 log_failure_msg() {
737 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
738 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${FAILURE}"" FAIL ""${BRACKET}""]""${NORMAL}"
739 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}" >> /run/var/bootlog
740 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${FAILURE}"" FAIL ""${BRACKET}""]""${NORMAL}" \
741 >> /run/var/bootlog
742 return 0
745 #*******************************************************************************
746 # Function - log_warning_msg "message"
748 # Purpose: print a warning message
750 # Inputs: $@ - Message
752 # Outputs: Text output to screen
754 # Dependencies: echo
756 # Todo: logging
758 #*******************************************************************************
759 log_warning_msg() {
760 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
761 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${WARNING}"" WARN ""${BRACKET}""]""${NORMAL}"
762 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}" >> /run/var/bootlog
763 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${WARNING}"" WARN ""${BRACKET}""]""${NORMAL}" \
764 >> /run/var/bootlog
765 return 0
768 #*******************************************************************************
769 # Function - log_skipped_msg "message"
771 # Purpose: print a message that the script was skipped
773 # Inputs: $@ - Message
775 # Outputs: Text output to screen
777 # Dependencies: echo
779 # Todo: logging
781 #*******************************************************************************
782 log_skipped_msg() {
783 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
784 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${WARNING}"" SKIP ""${BRACKET}""]""${NORMAL}"
785 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}" >> /run/var/bootlog
786 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${WARNING}"" SKIP ""${BRACKET}""]""${NORMAL}" \
787 >> /run/var/bootlog
788 return 0
791 # End boot functions