# shellcheck shell=bash # udevadm(8) completion -*- shell-script -*- # SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # Copyright © 2010 Ran Benita # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __contains_word () { local w word=$1; shift for w in "$@"; do [[ $w = "$word" ]] && return done } __get_all_sysdevs() { local -a devs=(/sys/bus/*/devices/*/ /sys/class/*/*/) printf '%s\n' "${devs[@]%/}" } __get_all_device_nodes() { find /dev -xtype b -o -xtype c } __get_all_device_units() { systemctl list-units -t device --full --no-legend --no-pager --plain 2>/dev/null | { while read -r a b; do echo "$a"; done; } } __get_all_devices() { __get_all_sysdevs __get_all_device_nodes __get_all_device_units } __get_root() { local i for ((i=0; i < COMP_CWORD; i++)); do if [[ "${COMP_WORDS[i]}" = --root=* ]]; then echo "${COMP_WORDS[i]#--root=}" break fi if (( i > 0 )) && [[ "${COMP_WORDS[i-1]}" == "--root" ]]; then echo "${COMP_WORDS[i]}" break fi done } __get_udev_rules_files() { local root=$( __get_root ) ls "$root"/usr/lib/udev/rules.d/*.rules \ "$root"/usr/local/lib/udev/rules.d/*.rules \ "$root"/run/udev/rules.d/*.rules \ "$root"/etc/udev/rules.d/*.rules 2>/dev/null } __get_udev_rules_names() { local -a rules=( $( __get_udev_rules_files ) ) printf '%s\n' "${rules[@]##*/}" } _udevadm() { local i verb comps builtin local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local -A OPTS=( [COMMON]='-h --help -V --version' [DEBUG]='-d --debug' [INFO_STANDALONE]='-r --root -a --attribute-walk -t --tree -x --export -e --export-db -c --cleanup-db -w --wait-for-initialization --value --no-pager --initialized-match --initialized-nomatch' [INFO_ARG]='-q --query -p --path -n --name -P --export-prefix -d --device-id-of-file --property --json --subsystem-match --subsystem-nomatch --attr-match --attr-nomatch --property-match --tag-match --sysname-match --name-match --parent-match' [TRIGGER_STANDALONE]='-v --verbose -n --dry-run -q --quiet -w --settle --wait-daemon --uuid --initialized-match --initialized-nomatch --include-parents' [TRIGGER_ARG]='-t --type -c --action -s --subsystem-match -S --subsystem-nomatch -a --attr-match -A --attr-nomatch -p --property-match -g --tag-match -y --sysname-match --name-match -b --parent-match --prioritized-subsystem' [SETTLE]='-t --timeout -E --exit-if-exists' [CONTROL_STANDALONE]='-e --exit -s --stop-exec-queue -S --start-exec-queue -R --reload --ping --revert --load-credentials' [CONTROL_ARG]='-l --log-priority -p --property -m --children-max -t --timeout --trace' [MONITOR_STANDALONE]='-k --kernel -u --udev -p --property' [MONITOR_ARG]='-s --subsystem-match -t --tag-match' [TEST_STANDALONE]='-v --verbose' [TEST_ARG]='-a --action -N --resolve-names -D --extra-rules-dir --json' [TEST_BUILTIN]='-a --action' [VERIFY_STANDALONE]='--no-summary --no-style' [VERIFY_ARG]='-N --resolve-names --root' [CAT_STANDALONE]='--tldr --config' [CAT_ARG]='--root' [WAIT]='-t --timeout --initialized=no --removed --settle' [LOCK]='-t --timeout -d --device -b --backing -p --print' ) local verbs=(info trigger settle control monitor test-builtin test verify cat wait lock) local builtins=(blkid btrfs dissect_image factory_reset hwdb input_id keyboard kmod net_driver net_id net_setup_link path_id uaccess usb_id) for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" "${verbs[@]}"; then verb=${COMP_WORDS[i]} break fi done if [[ -z ${verb-} ]]; then if [[ "$cur" = -* ]]; then COMPREPLY=( $(compgen -W '${OPTS[COMMON]} ${OPTS[DEBUG]}' -- "$cur") ) else COMPREPLY=( $(compgen -W '${verbs[*]}' -- "$cur") ) fi return 0 fi case $verb in 'info') if __contains_word "$prev" ${OPTS[INFO_ARG]}; then case $prev in -q|--query) comps='name symlink path property all' ;; -p|--path) comps=$( __get_all_sysdevs ) local IFS=$'\n' ;; -n|--name) comps=$( __get_all_device_nodes ) ;; --json) comps=$( udevadm info --json=help ) ;; --parent-match) comps=$( __get_all_sysdevs ) local IFS=$'\n' ;; --name-match) comps=$( __get_all_device_nodes ) ;; *) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ $cur = -* ]]; then comps="${OPTS[COMMON]} ${OPTS[INFO_STANDALONE]} ${OPTS[INFO_ARG]}" else comps=$( __get_all_devices ) local IFS=$'\n' fi ;; 'trigger') if __contains_word "$prev" ${OPTS[TRIGGER_ARG]}; then case $prev in -t|--type) comps='all devices subsystems' ;; -c|--action) comps=$( udevadm trigger --action help ) ;; -y|--sysname-match|-b|--parent-match) comps=$( __get_all_sysdevs ) local IFS=$'\n' ;; --name-match) comps=$( __get_all_device_nodes ) ;; *) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ $cur = -* ]]; then comps="${OPTS[COMMON]} ${OPTS[TRIGGER_STANDALONE]} ${OPTS[TRIGGER_ARG]}" else comps=$( __get_all_devices ) local IFS=$'\n' fi ;; 'settle') if __contains_word "$prev" ${OPTS[SETTLE]}; then case $prev in -E|--exit-if-exists) comps=$( compgen -A file -- "$cur" ) ;; *) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi comps="${OPTS[COMMON]} ${OPTS[SETTLE]}" ;; 'control') if __contains_word "$prev" ${OPTS[CONTROL_ARG]}; then case $prev in -l|--log-priority) comps='alert crit debug emerg err info notice warning' ;; --trace) comps='yes no' ;; *) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi comps="${OPTS[COMMON]} ${OPTS[CONTROL_STANDALONE]} ${OPTS[CONTROL_ARG]}" ;; 'monitor') if __contains_word "$prev" ${OPTS[MONITOR_ARG]}; then case $prev in *) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi comps="${OPTS[COMMON]} ${OPTS[MONITOR_STANDALONE]} ${OPTS[MONITOR_ARG]}" ;; 'test') if __contains_word "$prev" ${OPTS[TEST_ARG]}; then case $prev in -a|--action) comps=$( udevadm test --action help ) ;; -N|--resolve-names) comps=$( udevadm test --resolve-names help ) ;; -D|--extra-rules-dir) comps='' compopt -o dirnames ;; --json) comps=$( udevadm test --json help ) ;; esac elif [[ $cur = -* ]]; then comps="${OPTS[COMMON]} ${OPTS[TEST_ARG]} ${OPTS[TEST_STANDALONE]}" else comps=$( __get_all_devices ) local IFS=$'\n' fi ;; 'test-builtin') if __contains_word "$prev" ${OPTS[TEST_BUILTIN]}; then case $prev in -a|--action) comps=$( udevadm test-builtin --action help ) ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi for ((i=0; i < COMP_CWORD; i++)); do if __contains_word "${COMP_WORDS[i]}" "${builtins[@]}"; then builtin=${COMP_WORDS[i]} break fi done if [[ -z $builtin ]]; then comps="${builtins[@]}" elif [[ $cur = -* ]]; then comps="${OPTS[COMMON]} ${OPTS[TEST_BUILTIN]}" else comps=$( __get_all_devices ) local IFS=$'\n' fi ;; 'verify') if __contains_word "$prev" ${OPTS[VERIFY_ARG]}; then case $prev in -N|--resolve-names) comps=$( udevadm test --resolve-names help ) ;; --root) comps='' compopt -o dirnames ;; *) comps='' ;; esac elif [[ $cur = -* ]]; then comps="${OPTS[COMMON]} ${OPTS[VERIFY_ARG]} ${OPTS[VERIFY_STANDALONE]}" elif [[ $cur = */* ]]; then comps=$( __get_udev_rules_files ) compopt -o dirnames else comps=$( __get_udev_rules_names ) compopt -o default fi ;; 'cat') if __contains_word "$prev" ${OPTS[CAT_ARG]}; then case $prev in --root) comps='' compopt -o dirnames ;; *) comps='' ;; esac elif [[ $cur = -* ]]; then comps="${OPTS[COMMON]} ${OPTS[CAT_ARG]} ${OPTS[CAT_STANDALONE]}" elif __contains_word "--config" ${COMP_WORDS[*]}; then comps="${OPTS[COMMON]} ${OPTS[CAT_ARG]} ${OPTS[CAT_STANDALONE]}" elif [[ $cur = */* ]]; then comps=$( __get_udev_rules_files ) compopt -o dirnames else comps=$( __get_udev_rules_names ) compopt -o default fi ;; 'wait') if __contains_word "$prev" ${OPTS[WAIT]}; then case $prev in *) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ $cur = -* ]]; then comps="${OPTS[COMMON]} ${OPTS[WAIT]}" else comps=$( __get_all_devices ) local IFS=$'\n' fi ;; 'lock') if __contains_word "$prev" ${OPTS[LOCK]}; then case $prev in *) comps='' ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 fi if [[ $cur = -* ]]; then comps="${OPTS[COMMON]} ${OPTS[LOCK]}" else comps='' fi ;; *) comps=${VERBS[*]} ;; esac COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) return 0 } complete -F _udevadm udevadm