#!/bin/sh
# copy original nvram executable to /tmp
cp /bin/nvram /tmp/_nvram
# create nvram wrapper that calls original nvram executable in /tmp
cat << 'EOF' > /tmp/nvram
#!/bin/sh
#set -x # comment/uncomment to disable/enable debug mode
INTERVAL="100"
MAXCOUNT="3"
run_cmd () {
local to
local start
local child
# here as the number of tries required increases our usleep increases in case the sleep is not long enough.
to="$1"
to="$((to*INTERVAL))"; shift
$@ & local child="$!" start=0
usleep "$to"
while { [ "$(kill -0 $child >/dev/null 2>&1; printf "%s" "$?")" = "0" ] && [ "$start" -le "$to" ]; }; do
# to account for killing too soon, as the number of tries required increases our count requirement increases before we attempt to kill the process.
usleep 1
start="$((start+1))"
if [ $start -gt $to ]; then
kill -s 9 $child 2>/dev/null
return 1
fi
done
return 0
}
# make the new function accessible, on the first run we want to exit right away if successful.
i="1"
if { run_cmd "$i" /tmp/_nvram "$@"; }; then
exit 0
fi
# here we add an interval check and allow up to 3 retries.
while [ "$i" -le "$MAXCOUNT" ]; do
logger -t "nvram-override" "Waiting for NVRAM (retry attempt ${i}/${MAXCOUNT})"
usleep $INTERVAL
if { run_cmd "$i" /tmp/_nvram "$@"; }; then
exit 0
fi
i="$((i+1))"
done
logger -t "nvram-override" "NVRAM remained locked too long; continuing anyway."
exit 1
EOF
chmod +x /tmp/nvram
# replace nvram in /usr/sbin w/ nvram wrapper in /tmp
mount -o bind /tmp/nvram /bin/nvram