Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
bashdevil - bashmount on udevil
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Unsupported Software
View previous topic :: View next topic  
Author Message
i92guboj
Bodhisattva
Bodhisattva


Joined: 30 Nov 2004
Posts: 10315
Location: Córdoba (Spain)

PostPosted: Tue Feb 11, 2014 6:33 pm    Post subject: bashdevil - bashmount on udevil Reply with quote

Yeah, I suck at naming things, my dogs know that very well :lol:

Regardless, I think this might be useful to someone else, so I put it here. This is a quick hack on bashmount-1.6.2 which allows it to run udisks-less, using udevil as the backend. This will be of use to those running a *kit-less system without udisks, since the only frontend to udevil seems to be spacefm, which is not always convenient.

Beware that this is, as said, a quick hack. That means I only tested the features I use, namely:


  • usb device detection
  • usb device info
  • usb device mount/umount


I didn't test at all cdrom/dvd handling, nor any other feature. So, this probably will have some quirks here and there. I am willing to fix issues if someone reports them, as time permits. This is a simple bash script, so you can just put it somewhere in your path and be done. I'll probably hack the bashmount ebuild at some point to support this as an option, but don't hold your breath for it :)

Oh, almost forgot, this relies in the --enumerate-device-files feature of devmon (devmon is part of udevil). That feature is only available from udevil-0.4.2, which is currently keyworded ~x86 and ~amd64. So, if you want to use this script you will have to keyword udevil conveniently and emerge the 0.4.3 version, which is in portage. 0.4.1 WILL NOT WORK.

Code:

#!/bin/bash
#
# relies upon udevil 0.4.2, which has --enumerate-device-files!!!
#
#=============================================================================#
#        FILE: bash-devil                                                     #
#     VERSION: 1.6.2                                                          #
# DESCRIPTION: bash-devil is a menu-driven bash script that uses udevil to    #
#              easily mount, unmount or eject removable devices without       #
#              dependencies on any GUI or desktop environment. An extensive   #
#              configuration file allows many aspects of the script to be     #
#              modified and custom commands to be run on devices.             #
#              bash-devil is a quick hack, forked from bashmount-1.6.2,       #
#              from Jamie Nguyen, all credit goes to him.                     #
#              modifications to migrate to udevil are -at least for now-      #
#              very minimal, so...                                            #
#     LICENSE: GPLv2                                                          #
#      AUTHOR: Jamie Nguyen                                                   #
# UDEVIL PORT: Jesús Guerrero                                                 #
#=============================================================================#

# Copyright (C) 2011 Jamie Nguyen
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License v2 as published by the
# Free Software Foundation.
#
# This program 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 General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA


declare -r VERSION="1.6.2"

#-------------------------------------#
#           CONFIGURATION             #
#-------------------------------------#
# {{{

# Make sure that user defined options will not interfere with grep.
unset GREP_OPTIONS

# Set some defaults for the configuration variables. See bash-devil.conf for
# more information.
declare optical_devices="-E ^/dev/sr[0-9]+"
declare removable_devices="-E ^/dev/sd[b-z][0-9]*|^/dev/mmcblk[0-9]+p*[0-9]*"
declare mount_options="--mount-options nosuid,noexec,noatime"

declare -i show_removable=1
declare -i show_optical=1
declare -i show_commands=1
declare -i colourize=1
declare -i show_internal=0
declare -i show_removable_device_filename=1
declare -i show_optical_device_filename=1
declare -i fancy_sort=0
declare -i custom1_show=0
declare -i custom2_show=0
declare -i custom3_show=0
declare -i custom4_show=0
declare -i custom5_show=0
declare -i custom6_show=0
declare -i run_post_mount=0
declare -i run_post_unmount=0

declare -a blacklist=( )

filemanager() {
   cd "${1}" && ${SHELL}
   exit 0
}
post_mount() {
   error "No command specified in 'bash-devil.conf'."
   return 1
}
post_unmount() {
   error "No command specified in 'bash-devil.conf'."
   return 1
}

declare CONFIGFILE=

if [[ -n "${XDG_CONFIG_HOME}" ]]; then
   CONFIGFILE="${XDG_CONFIG_HOME}/bash-devil/config"
else
   CONFIGFILE="${HOME}/.config/bash-devil/config"
fi

if [[ ! -f "${CONFIGFILE}" ]]; then
   CONFIGFILE="/etc/bash-devil.conf"
fi

if [[ -f "${CONFIGFILE}" ]]; then
   . "${CONFIGFILE}"
   if (( $? != 0 )); then
      printf '%s' "bash-devil: '${CONFIGFILE}': "
      printf '%s\n' "failed to source configuration file"
      exit 78
   fi
fi

type -p udevil >/dev/null 2>&1
if (( $? != 0 )); then
   type -p udevil >/dev/null 2>&1
   if (( $? != 0 )); then
      printf '%s\n' "bash-devil: 'udevil': command not found"
      exit 69
   fi
fi
# }}}

#-------------------------------------#
#         GENERAL FUNCTIONS           #
#-------------------------------------#
# {{{

unset ALL_OFF BOLD BLUE GREEN RED
if (( colourize )); then
   if tput setaf 0 >/dev/null 2>&1; then
      ALL_OFF="$(tput sgr0)"
      BOLD="$(tput bold)"
      BLUE="${BOLD}$(tput setaf 4)"
      GREEN="${BOLD}$(tput setaf 2)"
      RED="${BOLD}$(tput setaf 1)"
   else
      ALL_OFF="\e[1;0m"
      BOLD="\e[1;1m"
      BLUE="${BOLD}\e[1;34m"
      GREEN="${BOLD}\e[1;32m"
      RED="${BOLD}\e[1;31m"
   fi
   readonly ALL_OFF BOLD BLUE GREEN RED
fi

