Skip to content

Commit

Permalink
45424: completion: Add **/sbin to PATH when completing commands like …
Browse files Browse the repository at this point in the history
…sudo

* Update _command_names to add **/sbin to PATH when not otherwise overridden
  and _comp_priv_prefix is set. This ensures that, on systems where
  unprivileged users don't have **/sbin in their PATHs, we can still complete
  those commands when they try to run them with e.g. sudo

* Update functions for privilege-gaining commands to use the aforementioned
  mechanism

* Fix some other minor issues in _pfexec and _doas

Changes from the posted diff:

* Fix a minor redundancy in _doas

* Add _c_p_p=( '' ) hack to _su
  • Loading branch information
okdana committed Mar 11, 2020
1 parent 0d7f888 commit 359e0da
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 22 deletions.
7 changes: 7 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
2020-03-11 dana <dana@dana.is>

* 45424 (tweaked): Completion/Solaris/Command/_pfexec,
Completion/Unix/Command/_doas, Completion/Unix/Command/_su,
Completion/Unix/Command/_sudo, Completion/Zsh/Type/_command_names:
Add **/sbin to PATH when completing commands like sudo

2020-03-10 Romain Porte <debian@microjoe.org>

* 45524: Completion/Debian/Command/_dscverify: Add completion
Expand Down
12 changes: 8 additions & 4 deletions Completion/Solaris/Command/_pfexec
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ _privset() {
}

_pfexec() {
local cmd cpp
local -a _comp_priv_prefix
_arguments \
'-P[privileges to acquire]:privspec:_privset' \
'(-):command name: _command_names -e' \
'*::arguments:{ _comp_priv_prefix=( pfexec ${(kv)opt_args[-P]} ) ; _normal }'
local -A opt_args
cmd="$words[1]"
cpp='_comp_priv_prefix=( $cmd ${(kv)opt_args[(I)-P]} )'
_arguments \
'-P+[privileges to acquire]:privspec:_privset' \
"(-): :{ $cpp; _command_names -e }" \
"*:: :{ $cpp; _normal }"
}

_pfexec "$@"
21 changes: 11 additions & 10 deletions Completion/Unix/Command/_doas
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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]: :_users' \
"(-)1: :{ $cpp; _command_names -e }" \
"*:: :{ $cpp; _normal }"
6 changes: 6 additions & 0 deletions Completion/Unix/Command/_su
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ if (( $words[(i)-] < CURRENT )); then
norm=2
fi

# This is set so that _command_names will understand that we're completing for
# a privileged command, but _call_program won't actually prepend anything to
# commands if gain-privileges is enabled (which would be undesirable here since
# su always prompts for a password). We delay setting it until this point so it
# doesn't cause issues for the check above
local -a _comp_priv_prefix=( '' )
_arguments $args ${(e)first} "*:shell arguments:= ->rest" && return

usr=${${(Q)line[norm]}/--/root}
Expand Down
14 changes: 9 additions & 5 deletions Completion/Unix/Command/_sudo
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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]' \
Expand All @@ -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

Expand Down
19 changes: 16 additions & 3 deletions Completion/Zsh/Type/_command_names
Original file line number Diff line number Diff line change
Expand Up @@ -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[@]"

0 comments on commit 359e0da

Please sign in to comment.