zsh-users / zsh-syntax-highlighting

Fish shell like syntax highlighting for Zsh.
github.com/zsh-users/zsh-syntax-highlighting
BSD 3-Clause "New" or "Revised" License
19.89k stars 1.32k forks source link

sudo and commands only in /sbin #592

Open Raizo62 opened 5 years ago

Raizo62 commented 5 years ago

Hi

Sorry, i come back for an other problem with sudo

With "sudo ls" , "ls" is colorized correctly with green

with "sudo ifup" where "ifup" is only in "/sbin", "ifup" is colorized in red

Raizo62 commented 5 years ago

However, I'm asking a different question: what algorithm should 'sudo foo' follow to decide what color to highlight 'foo' in when root's path is NOT configured.

'sudo foo' must follow the same algorithm as sudo to know what color to use with 'foo'. But zsh doesn't have the same right as the sudo command then it can't do the same thing, and you don't want tu use sudo (and you have right)

I am not the good person to answer to this question. I choose the solution which colors correctly more often foo. With me, initialize ZSH_HIGHLIGHT_SPECIAL_PATH with root's path will be the default. Then if an user removes the value of this variable, sudo ifconfig will be red.

Raizo62 commented 5 years ago

I can add also that unset ZSH_HIGHLIGHT_SPECIAL_PATH can is the case where the user is not in sudoers : then all commands behind sudo (even ls) will be red (This default choose will be do by the admin of the server)

danielshahaf commented 5 years ago

I can add also that unset ZSH_HIGHLIGHT_SPECIAL_PATH can is the case where the user is not in sudoers : then all commands behind sudo (even ls ) will be red

First, ls would be green when your variable is unset. (I agree that it would make sense for it to be red if the command would fail, but we can't determine that.)

Second, the common case, provided that the user has typed sudo, is that the user is in sudoers(5) and hasn't configured z-sy-h's "root's PATH" knob.

danielshahaf commented 5 years ago

You may have meant "set to empty" rather than "unset", but your code doesn't distinguish these two cases, and even if it did, I doubt zsh-syntax-highlighting is popular enough that admins will code their sudoers(5) configs into /usr/local/etc/zshrc's setting of your variable.

Raizo62 commented 5 years ago

You may have meant "set to empty" rather than "unset", but your code doesn't distinguish these two cases,

Yes, i know. I did think this idea when i was answer you. It is easy to modify the patch to do this.

I doubt zsh-syntax-highlighting is popular enough that admins will code their sudoers(5) configs into /usr/local/etc/zshrc's setting of your variable.

I doubt zsh-syntax-highlighting is popular enough that admins will code their sudoers(5) configs into /usr/local/etc/zshrc's setting of your variable.

Perhaps, but if zsh-syntax-highlighting is enough popular to be installed by the "admin", the "admin" can configured it ;-)

I propose a boolean variable to color the command after sudo : if this variable is unset or true, the command behind sudo is always uncolored, otherwise zsh uses ZSH_HIGHLIGHT_SPECIAL_PATH.

danielshahaf commented 5 years ago

If an user is not in sudoers and the admin does nothing, then the command sudo ls will fail and ls will be red. It is correct.

No, it won't be red. It will be green, like I already said.

I propose a boolean variable to color the command after sudo : if this variable is unset or true, the command behind sudo is always uncolored, otherwise zsh uses ZSH_HIGHLIGHT_SPECIAL_PATH.

That's what I proposed back in December. I'm glad we agree on something :-)

Raizo62 commented 5 years ago

If an user is not in sudoers and the admin does nothing, then the command sudo ls will fail and ls will be red. It is correct.

No, it won't be red. It will be green, like I already said.

I speaked with a system with ZSH_HIGHLIGHT_SPECIAL_PATH (and with unset)

I propose a boolean variable to color the command after sudo : if this variable is unset or true, the command behind sudo is always uncolored, otherwise zsh uses ZSH_HIGHLIGHT_SPECIAL_PATH.

That's what I proposed back in December. I'm glad we agree on something :-)

I am not against if i have always a functionality to color the commands behind sudo ;-)

danielshahaf commented 5 years ago

I speaked with a system with ZSH_HIGHLIGHT_SPECIAL_PATH (and with unset)

Yes, and I already said —

Second, the common case, provided that the user has typed sudo, is that the user is in sudoers(5) and hasn't configured z-sy-h's "root's PATH" knob.

That means ls shouldn't be red by default.

I regret to say that I find this thread/discussion/collaboration challenging to participate in; moreover, I suspect the feeling's mutual. There are still unanswered design questions¹, but I fear that trying to discuss them would frustrate both of us. I'd like to avoid that outcome, if possible.

¹ For one, shouldn't the actual argument to the -u option be part of the zstyle context the path is looked up under? But this doesn't answer all open questions, not to mention that there isn't yet consensus on how much sudo should be special-cased in the first place...

Raizo62 commented 5 years ago

I believe that you want a miracle solution. Miracle solution because zsh-syntax-highlighting doesn't have access to files like sudoers(5), but zsh-syntax-highlighting must have access to this files to choose automatically the good color for foo behind sudo.

I tried to convince you to accept a partial solution where it is the user who explains to zsh-syntax-highlighting what is the good color.

I'm afraid that this functionality stays in standby for a longtime. Already 3 months without progress. I think that a miracle solution will need more more time. It is too bad because we need it : When we tape a command, we have no interest for sudo but for foo.

At the end, i hoped that you accept to have a "beta-functionality" (beta because no perfect) disabled by default.

Ok. It is your code after all.

I will try to write a patch which applies our discussion. I will copy-paste it here.

danielshahaf commented 5 years ago

I believe that you want a miracle solution. Miracle solution because zsh-syntax-highlighting doesn't have access to files like sudoers(5), but zsh-syntax-highlighting must have access to this files to choose automatically the good color for foo behind sudo.

Then you misunderstood me. As far as I'm concerned, "z-sy-h doesn't have access to sudoers(5)" is a design constraint. What I'd like to do is to find a good solution, within the bounds of the effective constraints.

I tried to convince you to accept a partial solution where it is the user who explains to zsh-syntax-highlighting what is the good color.

That part I agree with.

At the end, i hoped that you accept to have a "beta-functionality" (beta because no perfect) disabled by default.

For avoidance of doubt, I never consider whether a fix is complete as a criterion to merging it; I only consider whether it is sound. In other words, I would happily merge a patch that implements only part of the desired behaviour. Your patch, however, fixes one use-case but regresses others.

I will try to write a patch which applies our discussion. I will copy-paste it here.

I look forward to the revised patch.

Raizo62 commented 5 years ago
_zsh_highlight_main__test_type_builtin() {

    if [[ -n  ${ZSH_HIGHLIGHT_SPECIAL_PATH} ]]; then
        if [ "$this_word" = ":sudo_opt::start:" ]; then
            # ZSH_HIGHLIGHT_SPECIAL_PATH exist is not empty : "Admin" says that user has access to commands in these paths with sudo
            local PATH="${ZSH_HIGHLIGHT_SPECIAL_PATH}"
        fi
    fi

    builtin type -w -- $1 >/dev/null 2>&1
}

# Get the type of a command.
#
# Uses the zsh/parameter module if available to avoid forks, and a
# wrapper around 'type -w' as fallback.
#
# If $2 is 0, do not consider aliases.
#
# The result will be stored in REPLY.
_zsh_highlight_main__type() {
  integer -r aliases_allowed=${2-1}
  # We won't cache replies of anything that exists as an alias at all, to
  # ensure the cached value is correct regardless of $aliases_allowed.
  #
  # ### We probably _should_ cache them in a cache that's keyed on the value of
  # ### $aliases_allowed, on the assumption that aliases are the common case.
  integer may_cache=1

  # Cache lookup
  if (( $+_zsh_highlight_main__command_type_cache )); then
    REPLY=$_zsh_highlight_main__command_type_cache[(e)$1]
    if [[ -n "$REPLY" ]]; then
      return
    fi
  fi

    if [[ -v ZSH_HIGHLIGHT_SPECIAL_COMMAND ]]; then
        if (( ${ZSH_HIGHLIGHT_SPECIAL_COMMAND[(I)$1]} )); then
            # ZSH_HIGHLIGHT_SPECIAL_COMMAND exists : if foo of "sudo foo" is in ZSH_HIGHLIGHT_SPECIAL_COMMAND then "Admin" says that user has access to this command
            REPLY=command
            return 0
        fi
    fi

    if [[ -v ZSH_HIGHLIGHT_SPECIAL_PATH ]]; then
        if [ "$this_word" = ":sudo_opt::start:" ]; then
            if [ -z  "${ZSH_HIGHLIGHT_SPECIAL_PATH}" ]; then
                # ZSH_HIGHLIGHT_SPECIAL_PATH exist and is empty : "Admin" wants to say that user has no access to sudo : foo in "sudo foo" is red
                REPLY=none
                return 0
            fi
        fi
    fi

  # Main logic
  if (( $#options_to_set )); then
    setopt localoptions $options_to_set;
  fi
  unset REPLY
  if zmodload -e zsh/parameter; then
    if (( $+aliases[(e)$1] )); then
      may_cache=0
    fi
    if (( $+aliases[(e)$1] )) && (( aliases_allowed )); then
      REPLY=alias
    elif [[ $1 == *.* && -n ${1%.*} ]] && (( $+saliases[(e)${1##*.}] )); then
      REPLY='suffix alias'
    elif (( $reswords[(Ie)$1] )); then
      REPLY=reserved
    elif (( $+functions[(e)$1] )); then
      REPLY=function
    elif (( $+builtins[(e)$1] )); then
      REPLY=builtin
    elif (( $+commands[(e)$1] )); then
      REPLY=command
    # zsh 5.2 and older have a bug whereby running 'type -w ./sudo' implicitly
    # runs 'hash ./sudo=/usr/local/bin/./sudo' (assuming /usr/local/bin/sudo
    # exists and is in $PATH).  Avoid triggering the bug, at the expense of
    # falling through to the $() below, incurring a fork.  (Issue #354.)
    #
    # The first disjunct mimics the isrelative() C call from the zsh bug.
    elif {  [[ $1 != */* ]] || is-at-least 5.3 } &&
         ! _zsh_highlight_main__test_type_builtin; then
      REPLY=none
    fi
  fi
  if ! (( $+REPLY )); then
    # Note that 'type -w' will run 'rehash' implicitly.
    #
    # We 'unalias' in a subshell, so the parent shell is not affected.
    #
    # The colon command is there just to avoid a command substitution that
    # starts with an arithmetic expression [«((…))» as the first thing inside
    # «$(…)»], which is area that has had some parsing bugs before 5.6
    # (approximately).
    REPLY="${$(:; (( aliases_allowed )) || unalias -- $1 2>/dev/null; LC_ALL=C _zsh_highlight_main__test_type_builtin)##*: }"
    if [[ $REPLY == 'alias' ]]; then
      may_cache=0
    fi
  fi

  # Cache population
  if (( may_cache )) && (( $+_zsh_highlight_main__command_type_cache )); then
    _zsh_highlight_main__command_type_cache[(e)$1]=$REPLY
  fi

  [[ -n $REPLY ]]
  return $?
}
danielshahaf commented 5 years ago
  • Add funtion zsh_highlight_main__test_type_builtin also the change of PATH can't modify the behavior of the commands in zsh_highlight_main__type

Thanks for the patch!

Please send the same code as a pull request so it's easier to review.

  • I wanted that foo in sudo foo has normal color if ZSH_HIGHLIGHT_SPECIAL_PATH is not exist, but i don't know how to do that.....

Good question.

Right now, it gets highlighted as unknown-token because of line 840 in master, right?

How about adding a new style, "indeterminate"? _zsh_highlight_main__type would return some new value, the loop would map that value to the style [indeterminate] (rather than [unknown-token], and we can make that style have no special highlighting by default. (@phy1729 what do you think?)


_zsh_highlight_main__test_type_builtin() {
}

_zsh_highlight_main__type() {
}

So, to summarize, your overall approach is:

Is that an accurate summary?

Thanks again for the patch; I'll have to sleep on it.

Raizo62 commented 5 years ago

Please send the same code as a pull request so it's easier to review.

It is done.

Is that an accurate summary?

Yes it is. ZSH_HIGHLIGHT_SPECIAL_PATH and ZSH_HIGHLIGHT_SPECIAL_COMMAND are not dependent on each other. These are 2 different approaches. ZSH_HIGHLIGHT_SPECIAL_PATH is more generic, and ZSH_HIGHLIGHT_SPECIAL_COMMAND is more precise

In the description of the pull request, i have put examples to use them.

phy1729 commented 5 years ago

How about adding a new style, "indeterminate"? _zsh_highlight_main__type would return some new value, the loop would map that value to the style [indeterminate] (rather than [unknown-token], and we can make that style have no special highlighting by default. (@phy1729 what do you think?)

I'm all for distinguishing the different meanings of unknown-token. Couple of questions,

I don't see it brought up before (apologies if I missed it), but the current approach would mishighlight other precomamnds (e.g. command ifconfig). This is partially an existing bug (since z-sy-h doesn't keep track of precommands), but the interface should allow for the user or admin to specify to which precommands the special path applies.

danielshahaf commented 5 years ago

This is partially an existing bug (since z-sy-h doesn't keep track of precommands), but the interface should allow for the user or admin to specify to which precommands the special path applies.

That's a textbook case for zstyle's, isn't it? (in order to simulate an associative array having plain arrays for values)

I wonder what to do with multiple precommands (e.g., builtin command doas -u alice sudo -u bob ssh foo ls). I suppose we can make them available in the style context (:…:builtin+command+…:…), or in a parameter for zstyle -e to access.

See also #608.

Note to self: upstream, should zstyle -e make available to the run code the concrete value of the style, as passed to the zstyle -[asb] call?

danielshahaf commented 4 years ago

See also workers/45424, "completion: Add **/sbin to PATH when completing commands like sudo".

danielshahaf commented 4 years ago

This is a special case of #695: once we have the additional styles proposed there, we could easily highlight the command word after sudo (or ssh or whatever) as "indeterminate" rather than as a hard error.

danielshahaf commented 4 years ago

… and a duplicate of #107.