Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[PATCH] Improve _su

I was looking at _su for workers/45410 and noticed a few things:

* Fetching the user's shell often doesn't work on macOS, because normal users
  don't appear in passwd; we can use Directory Service for this

* We try to use -s to set the shell even for implementations that don't
  support that; we should skip those

* For the getent passwd case, we weren't escaping the user name before passing
  it to eval

* For the non-getent passwd case, we were doing a prefix match on the user
  name (i don't think that was intended?)


diff --git a/Completion/Unix/Command/_su b/Completion/Unix/Command/_su
index 900905632..ea0beab94 100644
--- a/Completion/Unix/Command/_su
+++ b/Completion/Unix/Command/_su
@@ -58,12 +58,22 @@ fi
 _arguments $args ${(e)first} "*:shell arguments:= ->rest" && return
-if (( $#opt_args[(i)-(s|-shell)] )); then
+# Normal users generally don't appear in passwd on macOS; try the Directory
+# Service first
+if [[ $OSTYPE == darwin* ]] && (( $+commands[dscl] )); then
+  shell=${"$(
+    _call_program shells dscl . -read /Users/${(q)usr} UserShell
+  )"#UserShell: }
+[[ -z $shell ]] &&
+if (( ${#${(@M)args:#*-s\[*\]:*}} && $#opt_args[(i)-(s|-shell)] )); then
 elif (( ${+commands[getent]} )); then
-  shell="${$(_call_program shells getent passwd $usr)##*:}"
+  shell="${$(_call_program shells getent passwd ${(q)usr})##*:}"
-  shell="${${(M@)${(@f)$(</etc/passwd)}:#$usr*}##*:}"
+  shell="${${(M@)${(@f)$(</etc/passwd)}:#${usr}:*}##*:}"
 case $state in

Messages sorted by: Reverse Date, Date, Thread, Author