msg() {
   printf '%s\n' "${GREEN}==>${ALL_OFF}${BOLD} ${@}${ALL_OFF}" >&2
}
error() {
   printf '%s\n' "${RED}==>${ALL_OFF}${BOLD} ERROR: ${@}${ALL_OFF}" >&2
}
clear_screen() {
   clear
   printf '%s\n\n' "bash-devil ${VERSION}"
}
print_commands() {
   print_separator_commands
   printf '%s' "${BLUE}e${ALL_OFF}: eject   ${BLUE}i${ALL_OFF}: info   "
   printf '%s' "${BLUE}m${ALL_OFF}: mount   ${BLUE}o${ALL_OFF}: open   "
   printf '%s' "${BLUE}u${ALL_OFF}: unmount"
   printf '\n\n'
   printf '%s' "${BLUE}a${ALL_OFF}: unmount all   "
   printf '%s' "${BLUE}r${ALL_OFF}: refresh   "
   printf '%s' "${BLUE}q${ALL_OFF}: quit   ${BLUE}?${ALL_OFF}: help"
   printf '\n\n'
}
print_submenu_commands() {
   local -i info_mounted=

   print_separator_commands
   printf '%s' "${BLUE}e${ALL_OFF}: eject   ${BLUE}i${ALL_OFF}: info   "

   info_mounted="$(info_mounted "${devname}")"

   (( !info_mounted )) && printf '%s' "${BLUE}m${ALL_OFF}: mount   "

   printf '%s' "${BLUE}o${ALL_OFF}: open   "

   (( info_mounted )) && printf '%s' "${BLUE}u${ALL_OFF}: unmount"

   printf '\n\n'
   printf '%s' "${BLUE}b${ALL_OFF}: back   ${BLUE}r${ALL_OFF}: refresh   "
   printf '%s' "${BLUE}q${ALL_OFF}: quit   ${BLUE}?${ALL_OFF}: help"
   printf '\n'

   if (( custom1_show )) \
      || (( custom2_show )) \
      || (( custom3_show )); then
      printf '\n'
   fi

   if (( custom1_show )) && [[ -n "${custom1_desc}" ]]; then
      printf '%s' "${BLUE}1${ALL_OFF}: ${custom1_desc}   "
   fi

   if (( custom2_show )) && [[ -n "${custom2_desc}" ]]; then
      printf '%s' "${BLUE}2${ALL_OFF}: ${custom2_desc}   "
   fi

   if (( custom3_show )) && [[ -n "${custom3_desc}" ]]; then
      printf '%s' "${BLUE}3${ALL_OFF}: ${custom3_desc}   "
   fi

   if (( custom1_show )) \
      || (( custom2_show )) \
      || (( custom3_show )); then
      printf '\n'
   fi

   if (( custom4_show )) \
      || (( custom5_show )) \
      || (( custom6_show )); then
      printf '\n'
   fi

   if (( custom4_show )) && [[ -n "${custom4_desc}" ]]; then
      printf '%s' "${BLUE}4${ALL_OFF}: ${custom4_desc}   "
   fi

   if (( custom5_show )) && [[ -n "${custom5_desc}" ]]; then
      printf '%s' "${BLUE}5${ALL_OFF}: ${custom5_desc}   "
   fi

   if (( custom6_show )) && [[ -n "${custom6_desc}" ]]; then
      printf '%s' "${BLUE}6${ALL_OFF}: ${custom6_desc}   "
   fi

   if (( custom4_show )) \
      || (( custom5_show )) \
      || (( custom6_show )); then
      printf '\n'
   fi
}
enter_to_continue() {
   printf '\n'
   read -r -e -p "Press [${BLUE}enter${ALL_OFF}] to continue: " null
}
invalid_command() {
   printf '\n'
   error "Invalid command. See the help menu."
   enter_to_continue
}
print_separator() {
   printf '%s\n\n' "====================================================="
}
print_separator_commands() {
   printf '%s\n\n' "===================== COMMANDS ======================"
}
print_separator_device() {
   printf '%s\n\n' "==================== DEVICE MENU ===================="
}
print_separator_optical() {
   printf '%s\n\n' "=================== OPTICAL MEDIA ==================="
}
print_separator_removable() {
   printf '%s\n\n' "================== REMOVABLE MEDIA =================="
}
print_help() {
   clear_screen
   print_commands

   print_separator
   printf '%s' "${GREEN}==>${ALL_OFF} "
   printf '%s' "${BOLD}To mount the first device, enter ${ALL_OFF}"
   printf '%s' "${BLUE}1m${ALL_OFF}"
   printf '%s' "${BOLD}.${ALL_OFF}"
   printf '\n\n'
   printf '%s' "${GREEN}==>${ALL_OFF} "
   printf '%s' "${BOLD}To open the mountpath directory of the first${ALL_OFF}"
   printf '\n\n'
   printf '%s' "${BOLD}    device (mounting if required), enter "
   printf '%s' "${BLUE}1o${ALL_OFF}"
   printf '%s' "${BOLD}.${ALL_OFF}"
   printf '\n\n'
   printf '%s' "${GREEN}==>${ALL_OFF} "
   printf '%s' "${BOLD}To view a device sub-menu, "
   printf '%s' "just enter the number.${ALL_OFF}"
   printf '\n\n'
   printf '%s' "${GREEN}==>${ALL_OFF} "
   printf '%s' "${BLUE}a${ALL_OFF}"
   printf '%s' "${BOLD}, "
   printf '%s' "${BLUE}r${ALL_OFF}"
   printf '%s' "${BOLD}, "
   printf '%s'   "${BLUE}q${ALL_OFF} "
   printf '%s' "${BOLD}and "
   printf '%s' "${BLUE}?${ALL_OFF} "
   printf '%s' "${BOLD}do not require a number.${ALL_OFF}"
   printf '\n\n'
   print_separator

   enter_to_continue
}
print_help_sub() {
   clear_screen

   print_submenu_commands

   printf '\n'
   print_separator
   printf '%s' "${GREEN}==>${ALL_OFF} "
   printf '%s' "${BOLD}To perform a command, enter a character.${ALL_OFF}"
   printf '\n\n'
   printf '%s' "${GREEN}==>${ALL_OFF} "
   printf '%s' "${BOLD}For example, to mount this device, enter ${ALL_OFF}"
   printf '%s' "${BLUE}m${ALL_OFF}"
   printf '%s' "${BOLD}.${ALL_OFF}"
   printf '\n\n'
   print_separator

   enter_to_continue
}
# }}}

#-------------------------------------#
#            INTERNAL API             #
#-------------------------------------#
# {{{

#############################
### INFORMATION RETRIEVAL ###
#############################

# Functions to retrieve information. These functions simply parse the output
# of udevil --show-info.

