foxshell/fn/-z4h-chsh
2025-07-04 11:48:40 -05:00

123 lines
3.8 KiB
Bash

#!/usr/bin/env zsh
eval "$_z4h_opt"
local user=${(%):-%n}
[[ -n $user && -r /etc/shells && $_z4h_exe == /* && -x $_z4h_exe &&
$user != cloudshell-user && -t 0 && -t 1 && -t 2 ]] || return 0
if [[ $OSTYPE == linux* ]]; then
[[ -r /etc/passwd ]] || return 0
if (( ! $+commands[chsh] )); then
[[ $+commands[sudo] == 1 || -w /etc ]] || return 0
fi
local passwd
passwd="$(</etc/passwd)" || return '_z4h_err()'
local -a match mbegin mend
[[ $passwd == (#b)*((#s)|$'\n')$user:[^$'\n']#:([^:]##)((#e)|$'\n')* ]] || return 0
local login_shell=$match[2]
elif [[ $OSTYPE == darwin* ]]; then
(( $+commands[dscl] && $+commands[chsh] )) || return 0
local login_shell
login_shell=$(dscl . -read ~/ UserShell) || return '_z4h_err()'
[[ $login_shell == 'UserShell: /'* ]] || return '_z4h_err()'
login_shell=${login_shell#UserShell: }
else
return 0
fi
[[ -x $login_shell && ! $login_shell -ef $_z4h_exe ]] || return 0
local -a shells
shells=(${(f)"$(</etc/shells)"}) || return '_z4h_err()'
local my_shell=$shells[(re)$_z4h_exe]
if [[ -z $my_shell ]]; then
local shell
for shell in $shells; do
if [[ $shell -ef $_z4h_exe ]]; then
my_shell=$shell
break
fi
done
fi
[[ -n $my_shell || $+commands[sudo] == 1 || -w /etc/shells ]] || return 0
-z4h-flowing -- %F{3}z4h%f: login shell isn\'t the same as this shell
print -Pr -- ""
print -Pr -- " user %F{3}${user//\%/%%}%f"
print -Pr -- " login shell %F{2}${login_shell//\%/%%}%f"
print -Pr -- " this shell %F{2}${${my_shell:-$_z4h_exe}//\%/%%}%f"
print -Pr -- ""
-z4h-flowing -- Change login shell of "%F{3}${user//\%/%%}%f" to "%F{2}${${my_shell:-$_z4h_exe}//\%/%%}%f?"
print -Pr -- ""
print -Pr -- " %B(y)%b Yes. %BRecommended%b."
print -Pr -- " %B(n)%b No."
print -Pr -- ""
(
trap '' INT
(
local -i error
while true; do
if (( error )); then
print -Pr -- ''
print -Pr -- 'Bummer! Try again?'
print -Pr -- ""
print -Pr -- " %B(y)%b Yes."
print -Pr -- " %B(n)%b No."
print -Pr -- ""
fi
print -Prn -- "%BChoice [yn]:%b "
{
read -k choice || return
} always {
[[ $choice == $'\n' ]] || print
}
if [[ $choice == (n|N) ]]; then
print
print -rn >$Z4H/stickycache/no-chsh || return '_z4h_err()'
local home=~
local zdotdir=${${${(q)ZDOTDIR}/#${(q)home}/'~'}//\%/%%}
print -Pr -- "Won't ask again unless %U\$Z4H/stickycache/no-chsh%u is deleted."
return 1
fi
[[ $choice == $'\n' ]] && continue
if [[ $choice != (y|Y) ]]; then
print -Pr -- '%F{3}z4h%f: invalid choice: '${(q-)choice//\%/%%}
continue
fi
error=1
print
if [[ -z $my_shell ]]; then
print -Pr -- "Adding %F{2}${_z4h_exe//\%/%%}%f to %U/etc/shells%u."
local precmd=(command)
[[ -w /etc/shells ]] || precmd+=(sudo)
$precmd tee -a /etc/shells >/dev/null <<<$_z4h_exe || continue
my_shell=$_z4h_exe
(( $#precmd == 1 )) || print
fi
print -Pr -- "Changing login shell to %F{2}${my_shell//\%/%%}%f."
if (( $+commands[chsh] )); then
command chsh -s $my_shell || continue
else
local MATCH MBEGIN MEND
local p=("${(@)${(@f)passwd}/#%(#m)$user:*/${MATCH%:*}:$my_shell}")
if [[ ${(F)p} == $passwd ]]; then
print -Pru2 -- '%F{3}z4h%f: %F{1}internal error%f'
return '_z4h_err()'
fi
local precmd=(command)
[[ -w /etc ]] || precmd+=(sudo)
$precmd tee -- /etc/passwd.bak.$$ >/dev/null <<<${(F)p} || continue
$precmd mv -f -- /etc/passwd.bak.$$ /etc/passwd || continue
fi
print -Pr -- "Changed login shell of %F{3}${user//\%/%%}%f to %F{2}${my_shell//\%/%%}%f."
print
return 0
done
)
) && export SHELL=${my_shell:-$_z4h_exe}