1# busctl(1) completion -*- shell-script -*- 2# SPDX-License-Identifier: LGPL-2.1-or-later 3# 4# This file is part of systemd. 5# 6# systemd is free software; you can redistribute it and/or modify it 7# under the terms of the GNU Lesser General Public License as published by 8# the Free Software Foundation; either version 2.1 of the License, or 9# (at your option) any later version. 10# 11# systemd is distributed in the hope that it will be useful, but 12# WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14# General Public License for more details. 15# 16# You should have received a copy of the GNU Lesser General Public License 17# along with systemd; If not, see <http://www.gnu.org/licenses/>. 18 19__contains_word () { 20 local w word=$1; shift 21 for w in "$@"; do 22 [[ $w = "$word" ]] && return 23 done 24} 25 26__get_machines() { 27 local a b 28 machinectl list --full --no-legend --no-pager 2>/dev/null | 29 { while read a b; do echo " $a"; done; }; 30} 31 32__get_busnames() { 33 local mode=$1 34 local a b 35 busctl $mode list --no-legend --no-pager --full 2>/dev/null | 36 { while read a b; do echo " $a"; done; }; 37} 38 39__get_objects() { 40 local mode=$1 41 local busname=$2 42 local a b 43 busctl $mode tree --list --no-legend --no-pager $busname 2>/dev/null | 44 { while read a b; do echo " $a"; done; }; 45} 46 47__get_interfaces() { 48 local mode=$1 49 local busname=$2 50 local path=$3 51 local a b c 52 busctl $mode introspect --list --no-legend --no-pager $busname $path 2>/dev/null | 53 { while read a b c; do [[ "$b" == "interface" ]] && echo " $a"; done; }; 54} 55 56__get_members() { 57 local mode=$1 58 local busname=$2 59 local path=$3 60 local interface=$4 61 local type=$5 62 local flags=$6 63 local a b c d e 64 busctl $mode introspect --list --no-legend --no-pager $busname $path $interface 2>/dev/null | 65 sed -e 's/^\.//' | 66 { while read a b c d e; do [[ "$b" == "$type" && ( -z $flags || "$e" == "$flags" ) ]] && echo " $a"; done; }; 67} 68 69__get_signature() { 70 local mode=$1 71 local busname=$2 72 local path=$3 73 local interface=$4 74 local member=$5 75 local a b c d 76 busctl $mode introspect --list --no-legend --no-pager $busname $path $interface 2>/dev/null | 77 sed -e 's/^\.//' | { while read a b c d; do [[ "$a" == "$member" && "$c" != '-' ]] && echo " \"$c\""; done; }; 78} 79 80_busctl() { 81 local i n verb comps mode 82 local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} 83 local -A OPTS=( 84 [STANDALONE]='-h --help --version --no-pager --no-legend --system --user 85 --show-machine --unique --acquired --activatable --list 86 -q --quiet --verbose --expect-reply=no --auto-start=no 87 --allow-interactive-authorization=no --augment-creds=no 88 --watch-bind=yes -j -l --full' 89 [ARG]='--address -H --host -M --machine --match --timeout --size --json 90 --destination' 91 ) 92 93 if __contains_word "--user" ${COMP_WORDS[*]}; then 94 mode=--user 95 else 96 mode=--system 97 fi 98 99 if __contains_word "$prev" ${OPTS[ARG]}; then 100 case $prev in 101 --host|-H) 102 comps=$(compgen -A hostname) 103 ;; 104 --machine|-M) 105 comps=$( __get_machines ) 106 ;; 107 --json) 108 comps=$( busctl --json=help 2>/dev/null ) 109 ;; 110 --destination) 111 comps=$( __get_busnames $mode ) 112 ;; 113 esac 114 COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) 115 return 0 116 fi 117 118 if [[ "$cur" = -* ]]; then 119 COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) 120 return 0 121 fi 122 123 local -A VERBS=( 124 [STANDALONE]='list help' 125 [BUSNAME]='status monitor capture tree' 126 [OBJECT]='introspect' 127 [METHOD]='call' 128 [EMIT]='emit' 129 [PROPERTY_GET]='get-property' 130 [PROPERTY_SET]='set-property' 131 ) 132 133 for ((i=0; i < COMP_CWORD; i++)); do 134 if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && 135 ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then 136 verb=${COMP_WORDS[i]} 137 break 138 fi 139 done 140 141 n=$(($COMP_CWORD - $i)) 142 143 if [[ -z ${verb-} ]]; then 144 comps=${VERBS[*]} 145 elif __contains_word "$verb" ${VERBS[STANDALONE]}; then 146 comps='' 147 elif __contains_word "$verb" ${VERBS[BUSNAME]}; then 148 comps=$( __get_busnames $mode) 149 elif __contains_word "$verb" ${VERBS[OBJECT]}; then 150 if [[ $n -eq 1 ]] ; then 151 comps=$( __get_busnames $mode) 152 elif [[ $n -eq 2 ]] ; then 153 comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) 154 elif [[ $n -eq 3 ]] ; then 155 comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) 156 else 157 comps='' 158 fi 159 elif __contains_word "$verb" ${VERBS[METHOD]}; then 160 if [[ $n -eq 1 ]] ; then 161 comps=$( __get_busnames $mode) 162 elif [[ $n -eq 2 ]] ; then 163 comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) 164 elif [[ $n -eq 3 ]] ; then 165 comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) 166 elif [[ $n -eq 4 ]] ; then 167 comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} method) 168 elif [[ $n -eq 5 ]] ; then 169 comps=$( __get_signature $mode ${COMP_WORDS[COMP_CWORD-4]} ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) 170 else 171 comps='' 172 fi 173 elif __contains_word "$verb" ${VERBS[EMIT]}; then 174 comps='' 175 elif __contains_word "$verb" ${VERBS[PROPERTY_GET]}; then 176 if [[ $n -eq 1 ]] ; then 177 comps=$( __get_busnames $mode) 178 elif [[ $n -eq 2 ]] ; then 179 comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) 180 elif [[ $n -eq 3 ]] ; then 181 comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) 182 elif [[ $n -eq 4 ]] ; then 183 comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} property) 184 else 185 comps='' 186 fi 187 elif __contains_word "$verb" ${VERBS[PROPERTY_SET]}; then 188 if [[ $n -eq 1 ]] ; then 189 comps=$( __get_busnames $mode) 190 elif [[ $n -eq 2 ]] ; then 191 comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) 192 elif [[ $n -eq 3 ]] ; then 193 comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) 194 elif [[ $n -eq 4 ]] ; then 195 comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} property writable) 196 elif [[ $n -eq 5 ]] ; then 197 comps=$( __get_signature $mode ${COMP_WORDS[COMP_CWORD-4]} ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) 198 else 199 comps='' 200 fi 201 fi 202 203 COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) 204 return 0 205} 206 207complete -F _busctl busctl 208