zsh-workers
 help / color / Atom feed
From: dana <dana@dana.is>
To: Oliver Kiddle <okiddle@yahoo.co.uk>
Cc: Zsh hackers list <zsh-workers@zsh.org>,
	Daniel Shahaf <d.s@daniel.shahaf.name>
Subject: Re: sudo autocompletion
Date: Wed, 12 Feb 2020 19:21:08 -0600
Message-ID: <B8D456C0-2CFE-4B8E-BFA6-F227FB662A0E@dana.is> (raw)
In-Reply-To: <17405-1581415941.062275@CNCV.ghXS.ifR->

On 11 Feb 2020, at 04:12, Oliver Kiddle <okiddle@yahoo.co.uk> wrote:
> We already set _comp_priv_prefix, _command_names could detect that
> and adjust a local $path if it is set.

I made some related changes here that i can break out into separate patches if
it makes it easier. But this is the summary:

* Have _command_names append the sbin variants if command-path is not set but
  _comp_priv_prefix is

* Add some indirection around setting _c_p_p in _doas, _pfexec, and _sudo — i
  think the purpose of delaying the assignment is to make sure that opt_args
  has been populated

* Have _doas call `_command_names -e` separately like _sudo and _pfexec do (it
  can't complete shell commands)

* Have _pfexec use $words[1] for _c_p_p (the $cmd indirection is there because
  $words is changed by the *:: spec)

* Fix broken opt_args references in _doas and _pfexec — they need the (I)
  flag, and using argument sets in _doas makes it ugly to extract options, so
  i have it just using exclusion lists now instead

* Change -P to -P+ in _pfexec

Does this make sense?

PS: This does not fix `su -c` — _su doesn't set _c_p_p, presumably because it
always prompts for a password. But since _c_p_p is passed directly to eval, we
*could* make it set _c_p_p=( '' ), which would trick _command_names into doing
the right thing. Is that too silly?

dana


diff --git a/Completion/Solaris/Command/_pfexec b/Completion/Solaris/Command/_pfexec
index 2519c3cdc..fc2bca835 100644
--- a/Completion/Solaris/Command/_pfexec
+++ b/Completion/Solaris/Command/_pfexec
@@ -22,11 +22,15 @@ _privset() {
 }
 
 _pfexec() {
+	local cmd cpp
 	local -a _comp_priv_prefix
+	local -A opt_args
+	cmd="$words[1]"
+	cpp='_comp_priv_prefix=( $cmd ${(kv)opt_args[(I)-P]} )'
  	_arguments \
-		'-P[privileges to acquire]:privspec:_privset' \
- 		'(-):command name: _command_names -e' \
-		'*::arguments:{ _comp_priv_prefix=( pfexec ${(kv)opt_args[-P]} ) ; _normal }'
+		'-P+[privileges to acquire]:privspec:_privset' \
+ 		"(-): :{ $cpp; _command_names -e }" \
+		"*:: :{ $cpp; _normal }"
 }
 
 _pfexec "$@"
diff --git a/Completion/Unix/Command/_doas b/Completion/Unix/Command/_doas
index 94395557c..2494f1c5f 100644
--- a/Completion/Unix/Command/_doas
+++ b/Completion/Unix/Command/_doas
@@ -1,7 +1,8 @@
 #compdef doas
 
-local environ e cmd
+local environ e cmd cpp
 local -a _comp_priv_prefix
+local -A opt_args
 
 zstyle -a ":completion:${curcontext}:" environ environ
 
@@ -10,13 +11,13 @@ do local -x "$e"
 done
 
 cmd="$words[1]"
+cpp='_comp_priv_prefix=( $cmd -n ${(kv)opt_args[(I)-u]} )'
 _arguments -s -S -A '-*' : \
-  - optL \
-  '-L[clear any persisted authorizations]' \
-  - default \
-  '-a+[specify authentication style]:authentication style' \
-  '(-n -s)-C+[check config file and report on command matching]:config:_files' \
-  '(-C)-n[non-interactive: fail rather than prompt for a password]' \
-  '(-C *)-s[run a shell]' \
-  '-u+[run command as specified user]:user:_users' \
-  '*::arguments:{ _comp_priv_prefix=( $cmd -n ${(kv)opt_args[-u]} ) ; _normal }'
+  '(: * -)-L[clear any persisted authorizations]' \
+  '(-L)-a+[specify authentication style]:authentication style' \
+  '(-L -n -s)-C+[check config file and report on command matching]:config:_files' \
+  '(-C -L)-n[non-interactive: fail rather than prompt for a password]' \
+  '(-C -L *)-s[run a shell]' \
+  '(-L)-u+[run command as specified user]:user:_users' \
+  "(-)1: :{ $cpp; _command_names -e }" \
+  "*:: :{ $cpp; _normal }"
diff --git a/Completion/Unix/Command/_sudo b/Completion/Unix/Command/_sudo
index 41e32cbae..e3d12d72f 100644
--- a/Completion/Unix/Command/_sudo
+++ b/Completion/Unix/Command/_sudo
@@ -2,9 +2,9 @@
 
 setopt localoptions extended_glob
 
-local environ e cmd
-local -a args
-local -a _comp_priv_prefix
+local environ e cmd cpp
+local -a args _comp_priv_prefix
+local -A opt_args
 
 zstyle -a ":completion:${curcontext}:" environ environ
 
@@ -42,6 +42,10 @@ if [[ $service = sudoedit ]] || (( $words[(i)-e] < $words[(i)^(*sudo|-[^-]*)] ))
   args=( -A "-*" $args '!(-V --version -h --help)-e' '*:file:_files' )
 else
   cmd="$words[1]"
+  cpp='_comp_priv_prefix=(
+    $cmd -n
+    ${(kv)opt_args[(I)(-[ugHEP]|--(user|group|set-home|preserve-env|preserve-groups))]}
+  )'
   args+=(
     '(-e --edit 1 *)'{-e,--edit}'[edit files instead of running a command]' \
     '(-s --shell)'{-s,--shell}'[run shell as the target user; a command may also be specified]' \
@@ -51,8 +55,8 @@ else
     '(-E -i --login -s --shell -e --edit)--preserve-env=-[preserve user environment when running command]::environment variable:_sequence _parameters -g "*export*"' \
     '(-H --set-home -i --login -s --shell -e --edit)'{-H,--set-home}"[set HOME variable to target user's home dir]" \
     '(-P --preserve-groups -i -login -s --shell -e --edit)'{-P,--preserve-groups}"[preserve group vector instead of setting to target's]" \
-    '(-)1:command: _command_names -e'
-    '*::arguments:{ _comp_priv_prefix=( $cmd -n ${(kv)opt_args[(I)(-[ugHEP]|--(user|group|set-home|preserve-env|preserve-groups))]} ) ; _normal }'
+    "(-)1: :{ $cpp; _command_names -e }"
+    "*:: :{ $cpp; _normal }"
   )
 fi
 