# arg 1: device file
info_blank() {
   udevil --show-info ${1} \
      | grep -m 1 -w "^[[:space:]]*blank:" \
      | awk '{print $2}'
}
# arg 1: device file
info_has_media() {
   udevil --show-info ${1} \
      | grep -m 1 -w "^[[:space:]]*has media:" \
      | awk '{print $3}'
}
# arg 1: device file
info_internal() {
   udevil --show-info ${1} \
      | grep -m 1 -w "^[[:space:]]*system internal:" \
      | awk '{print $3}'
}
# arg 1: device file
info_label() {
   local info_label="$(udevil --show-info ${1} \
      | grep -m 1 -w "^  label:" \
      | awk '{$1="";print substr($0, index($0,$2))}')"
   [[ -n "${info_label}" ]] && printf '%s\n' "${info_label}"
}
# arg 1: device file
info_media() {
   udevil --show-info ${1} \
      | grep -m 1 -w "^[[:space:]]*media:" \
      | awk '{print $2}'
}
# arg 1: device file
info_model() {
   udevil --show-info ${1} \
      | grep -m 1 -w "^[[:space:]]*model:" \
      | awk '{$1="";print substr($0, index($0,$2))}'
}
# arg 1: device file
info_mounted() {
   udevil --show-info ${1} \
      | grep -m 1 -w "^[[:space:]]*is mounted:" \
      | awk '{print $3}'
}
# arg 1: device file
info_mountpath() {
   udevil --show-info ${1} \
      | grep -m 1 -w "^[[:space:]]*mount paths:" \
      | awk '{$1="";$2="";print substr($0, index($0,$3))}'
}
# arg 1: device file
info_type() {
   udevil --show-info ${1} \
      | grep -m 1 -w "^[[:space:]]*type:" \
      | awk '{print $2}'
}
# arg 1: device file
info_vendor() {
   udevil --show-info ${1} \
      | grep -m 1 -w "^[[:space:]]*vendor:" \
      | awk '{$1="";print substr($0, index($0,$2))}'
}

# arg 1: integer
# The size of the device/partition is given in bytes, so let's convert that
# to something more readable. Rounding done in bash is not accurate at all
# but we'll mitigate that by only rounding when the numbers get quite large.
convert_size() {
   local -i old_size="${1}"
   local new_size=

   if (( old_size > 21474836480 )); then
      new_size="$(( old_size / 1073741824 )) GB"
   elif (( old_size > 10485760 )); then
      new_size="$(( old_size / 1048576 )) MB"
   elif (( old_size > 10240 )); then
      new_size="$(( old_size / 1024 )) kB"
   else
      new_size="${old_size} bytes"
   fi

   printf '%s\n' "${new_size}"
}
# arg 1: device file
info_device_size() {
   local info_device_size=

   info_device_size="$(udevil --show-info ${1} \
      | grep -m 1 -w "^[[:space:]]*size:" \
      | awk '{print $2}')"

   if [[ -n "${info_device_size}" ]]; then
      info_device_size="$(convert_size "${info_device_size}")"
      printf '%s\n' "${info_device_size}"
   fi
}
# arg 1: device file
info_partition_size() {
   local info_partition_size=

   info_partition_size="$(udevil --show-info ${1} \
      | grep -m 1 -w "  size:" \
      | awk '{print $2}')"

   if [[ -n "${info_partition_size}" ]]; then
      info_partition_size="$(convert_size "${info_partition_size}")"
      printf '%s\n' "${info_partition_size}"
   fi
}

###########################
### DEVICE MANIPULATION ###
###########################

