You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
824 lines
20 KiB
824 lines
20 KiB
#!/bin/sh |
|
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- |
|
# ex: ts=8 sw=4 sts=4 et filetype=sh |
|
|
|
# returns OK if $1 contains $2 |
|
strstr() { |
|
[ "${1#*$2*}" != "$1" ] |
|
} |
|
|
|
# returns OK if $1 contains $2 at the beginning |
|
str_starts() { |
|
[ "${1#$2*}" != "$1" ] |
|
} |
|
|
|
# replaces all occurrences of 'search' in 'str' with 'replacement' |
|
# |
|
# str_replace str search replacement |
|
# |
|
# example: |
|
# str_replace ' one two three ' ' ' '_' |
|
str_replace() { |
|
local in="$1"; local s="$2"; local r="$3" |
|
local out='' |
|
|
|
while strstr "${in}" "$s"; do |
|
chop="${in%%$s*}" |
|
out="${out}${chop}$r" |
|
in="${in#*$s}" |
|
done |
|
echo "${out}${in}" |
|
} |
|
|
|
_getcmdline() { |
|
local _line |
|
local _i |
|
unset _line |
|
if [ -z "$CMDLINE" ]; then |
|
if [ -e /etc/cmdline ]; then |
|
while read -r _line; do |
|
CMDLINE_ETC="$CMDLINE_ETC $_line"; |
|
done </etc/cmdline; |
|
fi |
|
for _i in /etc/cmdline.d/*.conf; do |
|
[ -e "$_i" ] || continue |
|
while read -r _line; do |
|
CMDLINE_ETC_D="$CMDLINE_ETC_D $_line"; |
|
done <"$_i"; |
|
done |
|
read -r CMDLINE </proc/cmdline; |
|
CMDLINE="$CMDLINE_ETC_D $CMDLINE_ETC $CMDLINE" |
|
fi |
|
} |
|
|
|
_dogetarg() { |
|
local _o _val _doecho |
|
unset _val |
|
unset _o |
|
unset _doecho |
|
_getcmdline |
|
|
|
for _o in $CMDLINE; do |
|
if [ "${_o%%=*}" = "${1%%=*}" ]; then |
|
if [ -n "${1#*=}" -a "${1#*=*}" != "${1}" ]; then |
|
# if $1 has a "=<value>", we want the exact match |
|
if [ "$_o" = "$1" ]; then |
|
_val="1"; |
|
unset _doecho |
|
fi |
|
continue |
|
fi |
|
|
|
if [ "${_o#*=}" = "$_o" ]; then |
|
# if cmdline argument has no "=<value>", we assume "=1" |
|
_val="1"; |
|
unset _doecho |
|
continue |
|
fi |
|
|
|
_val=${_o#*=}; |
|
_doecho=1 |
|
fi |
|
done |
|
if [ -n "$_val" ]; then |
|
[ "x$_doecho" != "x" ] && echo "$_val"; |
|
return 0; |
|
fi |
|
return 1; |
|
} |
|
|
|
getarg() { |
|
set +x |
|
while [ $# -gt 0 ]; do |
|
case $1 in |
|
-y) if _dogetarg $2 >/dev/null; then |
|
echo 1 |
|
[ "$RD_DEBUG" = "yes" ] && set -x |
|
return 0 |
|
fi |
|
shift 2;; |
|
-n) if _dogetarg $2 >/dev/null; then |
|
echo 0; |
|
[ "$RD_DEBUG" = "yes" ] && set -x |
|
return 1 |
|
fi |
|
shift 2;; |
|
*) if _dogetarg $1; then |
|
[ "$RD_DEBUG" = "yes" ] && set -x |
|
return 0; |
|
fi |
|
shift;; |
|
esac |
|
done |
|
[ "$RD_DEBUG" = "yes" ] && set -x |
|
return 1 |
|
} |
|
|
|
getargbool() { |
|
local _b |
|
unset _b |
|
local _default |
|
_default=$1; shift |
|
_b=$(getarg "$@") |
|
[ $? -ne 0 -a -z "$_b" ] && _b=$_default |
|
if [ -n "$_b" ]; then |
|
[ $_b = "0" ] && return 1 |
|
[ $_b = "no" ] && return 1 |
|
[ $_b = "off" ] && return 1 |
|
fi |
|
return 0 |
|
} |
|
|
|
_dogetargs() { |
|
set +x |
|
local _o _found _key |
|
unset _o |
|
unset _found |
|
_getcmdline |
|
_key=$1 |
|
set -- |
|
for _o in $CMDLINE; do |
|
if [ "$_o" = "$_key" ]; then |
|
_found=1; |
|
elif [ "${_o%%=*}" = "${_key%=}" ]; then |
|
[ -n "${_o%%=*}" ] && set -- "$@" "${_o#*=}"; |
|
_found=1; |
|
fi |
|
done |
|
if [ -n "$_found" ]; then |
|
[ $# -gt 0 ] && echo -n "$@" |
|
return 0 |
|
fi |
|
return 1; |
|
} |
|
|
|
getargs() { |
|
set +x |
|
local _val _i _args _gfound |
|
unset _val |
|
unset _gfound |
|
_args="$@" |
|
set -- |
|
for _i in $_args; do |
|
_val="$(_dogetargs $_i)" |
|
[ $? -eq 0 ] && _gfound=1 |
|
[ -n "$_val" ] && set -- "$@" "$_val" |
|
done |
|
if [ -n "$_gfound" ]; then |
|
if [ $# -gt 0 ]; then |
|
echo -n "$@" |
|
else |
|
echo -n 1 |
|
fi |
|
[ "$RD_DEBUG" = "yes" ] && set -x |
|
return 0 |
|
fi |
|
[ "$RD_DEBUG" = "yes" ] && set -x |
|
return 1; |
|
} |
|
|
|
|
|
# Prints value of given option. If option is a flag and it's present, |
|
# it just returns 0. Otherwise 1 is returned. |
|
# $1 = options separated by commas |
|
# $2 = option we are interested in |
|
# |
|
# Example: |
|
# $1 = cipher=aes-cbc-essiv:sha256,hash=sha256,verify |
|
# $2 = hash |
|
# Output: |
|
# sha256 |
|
getoptcomma() { |
|
local line=",$1,"; local opt="$2"; local tmp |
|
|
|
case "${line}" in |
|
*,${opt}=*,*) |
|
tmp="${line#*,${opt}=}" |
|
echo "${tmp%%,*}" |
|
return 0 |
|
;; |
|
*,${opt},*) return 0;; |
|
esac |
|
return 1 |
|
} |
|
|
|
# Splits given string 'str' with separator 'sep' into variables 'var1', 'var2', |
|
# 'varN'. If number of fields is less than number of variables, remaining are |
|
# not set. If number of fields is greater than number of variables, the last |
|
# variable takes remaining fields. In short - it acts similary to 'read'. |
|
# |
|
# splitsep sep str var1 var2 varN |
|
# |
|
# example: |
|
# splitsep ':' 'foo:bar:baz' v1 v2 |
|
# in result: |
|
# v1='foo', v2='bar:baz' |
|
# |
|
# TODO: ':' inside fields. |
|
splitsep() { |
|
local sep="$1"; local str="$2"; shift 2 |
|
local tmp |
|
|
|
while [ -n "$str" -a -n "$*" ]; do |
|
tmp="${str%%$sep*}" |
|
eval "$1=${tmp}" |
|
str="${str#$tmp}" |
|
str="${str#$sep}" |
|
shift |
|
done |
|
|
|
return 0 |
|
} |
|
|
|
setdebug() { |
|
if [ -z "$RD_DEBUG" ]; then |
|
if [ -e /proc/cmdline ]; then |
|
RD_DEBUG=no |
|
if getargbool 0 rd.debug -y rdinitdebug -y rdnetdebug; then |
|
RD_DEBUG=yes |
|
[ -n "$BASH" ] && \ |
|
export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): '; |
|
fi |
|
fi |
|
export RD_DEBUG |
|
fi |
|
[ "$RD_DEBUG" = "yes" ] && set -x |
|
} |
|
|
|
setdebug |
|
|
|
source_all() { |
|
local f |
|
[ "$1" ] && [ -d "/$1" ] || return |
|
for f in "/$1"/*.sh; do [ -e "$f" ] && . "$f"; done |
|
} |
|
|
|
hookdir=/lib/dracut/hooks |
|
export hookdir |
|
|
|
source_hook() { |
|
source_all "/lib/dracut/hooks/$1" |
|
} |
|
|
|
check_finished() { |
|
local f |
|
for f in $hookdir/initqueue/finished/*.sh; do |
|
[ "$f" = "$hookdir/initqueue/finished/*.sh" ] && return 0 |
|
{ [ -e "$f" ] && ( . "$f" ) ; } || return 1 |
|
done |
|
return 0 |
|
} |
|
|
|
source_conf() { |
|
local f |
|
[ "$1" ] && [ -d "/$1" ] || return |
|
for f in "/$1"/*.conf; do [ -e "$f" ] && . "$f"; done |
|
} |
|
|
|
die() { |
|
{ |
|
echo "<24>dracut: FATAL: $@"; |
|
echo "<24>dracut: Refusing to continue"; |
|
} > /dev/kmsg |
|
|
|
{ |
|
echo "warn dracut: FATAL: \"$@\""; |
|
echo "warn dracut: Refusing to continue"; |
|
} >> $hookdir/emergency/01-die.sh |
|
|
|
> /run/initramfs/.die |
|
exit 1 |
|
} |
|
|
|
check_quiet() { |
|
if [ -z "$DRACUT_QUIET" ]; then |
|
DRACUT_QUIET="yes" |
|
getargbool 0 rd.info -y rdinfo && DRACUT_QUIET="no" |
|
getargbool 0 rd.debug -y rdinitdebug && DRACUT_QUIET="no" |
|
getarg quiet || DRACUT_QUIET="yes" |
|
fi |
|
} |
|
|
|
warn() { |
|
check_quiet |
|
echo "<28>dracut Warning: $@" > /dev/kmsg |
|
echo "dracut Warning: $@" >&2 |
|
} |
|
|
|
info() { |
|
check_quiet |
|
echo "<30>dracut: $@" > /dev/kmsg |
|
[ "$DRACUT_QUIET" != "yes" ] && \ |
|
echo "dracut: $@" |
|
} |
|
|
|
vwarn() { |
|
while read line; do |
|
warn $line; |
|
done |
|
} |
|
|
|
vinfo() { |
|
while read line; do |
|
info $line; |
|
done |
|
} |
|
|
|
check_occurances() { |
|
# Count the number of times the character $ch occurs in $str |
|
# Return 0 if the count matches the expected number, 1 otherwise |
|
local str="$1" |
|
local ch="$2" |
|
local expected="$3" |
|
local count=0 |
|
|
|
while [ "${str#*$ch}" != "${str}" ]; do |
|
str="${str#*$ch}" |
|
count=$(( $count + 1 )) |
|
done |
|
|
|
[ $count -eq $expected ] |
|
} |
|
|
|
incol2() { |
|
local dummy check; |
|
local file="$1"; |
|
local str="$2"; |
|
|
|
[ -z "$file" ] && return 1; |
|
[ -z "$str" ] && return 1; |
|
|
|
while read dummy check restofline; do |
|
[ "$check" = "$str" ] && return 0 |
|
done < $file |
|
return 1 |
|
} |
|
|
|
udevsettle() { |
|
[ -z "$UDEVVERSION" ] && UDEVVERSION=$(udevadm --version) |
|
|
|
if [ $UDEVVERSION -ge 143 ]; then |
|
udevadm settle --exit-if-exists=$hookdir/initqueue/work $settle_exit_if_exists |
|
else |
|
udevadm settle --timeout=30 |
|
fi |
|
} |
|
|
|
udevproperty() { |
|
[ -z "$UDEVVERSION" ] && UDEVVERSION=$(udevadm --version) |
|
|
|
if [ $UDEVVERSION -ge 143 ]; then |
|
for i in "$@"; do udevadm control --property=$i; done |
|
else |
|
for i in "$@"; do udevadm control --env=$i; done |
|
fi |
|
} |
|
|
|
ismounted() { |
|
while read a m a; do |
|
[ "$m" = "$1" ] && return 0 |
|
done < /proc/mounts |
|
return 1 |
|
} |
|
|
|
wait_for_if_up() { |
|
local cnt=0 |
|
while [ $cnt -lt 200 ]; do |
|
li=$(ip link show $1) |
|
[ -z "${li##*state UP*}" ] && return 0 |
|
sleep 0.1 |
|
cnt=$(($cnt+1)) |
|
done |
|
return 1 |
|
} |
|
|
|
wait_for_route_ok() { |
|
local cnt=0 |
|
while [ $cnt -lt 200 ]; do |
|
li=$(ip route show) |
|
[ -n "$li" ] && [ -z "${li##*$1*}" ] && return 0 |
|
sleep 0.1 |
|
cnt=$(($cnt+1)) |
|
done |
|
return 1 |
|
} |
|
|
|
# root=nfs:[<server-ip>:]<root-dir>[:<nfs-options>] |
|
# root=nfs4:[<server-ip>:]<root-dir>[:<nfs-options>] |
|
nfsroot_to_var() { |
|
# strip nfs[4]: |
|
local arg="$@:" |
|
nfs="${arg%%:*}" |
|
arg="${arg##$nfs:}" |
|
|
|
# check if we have a server |
|
if strstr "$arg" ':/*' ; then |
|
server="${arg%%:/*}" |
|
arg="/${arg##*:/}" |
|
fi |
|
|
|
path="${arg%%:*}" |
|
|
|
# rest are options |
|
options="${arg##$path}" |
|
# strip leading ":" |
|
options="${options##:}" |
|
# strip ":" |
|
options="${options%%:}" |
|
|
|
# Does it really start with '/'? |
|
[ -n "${path%%/*}" ] && path="error"; |
|
|
|
#Fix kernel legacy style separating path and options with ',' |
|
if [ "$path" != "${path#*,}" ] ; then |
|
options=${path#*,} |
|
path=${path%%,*} |
|
fi |
|
} |
|
|
|
ip_to_var() { |
|
local v=${1}: |
|
local i |
|
set -- |
|
while [ -n "$v" ]; do |
|
if [ "${v#\[*:*:*\]:}" != "$v" ]; then |
|
# handle IPv6 address |
|
i="${v%%\]:*}" |
|
i="${i##\[}" |
|
set -- "$@" "$i" |
|
v=${v#\[$i\]:} |
|
else |
|
set -- "$@" "${v%%:*}" |
|
v=${v#*:} |
|
fi |
|
done |
|
|
|
unset ip srv gw mask hostname dev autoconf |
|
case $# in |
|
0) autoconf="error" ;; |
|
1) autoconf=$1 ;; |
|
2) dev=$1; autoconf=$2 ;; |
|
*) ip=$1; srv=$2; gw=$3; mask=$4; hostname=$5; dev=$6; autoconf=$7 ;; |
|
esac |
|
} |
|
|
|
# Create udev rule match for a device with its device name, or the udev property |
|
# ID_FS_UUID or ID_FS_LABEL |
|
# |
|
# example: |
|
# udevmatch LABEL=boot |
|
# prints: |
|
# ENV{ID_FS_LABEL}="boot" |
|
# |
|
# TOOD: symlinks |
|
udevmatch() { |
|
case "$1" in |
|
UUID=????????-????-????-????-????????????|LABEL=*) |
|
printf 'ENV{ID_FS_%s}=="%s"' "${1%%=*}" "${1#*=}" |
|
;; |
|
UUID=*) |
|
printf 'ENV{ID_FS_UUID}=="%s*"' "${1#*=}" |
|
;; |
|
/dev/?*) printf 'KERNEL=="%s"' "${1#/dev/}" ;; |
|
*) return 255 ;; |
|
esac |
|
} |
|
|
|
# Prints unique path for potential file inside specified directory. It consists |
|
# of specified directory, prefix and number at the end which is incremented |
|
# until non-existing file is found. |
|
# |
|
# funiq dir prefix |
|
# |
|
# example: |
|
# # ls /mnt |
|
# cdrom0 cdrom1 |
|
# |
|
# # funiq /mnt cdrom |
|
# /mnt/cdrom2 |
|
funiq() { |
|
local dir="$1"; local prefix="$2" |
|
local i=0 |
|
|
|
[ -d "${dir}" ] || return 1 |
|
|
|
while [ -e "${dir}/${prefix}$i" ]; do |
|
i=$(($i+1)) || return 1 |
|
done |
|
|
|
echo "${dir}/${prefix}$i" |
|
} |
|
|
|
# Creates unique directory and prints its path. It's using funiq to generate |
|
# path. |
|
# |
|
# mkuniqdir subdir new_dir_name |
|
mkuniqdir() { |
|
local dir="$1"; local prefix="$2" |
|
local retdir; local retdir_new |
|
|
|
[ -d "${dir}" ] || mkdir -m 0755 -p "${dir}" || return 1 |
|
|
|
retdir=$(funiq "${dir}" "${prefix}") || return 1 |
|
until mkdir -m 0755 "${retdir}" 2>/dev/null; do |
|
retdir_new=$(funiq "${dir}" "${prefix}") || return 1 |
|
[ "$retdir_new" = "$retdir" ] && return 1 |
|
retdir="$retdir_new" |
|
done |
|
|
|
echo "${retdir}" |
|
} |
|
|
|
# Evaluates command for UUIDs either given as arguments for this function or all |
|
# listed in /dev/disk/by-uuid. UUIDs doesn't have to be fully specified. If |
|
# beginning is given it is expanded to all matching UUIDs. To pass full UUID to |
|
# your command use '$___' as a place holder. Remember to escape '$'! |
|
# |
|
# foreach_uuid_until [ -p prefix ] command UUIDs |
|
# |
|
# prefix - string to put just before $___ |
|
# command - command to be evaluated |
|
# UUIDs - list of UUIDs separated by space |
|
# |
|
# The function returns after *first successful evaluation* of the given command |
|
# with status 0. If evaluation fails for every UUID function returns with |
|
# status 1. |
|
# |
|
# Example: |
|
# foreach_uuid_until "mount -U \$___ /mnt; echo OK; umount /mnt" \ |
|
# "01234 f512 a235567f-12a3-c123-a1b1-01234567abcb" |
|
foreach_uuid_until() ( |
|
cd /dev/disk/by-uuid |
|
|
|
[ "$1" = -p ] && local prefix="$2" && shift 2 |
|
local cmd="$1"; shift; local uuids_list="$*" |
|
local uuid; local full_uuid; local ___ |
|
|
|
[ -n "${cmd}" ] || return 1 |
|
|
|
for uuid in ${uuids_list:-*}; do |
|
for full_uuid in ${uuid}*; do |
|
[ -e "${full_uuid}" ] || continue |
|
___="${prefix}${full_uuid}" |
|
eval ${cmd} && return 0 |
|
done |
|
done |
|
|
|
return 1 |
|
) |
|
|
|
# Get kernel name for given device. Device may be the name too (then the same |
|
# is returned), a symlink (full path), UUID (prefixed with "UUID=") or label |
|
# (prefixed with "LABEL="). If just a beginning of the UUID is specified or |
|
# even an empty, function prints all device names which UUIDs match - every in |
|
# single line. |
|
# |
|
# NOTICE: The name starts with "/dev/". |
|
# |
|
# Example: |
|
# devnames UUID=123 |
|
# May print: |
|
# /dev/dm-1 |
|
# /dev/sdb1 |
|
# /dev/sdf3 |
|
devnames() { |
|
local dev="$1"; local d; local names |
|
|
|
case "$dev" in |
|
UUID=*) |
|
dev="$(foreach_uuid_until '! blkid -U $___' "${dev#UUID=}")" \ |
|
&& return 255 |
|
[ -z "$dev" ] && return 255 |
|
;; |
|
LABEL=*) dev="$(blkid -L "${dev#LABEL=}")" || return 255 ;; |
|
/dev/?*) ;; |
|
*) return 255 ;; |
|
esac |
|
|
|
for d in $dev; do |
|
names="$names |
|
$(readlink -e -q "$d")" || return 255 |
|
done |
|
|
|
echo "${names# |
|
}" |
|
} |
|
|
|
|
|
usable_root() { |
|
local _d |
|
[ -d $1 ] || return 1 |
|
for _d in proc sys dev; do |
|
[ -e "$1"/$_d ] || return 1 |
|
done |
|
return 0 |
|
} |
|
|
|
inst_hook() { |
|
local _hookname _unique _name _job _exe |
|
while [ $# -gt 0 ]; do |
|
case "$1" in |
|
--hook) |
|
_hookname="/$2";shift;; |
|
--unique) |
|
_unique="yes";; |
|
--name) |
|
_name="$2";shift;; |
|
*) |
|
break;; |
|
esac |
|
shift |
|
done |
|
|
|
if [ -z "$_unique" ]; then |
|
_job="${_name}$$" |
|
else |
|
_job="${_name:-$1}" |
|
_job=${_job##*/} |
|
fi |
|
|
|
_exe=$1 |
|
shift |
|
|
|
[ -x "$_exe" ] || _exe=$(command -v $_exe) |
|
|
|
if [ -n "$onetime" ]; then |
|
{ |
|
echo '[ -e "$_job" ] && rm "$_job"' |
|
echo "$_exe $@" |
|
} > "/tmp/$$-${_job}.sh" |
|
else |
|
echo "$_exe $@" > "/tmp/$$-${_job}.sh" |
|
fi |
|
|
|
mv -f "/tmp/$$-${_job}.sh" "$hookdir/${_hookname}/${_job}.sh" |
|
} |
|
|
|
# inst_mount_hook <mountpoint> <prio> <name> <script> |
|
# |
|
# Install a mount hook with priority <prio>, |
|
# which executes <script> as soon as <mountpoint> is mounted. |
|
inst_mount_hook() { |
|
local _prio="$2" _jobname="$3" _script="$4" |
|
local _hookname="mount-$(str_replace "$1" '/' '\\x2f')" |
|
[ -d "$hookdir/${_hookname}" ] || mkdir -p "$hookdir/${_hookname}" |
|
inst_hook --hook "$_hookname" --unique --name "${_prio}-${_jobname}" "$_script" |
|
} |
|
|
|
# add_mount_point <dev> <mountpoint> <filesystem> <fsopts> |
|
# |
|
# Mount <dev> on <mountpoint> with <filesystem> and <fsopts> |
|
# and call any mount hooks, as soon, as it is mounted |
|
add_mount_point() { |
|
local _dev="$1" _mp="$2" _fs="$3" _fsopts="$4" |
|
local _hookname="mount-$(str_replace "$2" '/' '\\x2f')" |
|
local _devname="dev-$(str_replace "$1" '/' '\\x2f')" |
|
echo "$_dev $_mp $_fs $_fsopts 0 0" >> /etc/fstab |
|
|
|
exec 7>/etc/udev/rules.d/99-mount-${_devname}.rules |
|
echo 'SUBSYSTEM!="block", GOTO="mount_end"' >&7 |
|
echo 'ACTION!="add|change", GOTO="mount_end"' >&7 |
|
if [ -n "$_dev" ]; then |
|
udevmatch "$_dev" >&7 || { |
|
warn "add_mount_point dev=$_dev incorrect!" |
|
continue |
|
} |
|
printf ', ' >&7 |
|
fi |
|
|
|
{ |
|
printf -- 'RUN+="%s --unique --onetime ' $(command -v initqueue) |
|
printf -- '--name mount-%%k ' |
|
printf -- '%s %s"\n' "$(command -v mount_hook)" "${_mp}" |
|
} >&7 |
|
echo 'LABEL="mount_end"' >&7 |
|
exec 7>&- |
|
} |
|
|
|
# wait_for_mount <mountpoint> |
|
# |
|
# Installs a initqueue-finished script, |
|
# which will cause the main loop only to exit, |
|
# if <mountpoint> is mounted. |
|
wait_for_mount() |
|
{ |
|
local _name |
|
_name="$(str_replace "$1" '/' '\\x2f')" |
|
printf '. /lib/dracut-lib.sh\nismounted "%s"\n' $1 \ |
|
>> "$hookdir/initqueue/finished/ismounted-${_name}.sh" |
|
{ |
|
printf 'ismounted "%s" || ' $1 |
|
printf 'warn "\"%s\" is not mounted"\n' $1 |
|
} >> "$hookdir/emergency/90-${_name}.sh" |
|
} |
|
|
|
# wait_for_dev <dev> |
|
# |
|
# Installs a initqueue-finished script, |
|
# which will cause the main loop only to exit, |
|
# if the device <dev> is recognized by the system. |
|
wait_for_dev() |
|
{ |
|
local _name |
|
_name="$(str_replace "$1" '/' '\\x2f')" |
|
printf '[ -e "%s" ]\n' $1 \ |
|
>> "$hookdir/initqueue/finished/devexists-${_name}.sh" |
|
{ |
|
printf '[ -e "%s" ] || ' $1 |
|
printf 'warn "\"%s\" does not exist"\n' $1 |
|
} >> "$hookdir/emergency/80-${_name}.sh" |
|
} |
|
|
|
cancel_wait_for_dev() |
|
{ |
|
local _name |
|
_name="$(str_replace "$1" '/' '\\x2f')" |
|
rm -f "$hookdir/initqueue/finished/devexists-${_name}.sh" |
|
rm -f "$hookdir/emergency/80-${_name}.sh" |
|
} |
|
|
|
killproc() { |
|
local _exe="$(command -v $1)" |
|
local _sig=$2 |
|
local _i |
|
[ -x "$_exe" ] || return 1 |
|
for _i in /proc/[0-9]*; do |
|
[ "$_i" = "/proc/1" ] && continue |
|
if [ -e "$_i"/_exe ] && [ "$_i/_exe" -ef "$_exe" ] ; then |
|
kill $_sig ${_i##*/} |
|
fi |
|
done |
|
} |
|
|
|
need_shutdown() { |
|
>/run/initramfs/.need_shutdown |
|
} |
|
|
|
wait_for_loginit() |
|
{ |
|
[ "$RD_DEBUG" = "yes" ] || return |
|
[ -e /run/initramfs/loginit.pipe ] || return |
|
set +x |
|
echo "DRACUT_LOG_END" |
|
exec 0<>/dev/console 1<>/dev/console 2<>/dev/console |
|
# wait for loginit |
|
i=0 |
|
while [ $i -lt 10 ]; do |
|
if [ ! -e /run/initramfs/loginit.pipe ]; then |
|
j=$(jobs) |
|
[ -z "$j" ] && break |
|
[ -z "${j##*Running*}" ] || break |
|
fi |
|
sleep 0.1 |
|
i=$(($i+1)) |
|
done |
|
|
|
if [ $i -eq 10 ]; then |
|
kill %1 >/dev/null 2>&1 |
|
kill $(while read line;do echo $line;done</run/initramfs/loginit.pid) |
|
fi |
|
|
|
setdebug |
|
rm -f /run/initramfs/loginit.pipe /run/initramfs/loginit.pid |
|
} |
|
|
|
emergency_shell() |
|
{ |
|
local _ctty |
|
set +e |
|
if [ "$1" = "-n" ]; then |
|
_rdshell_name=$2 |
|
shift 2 |
|
else |
|
_rdshell_name=dracut |
|
fi |
|
echo ; echo |
|
warn $@ |
|
source_hook emergency |
|
echo |
|
wait_for_loginit |
|
[ -e /run/initramfs/.die ] && exit 1 |
|
if getargbool 1 rd.shell -y rdshell || getarg rd.break rdbreak; then |
|
echo "Dropping to debug shell." |
|
echo |
|
export PS1="$_rdshell_name:\${PWD}# " |
|
[ -e /.profile ] || >/.profile |
|
|
|
_ctty="$(getarg rd.ctty=)" && _ctty="/dev/${_ctty##*/}" |
|
if [ -z "$_ctty" ]; then |
|
_ctty=console |
|
while [ -f /sys/class/tty/$_ctty/active ]; do |
|
_ctty=$(cat /sys/class/tty/$_ctty/active) |
|
_ctty=${_ctty##* } # last one in the list |
|
done |
|
_ctty=/dev/$_ctty |
|
fi |
|
[ -c "$_ctty" ] || _ctty=/dev/tty1 |
|
strstr "$(setsid --help 2>/dev/null)" "control" && CTTY="-c" |
|
setsid $CTTY /bin/sh -i -l 0<$_ctty 1>$_ctty 2>&1 |
|
else |
|
warn "Boot has failed. To debug this issue add \"rdshell\" to the kernel command line." |
|
# cause a kernel panic |
|
exit 1 |
|
fi |
|
}
|
|
|