PKGBUILDs/core/initscripts/functions
2011-06-17 23:44:09 -05:00

398 lines
9.8 KiB
Bash

#!/bin/bash
# initscripts functions
#
# width:
STAT_COL=80
if [[ ! -t 1 ]]; then
USECOLOR=""
elif [[ -t 0 ]]; then
# stty will fail when stdin isn't a terminal
STAT_COL="$(/bin/stty size)"
# stty gives "rows cols"; strip the rows number, we just want columns
STAT_COL="${STAT_COL##* }"
elif /bin/tput cols &>/dev/null; then
# is /usr/share/terminfo already mounted, and TERM recognized?
STAT_COL=$(/bin/tput cols)
fi
if ((STAT_COL==0)); then
# if output was 0 (serial console), set default width to 80
STAT_COL=80
USECOLOR=""
fi
# we use 13 characters for our own stuff
STAT_COL=$(($STAT_COL - 13))
# disable colors on broken terminals
TERM_COLORS="$(/bin/tput colors 2>/dev/null)"
if (($? != 3)); then
case $TERM_COLORS in
*[!0-9]*) USECOLOR="";;
[0-7]) USECOLOR="";;
'') USECOLOR="";;
esac
fi
unset TERM_COLORS
# clear the TZ envvar, so daemons always respect /etc/localtime
unset TZ
# sanitize the locale settins
unset LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY \
LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE \
LC_MEASUREMENT LC_IDENTIFICATION LC_ALL
if [[ $DAEMON_LOCALE =~ yes|YES && -n $LOCALE ]]; then
export LANG="${LOCALE}"
else
export LANG=C
fi
# set colors
if [[ $USECOLOR =~ yes|YES ]]; then
if /bin/tput setaf 0 &>/dev/null; then
C_CLEAR="$(tput sgr0)" # clear text
C_MAIN="${C_CLEAR}$(/bin/tput bold)" # main text
C_OTHER="${C_MAIN}$(/bin/tput setaf 4)" # prefix & brackets
C_SEPARATOR="${C_MAIN}$(/bin/tput setaf 0)" # separator
C_BUSY="${C_CLEAR}$(/bin/tput setaf 6)" # busy
C_FAIL="${C_MAIN}$(/bin/tput setaf 1)" # failed
C_DONE="${C_MAIN}" # completed
C_BKGD="${C_MAIN}$(/bin/tput setaf 5)" # backgrounded
C_H1="${C_MAIN}" # highlight text 1
C_H2="${C_MAIN}$(/bin/tput setaf 6)" # highlight text 2
else
C_CLEAR="\e[m" # clear text
C_MAIN="\e[;1m" # main text
C_OTHER="\e[1;34m" # prefix & brackets
C_SEPARATOR="\e[1;30m" # separator
C_BUSY="\e[;36m" # busy
C_FAIL="\e[1;31m" # failed
C_DONE="${C_MAIN}" # completed
C_BKGD="\e[1;35m" # backgrounded
C_H1="${C_MAIN}" # highlight text 1
C_H2="\e[1;36m" # highlight text 2
fi
fi
if [[ -t 1 ]]; then
SAVE_POSITION="\e[s"
RESTORE_POSITION="\e[u"
DEL_TEXT="\e[$(($STAT_COL+4))G"
else
SAVE_POSITION=""
RESTORE_POSITION=""
DEL_TEXT=""
fi
# prefixes:
PREFIX_REG="::"
PREFIX_HL=" >"
# functions:
deltext() {
printf "${DEL_TEXT}"
}
printhl() {
printf "${C_OTHER}${PREFIX_HL} ${C_H1}${1}${C_CLEAR} \n"
}
printsep() {
printf "\n${C_SEPARATOR} ------------------------------\n"
}
stat_bkgd() {
printf "${C_OTHER}${PREFIX_REG} ${C_MAIN}${1}${C_CLEAR} "
deltext
printf " ${C_OTHER}[${C_BKGD}BKGD${C_OTHER}]${C_CLEAR} "
}
stat_busy() {
printf "${C_OTHER}${PREFIX_REG} ${C_MAIN}${1}${C_CLEAR} "
printf "${SAVE_POSITION}"
deltext
printf " ${C_OTHER}[${C_BUSY}BUSY${C_OTHER}]${C_CLEAR} "
}
stat_append() {
printf "${RESTORE_POSITION}"
printf -- "${C_MAIN}${1}${C_CLEAR}"
printf "${SAVE_POSITION}"
}
stat_done() {
deltext
printf " ${C_OTHER}[${C_DONE}DONE${C_OTHER}]${C_CLEAR} \n"
}
stat_fail() {
deltext
printf " ${C_OTHER}[${C_FAIL}FAIL${C_OTHER}]${C_CLEAR} \n"
}
stat_die() {
stat_fail
exit ${1:-1}
}
status() {
stat_busy "$1"
shift
if "$@" >/dev/null 2>&1; then
stat_done
return 0
fi
stat_fail
return 1
}
# usage : in_array( $needle, $haystack )
# return : 0 - found
# 1 - not found
# Copied from makepkg
in_array() {
[[ $2 ]] || return 1
local needle=$1; shift
local item
for item in "$@"; do
[[ ${item#@} = $needle ]] && return 0
done
return 1 # Not Found
}
# daemons:
add_daemon() {
[[ -d /run/daemons ]] || /bin/mkdir -p /run/daemons
> /run/daemons/"$1"
}
rm_daemon() {
/bin/rm -f /run/daemons/"$1"
}
ck_daemon() {
[[ ! -f /run/daemons/$1 ]]
}
# Check if $1 is a valid daemon name
have_daemon() {
[[ -f /etc/rc.d/$1 && -x /etc/rc.d/$1 ]]
}
# Check if $1 is started at boot
ck_autostart() {
local d
for d in "${DAEMONS[@]}"; do
[[ "$1" = ${d#@} ]] && return 1
done
return 0
}
start_daemon() {
have_daemon "$1" && /etc/rc.d/"$1" start
}
ck_depends() {
for daemon in "$@"; do
ck_daemon "$daemon" && start_daemon "$daemon"
done
}
start_daemon_bkgd() {
stat_bkgd "Starting $1"
have_daemon "$1" && (start_daemon "$1") &>/dev/null &
}
stop_daemon() {
have_daemon "$1" && /etc/rc.d/"$1" stop
}
# Status functions
status_started() {
deltext
echo -ne "$C_OTHER[${C_STRT}STARTED$C_OTHER]$C_CLEAR "
}
status_stopped() {
deltext
echo -ne "$C_OTHER[${C_STRT}STOPPED$C_OTHER]$C_CLEAR "
}
ck_status() {
if ! ck_daemon "$1"; then
status_started
else
status_stopped
fi
}
# PIDs to be omitted by killall5
declare -a omit_pids
add_omit_pids() {
omit_pids+=( $@ )
}
kill_everything() {
# $1 = where we are being called from.
# This is used to determine which hooks to run.
# Find daemons NOT in the DAEMONS array. Shut these down first
for daemon in /run/daemons/*; do
[[ -f $daemon ]] || continue
daemon=${daemon##*/}
in_array "$daemon" "${DAEMONS[@]}" || stop_daemon "$daemon"
done
# Shutdown daemons in reverse order
for ((i=${#DAEMONS[@]}-1; i>=0; i--)); do
[[ ${DAEMONS[$i]:0:1} = '!' ]] && continue
ck_daemon ${DAEMONS[$i]#@} || stop_daemon ${DAEMONS[$i]#@}
done
# Terminate all processes
stat_busy "Sending SIGTERM To Processes"
run_hook "$1_prekillall"
local pid k5args=""
for pid in ${omit_pids[@]}; do
k5args+=" -o $pid"
done
/sbin/killall5 -15 $k5args &> /dev/null
/bin/sleep 5
stat_done
stat_busy "Sending SIGKILL To Processes"
/sbin/killall5 -9 $k5args &> /dev/null
/bin/sleep 1
stat_done
run_hook "$1_postkillall"
}
activate_vgs() {
[[ $USELVM =~ yes|YES && -x /sbin/lvm && -d /sys/block ]] || return
# Kernel 2.6.x, LVM2 groups
/sbin/modprobe -q dm-mod 2>/dev/null
stat_busy "Activating LVM2 groups"
if /sbin/vgchange --sysinit -a y >/dev/null; then
stat_done
else
stat_fail
fi
}
# Arch cryptsetup packages traditionally contained the binaries
# /usr/sbin/cryptsetup
# /sbin/cryptsetup.static
# By default, initscripts used the /sbin/cryptsetup.static.
# Newer packages will only have /sbin/cryptsetup and no static binary
# This ensures maximal compatibility with the old and new layout
for CS in /sbin/cryptsetup /usr/sbin/cryptsetup \
/sbin/cryptsetup.static ''; do
[[ -x $CS ]] && break
done
read_crypttab() {
# $1 = function to call with the split out line from the crypttab
local line nspo failed=0
while read line; do
[[ $line && ${line:0:1} != '#' ]] || continue
eval nspo=("${line%#*}")
if $1 "${nspo[0]}" "${nspo[1]}" "${nspo[2]}" "${nspo[*]:3}"; then
crypto_unlocked=1
else
failed=1
fi
done < /etc/crypttab
return $failed
}
###############################
# Custom hooks in initscripts #
###############################
# Hooks can be used to include custom code in various places in the rc.* scripts
#
# Define a hook function in a functions.d file using:
# function_name() {
# ...
# }
# add_hook hook_name function_name
# It is allowed to register several hook functions for the same hook
# Is is also allowed to register the same hook function for several hooks
#
# Currently, the following hooks exist:
# sysinit_start: at the beginning of rc.sysinit
# multi_start: at the beginning of rc.multi
# single_start: at the beginning of rc.single
# shutdown_start: at the beginning of rc.shutdown
# sysinit_end: at the end of rc.sysinit
# multi_end: at the end of rc.multi
# single_end: at the end of rc.single
# sysinit_udevlaunched: after udev has been launched in rc.sysinit
# single_udevlaunched: after udev has been launched in rc.single
# sysinit_udevsettled: after uevents have settled in rc.sysinit
# single_udevsettled: after uevents have settled in rc.single
# sysinit_premount: before local filesystems are mounted, but after root is mounted read-write in rc.sysinit
# shutdown_prekillall: before all processes are being killed in rc.shutdown
# single_prekillall: before all processes are being killed in rc.single
# shutdown_postkillall: after all processes have been killed in rc.shutdown
# single_postkillall: after all processes have been killed in rc.single
# shutdown_poweroff: directly before powering off in rc.shutdown
#
# Declare add_hook and run_hook as read-only to prevent overwriting them.
# Too bad we cannot do the same thing with hook_funcs
if [[ $RC_FUNCTIONS_HOOK_FUNCS_DEFINED -ne 1 ]]; then
declare -A hook_funcs
add_hook() {
[[ $1 && $2 ]] || return 1
hook_funcs["$1"]+=" $2"
}
run_hook() {
[[ $1 ]] || return 1
local func
for func in ${hook_funcs["$1"]}; do
"${func}"
done
}
declare -fr add_hook run_hook
declare -r RC_FUNCTIONS_HOOK_FUNCS_DEFINED=1
fi
# Function for setting console font if required
set_consolefont() {
[[ $CONSOLEFONT ]] || return 0
stat_busy "Loading Console Font: $CONSOLEFONT"
#CONSOLEMAP in UTF-8 shouldn't be used
[[ $CONSOLEMAP && ${LOCALE,,} =~ utf ]] && CONSOLEMAP=""
for i in /dev/tty[0-9]*; do
/usr/bin/setfont ${CONSOLEMAP:+-m ${CONSOLEMAP}} \
$CONSOLEFONT -C ${i} >/dev/null 2>&1
done
if (($? != 0)); then
stat_fail
elif [[ $CONSOLEMAP ]]; then
cat <<"EOF" >>/etc/profile.d/locale.sh
if [ "$CONSOLE" = "" -a "$TERM" = "linux" -a -t 1 ]; then printf "\033(K"; fi
EOF
stat_done
else
stat_done
fi
}
# Source additional functions at the end to allow overrides
for f in /etc/rc.d/functions.d/*; do
[[ -e $f ]] && . "$f"
done
# End of file
# vim: set ts=2 sw=2 noet: