Package: pmount
Version: 0.9.23-3+b2
Severity: normal
Tags: patch
File: /etc/bash_completion.d/pmount

When I used tab-completion on a pmount command, it would hang
indefinitely.  The problem was here:

/--------
| grep $mdir /proc/mounts
\--------

Because $mdir isn't set in _pmount(), grep sees only one argument
"/proc/mounts", which it interprets as the search regexp, and so it
waits for input on stdin.

A simple fix would be to copy the initialisation of $mdir from
_pumount(), but I got carried away: I was frustrated by being unable to
complete using the links in /dev/disk/by-*/.

So I include a pair of completions, to go into the more modern location
of /usr/share/bash-completion/completions:

_pmount() {
    # shellcheck disable=SC2034
    local cur prev words cword
    _init_completion || return

   case "$prev" in
       -@(t|-type))
      COMPREPLY=($(grep "^[[:space:]]$cur" /proc/filesystems) $(find "/lib/modules/$(uname -r)/kernel/fs" -name "*.ko" -print0 | xargs -r -0 /sbin/modinfo | sed -ne 's/^alias: *fs-//p' | grep "^$cur"))
      return 0
      ;;

      -@(c|-charset))
      local encodings=(/sys/module/nls_* $(find "/lib/modules/$(uname -r)/kernel/fs/nls" -name '*.ko' -print0 | xargs -r -0 /sbin/modinfo | sed -ne 's/^\(name\|alias\): *//p'))
      COMPREPLY=($(compgen -W "${encodings[*]##*nls_}" -- "$cur"))
      return 0
      ;;
      -@(u|d|f|-umask|-dmask|-fmask))
      case "$cur" in
          '') COMPREPLY=( {0..7} ) ;;
          [0-7]|[0-7][0-7]) COMPREPLY=( $cur{0..7} ) ;;
          [0-7][0-7][0-7]) COMPREPLY=( $cur ) ;;
          *) return 1 ;;
      esac
      return 0
      ;;

      -@(p|-passphrase))
      _filedir
      return 0
      ;;

   esac

   if [[ "$cur" == -* ]]; then
        # transform "--help" output into completion list
       COMPREPLY=($(compgen -W "$(pmount --help | sed -e '/^..-/!d' -e 's/:.*//' -e 's/<[^>]*>//g' -e 'y/,/ /')" -- "$cur"))
   else
       local i allowed removable devices search
       local IFS=$'\n'
       allowed=($(grep -v '^[[:space:]]*#' /etc/pmount.allow))
       removable=($(for i in /sys/block/*
                    do
                        grep -Fxq 1 "$i/removable" || continue
                        # Replace with its partitions, if it has any - N.B. final /. is crucial, as
                        # subsystem entries are symlinks!
                        find "$i"/*/subsystem/. -maxdepth 0 -samefile "$i"/subsystem/. -print0 \
                            | awk -F/ -v RS='\0' -v i="${i##*/}" '{print"/dev/"$(NF-2)} END{if(!NR)print"/dev/"i}'
                        # # alternative non-awk version:
                        # j=$(find "$i"/*/subsystem/. -maxdepth 0 -samefile "$i"/subsystem/. -exec dirname '{}' \;)
                        # sed -e 's,.*/,/dev/,' <<<"${j:-$i}"
                    done))
       # Select only actual block devices that aren't already mounted
       # N.B. expansion of $allowed is unquoted, as wildcards are permitted
       devices=($(for i in ${allowed[*]} "${removable[@]}"; do test -b "$i" && echo "$i"; done | grep -vxF "$(cut -d' ' /proc/mounts -f1)"))
       test "${#devices[@]}" -gt 0 || return 0
       for i in "${devices[@]}"
       do search+=(-o -samefile "$i")
       done
       # alternative names - symlinks in /dev/disk/*/
       devices+=($(find -L /dev/disk -false "${search[@]}"))
       # all found names for mountable block devices, with and without initial /dev/
       COMPREPLY=($(compgen -W "$(printf '%q\n' "${devices[@]}" "${devices[@]#/dev/}")" -- "$cur"))
   fi
} &&
complete -F _pmount pmount
_pumount() {
    # shellcheck disable=SC2034
    local cur prev words cword
    _init_completion || return

    if [[ "$cur" == -* ]]; then
        # transform "--help" output into completion list
       COMPREPLY=($(compgen -W "$(pumount --help | sed -e '/^..-/!d' -e 's/:.*//' -e 's/<[^>]*>//g' -e 'y/,/ /')" -- "$cur"))
   else
       local i mdir devices mounts search symlinks
       mdir=$(readlink -f /media)
       # shellcheck disable=SC2013
       for i in $(cut -d' ' -f1,2 /proc/mounts | grep -F " $mdir/")
       do
           # expand backslash escapes
           i=$(printf '%b' "$i")
           if test -b "$i"
           then
               search+=(-o -samefile "$i")
               devices+=("$i" "${i#/dev/}")
           elif test -d "$i"
           then
               mounts+=("$i" "${i#$mdir/}")
           fi
       done

       # alternative names - symlinks in /dev/disk/*/ and device or mountpoint basenames
       local IFS=$'\n'
       symlinks=($(find -L /dev/disk -false "${search[@]}"))
       COMPREPLY=($(compgen -W "$(printf '%q\n' "${mounts[@]}" "${devices[@]}" "${symlinks[@]}" "${symlinks[@]#/dev/}")" -- "$cur"))
   fi
} &&
complete -F _pumount pumount
I think these are a better match for what pmount and pumount accept as
arguments.  I've tested them with a variety of removable media (with
various partition layouts and some with multiple LUNs) and have been
using this frequently over the past year or so without problems.

I requested a code review, but received no answers,
at https://codereview.stackexchange.com/q/191141

The version I'm using does depend on awk - if that's a problem, I've
included a sed version (commented out) that does the same thing, but
less clearly IMO.


-- System Information:
Debian Release: buster/sid
  APT prefers testing
  APT policy: (900, 'testing'), (900, 'stable'), (400, 'unstable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386, armel

Kernel: Linux 4.17.0-1-amd64 (SMP w/8 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: sysvinit (via /sbin/init)

Versions of packages pmount depends on:
ii  libblkid1  2.32.1-0.1
ii  libc6      2.27-5

pmount recommends no packages.

Versions of packages pmount suggests:
pn  cryptsetup  <none>

Reply via email to