From: Skye Soss Date: Sat, 18 Jul 2026 19:17:24 +0000 (-0500) Subject: setpriv: add bash completion to landlock options X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=664282961705617726f8bec81aefce32d268b26d;p=thirdparty%2Futil-linux.git setpriv: add bash completion to landlock options --landlock-access and --landlock-rule accept colon-separated arguments, which is difficult to generate completions for as Bash defaults to splitting words on colon. This implementation takes inspiration from the git's bash completion script and re-combines the words that were split in this way before processing the rest of the options. For example, `setpriv --landlock-access fs:execute` is provided as COMP_WORDS=('setpriv' '--landlock-access' 'fs' ':' 'execute'). The glue code then constructs words=('setpriv' '--landlock-access' 'fs:execute'), which is used to produce the completion. Signed-off-by: Skye Soss --- diff --git a/bash-completion/setpriv b/bash-completion/setpriv index e508be394..42603f800 100644 --- a/bash-completion/setpriv +++ b/bash-completion/setpriv @@ -1,9 +1,57 @@ +# See bash-completion's _comp_ltrim_colon_completions +_setpriv_ltrim_colon_completions() +{ + local cur="$1" + local colon_word i + if [[ $cur == *:* && $COMP_WORDBREAKS == *:* ]]; then + colon_word=${cur%"${cur##*:}"} + for i in "${!COMPREPLY[@]}"; do + COMPREPLY[i]=${COMPREPLY[i]#"$colon_word"} + done + fi +} + +_setpriv_landlock_rights() +{ + local cmd="$1" access="$2" prefix="$3" cur="$4" + local realcur RIGHTS RIGHTS_ALL WORD + RIGHTS_ALL=$("$cmd" --list-landlock-rights "$access" 2>/dev/null) || return 1 + realcur="${cur##*,}" + prefix+="${cur%"$realcur"}" + for WORD in $RIGHTS_ALL; do + if ! [[ $prefix == *"$WORD"* ]]; then + RIGHTS="$WORD ${RIGHTS:-""}" + fi + done + COMPREPLY=( $(compgen -P "$prefix" -W "$RIGHTS" -- "$realcur") ) + _setpriv_ltrim_colon_completions "$prefix$realcur" +} + _setpriv_module() { local cur prev OPTS COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" + # ':' is a field separator for landlock options, but it is also a default + # COMP_WORDBREAKS character. If it's still one here, COMP_WORDS may have + # been split on it, so glue any nonempty run of ":"s -- and the real word + # before it -- back onto $cur. + if [[ $COMP_WORDBREAKS == *:* ]]; then + local i=$COMP_CWORD + # $cur itself may be the lone ":" (e.g. a trailing "fs:"); absorb + # the word before it first so the loop below sees a real word in + # $cur to keep extending. + if (( i > 0 )) && [[ -n ${COMP_WORDS[i]} && -z ${COMP_WORDS[i]//:/} ]]; then + cur="${COMP_WORDS[i-1]}$cur" + ((i--)) + fi + while (( i > 1 )) && [[ -n ${COMP_WORDS[i-1]} && -z ${COMP_WORDS[i-1]//:/} ]]; do + cur="${COMP_WORDS[i-2]}${COMP_WORDS[i-1]}$cur" + (( i -= 2 )) + done + prev="${COMP_WORDS[i-1]}" + fi case $prev in '--ambient-caps'|'--inh-caps'|'--bounding-set') local prefix realcur INHERIT_ALL INHERIT @@ -94,13 +142,44 @@ _setpriv_module() return 0 ;; '--landlock-access') - # FIXME: how to list landlock accesses? - COMPREPLY=( $(compgen -W "access" -- $cur) ) + case $cur in + *:*) + _setpriv_landlock_rights "$1" "${cur%%:*}" "${cur%%:*}:" "${cur#*:}" + ;; + *) + local WORD OPTS_ACCESS + for WORD in $($1 --list-landlock-access); do + OPTS_ACCESS="$OPTS_ACCESS $WORD $WORD:" + done + compopt -o nospace + COMPREPLY=( $(compgen -W "$OPTS_ACCESS" -- $cur) ) + ;; + esac return 0 ;; '--landlock-rule') - # FIXME: how to list landlock rules? - COMPREPLY=( $(compgen -W "rule" -- $cur) ) + case $cur in + path-beneath:*:*) + # path-beneath:: + local rest="${cur#path-beneath:}" i + local prefix="path-beneath:${rest%%:*}:" + local path="${cur#"$prefix"}" + compopt -o filenames + mapfile -t COMPREPLY < <(compgen -f -- "$path") + for i in "${!COMPREPLY[@]}"; do + COMPREPLY[i]="$prefix${COMPREPLY[i]}" + done + _setpriv_ltrim_colon_completions "$cur" + ;; + path-beneath:*) + compopt -o nospace + _setpriv_landlock_rights "$1" fs 'path-beneath:' "${cur#path-beneath:}" + ;; + *) + compopt -o nospace + COMPREPLY=( $(compgen -W "path-beneath:" -- $cur) ) + ;; + esac return 0 ;; '--seccomp-filter') @@ -137,6 +216,7 @@ _setpriv_module() --apparmor-profile --landlock-access --landlock-rule + --landlock-support --seccomp-filter --help --version"