#!/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