diff --git a/Completion/Zsh/Type/_command_names b/Completion/Zsh/Type/_command_names
index cd630b7a4..b1c35f013 100644
--- a/Completion/Zsh/Type/_command_names
+++ b/Completion/Zsh/Type/_command_names
@@ -41,11 +41,24 @@ fi
 args=( "$@" )
 
 local -a cmdpath
-if zstyle -a ":completion:${curcontext}" command-path cmdpath &&
-   [[ $#cmdpath -gt 0 ]]
-then
+
+zstyle -a ":completion:${curcontext}" command-path cmdpath
+
+# Using the current PATH doesn't necessarily make sense when completing commands
+# to tools like sudo, which might set a different one. A common issue is that
+# /**/sbin appear in the PATH used by the tool, but not in the one used by the
+# unprivileged user who calls it. To do the right thing in the most common
+# cases, we'll simply ensure that the sbin variants always appear here when not
+# otherwise overridden (bash-completion's _sudo does something similar)
+if (( ! $#cmdpath && $#_comp_priv_prefix )); then
+  cmdpath=( $path ${path/%\/bin//sbin} )
+  cmdpath=( ${(u)^cmdpath}(/-N) )
+fi
+
+if (( $#cmdpath )); then
   local -a +h path
   local -A +h commands
   path=( $cmdpath )
 fi
+
 _alternative -O args "$defs[@]"


  parent reply index

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <912d22db-8a8f-90f2-6738-f9f395994dcb@gmail.com>
     [not found] ` <CAN=4vMqvzUTZ7bBLcbTzi-pKAVEP1xDbq=f5pLAxmffxUjTszQ@mail.gmail.com>
     [not found]   ` <1770be62-54d8-70a6-8b05-cfc98faa9b9f@gmail.com>
     [not found]     ` <20200210030219.527a3ccf@tarpaulin.shahaf.local2>
     [not found]       ` <ADE72275-1311-44BE-9B1D-5E617E3D9F94@gmail.com>
2020-02-10 17:13         ` dana
2020-02-10 17:40           ` Peter Stephenson
2020-02-10 18:57             ` dana
2020-02-10 19:20           ` Daniel Shahaf
2020-02-11 10:12             ` Oliver Kiddle
2020-02-11 10:28               ` Setting/Querying cache-policy (was: Re: sudo autocompletion) Daniel Shahaf
2020-02-12 16:51                 ` dana
2020-02-13  1:21               ` dana [this message]
2020-02-13  1:29                 ` sudo autocompletion Bart Schaefer
2020-02-15 22:22                 ` Andrey Butirsky
2020-02-15 22:48                   ` dana
2020-02-10 22:05           ` Andrey Butirsky
2020-02-10 23:02             ` dana

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=B8D456C0-2CFE-4B8E-BFA6-F227FB662A0E@dana.is \
    --to=dana@dana.is \
    --cc=d.s@daniel.shahaf.name \
    --cc=okiddle@yahoo.co.uk \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

zsh-workers

Archives are clonable: git clone --mirror http://inbox.vuxu.org/zsh-workers

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://inbox.vuxu.org/vuxu.archive.zsh.workers


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git