RHEL 6 /etc/rc.d/init.d/functions from initscripts-9.03.61-1.el6.centos.x86_64
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*-Shell-script-*- | |
# | |
# functions This file contains functions to be used by most or all | |
# shell scripts in the /etc/init.d directory. | |
# | |
TEXTDOMAIN=initscripts | |
# Make sure umask is sane | |
umask 022 | |
# Set up a default search path. | |
PATH="/sbin:/usr/sbin:/bin:/usr/bin" | |
export PATH | |
# Get a sane screen width | |
[ -z "${COLUMNS:-}" ] && COLUMNS=80 | |
[ -z "${CONSOLETYPE:-}" ] && CONSOLETYPE="$(/sbin/consoletype)" | |
if [ -f /etc/sysconfig/i18n -a -z "${NOLOCALE:-}" -a -z "${LANGSH_SOURCED:-}" ] ; then | |
. /etc/profile.d/lang.sh 2>/dev/null | |
# avoid propagating LANGSH_SOURCED any further | |
unset LANGSH_SOURCED | |
fi | |
# Read in our configuration | |
if [ -z "${BOOTUP:-}" ]; then | |
if [ -f /etc/sysconfig/init ]; then | |
. /etc/sysconfig/init | |
else | |
# This all seem confusing? Look in /etc/sysconfig/init, | |
# or in /usr/doc/initscripts-*/sysconfig.txt | |
BOOTUP=color | |
RES_COL=60 | |
MOVE_TO_COL="echo -en \\033[${RES_COL}G" | |
SETCOLOR_SUCCESS="echo -en \\033[1;32m" | |
SETCOLOR_FAILURE="echo -en \\033[1;31m" | |
SETCOLOR_WARNING="echo -en \\033[1;33m" | |
SETCOLOR_NORMAL="echo -en \\033[0;39m" | |
LOGLEVEL=1 | |
fi | |
if [ "$CONSOLETYPE" = "serial" ]; then | |
BOOTUP=serial | |
MOVE_TO_COL= | |
SETCOLOR_SUCCESS= | |
SETCOLOR_FAILURE= | |
SETCOLOR_WARNING= | |
SETCOLOR_NORMAL= | |
fi | |
fi | |
# Interpret escape sequences in an fstab entry | |
fstab_decode_str() { | |
fstab-decode echo "$1" | |
} | |
# Check if any of $pid (could be plural) are running | |
checkpid() { | |
local i | |
for i in $* ; do | |
[ -d "/proc/$i" ] && return 0 | |
done | |
return 1 | |
} | |
__readlink() { | |
ls -bl "$@" 2>/dev/null| awk '{ print $NF }' | |
} | |
__fgrep() { | |
s=$1 | |
f=$2 | |
while read line; do | |
if strstr "$line" "$s"; then | |
echo $line | |
return 0 | |
fi | |
done < $f | |
return 1 | |
} | |
__kill_pids_term_kill_checkpids() { | |
local base_stime=$1 | |
shift 1 | |
local pid= | |
local pids=$* | |
local remaining= | |
local stat= | |
local stime= | |
for pid in $pids ; do | |
[ -e "/proc/$pid" ] || continue | |
read -r line < "/proc/$pid/stat" 2> /dev/null || continue | |
stat=($line) | |
stime=${stat[21]} | |
[ -n "$stime" ] && [ "$base_stime" -lt "$stime" ] && continue | |
remaining+="$pid " | |
done | |
echo "$remaining" | |
[ -n "$remaining" ] && return 1 | |
return 0 | |
} | |
__kill_pids_term_kill() { | |
local try=0 | |
local delay=3; | |
local pid= | |
local stat= | |
local base_stime= | |
# We can't initialize stat & base_stime on the same line where 'local' | |
# keyword is, otherwise the sourcing of this file will fail for ksh... | |
stat=($(< /proc/self/stat)) | |
base_stime=${stat[21]} | |
if [ "$1" = "-d" ]; then | |
delay=$2 | |
shift 2 | |
fi | |
local kill_list=$* | |
kill_list=$(__kill_pids_term_kill_checkpids $base_stime $kill_list) | |
[ -z "$kill_list" ] && return 0 | |
kill -TERM $kill_list >/dev/null 2>&1 | |
usleep 100000 | |
kill_list=$(__kill_pids_term_kill_checkpids $base_stime $kill_list) | |
if [ -n "$kill_list" ] ; then | |
while [ $try -lt $delay ] ; do | |
sleep 1 | |
kill_list=$(__kill_pids_term_kill_checkpids $base_stime $kill_list) | |
[ -z "$kill_list" ] && break | |
let try+=1 | |
done | |
if [ -n "$kill_list" ] ; then | |
kill -KILL $kill_list >/dev/null 2>&1 | |
usleep 100000 | |
kill_list=$(__kill_pids_term_kill_checkpids $base_stime $kill_list) | |
fi | |
fi | |
[ -n "$kill_list" ] && return 1 | |
return 0 | |
} | |
# __umount_loop awk_program fstab_file first_msg retry_msg retry_umount_args | |
# awk_program should process fstab_file and return a list of fstab-encoded | |
# paths; it doesn't have to handle comments in fstab_file. | |
__umount_loop() { | |
local remaining sig= | |
local retry=3 count | |
remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r) | |
while [ -n "$remaining" -a "$retry" -gt 0 ]; do | |
if [ "$retry" -eq 3 ]; then | |
action "$3" fstab-decode umount $remaining | |
else | |
action "$4" fstab-decode umount $5 $remaining | |
fi | |
count=4 | |
remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r) | |
while [ "$count" -gt 0 ]; do | |
[ -z "$remaining" ] && break | |
count=$(($count-1)) | |
usleep 500000 | |
remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r) | |
done | |
[ -z "$remaining" ] && break | |
kill $sig $(fstab-decode /sbin/fuser -m $remaining 2>/dev/null | sed -e "s/\b$$\b//g") > /dev/null | |
sleep 3 | |
retry=$(($retry -1)) | |
sig=-9 | |
done | |
} | |
# Similar to __umount loop above, without calling fuser | |
__umount_loop_2() { | |
local remaining= | |
local count | |
local kill_list | |
#call regular umount | |
remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r) | |
action "$3" fstab-decode umount $remaining | |
count=4 | |
remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r) | |
while [ "$count" -gt 0 ]; do | |
[ -z "$remaining" ] && break | |
count=$(($count-1)) | |
usleep 500000 | |
remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r) | |
done | |
[ -z "$remaining" ] && return 0 | |
devs=$(stat -c "%d" $remaining) | |
action "$4" fstab-decode umount "-l" $remaining | |
# find fds that don't start with /, are not sockets or pipes or other. | |
# these are potentially detached fds | |
detached_fds=$(find /proc/ -regex '/proc/[0-9]+/fd/.*' -printf "%p %l\n" 2>/dev/null |\ | |
grep -Ev '/proc/[0-9]+/fd/[0-9]+ (/.*|inotify|\[.+\]|(socket|pipe):\[[0-9]+\])') | |
# check each detached fd to see if it has the same device | |
# as one of our lazy umounted filesystems | |
kill_list= | |
[ -n "$detached_fds" ] && while read fdline; do | |
fd=${fdline%% *} | |
pid=$(echo $fdline | sed -r 's/\/proc\/([0-9]+).+/\1/') | |
fd_dev=$(stat -L -c "%d" $fd) | |
for dev in $devs ; do | |
[ "$dev" = "$fd_dev" ] && kill_list+="$pid " | |
done | |
done <<< "$detached_fds" | |
if [ -n "$kill_list" ] ; then | |
STRING=$"Killing processes with open filedescriptors on the unmounted disk:" | |
__kill_pids_term_kill $kill_list && success "$STRING" || failure "$STRING" | |
echo | |
fi | |
} | |
__source_netdevs_fstab() { | |
NFSFSTAB=$(LC_ALL=C awk '!/^#/ && $3 ~ /^nfs/ && $3 != "nfsd" && $4 !~ /noauto/ { print $2 }' /etc/fstab) | |
CIFSFSTAB=$(LC_ALL=C awk '!/^#/ && $3 == "cifs" && $4 !~ /noauto/ { print $2 }' /etc/fstab) | |
NCPFSTAB=$(LC_ALL=C awk '!/^#/ && $3 == "ncpfs" && $4 !~ /noauto/ { print $2 }' /etc/fstab) | |
GLUSTERFSFSTAB=$(LC_ALL=C awk '!/^#/ && $3 == "glusterfs" && $4 !~ /noauto/ { print $2 }' /etc/fstab) | |
NETDEVFSTAB=$(LC_ALL=C awk '!/^#/ && $4 ~/_netdev/ && $4 !~ /noauto/ { print $1 }' /etc/fstab) | |
} | |
__source_netdevs_mtab() { | |
NFSMTAB=$(LC_ALL=C awk '$3 ~ /^nfs/ && $3 != "nfsd" && $2 != "/" { print $2 }' /proc/mounts) | |
CIFSMTAB=$(LC_ALL=C awk '$3 == "cifs" { print $2 }' /proc/mounts) | |
NCPMTAB=$(LC_ALL=C awk '$3 == "ncpfs" { print $2 }' /proc/mounts) | |
GLUSTERFSMTAB=$(LC_ALL=C awk '$3 == "fuse.glusterfs" { print $2 }' /proc/mounts) | |
NETDEVMTAB=$(LC_ALL=C awk '$4 ~ /_netdev/ && $2 != "/" { print $2 }' /etc/mtab) | |
ALLNETDEVMTAB="$NFSMTAB $CIFSMTAB $NCPMTAB $GLUSTERFSMTAB $NETDEVMTAB" | |
} | |
# Similar to __umount loop above, specialized for loopback devices | |
__umount_loopback_loop() { | |
local remaining devremaining sig= | |
local retry=3 | |
__find_mounts() { | |
if [ "$1" = "--netdev" ] ; then | |
__source_netdevs_mtab | |
remaining= | |
devremaining= | |
local mount= netdev= _rest | |
while read -r dev mount _rest ; do | |
[ "$dev" = "${dev##/dev/loop}" ] && continue | |
local back_file=$(losetup $dev | sed -e 's/^\/dev\/loop[0-9]\+: \[[0-9a-f]\+\]:[0-9]\+ (\(.*\))$/\1/') | |
for netdev in $ALLNETDEVMTAB ; do | |
local netdev_decoded= | |
netdev="${netdev}/" | |
netdev_decoded=$(fstab_decode_str ${netdev}) | |
if [ "$mount" != "${mount##$netdev}" ] || [ "$back_file" != "${back_file##$netdev_decoded}" ] ; then | |
remaining="$remaining $mount" | |
#device might be mounted in other location, | |
#but then losetup -d will be noop, so meh | |
devremaining="$devremaining $dev" | |
continue 2 | |
fi | |
done | |
done < /proc/mounts | |
else | |
remaining=$(awk '$1 ~ /^\/dev\/loop/ && $2 != "/" {print $2}' /proc/mounts) | |
devremaining=$(awk '$1 ~ /^\/dev\/loop/ && $2 != "/" {print $1}' /proc/mounts) | |
fi | |
} | |
__find_mounts $1 | |
while [ -n "$remaining" -a "$retry" -gt 0 ]; do | |
if [ "$retry" -eq 3 ]; then | |
action $"Unmounting loopback filesystems: " \ | |
fstab-decode umount $remaining | |
else | |
action $"Unmounting loopback filesystems (retry):" \ | |
fstab-decode umount $remaining | |
fi | |
for dev in $devremaining ; do | |
if [ "$1" = "--netdev" ] ; then | |
#some loopdevices might be mounted on top of non-netdev | |
#so ignore failures | |
losetup -d $dev > /dev/null 2>&1 | |
else | |
losetup $dev > /dev/null 2>&1 && \ | |
action $"Detaching loopback device $dev: " \ | |
losetup -d $dev | |
fi | |
done | |
#check what is still mounted | |
__find_mounts $1 | |
[ -z "$remaining" ] && break | |
fstab-decode /sbin/fuser -k -m $sig $remaining >/dev/null | |
sleep 3 | |
retry=$(($retry -1)) | |
sig=-9 | |
done | |
} | |
# __proc_pids {program} [pidfile] | |
# Set $pid to pids from /var/run* for {program}. $pid should be declared | |
# local in the caller. | |
# Returns LSB exit code for the 'status' action. | |
__pids_var_run() { | |
local base=${1##*/} | |
local pid_file=${2:-/var/run/$base.pid} | |
local pid_dir=$(/usr/bin/dirname $pid_file) | |
local binary=$3 | |
[ -d "$pid_dir" -a ! -r "$pid_dir" ] && return 4 | |
pid= | |
if [ -f "$pid_file" ] ; then | |
local line p | |
[ ! -r "$pid_file" ] && return 4 # "user had insufficient privilege" | |
while : ; do | |
read line | |
[ -z "$line" ] && break | |
for p in $line ; do | |
if [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] ; then | |
if [ -n "$binary" ] ; then | |
local b=$(readlink /proc/$p/exe | sed -e 's/\s*(deleted)$//') | |
[ "$b" != "$binary" ] && continue | |
fi | |
pid="$pid $p" | |
fi | |
done | |
done < "$pid_file" | |
if [ -n "$pid" ]; then | |
return 0 | |
fi | |
return 1 # "Program is dead and /var/run pid file exists" | |
fi | |
return 3 # "Program is not running" | |
} | |
# Output PIDs of matching processes, found using pidof | |
__pids_pidof() { | |
pidof -c -m -o $$ -o $PPID -o %PPID -x "$1" || \ | |
pidof -c -m -o $$ -o $PPID -o %PPID -x "${1##*/}" | |
} | |
# A function to start a program. | |
daemon() { | |
# Test syntax. | |
local gotbase= force= nicelevel corelimit | |
local pid base= user= nice= bg= pid_file= | |
local cgroup= | |
nicelevel=0 | |
while [ "$1" != "${1##[-+]}" ]; do | |
case $1 in | |
'') echo $"$0: Usage: daemon [+/-nicelevel] {program}" "[arg1]..." | |
return 1;; | |
--check) | |
base=$2 | |
gotbase="yes" | |
shift 2 | |
;; | |
--check=?*) | |
base=${1#--check=} | |
gotbase="yes" | |
shift | |
;; | |
--user) | |
user=$2 | |
shift 2 | |
;; | |
--user=?*) | |
user=${1#--user=} | |
shift | |
;; | |
--pidfile) | |
pid_file=$2 | |
shift 2 | |
;; | |
--pidfile=?*) | |
pid_file=${1#--pidfile=} | |
shift | |
;; | |
--force) | |
force="force" | |
shift | |
;; | |
[-+][0-9]*) | |
nice="nice -n $1" | |
shift | |
;; | |
*) echo $"$0: Usage: daemon [+/-nicelevel] {program}" "[arg1]..." | |
return 1;; | |
esac | |
done | |
# Save basename. | |
[ -z "$gotbase" ] && base=${1##*/} | |
# See if it's already running. Look *only* at the pid file. | |
__pids_var_run "$base" "$pid_file" | |
[ -n "$pid" -a -z "$force" ] && return | |
# make sure it doesn't core dump anywhere unless requested | |
corelimit="ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0}" | |
# if they set NICELEVEL in /etc/sysconfig/foo, honor it | |
[ -n "${NICELEVEL:-}" ] && nice="nice -n $NICELEVEL" | |
# if they set CGROUP_DAEMON in /etc/sysconfig/foo, honor it | |
if [ -n "${CGROUP_DAEMON}" ]; then | |
if [ ! -x /bin/cgexec ]; then | |
echo -n "Cgroups not installed"; warning | |
echo | |
else | |
cgroup="/bin/cgexec"; | |
for i in $CGROUP_DAEMON; do | |
cgroup="$cgroup -g $i"; | |
done | |
fi | |
fi | |
# Echo daemon | |
[ "${BOOTUP:-}" = "verbose" -a -z "${LSB:-}" ] && echo -n " $base" | |
# And start it up. | |
if [ -z "$user" ]; then | |
$cgroup $nice /bin/bash -c "$corelimit >/dev/null 2>&1 ; $*" | |
else | |
$cgroup $nice runuser -s /bin/bash $user -c "$corelimit >/dev/null 2>&1 ; $*" | |
fi | |
[ "$?" -eq 0 ] && success $"$base startup" || failure $"$base startup" | |
} | |
# A function to stop a program. | |
killproc() { | |
local RC killlevel= base pid pid_file= delay try binary= | |
RC=0; delay=3; try=0 | |
# Test syntax. | |
if [ "$#" -eq 0 ]; then | |
echo $"Usage: killproc [-p pidfile] [ -d delay] {program} [-signal]" | |
return 1 | |
fi | |
if [ "$1" = "-p" ]; then | |
pid_file=$2 | |
shift 2 | |
fi | |
if [ "$1" = "-b" ]; then | |
if [ -z $pid_file ]; then | |
echo $"-b option can be used only with -p" | |
echo $"Usage: killproc -p pidfile -b binary program" | |
return 1 | |
fi | |
binary=$2 | |
shift 2 | |
fi | |
if [ "$1" = "-d" ]; then | |
delay=$(echo $2 | awk -v RS=' ' -v IGNORECASE=1 '{if($1!~/^[0-9.]+[smhd]?$/) exit 1;d=$1~/s$|^[0-9.]*$/?1:$1~/m$/?60:$1~/h$/?60*60:$1~/d$/?24*60*60:-1;if(d==-1) exit 1;delay+=d*$1} END {printf("%d",delay+0.5)}') | |
if [ "$?" -eq 1 ]; then | |
echo $"Usage: killproc [-p pidfile] [ -d delay] {program} [-signal]" | |
return 1 | |
fi | |
shift 2 | |
fi | |
# check for second arg to be kill level | |
[ -n "${2:-}" ] && killlevel=$2 | |
# Save basename. | |
base=${1##*/} | |
# Find pid. | |
__pids_var_run "$1" "$pid_file" "$binary" | |
RC=$? | |
if [ -z "$pid" ]; then | |
if [ -z "$pid_file" ]; then | |
pid="$(__pids_pidof "$1")" | |
else | |
[ "$RC" = "4" ] && { failure $"$base shutdown" ; return $RC ;} | |
fi | |
fi | |
# Kill it. | |
if [ -n "$pid" ] ; then | |
[ "$BOOTUP" = "verbose" -a -z "${LSB:-}" ] && echo -n "$base " | |
if [ -z "$killlevel" ] ; then | |
__kill_pids_term_kill -d $delay $pid | |
RC=$? | |
[ "$RC" -eq 0 ] && success $"$base shutdown" || failure $"$base shutdown" | |
# use specified level only | |
else | |
if checkpid $pid; then | |
kill $killlevel $pid >/dev/null 2>&1 | |
RC=$? | |
[ "$RC" -eq 0 ] && success $"$base $killlevel" || failure $"$base $killlevel" | |
elif [ -n "${LSB:-}" ]; then | |
RC=7 # Program is not running | |
fi | |
fi | |
else | |
if [ -n "${LSB:-}" -a -n "$killlevel" ]; then | |
RC=7 # Program is not running | |
else | |
failure $"$base shutdown" | |
RC=0 | |
fi | |
fi | |
# Remove pid file if any. | |
if [ -z "$killlevel" ]; then | |
rm -f "${pid_file:-/var/run/$base.pid}" | |
fi | |
return $RC | |
} | |
# A function to find the pid of a program. Looks *only* at the pidfile | |
pidfileofproc() { | |
local pid | |
# Test syntax. | |
if [ "$#" = 0 ] ; then | |
echo $"Usage: pidfileofproc {program}" | |
return 1 | |
fi | |
__pids_var_run "$1" | |
[ -n "$pid" ] && echo $pid | |
return 0 | |
} | |
# A function to find the pid of a program. | |
pidofproc() { | |
local RC pid pid_file= | |
# Test syntax. | |
if [ "$#" = 0 ]; then | |
echo $"Usage: pidofproc [-p pidfile] {program}" | |
return 1 | |
fi | |
if [ "$1" = "-p" ]; then | |
pid_file=$2 | |
shift 2 | |
fi | |
fail_code=3 # "Program is not running" | |
# First try "/var/run/*.pid" files | |
__pids_var_run "$1" "$pid_file" | |
RC=$? | |
if [ -n "$pid" ]; then | |
echo $pid | |
return 0 | |
fi | |
[ -n "$pid_file" ] && return $RC | |
__pids_pidof "$1" || return $RC | |
} | |
status() { | |
local base pid lock_file= pid_file= binary= | |
# Test syntax. | |
if [ "$#" = 0 ] ; then | |
echo $"Usage: status [-p pidfile] {program}" | |
return 1 | |
fi | |
if [ "$1" = "-p" ]; then | |
pid_file=$2 | |
shift 2 | |
fi | |
if [ "$1" = "-l" ]; then | |
lock_file=$2 | |
shift 2 | |
fi | |
if [ "$1" = "-b" ]; then | |
if [ -z $pid_file ]; then | |
echo $"-b option can be used only with -p" | |
echo $"Usage: status -p pidfile -b binary program" | |
return 1 | |
fi | |
binary=$2 | |
shift 2 | |
fi | |
base=${1##*/} | |
# First try "pidof" | |
__pids_var_run "$1" "$pid_file" "$binary" | |
RC=$? | |
if [ -z "$pid_file" -a -z "$pid" ]; then | |
pid="$(__pids_pidof "$1")" | |
fi | |
if [ -n "$pid" ]; then | |
echo $"${base} (pid $pid) is running..." | |
return 0 | |
fi | |
case "$RC" in | |
0) | |
echo $"${base} (pid $pid) is running..." | |
return 0 | |
;; | |
1) | |
echo $"${base} dead but pid file exists" | |
return 1 | |
;; | |
4) | |
echo $"${base} status unknown due to insufficient privileges." | |
return 4 | |
;; | |
esac | |
if [ -z "${lock_file}" ]; then | |
lock_file=${base} | |
fi | |
# See if /var/lock/subsys/${lock_file} exists | |
if [ -f /var/lock/subsys/${lock_file} ]; then | |
echo $"${base} dead but subsys locked" | |
return 2 | |
fi | |
echo $"${base} is stopped" | |
return 3 | |
} | |
echo_success() { | |
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL | |
echo -n "[" | |
[ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS | |
echo -n $" OK " | |
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL | |
echo -n "]" | |
echo -ne "\r" | |
return 0 | |
} | |
echo_failure() { | |
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL | |
echo -n "[" | |
[ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE | |
echo -n $"FAILED" | |
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL | |
echo -n "]" | |
echo -ne "\r" | |
return 1 | |
} | |
echo_passed() { | |
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL | |
echo -n "[" | |
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING | |
echo -n $"PASSED" | |
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL | |
echo -n "]" | |
echo -ne "\r" | |
return 1 | |
} | |
echo_warning() { | |
[ "$BOOTUP" = "color" ] && $MOVE_TO_COL | |
echo -n "[" | |
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING | |
echo -n $"WARNING" | |
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL | |
echo -n "]" | |
echo -ne "\r" | |
return 1 | |
} | |
# Inform the graphical boot of our current state | |
update_boot_stage() { | |
if [ -x /bin/plymouth ]; then | |
/bin/plymouth --update="$1" | |
fi | |
return 0 | |
} | |
# Log that something succeeded | |
success() { | |
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_success | |
return 0 | |
} | |
# Log that something failed | |
failure() { | |
local rc=$? | |
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_failure | |
[ -x /bin/plymouth ] && /bin/plymouth --details | |
return $rc | |
} | |
# Log that something passed, but may have had errors. Useful for fsck | |
passed() { | |
local rc=$? | |
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_passed | |
return $rc | |
} | |
# Log a warning | |
warning() { | |
local rc=$? | |
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_warning | |
return $rc | |
} | |
# Run some action. Log its output. | |
action() { | |
local STRING rc | |
STRING=$1 | |
echo -n "$STRING " | |
shift | |
"$@" && success $"$STRING" || failure $"$STRING" | |
rc=$? | |
echo | |
return $rc | |
} | |
# Run some action. Silently. | |
action_silent() { | |
local STRING rc | |
STRING=$1 | |
echo -n "$STRING " | |
shift | |
"$@" >/dev/null && success $"$STRING" || failure $"$STRING" | |
rc=$? | |
echo | |
return $rc | |
} | |
# returns OK if $1 contains $2 | |
strstr() { | |
[ "${1#*$2*}" = "$1" ] && return 1 | |
return 0 | |
} | |
# Confirm whether we really want to run this service | |
confirm() { | |
[ -x /bin/plymouth ] && /bin/plymouth --hide-splash | |
while : ; do | |
echo -n $"Start service $1 (Y)es/(N)o/(C)ontinue? [Y] " | |
read answer | |
if strstr $"yY" "$answer" || [ "$answer" = "" ] ; then | |
return 0 | |
elif strstr $"cC" "$answer" ; then | |
rm -f /var/run/confirm | |
[ -x /bin/plymouth ] && /bin/plymouth --show-splash | |
return 2 | |
elif strstr $"nN" "$answer" ; then | |
return 1 | |
fi | |
done | |
} | |
# resolve a device node to its major:minor numbers in decimal or hex | |
get_numeric_dev() { | |
( | |
fmt="%d:%d" | |
if [ "$1" == "hex" ]; then | |
fmt="%x:%x" | |
fi | |
ls -lH "$2" | awk '{ sub(/,/, "", $5); printf("'"$fmt"'", $5, $6); }' | |
) 2>/dev/null | |
} | |
# Check whether file $1 is a backup or rpm-generated file and should be ignored | |
is_ignored_file() { | |
case "$1" in | |
*~ | *.bak | *.orig | *.rpmnew | *.rpmorig | *.rpmsave) | |
return 0 | |
;; | |
esac | |
return 1 | |
} | |
# Evaluate shvar-style booleans | |
is_true() { | |
case "$1" in | |
[tT] | [yY] | [yY][eE][sS] | [tT][rR][uU][eE] | 1) | |
return 0 | |
;; | |
esac | |
return 1 | |
} | |
# Evaluate shvar-style booleans | |
is_false() { | |
case "$1" in | |
[fF] | [nN] | [nN][oO] | [fF][aA][lL][sS][eE] | 0) | |
return 0 | |
;; | |
esac | |
return 1 | |
} | |
# Apply sysctl settings, including files in /etc/sysctl.d | |
apply_sysctl() { | |
sysctl -e -p /etc/sysctl.conf >/dev/null 2>&1 | |
for file in /etc/sysctl.d/* ; do | |
is_ignored_file "$file" && continue | |
test -f "$file" && sysctl -e -p "$file" >/dev/null 2>&1 | |
done | |
} | |
key_is_random() { | |
[ "$1" = "/dev/urandom" -o "$1" = "/dev/hw_random" \ | |
-o "$1" = "/dev/random" ] | |
} | |
find_crypto_mount_point() { | |
local fs_spec fs_file fs_vfstype remaining_fields | |
local fs | |
while read fs_spec fs_file remaining_fields; do | |
if [ "$fs_spec" = "/dev/mapper/$1" ]; then | |
echo $fs_file | |
break; | |
fi | |
done < /etc/fstab | |
} | |
# Because of a chicken/egg problem, init_crypto must be run twice. /var may be | |
# encrypted but /var/lib/random-seed is needed to initialize swap. | |
init_crypto() { | |
local have_random dst src key opt mode owner params makeswap skip arg opt | |
local param value rc ret mke2fs mdir prompt mount_point | |
ret=0 | |
have_random=$1 | |
while read dst src key opt; do | |
[ -z "$dst" -o "${dst#\#}" != "$dst" ] && continue | |
[ -b "/dev/mapper/$dst" ] && continue; | |
if [ "$have_random" = 0 ] && key_is_random "$key"; then | |
continue | |
fi | |
if [ -n "$key" -a "x$key" != "xnone" ]; then | |
if test -e "$key" ; then | |
owner=$(ls -l $key | (read a b owner rest; echo $owner)) | |
if ! key_is_random "$key"; then | |
mode=$(ls -l "$key" | cut -c 5-10) | |
if [ "$mode" != "------" ]; then | |
echo $"INSECURE MODE FOR $key" | |
fi | |
fi | |
if [ "$owner" != root ]; then | |
echo $"INSECURE OWNER FOR $key" | |
fi | |
else | |
echo $"Key file for $dst not found, skipping" | |
ret=1 | |
continue | |
fi | |
else | |
key="" | |
fi | |
params="" | |
makeswap="" | |
mke2fs="" | |
skip="" | |
# Parse the src field for UUID= and convert to real device names | |
if [ "${src%%=*}" == "UUID" ]; then | |
src=$(/sbin/blkid -t "$src" -l -o device) | |
elif [ "${src/^\/dev\/disk\/by-uuid\/}" != "$src" ]; then | |
src=$(__readlink $src) | |
fi | |
# Is it a block device? | |
[ -b "$src" ] || continue | |
# Is it already a device mapper slave? (this is gross) | |
devesc=${src##/dev/} | |
devesc=${devesc//\//!} | |
for d in /sys/block/dm-*/slaves ; do | |
[ -e $d/$devesc ] && continue 2 | |
done | |
# Parse the options field, convert to cryptsetup parameters and | |
# contruct the command line | |
while [ -n "$opt" ]; do | |
arg=${opt%%,*} | |
opt=${opt##$arg} | |
opt=${opt##,} | |
param=${arg%%=*} | |
value=${arg##$param=} | |
case "$param" in | |
cipher) | |
params="$params -c $value" | |
if [ -z "$value" ]; then | |
echo $"$dst: no value for cipher option, skipping" | |
skip="yes" | |
fi | |
;; | |
size) | |
params="$params -s $value" | |
if [ -z "$value" ]; then | |
echo $"$dst: no value for size option, skipping" | |
skip="yes" | |
fi | |
;; | |
hash) | |
params="$params -h $value" | |
if [ -z "$value" ]; then | |
echo $"$dst: no value for hash option, skipping" | |
skip="yes" | |
fi | |
;; | |
verify) | |
params="$params -y" | |
;; | |
swap) | |
makeswap=yes | |
;; | |
tmp) | |
mke2fs=yes | |
esac | |
done | |
if [ "$skip" = "yes" ]; then | |
ret=1 | |
continue | |
fi | |
if [ -z "$makeswap" ] && cryptsetup isLuks "$src" 2>/dev/null ; then | |
if key_is_random "$key"; then | |
echo $"$dst: LUKS requires non-random key, skipping" | |
ret=1 | |
continue | |
fi | |
if [ -n "$params" ]; then | |
echo "$dst: options are invalid for LUKS partitions," \ | |
"ignoring them" | |
fi | |
if [ -n "$key" ]; then | |
/sbin/cryptsetup -d $key luksOpen "$src" "$dst" <&1 2>/dev/null && success || failure | |
rc=$? | |
else | |
mount_point="$(find_crypto_mount_point $dst)" | |
[ -n "$mount_point" ] || mount_point=${src##*/} | |
prompt=$(printf $"%s is password protected" "$mount_point") | |
plymouth ask-for-password --prompt "$prompt" --command="/sbin/cryptsetup luksOpen -T1 $src $dst" <&1 | |
rc=$? | |
fi | |
else | |
[ -z "$key" ] && plymouth --hide-splash | |
/sbin/cryptsetup $params ${key:+-d $key} create "$dst" "$src" <&1 && success || failure | |
rc=$? | |
[ -z "$key" ] && plymouth --show-splash | |
fi | |
if [ $rc -ne 0 ]; then | |
ret=1 | |
continue | |
fi | |
if [ -b "/dev/mapper/$dst" ]; then | |
if [ "$makeswap" = "yes" ]; then | |
mkswap "/dev/mapper/$dst" 2>/dev/null >/dev/null | |
fi | |
if [ "$mke2fs" = "yes" ]; then | |
if mke2fs "/dev/mapper/$dst" 2>/dev/null >/dev/null \ | |
&& mdir=$(mktemp -d /tmp/mountXXXXXX); then | |
mount "/dev/mapper/$dst" "$mdir" && chmod 1777 "$mdir" | |
umount "$mdir" | |
rmdir "$mdir" | |
fi | |
fi | |
fi | |
done < /etc/crypttab | |
return $ret | |
} | |
# A sed expression to filter out the files that is_ignored_file recognizes | |
__sed_discard_ignored_files='/\(~\|\.bak\|\.orig\|\.rpmnew\|\.rpmorig\|\.rpmsave\)$/d' | |
#if we have privileges lets log to kmsg, otherwise to stderr | |
if strstr "$(cat /proc/cmdline)" "rc.debug"; then | |
[ -w /dev/kmsg ] && exec 30>/dev/kmsg && BASH_XTRACEFD=30 | |
set -x | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment