Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement auto-detection of subexecutor #12261

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Expand Up @@ -12,3 +12,6 @@ plugins/starship/ @axieax
plugins/universalarchive/ @Konfekt
plugins/wp-cli/ @joshmedeski
plugins/zoxide/ @ajeetdsouza

# Core library owners
lib/00subexecutor.zsh @pepoluan
34 changes: 34 additions & 0 deletions README.md
Expand Up @@ -44,6 +44,7 @@ To learn more, visit [ohmyz.sh](https://ohmyz.sh), follow [@ohmyzsh](https://twi
- [Enable GNU ls In macOS And freeBSD Systems](#enable-gnu-ls-in-macos-and-freebsd-systems)
- [Skip Aliases](#skip-aliases)
- [Disable async git prompt](#disable-async-git-prompt)
- [Specifying a Subexecutor](#specifying-a-subexecutor)
- [Getting Updates](#getting-updates)
- [Updates Verbosity](#updates-verbosity)
- [Manual Updates](#manual-updates)
Expand Down Expand Up @@ -382,6 +383,39 @@ zstyle ':omz:alpha:lib:git' async-prompt no
> It is also not currently aware of "aliases" that are defined as functions. Example of such
> are `gccd`, `ggf`, or `ggl` functions from the git plugin.


### Specifying a Subexecutor

A ***subexecutor*** is a tool that can execute other programs as if running using a different user, usually as `EUID=0` (`root`).

The most well-known subexecutor is probably the `sudo` tool; however, `sudo` is not the only subexecutor tool available. In addition, `sudo` is only available for the Gnu/Linux operating system.

Users of *BSD operating systems usually just use either the `su` tool or the `doas` tool; the latter is now also available for Gnu/Linux through the [OpenDoas](https://github.com/Duncaen/OpenDoas) package.

By default, Oh My Zsh will try to automatically detect which subexecutor is in use (prioritizing detection of `doas` over `sudo`). However, you can explicitly specify which subexecutor you want to use using the following:

```sh
zstyle ':omz' subexecutor $SUBEXECUTOR

# For example, if you want to use sudo as the subexecutor regardless of the result of detection, specify:
zstyle ':omz' subexecutor sudo
```

To allow flexibility/transparency, a function `subex` is provided. With this function, you can invoke the subexecutor without needing to know which subexecutor is available on the system; this will be very helpful for instance if you are writing plugins for Oh My Zsh.

```sh
# Example of editing a root-only-editable file
subex vim /etc/hosts

# Example of creating a new user
subex useradd -m -s $(which zsh) user2
```

Do note that the `subex` function is a thin wrapper around the subexecutor: it passes all arguments to the subexecutor without any processing; it is not meant to be a compatibility thunking layer between the various subexecutor tools available. Care must still be taken if you need to use subexecutor-specific options because what's available for one subexecutor might not be available for the other subexecutors.

The `subex` function dynamically adjusts to in-session changes of `zstyle ':omz' subexecutor` value.


## Getting Updates

By default, you will be prompted to check for updates every 2 weeks. You can choose other update modes by adding a line to your `~/.zshrc` file, **before Oh My Zsh is loaded**:
Expand Down
44 changes: 44 additions & 0 deletions lib/00subexecutor.zsh
@@ -0,0 +1,44 @@
## Provides auto-detection of subexecutor to use

# If in the future a new subexecuter is created, we only need to edit this array
typeset _KNOWN_SUBEXES=( "doas" "sudo" )
typeset _SUBEX

function _SetupSubexecutor() {
local _i
local _cmd
zstyle -s ':omz' 'subexecutor' _SUBEX
if [[ "$_SUBEX" ]]; then
if command -v "$_SUBEX" > /dev/null; then
return 0
fi
print "Cannot find subexecutor '${_SUBEX}'; please check your configuration!" >&2
return 1
fi
for _i in "${_KNOWN_SUBEXES[@]}"; do
if command -v "$_i" > /dev/null; then
_SUBEX="$_i"
break
fi
done
if [[ -z $_SUBEX ]]; then
print "oh-my-zsh: cannot auto-detect subexecutor; please specify explicitly using 'zstyle :omz subexecutor'." >&2
return 1
fi
zstyle ':omz' 'subexecutor' "$_SUBEX"
}

_SetupSubexecutor
unfunction _SetupSubexecutor
unset _KNOWN_SUBEXES

# The alias provides a 'hardcoded', invariant subexecutor to use throughout the shell session
alias _="$_SUBEX "
Comment on lines +35 to +36
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is taken out from lib/misc.zsh because the definition of the alias now relies completely on what subexecutor is being used.


# The function is, in contrast, modifiable by changing the :omz->subexecutor zstyle
function subex() {
local _subex
zstyle -s ':omz' 'subexecutor' _subex
${_subex} "$@"
}

6 changes: 5 additions & 1 deletion lib/correction.zsh
Expand Up @@ -3,8 +3,12 @@ if [[ "$ENABLE_CORRECTION" == "true" ]]; then
alias man='nocorrect man'
alias mkdir='nocorrect mkdir'
alias mv='nocorrect mv'
alias sudo='nocorrect sudo'
alias su='nocorrect su'

zstyle -s ':omz' 'subexecutor' _subex
alias "$_subex"="nocorrect $_subex"
unset _subex
alias subex='nocorrect subex'

setopt correct_all
fi
3 changes: 0 additions & 3 deletions lib/misc.zsh
Expand Up @@ -27,9 +27,6 @@ elif (( ${+commands[more]} )); then
env_default 'PAGER' 'more'
fi

## super user alias
alias _='sudo '

Comment on lines -30 to -32
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to 00subexecutor.zsh

## more intelligent acking for ubuntu users and no alias for users without ack
if (( $+commands[ack-grep] )); then
alias afind='ack-grep -il'
Expand Down
6 changes: 4 additions & 2 deletions lib/termsupport.zsh
Expand Up @@ -95,8 +95,10 @@ function omz_termsupport_preexec {
fi
fi

# cmd name only, or if this is sudo or ssh, the next cmd
local CMD="${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%}"
# cmd name only, or if this is doas/sudo or ssh, the next cmd
local _subex
zstyle -s ':omz' 'subexecutor' _subex
local CMD="${1[(wr)^(*=*|${_subex}|_|subex|ssh|mosh|rake|-*)]:gs/%/%%}"
local LINE="${2:gs/%/%%}"

title "$CMD" "%100>...>${LINE}%<<"
Expand Down