# arg 1: device file
# Here we check if the device actually exists, just in case the list of
# available devices has not been refreshed for a while.
check_device() {
   devmon --enumerate-device-files | grep -ow ^${1}$ >/dev/null 2>&1

   if (( $? != 0 )); then
      printf '\n'
      error "${1} is no longer available."
      enter_to_continue
      return 1
   fi

   return 0
}
# arg 1: device file
# Eject the device, unmounting with a call to action_unmount if required.
action_eject() {
   local -i info_mounted=

   check_device "${1}" || return 1

   info_mounted="$(info_mounted "${1}")"
   (( info_mounted )) && action_unmount ${1}

   info_mounted="$(info_mounted "${1}")"
   if (( !info_mounted )); then
      printf '\n'
      msg "Ejecting ${1} ..."
      printf '\n'
      udevil --eject ${1}
      # Give the device some time to eject. If we don't then sometimes
      # the ejected device will still be present when returning to the
      # main menu.
      sleep 2
   fi

   enter_to_continue
}
# arg 1: device file
# Pipe the device information into a pager for easy viewing.
action_info() {
   check_device "${1}" || return 1
   udevil --show-info "${1}" | less
}
# arg 1: device file
# Mount the device if it is not already mounted, and run the post_mount hook
# after a successful mount operation if it has been enabled.
action_mount() {
   local -i info_mounted=

   check_device "${1}" || return 1

   info_mounted="$(info_mounted ${1})"
   if (( info_mounted )); then
      printf '\n'
      error "${1} is already mounted."
      enter_to_continue
      return 1
   fi

   printf '\n'
   msg "Mounting ${1} ..."
   printf '\n'
   udevil --mount ${1} ${mount_options}

   info_mounted="$(info_mounted "${1}")"
   if (( !info_mounted )); then
      printf '\n'
      error "${1} could not be mounted."
      enter_to_continue
      return 1
   fi

   printf '\n'
   msg "${1} mounted successfully."

   (( run_post_mount )) && post_mount ${1}

   enter_to_continue
}
# arg 1: device file
# Open the device with the filemanager specified in the configuration file,
# mounting with a call to action_mount if required.
action_open() {
   local -i info_mounted=

   check_device "${1}" || return 1

   info_mounted="$(info_mounted "${1}")"
   if (( !info_mounted )); then
      printf '\n'
      msg "Mounting and opening ${1} ..."
      printf '\n'
      udevil --mount ${1} ${mount_options}

      info_mounted="$(info_mounted "${1}")"
      if (( info_mounted )); then
         printf '\n'
         msg "${1} mounted successfully."
      else
         printf '\n'
         error "${1} could not be mounted."
         enter_to_continue
         return 1
      fi
   fi

   info_mountpath="$(info_mountpath "${1}")"
   if [[ -z "${info_mountpath}" ]]; then
      printf '\n'
      error "No mountpath detected."
      enter_to_continue
      return 1
   fi

   printf '\n'
   msg "Opening ${1} ..."
   printf '\n'
   filemanager "${info_mountpath}"
   enter_to_continue
}
# arg 1: device file
# Unmount the device if it is not already unmounted, and run the post_unmount
# hook after a successful unmount operation if it has been enabled.
action_unmount() {
   local -i info_mounted=

   check_device "${1}" || return 1

   info_mounted="$(info_mounted "${1}")"
   if (( !info_mounted )); then
      printf '\n'
      error "${1} is already unmounted."
      return 1
   fi

   printf '\n'
   msg "Unmounting ${1} ..."
   printf '\n'
   udevil --unmount ${1}

   info_mounted="$(info_mounted "${1}")"
   if (( info_mounted )); then
      printf '\n'
      error "${1} could not be unmounted."
      return 1
   fi

   msg "${1} unmounted successfully."

   (( run_post_unmount )) && post_unmount ${1}
}
fancy_sort() {
   # This is a very hacky way to sort devices so that /dev/sdc11 wont come
   # before /dev/sdc2, which happens due to a shortcoming of the sort command.

   # We won't tell bash that partition_number is a number, otherwise it
   # breaks when leading zeros are added (interpreted as hex).
   local devname= devmajor= partition_number=
   local -i array_position=

   # First lets put a leading zero in front of single digits (sdc1 -> sdc01).
   # We are going to ignore /dev/mmcblk*p* devices... too complicated to sort
   # and not really worthwhile since most users won't have 10 such devices.
   for devname in ${removable[@]}; do
      if [[ "${devname}" =~ ^/dev/dm-[0-9]+ ]]; then
         devmajor="${devname%%[0-9]*}"
      elif [[ "${devname}" =~ ^/dev/fd[0-9]+ ]]; then
         devmajor="${devname%%[0-9]*}"
      elif [[ "${devname}" =~ ^/dev/sd[a-z][0-9]+ ]]; then
         devmajor="${devname%%[0-9]*}"
      else
         (( ++array_position )); continue
      fi

      if [[ "${devname}" = "${devmajor}" ]]; then
         (( ++array_position )); continue
      fi

      partition_number="${devname#${devmajor}}"
      removable[array_position]=${devmajor}$(printf \
         '%02d' "${partition_number}")
      (( ++array_position )); continue
   done

   # Now the device array can be sorted properly.
   removable=( $(printf '%s\n' "${removable[@]}" | sort) )

   # Now let's remove those leading zeros that we added.
   array_position=0
   for devname in ${removable[@]}; do
      if [[ "${devname}" =~ ^/dev/dm-[0-9]+ ]]; then
         devmajor="${devname%%[0-9]*}"
      elif [[ "${devname}" =~ ^/dev/fd[0-9]+ ]]; then
         devmajor="${devname%%[0-9]*}"
      elif [[ "${devname}" =~ ^/dev/sd[a-z][0-9]+ ]]; then
         devmajor="${devname%%[0-9]*}"
      else
         (( ++array_position )); continue
      fi

      if [[ "${devname}" = "${devmajor}" ]]; then
         (( ++array_position )); continue
      fi

      partition_number="${devname#${devmajor}}"
      removable[array_position]=${devmajor}${partition_number#0}
      (( ++array_position )); continue
   done
}
# }}}

#-------------------------------------#
#           MENU FUNCTIONS            #
#-------------------------------------#
# {{{

# Here we list devices matched by the "removable_devices" regex specified in
# the configuration file.
removable_devices() {
   local -a removable=( )

   device_number=0
   all_media=( )
   mounted_media=( )

   removable=( $(devmon --enumerate-device-files \
      | grep -ow ${removable_devices} | sort) )

   if (( fancy_sort )) && (( ${#removable[*]} > 1 )); then
      fancy_sort
   fi

   print_separator_removable

   for devname in ${removable[@]}; do
      local devmajor= info_label= menu_number=
      local -i internal=0 info_mounted=0 partitions=0

      # Check here to see if a device such as /dev/sdb has partitions. If
      # there are partitions, such as /dev/sdb1, then hide /dev/sdb from
      # being shown.
      if [[ "${devname}" =~ ^/dev/mmcblk[0-9]+p*[0-9]* ]]; then
         devmajor="${devname%%p[0-9]*}"
         if [[ "${devname}" = "${devmajor}" ]]; then
            partitions="$(devmon --enumerate-device-files \
               | grep -ow -E ^${devname}p[0-9]+ -c)"
            if (( partitions )); then
               continue
            fi
         fi
      else
         devmajor="${devname%%[0-9]*}"
         if [[ "${devname}" = "${devmajor}" ]]; then
            partitions="$(devmon --enumerate-device-files \
               | grep -ow -E ^${devname}[0-9]+ -c)"
            if (( partitions )); then
               continue
            fi
         fi
      fi

      internal="$(info_internal "${devmajor}")"

      if (( internal )) && (( !show_internal )); then
         continue
      fi

      if (( !internal )) || (( show_internal )); then

         # Hide blacklisted devices.
         for string in "${blacklist[@]}"; do
            udevil --show-info "${devname}" \
               | grep -E "${string}" >/dev/null 2>&1
            (( $? == 0 )) && continue 2
         done

         (( ++device_number ))

         info_label="$(info_label "${devname}")"
         # If no label is present, then use information about the device
         # instead.
         if [[ -z "${info_label}" ]]; then
            info_label="$(info_label "${devmajor}")"
            if [[ -z "${info_label}" ]]; then
               info_label="$(info_model "${devmajor}")"
            fi
            if [[ -z "${info_label}" ]]; then
               info_label="$(info_vendor "${devmajor}")"
            fi
            if [[ -z "${info_label}" ]]; then
               info_label="No label"
            else
               info_label="No label (${info_label})"
            fi
         fi

         if (( device_number < 10 )); then
            menu_number=" ${device_number}"
         else
            menu_number="${device_number}"
         fi

         info_mounted="$(info_mounted "${devname}")"
         if (( !info_mounted )); then
            if (( !show_removable_device_filename )); then
               printf '%s' "${BLUE}${menu_number})${ALL_OFF} "
               printf '%s\n' "${info_label}"
            else
               printf '%s' "${BLUE}${menu_number})${ALL_OFF} "
               printf '%s' "${devname#/dev/}: "
               printf '%s\n' "${info_label}"
            fi
         else
            if (( !show_removable_device_filename )); then
               printf '%s' "${BLUE}${menu_number})${ALL_OFF} "
               printf '%s' "${info_label} "
               printf '%s\n' "${GREEN}[mounted]${ALL_OFF}"
            else
               printf '%s' "${BLUE}${menu_number})${ALL_OFF} "
               printf '%s' "${devname#/dev/}: "
               printf '%s\n' "${info_label} ${GREEN}[mounted]${ALL_OFF}"
            fi
            mounted_media[${#mounted_media[*]}]=${devname}
         fi

         all_media[${#all_media[*]}]=${devname}
      fi
   done

   printf '\n'
}

# Here we list devices matched by the "optical_devices" regex specified in
# the configuration file.
optical_devices() {
   local -a optical=( )
   local menu_number=
   local -i info_mounted=

   if (( !show_removable )); then
      device_number=0
      all_media=( )
      mounted_media=( )
   fi

   optical=( $(devmon --enumerate-device-files \
      | grep -ow ${optical_devices} | sort) )

   print_separator_optical

   for devname in ${optical[@]}; do
      local info_label=
      local -i blank= info_has_media= info_mounted=

      info_has_media="$(info_has_media "${devname}")"
      if (( !info_has_media )); then
         continue
      fi

      # Hide blacklisted devices.
      for string in "${blacklist[@]}"; do
         udevil --show-info "${devname}" \
            | grep -E "${string}" >/dev/null 2>&1
         (( $? == 0 )) && continue 2
      done

      (( ++device_number ))
      blank="$(info_blank "${devname}")"
      if (( blank )); then
         info_label="Blank media"
      else
         info_label="$(info_label ${devname})"
         [[ -z "${info_label}" ]] && info_label="$(info_model "${devname}")"
         [[ -z "${info_label}" ]] && info_label="No label"
      fi

      if (( device_number < 10 )); then
         menu_number=" ${device_number}"
      else
         menu_number="${device_number}"
      fi

      info_mounted="$(info_mounted "${devname}")"
      if (( !info_mounted )); then
         if (( !show_optical_device_filename )); then
            printf '%s' "${BLUE}${menu_number})${ALL_OFF} "
            printf '%s\n' "${info_label}"
         else
            printf '%s' "${BLUE}${menu_number})${ALL_OFF} "
            printf '%s' "${devname#/dev/}: "
            printf '%s\n' "${info_label}"
         fi
      else
         if (( !show_optical_device_filename )); then
            printf '%s' "${BLUE}${menu_number})${ALL_OFF} "
            printf '%s' "${info_label} "
            printf '%s\n' "${GREEN}[mounted]${ALL_OFF}"
         else
            printf '%s' "${BLUE}${menu_number})${ALL_OFF} "
            printf '%s' "${devname#/dev/}: "
            printf '%s\n' "${info_label} ${GREEN}[mounted]${ALL_OFF}"
         fi
         mounted_media[${#mounted_media[*]}]=${devname}
      fi

      all_media[${#all_media[*]}]=${devname}
   done

   printf '\n'
}

# Here we provide a submenu for each device, which also displays any custom
# commands that have been set.
submenu() {
   local devmajor= info_label= info_model= info_mountpath= info_vendor=
   local info_device_size= info_media= info_partition_size= info_type=
   local -i info_mounted= is_optical=

   check_device "${devname}" || return 1

   printf '%s\n' "${devname}" | grep -ow ${optical_devices} >/dev/null 2>&1
   if (( $? != 0 )); then
      is_optical=0; devmajor="${devname%%[0-9]*}"
   else
      is_optical=1; devmajor="${devname}"
   fi

   clear_screen

   print_separator_device

   info_mounted="$(info_mounted "${devname}")"
   if (( info_mounted )); then
      info_mountpath="$(info_mountpath "${devname}")"
   fi

   info_label="$(info_label "${devname}")"
   info_vendor="$(info_vendor "${devmajor}")"
   info_model="$(info_model "${devmajor}")"
   info_type="$(info_type "${devname}")"
   info_device_size="$(info_device_size "${devmajor}")"

   if (( is_optical )); then
      info_media="$(info_media ${devname})"
   fi

   if (( !is_optical )) && [[ "${devname}" != "${devmajor}" ]]; then
      info_partition_size="$(info_partition_size "${devname}")"
   fi

   printf '%s\n' "device           : ${devname}"
   printf '%s\n' "label            : ${info_label}"
   printf '%s' "mounted          : "
   if (( info_mounted )); then
      printf '%s\n' "${GREEN}yes${ALL_OFF}"
      printf '%s\n\n' "mountpath        : ${info_mountpath}"
   else
      printf '%s\n\n' "${RED}no${ALL_OFF}"
   fi
   printf '%s\n' "vendor           : ${info_vendor}"
   printf '%s\n' "model            : ${info_model}"
   printf '%s\n' "type             : ${info_type}"
   if [[ -n "${info_media}" ]]; then
      printf '%s\n' "media            : ${info_media}"
   fi
   if [[ -n "${info_partition_size}" ]]; then
      printf '%s\n' "size (partition) : ${info_partition_size}"
   fi
   printf '%s\n' "size (device)    : ${info_device_size}"

   if (( show_commands )); then
      printf '\n'
      print_submenu_commands
   fi

   printf '\n'
   print_separator
   printf '\n'

   read -r -e -p "Command: " action

   case "${action}" in
   "e")
      action_eject "${devname}"
      return 0;;
   "i")
      action_info "${devname}"
      return 0;;
   "m")
      action_mount "${devname}"
      return 0;;
   "o")
      action_open "${devname}"
      return 0;;
   "u")
      action_unmount "${devname}"
      enter_to_continue
      return 0;;
   "b")
      return 1;;
   "r"|"")
      return 0;;
   "q")
      exit;;
   "?")
      print_help_sub
      return 0;;
   "1")
      if (( custom1_show )); then
         printf '\n'
         msg "Running custom command '${custom1_desc}' ..."
         printf '\n'
         custom1_command "${devname}"
         enter_to_continue
      else
         invalid_command
      fi
      return 0;;
   "2")
      if (( custom2_show )); then
         printf '\n'
         msg "Running custom command '${custom2_desc}' ..."
         printf '\n'
         custom2_command "${devname}"
         enter_to_continue
      else
         invalid_command
      fi
      return 0;;
   "3")
      if (( custom3_show )); then
         printf '\n'
         msg "Running custom command '${custom3_desc}' ..."
         printf '\n'
         custom3_command "${devname}"
         enter_to_continue
      else
         invalid_command
      fi
      return 0;;
   "4")
      if (( custom4_show )); then
         printf '\n'
         msg "Running custom command '${custom4_desc}' ..."
         printf '\n'
         custom4_command "${devname}"
         enter_to_continue
      else
         invalid_command
      fi
      return 0;;
   "5")
      if (( custom5_show )); then
         printf '\n'
         msg "Running custom command '${custom5_desc}' ..."
         printf '\n'
         custom5_command "${devname}"
         enter_to_continue
      else
         invalid_command
      fi
      return 0;;
   "6")
      if (( custom6_show )); then
         printf '\n'
         msg "Running custom command '${custom6_desc}' ..."
         printf '\n'
         custom6_command "${devname}"
         enter_to_continue
      else
         invalid_command
      fi
      return 0;;
    * )
      invalid_command
      return 0;;
   esac
}

