logincaps (3012B)
1 #!/bin/zsh 2 setopt no_unset warn_create_global 3 PS4="cap $PS4" 4 5 trap 'printf >&2 "\nlogincaps: ALRM!\n"' ALRM 6 trap 'printf >&2 "\nlogincaps: HUP!\n"' HUP 7 8 pretendrun() { : "$@" } 9 typeset -f -t pretendrun 10 11 12 stop_x() { 13 (($+X)) || return 1 14 [[ $X == $1 ]] || return 2 15 shift 16 s6-svc -wD -T 8000 -t /run/service/container.X$X && 17 chown root:root /run/Xauthority.$X 18 } 19 20 run_x() { 21 (($+X)) || return 1 22 [[ $X == $1 ]] || return 2 23 shift 24 truncate -s 0 /run/Xauthority.$X && 25 # TODO: replace the 2 lines below with s6-svperm after updating s6 26 chgrp -R -- $USER /run/service/container.X$X/{event,supervise} && 27 chmod 750 /run/service/container.X$X/supervise && 28 s6-svc -wU -T 8000 -o /run/service/container.X$X && 29 chmod 640 /run/Xauthority.$X && 30 chown xorg:$USER /run/Xauthority.$X && 31 cat /run/containers/X$X.xorg/run/X/Xauthority > /run/Xauthority.$X && 32 chmod o+x /run/containers/X$X.xorg/tmp /run/containers/X$X.xorg/tmp/.X11-unix && 33 chown $USER:$USER /run/containers/X$X.xorg/tmp/.X11-unix/X$X 34 # with /proc/sys/fs/protected_hardlinks = 1 only owner can hardlink a socket 35 } 36 typeset -f -t run_x 37 38 check_wheel() { 39 local wheel_gid 40 wheel_gid=${${(s.:.)"$(getent group wheel)"}[3]} || return $? 41 [[ $wheel_gid == [1-9]* ]] || return 1 42 WHEEL_GID=$wheel_gid s6-envuidgid ccx zsh -c '(( ${${(s/,/)GIDLIST}[(I)$WHEEL_GID]} ))' 43 return $? 44 } 45 typeset -f -t check_wheel 46 47 cap_cmd() { 48 if "$@"; then 49 printf 'OK\n' 50 else 51 printf 'EX%d\n' $? 52 fi 53 } 54 typeset -f -t cap_cmd 55 56 terminal_spawn_common() { 57 local term_cmd term_env 58 term_cmd="${3#* }" 59 term_env=${term_cmd%% *} 60 if ! [[ $term_env =~ ^[-.0-9a-zA-Z]*$ ]]; then 61 printf 'ERR: invalid TERM' 62 return 1 63 fi 64 term_cmd="${term_cmd#* }" 65 cap_cmd execlineb -c "$1 ${(qqq)term_env} $2 cd / s6-setuidgid ${(qqq)USER} $term_cmd" 66 } 67 68 terminal_spawn_password() { 69 if check_wheel; then 70 terminal_spawn_common "check-root-password.py spawn-pty.py" '{ login -f root }' "$1" 71 else 72 printf 'ERR: Not in the group "wheel" (ex:%d)\n' $? 73 fi 74 } 75 76 terminal_spawn() { 77 terminal_spawn_common spawn-pty.py "{ $1 }" "$2" 78 } 79 80 main() { 81 local line term_cmd term_env REPLY 82 while read line; do 83 case $line in 84 ((|no)xtrace) 85 setopt $line 86 printf 'OK\n' 87 ;; 88 89 (o) 90 cap_cmd poweroff 91 ;; 92 93 (b) 94 cap_cmd reboot 95 ;; 96 97 (terminal *) 98 terminal_spawn_password "$line" 99 ;; 100 101 (terminal-wpa_cli *) 102 terminal_spawn "wpa_cli" "$line" 103 ;; 104 105 (chvt tty) 106 cap_cmd chvt ${LOGIN_TTY#/dev/tty} 107 ;; 108 109 (chvt [Xx]) 110 cap_cmd chvt $X 111 ;; 112 113 (X [5678]*) 114 cap_cmd run_x "${(Q@)${(z)${line#X }}}" 115 ;; 116 117 (stopX [5678]*) 118 cap_cmd stop_x "${(Q@)${(z)${line#stopX }}}" 119 ;; 120 121 (login.capability.*) 122 local cap_exe=${${=line}[1]} 123 if (($+commands[$cap_exe])); then 124 cap_cmd execlineb -c "$line" 125 else 126 printf 'ECMD\n' 127 fi 128 ;; 129 (*) printf 'ECMD\n';; 130 esac 131 done 132 stop_x >&2 </dev/null 133 } 134 135 if [[ $LOGIN_TTY == /dev/tty[1-4] ]]; then 136 typeset -g X 137 X=$[ ${LOGIN_TTY#/dev/tty} + 4 ] 138 export X 139 fi 140 141 main 142 # vim: ft=zsh noet ts=4 sts=4 sw=4