#!/bin/bash ffoo import inigrep ffoo import pretty ffoo import sync __zleep_user_part() { saturnin iam undocking slock & } __zleep_try_umount() { local mp=$1 mountpoint -q "$mp" || return 0 umount "$mp" || return 1 mount | grep "$mp" && return 1 return 0 } __zleep_try_umount_all() { local mp for mp in $(inigrep -p iam.mounting.point); do __zleep_try_umount "$mp" || return 1 done return 0 } __zleep_sudo_part() { wait_until -d 5 -t 30 __zleep_try_umount_all || die "unable to unmount drives" pm-suspend } __zleep_sudo_part_started() { # i.e. password prompt went ok test -e "$ZLEEP_ON_ROOT" rv=$? debug -v rv return $rv } __zleep_user_part_done() { ! test -e "$ZLEEP_ON_USER" rv=$? debug -v rv return $rv } __zleep_min_path() { echo -n "$(sudo env | grep ^PATH)" echo -n : echo -n "$(dirname "$(which ffoom)")" echo -n : echo -n "$(dirname "$(which saturnin)")" } zleep() { # # Put the host on sleep # # We need to # # 1. authenticate # 2. start user's part in the background -- mainly slock # 3. start root's part -- put system on sleep (unmount, suspend) # # This is solved by forking with sudo, and waiting for user part to indicate # it has finished. That way, we can ensure that suspend happens *after* the # screen has been locked, and at the same time we leave authentication part # on sudo. # if test -z "$ZLEEP_ON_USER"; ## we are parent (running as normal user) then ZLEEP_ON_USER=$(mktemp) ZLEEP_ON_ROOT=$(mktemp -u) SUDO_PATH=$(__zleep_min_path) # needed while bins are still under local debug -v ZLEEP_ON_USER ZLEEP_ON_ROOT SUDO_PATH sudo env \ ZLEEP_ON_ROOT="$ZLEEP_ON_ROOT" \ ZLEEP_ON_USER="$ZLEEP_ON_USER" \ PATH="$SUDO_PATH" \ saturnin iam zleeping & wait_until -t 60 __zleep_sudo_part_started # i.e. password prompt done __zleep_user_part rm -f "$ZLEEP_ON_USER" else ## we are child (running as root) touch "$ZLEEP_ON_ROOT" test "$(id -u)" -eq 0 || die "must be root" wait_until __zleep_user_part_done || die "timeout waiting for parent" __zleep_sudo_part rm -f "$ZLEEP_ON_ROOT" return $? fi }