diff --git a/init b/init index a066bbe..85aab7d 100755 --- a/init +++ b/init @@ -1,8 +1,8 @@ #!/bin/sh # -# tiny init +# Tiny init # -# false positive +# https://www.shellcheck.net/wiki/SC2154 # shellcheck disable=2154 print() @@ -13,8 +13,10 @@ print() panic() { print "${1:-unexpected error occurred}" \ - "\033[1;31m!!\033[m" >&2; sh -} + "\033[1;31m!!\033[m" + + sh +} >&2 resolve_device() { @@ -28,12 +30,16 @@ resolve_device() *) return 0 ;; esac - # prevent race condition - while [ ! -b "$device" ]; do sleep 1 - [ "$((count += 1))" = "${rootdelay:=30}" ] && { + # Race condition may occur if device manager is not yet initialized device. + # To fix this, we simply waiting until device is available. If device + # didn't appear in specified time, we panic. + while [ ! -b "$device" ]; do + if [ "$((count += 1))" = "${rootdelay:=30}" ]; then panic "failed to lookup partition" break - } + else + sleep 1 + fi done || : } @@ -41,8 +47,9 @@ run_hook() { type="$1" - # run hooks if any - # false positive + # Run hooks if any exist. + # + # https://www.shellcheck.net/wiki/SC1090 # shellcheck disable=1090 for hook in $hooks; do [ -f "/usr/share/tinyramfs/hooks/${hook}/${hook}.${type}" ] || continue @@ -52,7 +59,7 @@ run_hook() prepare_environment() { - # false positive + # https://www.shellcheck.net/wiki/SC1091 # shellcheck disable=1091 . /etc/tinyramfs/config @@ -92,13 +99,11 @@ mount_root() resolve_device "$root" - set -- \ - "${rorw:--o ro}${root_opts:+,$root_opts}" \ - "${root_type:+-t $root_type}" "$device" "/mnt/root" - - # word splitting is safe by design - # shellcheck disable=2068 - mount $@ || panic "failed to mount root" + # https://www.shellcheck.net/wiki/SC2086 + # shellcheck disable=2086 + mount \ + ${rorw:--o ro}${root_opts:+,$root_opts} ${root_type:+-t $root_type} \ + -- "$device" /mnt/root || panic "failed to mount root" } boot_system() @@ -109,19 +114,26 @@ boot_system() mount -o move "$dir" "/mnt/root/${dir}" done - set -- "/mnt/root" "${init:-/sbin/init}" "$init_args" - - # POSIX exec has no -c flag to execute command with empty environment - # use 'env -i' to prevent leaking exported variables - # word splitting is safe by design - # shellcheck disable=2068 - exec env -i TERM=linux PATH=/bin:/sbin:/usr/bin:/usr/sbin \ - switch_root $@ || panic "failed to boot system" + # POSIX 'exec' has no '-c' flag to execute command with empty environment. + # Using 'env -i' instead to prevent leaking exported variables. + # + # Some implementations of 'switch_root' doesn't conform to POSIX utility + # guidelines and doesn't support '--'. This means that we can't guarantee + # safety of init_args. + # shellcheck disable=2086 + exec \ + env -i TERM=linux PATH=/bin:/sbin:/usr/bin:/usr/sbin \ + switch_root /mnt/root "${init-/sbin/init}" $init_args || + panic "failed to boot system" } -# enable exit on error and disable globbing -# trap EXIT signal -set -ef; trap panic EXIT +# Exit if command fails and disable globbing. +set -ef + +# Run emergency shell if init unexpectedly exiting due to error. +trap panic EXIT + +# TODO display fancy colored status info prepare_environment parse_cmdline