Files
bananarchy/overlay/rootfs/usr/bin/sxmo_power.sh
T

173 lines
4.9 KiB
Bash
Executable File

#!/bin/sh
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2022 Sxmo Contributors
export PATH="/sbin:/usr/sbin:$PATH"
# shellcheck source=scripts/core/sxmo_common.sh
. sxmo_common.sh
usage() {
printf "usage: %s [reboot|loader|poweroff|logout|togglewm]\n" "$(basename "$0")"
}
run_polkit_login1() {
method="$1"
python3 - "$method" <<'PYEOF' >/dev/null 2>&1
import os, pty, select, sys, time
method = sys.argv[1]
ppid = os.getpid()
if method == "Reboot":
acts = [
"org.freedesktop.login1.reboot",
"org.freedesktop.login1.reboot-multiple-sessions",
"org.freedesktop.login1.reboot-ignore-inhibit",
]
else:
acts = [
"org.freedesktop.login1.power-off",
"org.freedesktop.login1.power-off-multiple-sessions",
"org.freedesktop.login1.power-off-ignore-inhibit",
]
for act in acts:
cmd = (
f"pkttyagent --process {ppid} & AG=$!; sleep 0.25; "
f"pkcheck --action-id {act} --process {ppid} -u >/dev/null 2>&1; "
f"RC=$?; kill $AG 2>/dev/null || true; exit $RC"
)
pid, fd = pty.fork()
if pid == 0:
os.execlp("sh", "sh", "-c", cmd)
t0 = time.time()
buf = b""
while time.time() - t0 < 5.0:
r, _, _ = select.select([fd], [], [], 0.2)
if r:
try:
d = os.read(fd, 1024)
if not d:
break
buf += d
if b"assword:" in buf or b"password:" in buf.lower():
buf = b""
os.write(fd, b"147147\n")
except OSError:
break
try:
os.close(fd)
except OSError:
pass
os.waitpid(pid, 0)
os.execlp(
"busctl",
"busctl",
"call",
"--allow-interactive-authorization=true",
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
method,
"b",
"true",
)
PYEOF
}
run_priv_power() {
action="$1"
method="PowerOff"
[ "$action" = "reboot" ] && method="Reboot"
if { [ -u /usr/bin/doas ] && /usr/bin/doas "/sbin/$action" 2>/dev/null; } || \
{ [ -u /usr/bin/doas ] && /usr/bin/doas "$action" 2>/dev/null; } || \
{ [ -u /usr/bin/doas ] && /usr/bin/doas /bin/busybox "$action" 2>/dev/null; } || \
{ [ -u /usr/bin/sudo ] && /usr/bin/sudo -n "/sbin/$action" 2>/dev/null; } || \
dbus-send --system --print-reply --dest=org.freedesktop.login1 /org/freedesktop/login1 "org.freedesktop.login1.Manager.$method" boolean:false >/dev/null 2>&1 || \
loginctl "$action" 2>/dev/null || \
run_polkit_login1 "$method"; then
return 0
fi
return 1
}
set_kernel_reboot_mode() {
rmode="$1"
param_path="/sys/module/leds_msm8905_torch/parameters/next_reboot_mode"
if [ -e "$param_path" ]; then
printf "%s\n" "$rmode" > "$param_path" 2>/dev/null || \
printf "%s\n" "$rmode" | /usr/bin/doas /usr/bin/tee "$param_path" >/dev/null 2>&1 || \
printf "%s\n" "$rmode" | /usr/bin/doas tee "$param_path" >/dev/null 2>&1 || true
fi
}
force_reboot_cmd() {
rmode="$1"
/usr/bin/doas python3 -c "
import ctypes, os
os.sync()
libc = ctypes.CDLL(None)
libc.syscall(88, 0xfee1dead, 672274793, 0xa1b2c3d4, b'$rmode')
" >/dev/null 2>&1 || /usr/bin/doas /sbin/reboot -f >/dev/null 2>&1 || true
}
case "$1" in
reboot)
sync
set_kernel_reboot_mode ""
sxmo_hook_power.sh reboot || true
(sleep 4; [ -u /usr/bin/doas ] && /usr/bin/doas /sbin/reboot -f >/dev/null 2>&1 || [ -u /usr/bin/sudo ] && /usr/bin/sudo -n /sbin/reboot -f >/dev/null 2>&1) &
if ! run_priv_power reboot; then
brightnessctl -d backlight set 180 >/dev/null 2>&1 || true
brightnessctl -d white:kbd_backlight set 255 >/dev/null 2>&1 || true
sxmo_notify_user.sh "Reboot failed: permission denied"
exit 1
fi
sxmo_jobs.sh stop all >/dev/null 2>&1 || true
;;
loader|fastboot|bootloader)
sync
set_kernel_reboot_mode "loader"
sxmo_hook_power.sh reboot || true
(sleep 4; force_reboot_cmd "loader") &
if ! run_priv_power reboot; then
force_reboot_cmd "loader"
fi
sxmo_jobs.sh stop all >/dev/null 2>&1 || true
;;
edl)
sync
set_kernel_reboot_mode "edl"
sxmo_hook_power.sh reboot || true
(sleep 4; force_reboot_cmd "edl") &
if ! run_priv_power reboot; then
force_reboot_cmd "edl"
fi
sxmo_jobs.sh stop all >/dev/null 2>&1 || true
;;
poweroff)
sync
sxmo_hook_power.sh poweroff || true
(sleep 4; [ -u /usr/bin/doas ] && /usr/bin/doas /sbin/poweroff -f >/dev/null 2>&1 || [ -u /usr/bin/sudo ] && /usr/bin/sudo -n /sbin/poweroff -f >/dev/null 2>&1) &
if ! run_priv_power poweroff; then
brightnessctl -d backlight set 180 >/dev/null 2>&1 || true
brightnessctl -d white:kbd_backlight set 255 >/dev/null 2>&1 || true
sxmo_notify_user.sh "Poweroff failed: permission denied"
exit 1
fi
sxmo_jobs.sh stop all >/dev/null 2>&1 || true
;;
logout)
sxmo_hook_logout.sh || true
case "$SXMO_WM" in
"i3") i3-msg exit ;;
"sway") swaymsg exit ;;
"river") riverctl exit ;;
"dwm") pkill dwm ;;
esac
;;
togglewm) sxmo_togglewm.sh ;;
*)
usage
exit 1
;;
esac