# Here we decide what action to take depending on input from the user.
select_action() {
   local devname=

   print_separator
   printf '\n'
   read -r -e -p "Command: " action

   if [[ ! "${action}" =~ ^[1-9][0-9]*[eimou]?$ ]]; then
      case "${action}" in
      "a")
         if (( !${#mounted_media[@]} )); then
            printf '\n'
            error "No devices mounted."
            enter_to_continue
            return 1
         fi
         printf '\n'
         read -r -e -p "Unmount all devices [y/N]?: " unmount
         if [[ "${unmount}" != "y" ]] && [[ "${unmount}" != "Y" ]]; then
            return 0
         fi
         clear_screen
         for devname in ${mounted_media[@]}; do
            action_unmount "${devname}" || continue
         done
         enter_to_continue
         return 1;;
      "r"|"")
         return 0;;
      "q"|"b")
         exit 0;;
      "?")
         print_help
         return 0;;
       * )
         invalid_command
         return 1;;
      esac
   fi

   local -i number=
   local letter= devname=

   number="$(($(printf '%s\n' "${action}" | grep -o -E ^[1-9][0-9]*)-1))"
   letter="$(printf '%s\n' "${action}" | grep -o -E [eimou]{1}$)"

   if (( number >= device_number )); then
      invalid_command; return 1
   fi

   devname="${all_media[number]}"

   case "${letter}" in
   "e")
      action_eject "${devname}"
      return 0;;
   "i")
      action_info "${devname}"
      return 0;;
   "m")
      action_mount "${devname}"
      return 0;;
   "o")
      action_open "${devname}"
      return 0;;
   "u")
      action_unmount "${devname}"
      enter_to_continue; return 0;;
    * )
      while true; do
         submenu || break
      done
      return 0;;
   esac
}
# }}}

