summarylogtreecommitdiffstats
path: root/obdevicemenu
diff options
context:
space:
mode:
Diffstat (limited to 'obdevicemenu')
-rwxr-xr-xobdevicemenu724
1 files changed, 724 insertions, 0 deletions
diff --git a/obdevicemenu b/obdevicemenu
new file mode 100755
index 000000000000..efe3fc0c74f9
--- /dev/null
+++ b/obdevicemenu
@@ -0,0 +1,724 @@
+#!/bin/bash
+
+#=============================================================================#
+# FILE: obdevicemenu #
+# VERSION: 1.7.0 #
+# #
+# DESCRIPTION: obdevicemenu is an Openbox pipe menu that uses udisks to #
+# easily mount, unmount or eject removable devices. An #
+# extensive configuration file allows desktop notifications #
+# about the success or failure of operations, as well as the #
+# modification of several other options. #
+# LICENSE: GPL2 #
+# AUTHOR: Jamie Nguyen #
+#=============================================================================#
+
+# 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
+
+
+#-------------------------------------#
+# CONFIGURATION #
+#-------------------------------------#
+# {{{
+
+unset GREP_OPTIONS
+
+declare filemanager="/usr/bin/Thunar"
+declare notify="/usr/bin/notify-send"
+declare notify_options="--expire-time=3000"
+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_internal=0
+declare -i show_notifications=1
+declare -i show_optical_device_filename=1
+declare -i show_removable_device_filename=1
+declare -i fancy_sort=0
+declare -i run_post_mount=0
+declare -i run_post_unmount=0
+
+declare -a blacklist=( )
+
+declare CONFIGFILE
+
+if [[ -n "${XDG_CONFIG_HOME}" ]]; then
+ CONFIGFILE="${XDG_CONFIG_HOME}/obdevicemenu/config"
+else
+ CONFIGFILE="${HOME}/.config/obdevicemenu/config"
+fi
+
+if [[ ! -f "${CONFIGFILE}" ]]; then
+ CONFIGFILE="/etc/obdevicemenu.conf"
+fi
+
+if [[ -f "${CONFIGFILE}" ]]; then
+ . "${CONFIGFILE}"
+ if (( $? != 0 )); then
+ printf '%s\n' "<openbox_pipe_menu>"
+ printf '%s\n' "<separator label=\"obdevicemenu\" />"
+ printf '%s\n' "<item label=\"Failed to source configuration file\" />"
+ printf '%s\n' "</openbox_pipe_menu>"
+ exit 1
+ fi
+fi
+
+if ! command -v udisks >/dev/null 2>&1; then
+ printf '%s\n' "<openbox_pipe_menu>"
+ printf '%s\n' "<separator label=\"obdevicemenu\" />"
+ printf '%s\n' "<item label=\"Udisks not installed\" />"
+ printf '%s\n' "</openbox_pipe_menu>"
+ exit 1
+fi
+# }}}
+
+#-------------------------------------#
+# INTERNAL API #
+#-------------------------------------#
+# {{{
+
+notify() {
+ if [ -z "${notify_options}" ]; then
+ $notify "$*"
+ else
+ $notify ${notify_options} "$*"
+ fi
+}
+
+# Functions to retrieve information. These functions simply parse the output
+# of udisks --show-info.
+info_blank() {
+ udisks --show-info ${1} \
+ | grep -m 1 -w "^[[:space:]]*blank:" \
+ | awk '{print $2}'
+}
+info_ejectable() {
+ udisks --show-info ${1} \
+ | grep -m 1 -w "^[[:space:]]*ejectable:" \
+ | awk '{print $2}'
+}
+info_has_media() {
+ udisks --show-info ${1} \
+ | grep -m 1 -w "^[[:space:]]*has media:" \
+ | awk '{print $3}'
+}
+info_internal() {
+ udisks --show-info ${1} \
+ | grep -m 1 -w "^[[:space:]]*system internal:" \
+ | awk '{print $3}'
+}
+info_label() {
+ local info_label=
+ info_label="$(udisks --show-info ${1} \
+ | grep -m 1 -w "^ label:" \
+ | awk '{gsub(/_/,"");$1="";print substr($0, index($0,$2))}')"
+ [[ -n "${info_label}" ]] && printf '%s\n' "${info_label}"
+}
+info_media() {
+ udisks --show-info ${1} \
+ | grep -m 1 -w "^[[:space:]]*media:" \
+ | awk '{gsub(/_/,"");print $2}'
+}
+info_model() {
+ udisks --show-info ${1} \
+ | grep -m 1 -w "^[[:space:]]*model:" \
+ | awk '{gsub(/_/,"");$1="";print substr($0, index($0,$2))}'
+}
+info_mounted() {
+ udisks --show-info ${1} \
+ | grep -m 1 -w "^[[:space:]]*is mounted:" \
+ | awk '{print $3}'
+}
+info_mountpath() {
+ udisks --show-info ${1} \
+ | grep -m 1 -w "^[[:space:]]*mount paths:" \
+ | awk '{$1="";$2="";print substr($0, index($0,$3))}'
+}
+info_type() {
+ udisks --show-info ${1} \
+ | grep -m 1 -w "^[[:space:]]*type:" \
+ | awk '{gsub(/_/,"");print $2}'
+}
+info_vendor() {
+ udisks --show-info ${1} \
+ | grep -m 1 -w "^[[:space:]]*vendor:" \
+ | awk '{gsub(/_/,"");$1="";print substr($0, index($0,$2))}'
+}
+# 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=
+
+ printf '%s\n' "${old_size}" | grep -ow -E ^[1-9]{1}[0-9]*$ >/dev/null 2>&1
+ (( $? != 0 )) && return 1
+
+ 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}"
+}
+info_device_size() {
+ local info_device_size=
+ info_device_size="$(udisks --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
+}
+info_partition_size() {
+ local info_partition_size=
+ info_partition_size="$(udisks --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
+}
+
+# Functions to perform udisks commands.
+
+# Eject the device, unmounting with a call to action_unmount if required.
+action_eject() {
+ local devname="${1}"
+ local -i mounted=0
+ mounted="$(info_mounted "${devname}")"
+ if (( mounted == 1 )); then
+ action_unmount "${devname}"
+ fi
+ mounted="$(info_mounted "${devname}")"
+ if (( mounted == 0 )); then
+ if (( show_notifications == 1 )); then
+ if command -v "${notify}" >/dev/null 2>&1; then
+ notify "$(printf '%s\n' "Ejecting ${devname} ...")"
+ notify "$(udisks --eject ${devname})"
+ fi
+ else
+ udisks --eject ${devname}
+ fi
+ fi
+}
+# 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 devname="${1}"
+ if (( show_notifications == 1 )); then
+ if command -v "${notify}" >/dev/null 2>&1; then
+ notify "$(printf '%s\n' "Mounting ${devname} ...")"
+ notify "$(udisks --mount ${devname} ${mount_options})"
+ fi
+ else
+ udisks --mount ${devname} ${mount_options}
+ fi
+
+ if (( run_post_mount == 1 )); then
+ post_mount ${devname}
+ fi
+}
+# Open the device with the filemanager specified in the configuration file,
+# mounting with a call to action_mount if required.
+action_open() {
+ local devname="${1}"
+ local info_mountpath="$(info_mountpath "${devname}")"
+ if [[ -n "${info_mountpath}" ]]; then
+ $filemanager "${info_mountpath}"
+ else
+ $filemanager
+ fi
+}
+# 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 devname="${1}"
+ if (( show_notifications == 1 )); then
+ if command -v "${notify}" >/dev/null 2>&1; then
+ notify "$(printf '%s\n' "Unmounting ${devname} ...")"
+ notify "$(udisks --unmount ${devname})"
+ fi
+ mounted="$(info_mounted ${devname})"
+ if (( mounted == 1 )); then
+ notify "$(printf '%s\n' "${devname} unmounted successfully")"
+ fi
+ else
+ udisks --unmount ${devname}
+ fi
+
+ if (( run_post_unmount == 1 )); then
+ post_unmount ${devname}
+ fi
+}
+action_unmount_all() {
+ for devname in $*; do
+ action_unmount ${devname}
+ done
+}
+action_info() {
+ local devname="${1}"
+ local devmajor="${devname%%[0-9]*}"
+
+ udisks --show-info ${devname} >/dev/null 2>&1
+ if (( $? != 0 )); then
+ printf '%s\n' "<openbox_pipe_menu>"
+ printf '%s\n' "<item label=\"Udisks failed.\" />"
+ printf '%s\n' "</openbox_pipe_menu>"
+ exit 0
+ fi
+
+ local info_label="$(info_label "${devname}")"
+ local info_vendor="$(info_vendor "${devmajor}")"
+ local info_model="$(info_model "${devmajor}")"
+ local info_device_size="$(info_device_size "${devmajor}")"
+ local info_type="$(info_type "${devname}")"
+ local info_media="$(info_media ${devname})"
+
+ if [[ "${devname}" != "${devmajor}" ]]; then
+ local info_partition_size="$(info_partition_size "${devname}")"
+ fi
+
+ printf '%s\n' "<openbox_pipe_menu>"
+
+ printf '%s\n' "<separator label=\"Device information\" />"
+
+ [[ -n "${info_device_filename}" ]] && \
+ printf '%s\n' "<item label=\"device: ${devname}\" />"
+ [[ -n "${info_label}" ]] && \
+ printf '%s\n' "<item label=\"label: ${info_label}\" />"
+ [[ -n "${info_vendor}" ]] && \
+ printf '%s\n' "<item label=\"vendor: ${info_vendor}\" />"
+ [[ -n "${info_model}" ]] && \
+ printf '%s\n' "<item label=\"model: ${info_model}\" />"
+ [[ -n "${info_type}" ]] && \
+ printf '%s\n' "<item label=\"type: ${info_type}\" />"
+ [[ -n "${info_media}" ]] && \
+ printf '%s\n' "<item label=\"media: ${info_media}\" />"
+ [[ -n "${info_partition_size}" ]] && \
+ printf '%s\n' "<item label=\"size (partition): ${info_partition_size}\" />"
+ [[ -n "${info_device_size}" ]] && \
+ printf '%s\n' "<item label=\"size (device): ${info_device_size}\" />"
+
+ printf '%s\n' "</openbox_pipe_menu>"
+}
+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 wont 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=0
+
+ # 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.
+ 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=$((++array_position)); continue
+ fi
+
+ if [[ "${devname}" = "${devmajor}" ]]; then
+ array_position=$((++array_position)); continue
+ fi
+
+ partition_number="${devname#${devmajor}}"
+ removable[${array_position}]=${devmajor}$(printf '%02d' "${partition_number}")
+ array_position=$((++array_position))
+ 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=$((++array_position)); continue
+ fi
+
+ if [[ "${devname}" = "${devmajor}" ]]; then
+ array_position=$((++array_position)); continue
+ fi
+
+ partition_number="${devname#${devmajor}}"
+ removable[${array_position}]=${devmajor}${partition_number#0}
+ array_position=$((++array_position))
+ done
+}
+
+# }}}
+
+#-------------------------------------#
+# MENU FUNCTIONS #
+#-------------------------------------#
+# {{{
+
+device_menu() {
+ local -a removable=( )
+ local -a optical=( )
+ local -a mounted_removable=( )
+ local -a mounted_optical=( )
+ local -i total_removable=0
+
+ printf '%s\n' "<openbox_pipe_menu>"
+
+ udisks --enumerate-device-files >/dev/null 2>&1
+ if [[ $? -ne 0 ]]; then
+ printf '%s\n' "<item label=\"Udisks failed.\" />"
+ printf '%s\n' "</openbox_pipe_menu>"
+ exit 0
+ fi
+
+ # Here we list devices matched by the "removable_devices" regex specified in
+ # the configuration file.
+
+ printf '%s\n' "<separator label=\"Removable media\" />"
+
+ removable=( $(udisks --enumerate-device-files \
+ | grep -ow ${removable_devices} | sort) )
+
+ if (( fancy_sort == 1 )); then
+ fancy_sort
+ fi
+
+ for devname in ${removable[@]}; do
+ local devmajor=
+ local info_label=
+ local -i info_internal=
+ local -i mounted=
+ local -i partitions=
+
+ # 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="$(udisks --enumerate-device-files \
+ | grep -ow -E ^${devname}p[0-9]+ -c)"
+ if (( partitions > 0 )); then
+ continue
+ fi
+ fi
+ else
+ devmajor="${devname%%[0-9]*}"
+ if [[ "${devname}" = "${devmajor}" ]]; then
+ partitions="$(udisks --enumerate-device-files \
+ | grep -ow -E ^${devname}[0-9]+ -c)"
+ if (( partitions > 0 )); then
+ continue
+ fi
+ fi
+ fi
+
+ info_internal="$(info_internal "${devmajor}")"
+
+ if (( info_internal == 1 )) && (( show_internal == 0 )); then
+ continue
+ fi
+
+ if (( info_internal == 0 )) || (( show_internal == 1 )); then
+
+ # Hide blacklisted devices.
+ for string in ${blacklist[@]}; do
+ udisks --show-info "${devname}" | grep -E "${string}" >/dev/null 2>&1
+ (( $? == 0 )) && continue 2
+ done
+
+ total_removable=$((++total_removable))
+
+ 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}")"
+ [[ -z "${info_label}" ]] && info_label="$(info_model "${devmajor}")"
+ [[ -z "${info_label}" ]] && info_label="$(info_vendor "${devmajor}")"
+ if [[ -z "${info_label}" ]]; then
+ info_label="No label"
+ else
+ info_label="No label (${info_label})"
+ fi
+ fi
+
+ mounted="$(info_mounted "${devname}")"
+ if (( mounted == 0 )); then
+ if (( show_removable_device_filename == 1 )); then
+ printf '%s' "<menu id=\"mount${devname}\" "
+ printf '%s' "label=\"${devname#/dev/}: ${info_label}\" "
+ printf '%s' "execute=\"$0 --mount-menu removable "
+ printf '%s' "${devname}\" />"
+ printf '\n'
+ else
+ printf '%s' "<menu id=\"mount${devname}\" "
+ printf '%s' "label=\"${info_label}\" "
+ printf '%s' "execute=\"$0 --mount-menu removable "
+ printf '%s' "${devname}\" />"
+ printf '\n'
+ fi
+ else
+ if (( show_removable_device_filename == 1 )); then
+ printf '%s' "<menu id=\"mount${devname}\" "
+ printf '%s' "label=\"${devname#/dev/}: "
+ printf '%s' "${info_label} (mounted)\" "
+ printf '%s' "execute=\"$0 --mount-menu removable "
+ printf '%s' "${devname}\" />"
+ printf '\n'
+ else
+ printf '%s' "<menu id=\"mount${devname}\" "
+ printf '%s' "label=\"${info_label} (mounted)\" "
+ printf '%s' "execute=\"$0 --mount-menu removable "
+ printf '%s' "${devname}\" />"
+ printf '\n'
+ fi
+ mounted_removable[${#mounted_removable[*]}]=${devname}
+ fi
+ fi
+ done
+
+ if (( total_removable == 0 )); then
+ printf '%s\n' "<item label=\"None\" />"
+ elif (( ${#mounted_removable[*]} > 0 )); then
+ printf '%s\n' "<item label=\"Unmount all\">"
+ printf '%s\n' "<action name=\"Execute\">"
+ printf '%s\n' "<command>$0 --unmount-all-removable \
+ ${mounted_removable[*]}</command>"
+ printf '%s\n' "<prompt>Unmount all removable devices?</prompt>"
+ printf '%s\n' "</action>"
+ printf '%s\n' "</item>"
+ fi
+
+ # Here we list devices matched by the "optical_devices" regex specified in
+ # the configuration file.
+ printf '%s\n' "<separator label=\"Optical media\" />"
+
+ optical=( $(udisks --enumerate-device-files \
+ | grep -ow ${optical_devices} | sort) )
+
+ if (( ${#optical[*]} == 0 )); then
+ printf '%s\n' "<item label=\"None\" />"
+ printf '%s\n' "</openbox_pipe_menu>"
+ return 0
+ fi
+
+ for devname in ${optical[@]}; do
+ local info_label=
+ local -i info_blank=0
+ local -i info_has_media=0
+ local -i mounted=0
+
+ info_has_media="$(info_has_media "${devname}")"
+
+ # Hide blacklisted devices.
+ for string in ${blacklist[@]}; do
+ udisks --show-info "${devname}" | grep -E "${string}" >/dev/null 2>&1
+ (( $? == 0 )) && continue 2
+ done
+
+ if (( info_has_media == 0 )); then
+ printf '%s\n' "<item label=\"${devname#/dev/}: None\" />"
+ else
+ info_blank="$(info_blank "${devname}")"
+ if (( info_blank == 1 )); 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
+
+ mounted="$(info_mounted "${devname}")"
+ if (( mounted == 0 )); then
+ if (( show_optical_device_filename == 1 )); then
+ printf '%s' "<menu id=\"mount${devname}\" "
+ printf '%s' "label=\"${devname#/dev/}: ${info_label}\" "
+ printf '%s' "execute=\"$0 --mount-menu optical "
+ printf '%s' "${devname}\" />"
+ printf '\n'
+ else
+ printf '%s' "<menu id=\"mount${devname}\" "
+ printf '%s' "label=\"${info_label}\" "
+ printf '%s' "execute=\"$0 --mount-menu optical "
+ printf '%s' "${devname}\" />"
+ printf '\n'
+ fi
+ else
+ if (( show_optical_device_filename == 1 )); then
+ printf '%s' "<menu id=\"mount${devname}\" "
+ printf '%s' "label=\"${devname#/dev/}: "
+ printf '%s' "${info_label} (mounted)\" "
+ printf '%s' "execute=\"$0 --mount-menu optical "
+ printf '%s' "${devname}\" />"
+ printf '\n'
+ else
+ printf '%s' "<menu id=\"mount${devname}\" "
+ printf '%s' "label=\"${info_label} (mounted)\" "
+ printf '%s' "execute=\"$0 --mount-menu optical "
+ printf '%s' "${devname}\" />"
+ printf '\n'
+ fi
+ mounted_optical[${#mounted_optical[*]}]=${devname}
+ fi
+ fi
+ done
+
+ if (( ${#mounted_optical[*]} > 0 )); then
+ printf '%s\n' "<item label=\"Unmount all\">"
+ printf '%s\n' "<action name=\"Execute\">"
+ printf '%s\n' "<command>$0 --unmount-all-optical \
+ ${mounted_optical[*]}</command>"
+ printf '%s\n' "<prompt>Unmount all optical devices?</prompt>"
+ printf '%s\n' "</action>"
+ printf '%s\n' "</item>"
+ fi
+
+ printf '%s\n' "</openbox_pipe_menu>"
+}
+# Here we provide a submenu for each device, which displays the available
+# actions that can be performed.
+mount_menu() {
+ local media_type="${1}"
+ local devname="${2}"
+ local info_label="${3}"
+ local devname_short="${devname##*/}"
+ local -i info_ejectable=0
+ local -i mounted=0
+
+ printf '%s\n' "<openbox_pipe_menu>"
+
+ if [[ "${media_type}" = "removable" ]]; then
+ if (( show_removable_device_filename == 1 )); then
+ printf '%s\n' "<separator label=\"${devname}\" />"
+ else
+ printf '%s\n' "<separator label=\"${info_label}\" />"
+ fi
+ elif [[ "${media_type}" = "optical" ]]; then
+ if (( show_optical_device_filename == 1 )); then
+ printf '%s\n' "<separator label=\"${devname}\" />"
+ else
+ printf '%s\n' "<separator label=\"${info_label}\" />"
+ fi
+ fi
+
+ mounted="$(info_mounted "${devname}")"
+
+ if (( mounted == 0 )); then
+ printf '%s\n' "<item label=\"Open\">"
+ printf '%s\n' "<action name=\"Execute\">"
+ printf '%s\n' "<command>$0 --mount-and-open ${devname}</command>"
+ printf '%s\n' "</action>"
+ printf '%s\n' "</item>"
+
+ printf '%s\n' "<item label=\"Mount\">"
+ printf '%s\n' "<action name=\"Execute\">"
+ printf '%s\n' "<command>$0 --mount-device ${devname}</command>"
+ printf '%s\n' "</action>"
+ printf '%s\n' "</item>"
+ else
+ printf '%s\n' "<item label=\"Open\">"
+ printf '%s\n' "<action name=\"Execute\">"
+ printf '%s\n' "<command>$0 --open-directory ${devname}</command>"
+ printf '%s\n' "</action>"
+ printf '%s\n' "</item>"
+
+ printf '%s\n' "<item label=\"Unmount\">"
+ printf '%s\n' "<action name=\"Execute\">"
+ printf '%s\n' "<command>$0 --unmount-device ${devname}</command>"
+ printf '%s\n' "</action>"
+ printf '%s\n' "</item>"
+ fi
+
+ info_ejectable="$(info_ejectable "${devname}")"
+
+ if (( info_ejectable == 1 )); then
+ printf '%s\n' "<item label=\"Eject\">"
+ printf '%s\n' "<action name=\"Execute\">"
+ printf '%s\n' "<command>$0 --eject-device ${devname}</command>"
+ printf '%s\n' "</action>"
+ printf '%s\n' "</item>"
+ fi
+
+ printf '%s' "<menu id=\"showinfo${devname##*/}\" "
+ printf '%s' "label=\"Info\" "
+ printf '%s' "execute=\"$0 --show-info ${devname}\" />"
+ printf '\n'
+
+ printf '%s\n' "</openbox_pipe_menu>"
+}
+# }}}
+
+#-------------------------------------#
+# INT MAIN #
+#-------------------------------------#
+
+if (( $# == 0 )); then
+ device_menu
+ exit 0
+fi
+
+# The script calls itself with different options in order to get nested pipe
+# menus.
+case "${1}" in
+ "--mount-menu")
+ mount_menu ${2} ${3}
+ ;;
+ "--mount-device")
+ action_mount "${2}"
+ ;;
+ "--unmount-device")
+ action_unmount "${2}"
+ ;;
+ "--eject-device")
+ action_eject "${2}"
+ ;;
+ "--open-directory")
+ action_open "${2}"
+ ;;
+ "--mount-and-open")
+ action_mount "${2}" && action_open "${2}"
+ ;;
+ "--show-info")
+ action_info "${2}"
+ ;;
+ "--unmount-all-removable")
+ shift 1 && action_unmount_all $@
+ ;;
+ "--unmount-all-optical")
+ shift 1 && action_unmount_all $@
+ ;;
+esac
+
+# vim: set ts=4 sw=4 noet foldmethod=marker :