#-------------------------------------#
#              INT MAIN               #
#-------------------------------------#

while true; do
   declare -i device_number= # Tracks number assigned to each device.
   declare -a mounted_media=( )
   declare -a all_media=( )
   clear_screen
   (( show_removable )) && removable_devices
   (( show_optical )) && optical_devices
   (( show_commands )) && print_commands
   select_action
done

# vim: set ts=4 sw=4 noet foldmethod=marker :


EDITED: so finally I hacked an ebuild for this. It has two use flags, namely, udisks and udevil. You can only select one at a time, obviously. You can fetch it here
Back to top
View user's profile Send private message
Slippery Jim
Apprentice
Apprentice


Joined: 08 Jan 2005
Posts: 264

PostPosted: Tue Feb 18, 2014 1:32 am    Post subject: Reply with quote

How about "cludevil", as in command line udevil?
Back to top
View user's profile Send private message
i92guboj
Bodhisattva
Bodhisattva


Joined: 30 Nov 2004
Posts: 10315
Location: Córdoba (Spain)

PostPosted: Tue Feb 18, 2014 7:32 am    Post subject: Reply with quote

Well, you can call it whatever you want :lol:

It's not like I am going to fork off new project or something. I just wanted to differentiate it from unpatched bashmount, so that the original author doesn't get blamed if this thing I made eats your kitten or something.

If there's any interest in it at all (and nothing points to that) I'd rather try to get in touch with the original authoer and get proper udevil support into bashmount, since the differences are minimal and very trivial to handle.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Unsupported Software All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum