Browse code

Initial commit

Steven Saus authored on 14/08/2019 21:41:29
Showing 4 changed files

1 1
new file mode 100644
... ...
@@ -0,0 +1,176 @@
1
+# reference, old shit
2
+reference/
3
+
4
+# macOS Junks
5
+.DS_Store
6
+
7
+# VSCode Junks
8
+.vscode
9
+.vscode/*
10
+
11
+# Microsoft Office Junks
12
+~$*.*
13
+
14
+# C/C++ Junks
15
+# Prerequisites
16
+*.d
17
+
18
+# Compiled Object files
19
+*.slo
20
+*.lo
21
+*.o
22
+*.obj
23
+
24
+# Precompiled Headers
25
+*.gch
26
+*.pch
27
+
28
+# Compiled Dynamic libraries
29
+*.so
30
+*.dylib
31
+*.dll
32
+
33
+# Fortran module files
34
+*.mod
35
+*.smod
36
+
37
+# Compiled Static libraries
38
+*.lai
39
+*.la
40
+*.a
41
+*.lib
42
+
43
+# Executables
44
+*.exe
45
+*.out
46
+*.app
47
+
48
+# Python Junks
49
+# Byte-compiled / optimized / DLL files
50
+__pycache__/
51
+*.py[cod]
52
+*$py.class
53
+
54
+# C extensions
55
+*.so
56
+
57
+# Distribution / packaging
58
+.Python
59
+build/
60
+develop-eggs/
61
+dist/
62
+downloads/
63
+eggs/
64
+.eggs/
65
+lib/
66
+lib64/
67
+parts/
68
+sdist/
69
+var/
70
+wheels/
71
+pip-wheel-metadata/
72
+share/python-wheels/
73
+*.egg-info/
74
+.installed.cfg
75
+*.egg
76
+MANIFEST
77
+share/
78
+bin/
79
+bin/*
80
+include/
81
+include/*
82
+
83
+# PyInstaller
84
+#  Usually these files are written by a python script from a template
85
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
86
+*.manifest
87
+*.spec
88
+
89
+# Installer logs
90
+pip-log.txt
91
+pip-delete-this-directory.txt
92
+
93
+# Unit test / coverage reports
94
+htmlcov/
95
+.tox/
96
+.nox/
97
+.coverage
98
+.coverage.*
99
+.cache
100
+nosetests.xml
101
+coverage.xml
102
+*.cover
103
+.hypothesis/
104
+.pytest_cache/
105
+
106
+# Translations
107
+*.mo
108
+*.pot
109
+
110
+# Django stuff:
111
+*.log
112
+local_settings.py
113
+db.sqlite3
114
+
115
+# Flask stuff:
116
+instance/
117
+.webassets-cache
118
+
119
+# Scrapy stuff:
120
+.scrapy
121
+
122
+# Sphinx documentation
123
+docs/_build/
124
+
125
+# PyBuilder
126
+target/
127
+
128
+# Jupyter Notebook
129
+.ipynb_checkpoints
130
+
131
+# IPython
132
+profile_default/
133
+ipython_config.py
134
+
135
+# pyenv
136
+.python-version
137
+
138
+# pipenv
139
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
140
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
141
+#   having no cross-platform support, pipenv may install dependencies that don’t work, or not
142
+#   install all needed dependencies.
143
+Pipfile.lock
144
+
145
+# celery beat schedule file
146
+celerybeat-schedule
147
+
148
+# SageMath parsed files
149
+*.sage.py
150
+
151
+# Environments
152
+.env
153
+.venv
154
+env/
155
+venv/
156
+ENV/
157
+env.bak/
158
+venv.bak/
159
+
160
+# Spyder project settings
161
+.spyderproject
162
+.spyproject
163
+
164
+# Rope project settings
165
+.ropeproject
166
+
167
+# mkdocs documentation
168
+/site
169
+
170
+# mypy
171
+.mypy_cache/
172
+.dmypy.json
173
+dmypy.json
174
+
175
+# Pyre type checker
176
+.pyre/
... ...
@@ -1,2 +1,36 @@
1 1
 # obdevicemenu_udisks2_bash
2 2
 A bash implementation of obdevicemenu that utilizes udisks2
3
+
4
+
5
+An Openbox pipe menu for the management of removable media with Udisks
6
+
7
+dependecies
8
+
9
+udisks2
10
+lsblk
11
+
12
+
13
+A WORK IN PROGRESS, folks.
14
+
15
+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 commands.
16
+
17
+This script does not provide automounting of removable media as there are already many ways to automount. The file managers in GNOME and KDE handle automounting, while udev rules or scripts like Udiskie can be used in other environments.
18
+
19
+Notes
20
+Dbus  and consolekit/policykit need to be running. If you aren't using a login manager, put this in ~/.xinitrc:
21
+
22
+source /etc/X11/xinit/xinitrc.d/30-dbus
23
+exec ck-launch-session openbox
24
+
25
+If it doesn't already exist, create the file "/etc/polkit-1/localauthority/50-local.d/10-udiskie.pkla" with these contents:
26
+```
27
+[Local Users]
28
+Identity=unix-group:storage
29
+Action=org.freedesktop.udisks.*
30
+ResultAny=yes
31
+ResultInactive=no
32
+ResultActive=yes
33
+```
34
+Then put inside the "root-menu" part of ~/.config/openbox/menu.xml something like this:
35
+
36
+ <menu id="devices" label="Devices" execute="/usr/bin/obdevicemenu" />
3 37
new file mode 100644
... ...
@@ -0,0 +1,101 @@
1
+# Configuration file for obdevicemenu.
2
+
3
+# Place in /etc/obdevicemenu.conf for system wide configuration.
4
+# Place in ~/.config/obdevicemenu/config for per-user configuration.
5
+# XDG_CONFIG_HOME is respected if it has been set.
6
+
7
+# Set Udisks command path.
8
+udisks="/usr/bin/udisks"
9
+
10
+# Set filemanager command. The mount point is passed as the first argument.
11
+#filemanager="/usr/bin/uxterm -wf -e /usr/bin/mc"
12
+filemanager="/usr/bin/Thunar"
13
+#filemanager="/usr/bin/pcmanfm"
14
+
15
+# Set whether notifications will be shown. This can be "0" or "1".
16
+show_notifications=1
17
+
18
+# Set notification command path and options to pass. These are only used if
19
+# show_notifications is set to "1". The messages are passed to this command
20
+# as the final argument. notify_options can be left blank if you do not need
21
+# to pass any options to the notification command.
22
+notify="/usr/bin/notify-send"
23
+notify_options="--expire-time=3000"
24
+
25
+# Set optical device location. This string is matched using grep like so:
26
+# udisks --enumerate | grep -ow ${optical_devices} | sort
27
+# If you wish to do more complicated matches, the string can be modified to
28
+# include grep options, such as setting it to "-e sr0 -e sr[2-9]". This
29
+# allows more control over which devices are processed/ignored by the menu.
30
+#optical_devices="sr[0-9]*"
31
+#optical_devices="-E ^/dev/sr[0-9]+"
32
+
33
+# Set removable devices location. The default is to ignore /dev/sda*, which is
34
+# usually the primary system drive. This string is matched using grep like so:
35
+# udisks --enumerate | grep -ow ${removable_devices} | sort
36
+# If you wish to do more complicated matches, the string can be modified to
37
+# include grep options, such as setting it to "-e sdb[0-9]* -e sdc1". This
38
+# allows more control over which devices are processed/ignored by the menu.
39
+removable_devices="-E ^/dev/sd[b-z][0-9]*|^/dev/mmcblk[0-9]+p*[0-9]*"
40
+# old config below
41
+#removable_devices="sd[b-z]*[0-9]*"
42
+#removable_devices="mmc[a-z]*[0-9]*"
43
+
44
+###
45
+### This example also includes LUKS encrypted partitions:
46
+### removable_devices="-E ^/dev/sd[b-z][0-9]*|^/dev/mmcblk[0-9]+p*[0-9]*|^/dev/dm-[0-9]+"
47
+###
48
+### This example also includes LUKS encrypted partitions but hides /dev/dm-0 to
49
+### /dev/dm-7 which are system partitions:
50
+### removable_devices="-E ^/dev/sd[b-z][0-9]*|^/dev/dm-[8-9]|^/dev/dm-[1-9][0-9]+"
51
+###
52
+### This example also includes floppy drives (note that the device will always
53
+### be shown whether or not there is a floppy disk inserted):
54
+### removable_devices="-E ^/dev/sd[b-z][0-9]*|^/dev/fd[0-9]+"
55
+###
56
+
57
+
58
+# Do not show internal devices. This can be "0" or "1". If you have system
59
+# drives that are always found at the same location (e.g. /dev/sda), it is
60
+# better and faster to hide them using the "removable_devices" option above.
61
+show_internal="0"
62
+
63
+# Set whether to show the device filename in the menu. This can be "0" or "1".
64
+# Example: If this is set to "1" then the menu entry will show "sdb1: Cruzer",
65
+# while if this is set to "0" then the menu entry will only show "Cruzer".
66
+show_removable_device_filename="0"
67
+show_optical_device_filename="1"
68
+
69
+# Set whether to sort devices more thoroughly. This can be "0" or "1".
70
+# This option is basically a big hack to get around a shortcoming of the sort
71
+# command, which causes /dev/sdc11 to be shown in the menu before /dev/sdc2.
72
+# It will deal with /dev/sd* and /dev/dm-* devices, but not /dev/mmcblk* as
73
+# the sorting is not really that simple. It is a big hack so if you enable it
74
+# then i can make no promises that it will be fast or bug free.
75
+fancy_sort="0"
76
+
77
+# Set custom commands to be run automatically after mounting or unmounting.
78
+# This is useful for spinning down a hard drive after unmounting it. The
79
+# device name (e.g. /dev/sdb1) is passed as the first and only argument.
80
+# Uncomment the examples below, or modify them to pass any arbitrary commands.
81
+# post_mount is run immediately after a successful mount operation, and
82
+# post_unmount is run immediately after a successful unmount operation.
83
+
84
+# Set "run_post_mount" to "0" to disable or "1" to enable.
85
+run_post_mount="1"
86
+
87
+# This example uses udisks to set the spindown timeout after mounting.
88
+#post_mount() {
89
+#	udisks --set-spindown ${1} --spindown-timeout 240
90
+#}
91
+
92
+# Set "run_post_unmount" to "0" to disable or "1" to enable.
93
+run_post_unmount="1"
94
+
95
+# This example uses udisks to set the spindown timeout after unmounting.
96
+#post_unmount() {
97
+#	udisks --set-spindown ${1} --spindown-timeout 240
98
+#}
99
+
100
+# Set default mount options for Udisks.
101
+mount_options="--mount-options nosuid,noexec,noatime"
0 102
new file mode 100755
... ...
@@ -0,0 +1,671 @@
1
+#!/bin/bash
2
+
3
+#=============================================================================#
4
+#          FILE: obdevicemenu                                                 #
5
+#       VERSION: 1.6.1                                                        #
6
+#                                                                             #
7
+#   DESCRIPTION: obdevicemenu is an Openbox pipe menu that uses udisks to     #
8
+#                easily mount, unmount or eject removable devices. An         #
9
+#                extensive configuration file allows desktop notifications    #
10
+#                about the success or failure of operations, as well as the   #
11
+#                modification of several other options.                       #
12
+#       LICENSE: GPL3                                                         #
13
+#        AUTHOR: Jamie Nguyen   
14
+#       Udisks2 tweaks: Steven Saus                                              #
15
+#=============================================================================#
16
+
17
+# Copyright (C) 2011 Jamie Nguyen
18
+#
19
+# This program is free software; you can redistribute it and/or modify it
20
+# under the terms of the GNU General Public License v3 as published by the
21
+# Free Software Foundation.
22
+#
23
+# This program is distributed in the hope that it will be useful, but WITHOUT
24
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
26
+# more details.
27
+#
28
+# You should have received a copy of the GNU General Public License along with
29
+# this program; if not, write to the Free Software Foundation, Inc.,
30
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
31
+
32
+
33
+#-------------------------------------#
34
+#           CONFIGURATION             #
35
+#-------------------------------------#
36
+# {{{
37
+
38
+unset GREP_OPTIONS
39
+
40
+declare filemanager="/usr/bin/Thunar"
41
+declare notify="/usr/bin/notify-send"
42
+declare notify_options="--expire-time=3000"
43
+declare optical_devices="-E ^/dev/sr[0-9]+"
44
+declare removable_devices="-E ^/dev/sd[b-z][0-9]*|^/dev/mmcblk[0-9]+p*[0-9]*"
45
+
46
+#May have to remove these
47
+declare mount_options="-o nosuid,noexec,noatime"
48
+
49
+declare -i show_internal=0
50
+declare -i show_notifications=0
51
+declare -i show_optical_device_filename=1
52
+declare -i show_removable_device_filename=1
53
+declare -i fancy_sort=0
54
+declare -i run_post_mount=0
55
+declare -i run_post_unmount=0
56
+
57
+declare CONFIGFILE
58
+
59
+if [[ -n "${XDG_CONFIG_HOME}" ]]; then
60
+	CONFIGFILE="${XDG_CONFIG_HOME}/obdevicemenu/config"
61
+else
62
+	CONFIGFILE="${HOME}/.config/obdevicemenu/config"
63
+fi
64
+
65
+if [[ ! -f "${CONFIGFILE}" ]]; then
66
+	CONFIGFILE="/etc/obdevicemenu.conf"
67
+fi
68
+
69
+if [[ -f "${CONFIGFILE}" ]]; then
70
+	. "${CONFIGFILE}"
71
+	if (( $? != 0 )); then
72
+		printf '%s\n' "<openbox_pipe_menu>"
73
+		printf '%s\n' "<separator label=\"obdevicemenu\" />"
74
+		printf '%s\n' "<item label=\"Failed to source configuration file\" />"
75
+		printf '%s\n' "</openbox_pipe_menu>"
76
+		exit 1
77
+	fi
78
+fi
79
+
80
+if ! command -v udisksctl >/dev/null 2>&1; then
81
+	printf '%s\n' "<openbox_pipe_menu>"
82
+	printf '%s\n' "<separator label=\"obdevicemenu\" />"
83
+	printf '%s\n' "<item label=\"udisks2 not installed\" />"
84
+	printf '%s\n' "</openbox_pipe_menu>"
85
+	exit 1
86
+fi
87
+# }}}
88
+
89
+#-------------------------------------#
90
+#            INTERNAL API             #
91
+#-------------------------------------#
92
+# {{{
93
+
94
+notify() {
95
+	if [ -z "${notify_options}" ]; then
96
+		$notify "$*"
97
+	else
98
+		$notify ${notify_options} "$*"
99
+	fi
100
+}
101
+
102
+# Functions to retrieve information. These functions simply parse the output
103
+# of udisks --show-info.
104
+
105
+info_has_media() {
106
+	udisksctl info -b ${1}  \
107
+		| grep -m 1 -w "IdUUID:" \
108
+		| awk '{print $2}'
109
+}
110
+
111
+# Need to find the udisks2 version - does it exist?
112
+info_internal() {
113
+	udisks --show-info ${1} \
114
+		| grep -m 1 -w "^[[:space:]]*system internal:" \
115
+		| awk '{print $3}'
116
+}
117
+
118
+info_label() {
119
+	local info_label=
120
+	info_label="$(udisksctl info -b ${1} \
121
+		| grep -m 1 -w "IdLabel:" \
122
+		| awk '{print $2}')"
123
+	if [[ -n "${info_label}" ]]; then
124
+		printf '%s\n' "${info_label}"; return
125
+	fi
126
+}
127
+# Need to find the udisks2 version - does it exist?
128
+info_media() {
129
+udisksctl info -b ${1}  \
130
+		| grep -m 1 -w "IdUUID:" \
131
+		| awk '{print $2}'
132
+}
133
+
134
+info_mounted() {
135
+    bob=$(udisksctl info -b ${1} | grep -m 1 -w "MountPoints:" | awk '{print $2}')
136
+    if [ -z "$bob" ];then 
137
+        echo "0"
138
+    else
139
+        echo "1"
140
+    fi
141
+}
142
+info_mountpath() {
143
+	udisksctl info -b ${1} \
144
+		| grep -m 1 -w "MountPoints:" \
145
+		| awk '{print $2}'
146
+}
147
+info_type() {
148
+	lsblk -f ${1} \
149
+        | tail -1 \
150
+		| awk '{print $2}'
151
+}
152
+
153
+
154
+# The size of the device/partition is given in bytes, so let's convert that
155
+# to something more readable. Rounding done in bash is not accurate at all
156
+# but we'll mitigate that by only rounding when the numbers get quite large.
157
+convert_size() {
158
+	local -i old_size="${1}"
159
+	local new_size=
160
+
161
+	printf '%s\n' "${old_size}" | grep -ow -E ^[1-9]{1}[0-9]*$ >/dev/null 2>&1
162
+	(( $? != 0 )) && return 1
163
+
164
+	if (( old_size > 21474836480 )); then
165
+		new_size="$((${old_size}/1073741824)) GB"
166
+	elif (( old_size > 10485760 )); then
167
+		new_size="$((${old_size}/1048576)) MB"
168
+	elif (( old_size > 10240 )); then
169
+		new_size="$((${old_size}/1024)) kB"
170
+	else
171
+		new_size="${old_size} bytes"
172
+	fi
173
+
174
+	printf '%s\n' "${new_size}"
175
+}
176
+info_device_size() {
177
+	local info_device_size=
178
+	info_device_size="$(udisksctl info -b ${1} \
179
+		| grep -m 1 -w "Size:" \
180
+		| awk '{print $2}')"
181
+	if [[ -n "${info_device_size}" ]]; then
182
+		info_device_size="$(convert_size "${info_device_size}")"
183
+		printf '%s\n' "${info_device_size}"
184
+	fi
185
+}
186
+info_partition_size() {
187
+	local info_partition_size=
188
+	info_partition_size="$(udisksctl info -b ${1} \
189
+		| grep -m 1 -w "Size:" \
190
+		| awk '{print $2}')"
191
+	if [[ -n "${info_partition_size}" ]]; then
192
+		info_partition_size="$(convert_size "${info_partition_size}")"
193
+		printf '%s\n' "${info_partition_size}"
194
+	fi
195
+}
196
+
197
+# Functions to perform udisks commands.
198
+
199
+
200
+# Mount the device if it is not already mounted, and run the post_mount hook
201
+# after a successful mount operation if it has been enabled.
202
+action_mount() {
203
+	local devname="${1}"
204
+	if (( show_notifications == 1 )); then
205
+		if command -v "${notify}" >/dev/null 2>&1; then
206
+			notify "$(printf '%s\n' "Mounting ${devname} ...")"
207
+			notify "$(udisksctl mount -b ${devname})"
208
+		fi
209
+	else
210
+		udisksctl --mount -b ${devname}
211
+	fi
212
+
213
+	if (( run_post_mount == 1 )); then
214
+		post_mount ${devname}
215
+	fi
216
+}
217
+
218
+
219
+# Open the device with the filemanager specified in the configuration file,
220
+# mounting with a call to action_mount if required.
221
+action_open() {
222
+	local devname="${1}"
223
+	local info_mountpath="$(info_mountpath "${devname}")"
224
+	if [[ -n "${info_mountpath}" ]]; then
225
+		$filemanager "${info_mountpath}"
226
+	else
227
+		$filemanager
228
+	fi
229
+}
230
+# Unmount the device if it is not already unmounted, and run the post_unmount
231
+# hook after a successful unmount operation if it has been enabled.
232
+action_unmount() {
233
+	local devname="${1}"
234
+	if (( show_notifications == 1 )); then
235
+		if command -v "${notify}" >/dev/null 2>&1; then
236
+			notify "$(printf '%s\n' "Unmounting ${devname} ...")"
237
+			notify "$(udisksctl unmount -b ${devname})"
238
+		fi
239
+		mounted="$(info_mounted ${devname})"
240
+		if (( mounted == 0 )); then
241
+			notify "$(printf '%s\n' "${devname} unmounted successfully")"
242
+		fi
243
+	else
244
+		udisksctl unmount -b ${devname}
245
+	fi
246
+
247
+	if (( run_post_unmount == 1 )); then
248
+		post_unmount ${devname}
249
+	fi
250
+}
251
+action_unmount_all() {
252
+	for devname in $*; do
253
+		action_unmount ${devname}
254
+	done
255
+}
256
+action_info() {
257
+	local devname="${1}"
258
+	local devmajor="${devname%%[0-9]*}"
259
+
260
+	udisksctl info -b ${devname} >/dev/null 2>&1
261
+	if (( $? != 0 )); then
262
+		printf '%s\n' "<openbox_pipe_menu>"
263
+		printf '%s\n' "<item label=\"Udisks failed.\" />"
264
+		printf '%s\n' "</openbox_pipe_menu>"
265
+		exit 0
266
+	fi
267
+
268
+	local info_label="$(info_label "${devname}")"
269
+	local info_vendor="$(info_vendor "${devmajor}")"
270
+	local info_model="$(info_model "${devmajor}")"
271
+	local info_device_size="$(info_device_size "${devmajor}")"
272
+	local info_type="$(info_type "${devname}")"
273
+	local info_media="$(info_media ${devname})"
274
+
275
+	if [[ "${devname}" != "${devmajor}" ]]; then
276
+		local info_partition_size="$(info_partition_size "${devname}")"
277
+	fi
278
+
279
+	printf '%s\n' "<openbox_pipe_menu>"
280
+
281
+	printf '%s\n' "<separator label=\"Device information\" />"
282
+
283
+	[[ -n "${info_device_filename}" ]] && \
284
+		printf '%s\n' "<item label=\"device: ${devname}\" />"
285
+	[[ -n "${info_label}" ]] && \
286
+		printf '%s\n' "<item label=\"label: ${info_label} $1\" />"
287
+	[[ -n "${info_type}" ]] && \
288
+		printf '%s\n' "<item label=\"type: ${info_type}\" />"
289
+	[[ -n "${info_media}" ]] && \
290
+		printf '%s\n' "<item label=\"media: ${info_media}\" />"
291
+	[[ -n "${info_partition_size}" ]] && \
292
+		printf '%s\n' "<item label=\"size (partition): ${info_partition_size}\" />"
293
+	[[ -n "${info_device_size}" ]] && \
294
+		printf '%s\n' "<item label=\"size (device): ${info_device_size}\" />"
295
+
296
+	printf '%s\n' "</openbox_pipe_menu>"
297
+}
298
+fancy_sort() {
299
+	# This is a very hacky way to sort devices so that /dev/sdc11 wont come
300
+	# before /dev/sdc2, which happens due to a shortcoming of the sort command.
301
+
302
+	# We wont tell bash that partition_number is a number, otherwise it
303
+	# breaks when leading zeros are added (interpreted as hex).
304
+	local devname= devmajor= partition_number=
305
+	local -i array_position=0
306
+
307
+	# First lets put a leading zero in front of single digits (sdc1 -> sdc01).
308
+	# We are going to ignore /dev/mmcblk*p* devices... too complicated to sort.
309
+	array_position=0
310
+	for devname in ${removable[@]}; do
311
+		if [[ "${devname}" =~ ^/dev/dm-[0-9]+ ]]; then
312
+			devmajor="${devname%%[0-9]*}"
313
+		elif [[ "${devname}" =~ ^/dev/fd[0-9]+ ]]; then
314
+			devmajor="${devname%%[0-9]*}"
315
+		elif [[ "${devname}" =~ ^/dev/sd[a-z][0-9]+ ]]; then
316
+			devmajor="${devname%%[0-9]*}"
317
+		else
318
+			array_position=$((++array_position)); continue
319
+		fi
320
+
321
+		if [[ "${devname}" = "${devmajor}" ]]; then
322
+			array_position=$((++array_position)); continue
323
+		fi
324
+
325
+		partition_number="${devname#${devmajor}}"
326
+		removable[${array_position}]=${devmajor}$(printf '%02d' "${partition_number}")
327
+		array_position=$((++array_position))
328
+	done
329
+
330
+	# Now the device array can be sorted properly.
331
+	removable=( $(printf '%s\n' "${removable[@]}" | sort) )
332
+
333
+	# Now let's remove those leading zeros that we added.
334
+	array_position=0
335
+	for devname in ${removable[@]}; do
336
+		if [[ "${devname}" =~ ^/dev/dm-[0-9]+ ]]; then
337
+			devmajor="${devname%%[0-9]*}"
338
+		elif [[ "${devname}" =~ ^/dev/fd[0-9]+ ]]; then
339
+			devmajor="${devname%%[0-9]*}"
340
+		elif [[ "${devname}" =~ ^/dev/sd[a-z][0-9]+ ]]; then
341
+			devmajor="${devname%%[0-9]*}"
342
+		else
343
+			array_position=$((++array_position)); continue
344
+		fi
345
+
346
+		if [[ "${devname}" = "${devmajor}" ]]; then
347
+			array_position=$((++array_position)); continue
348
+		fi
349
+
350
+		partition_number="${devname#${devmajor}}"
351
+		removable[${array_position}]=${devmajor}${partition_number#0}
352
+		array_position=$((++array_position))
353
+	done
354
+}
355
+
356
+# }}}
357
+
358
+#-------------------------------------#
359
+#           MENU FUNCTIONS            #
360
+#-------------------------------------#
361
+# {{{
362
+
363
+device_menu() {
364
+	local -a removable=( )
365
+	local -a optical=( )
366
+	local -a mounted_removable=( )
367
+	local -a mounted_optical=( )
368
+	local -i total_removable=0
369
+
370
+	printf '%s\n' "<openbox_pipe_menu>"
371
+
372
+#lsblk -l -n 
373
+	lsblk -l -n | awk '{print "/dev/"$1}' >/dev/null 2>&1
374
+	if [[ $? -ne 0 ]]; then
375
+		printf '%s\n' "<item label=\"Udiskdds failed.\" />"
376
+		printf '%s\n' "</openbox_pipe_menu>"
377
+		exit 0
378
+	fi
379
+
380
+	# Here we list devices matched by the "removable_devices" regex specified in
381
+	# the configuration file.
382
+
383
+	printf '%s\n' "<separator label=\"Removable media\" />"
384
+
385
+	removable=( $(lsblk -l -n | grep "part" | awk '{print "/dev/"$1}' \
386
+		| grep -ow ${removable_devices} | sort) )
387
+
388
+	if (( fancy_sort == 1 )); then
389
+		fancy_sort
390
+	fi
391
+
392
+	for devname in ${removable[@]}; do
393
+		local devmajor=
394
+		local info_label=
395
+		local -i info_internal=
396
+		local -i mounted=
397
+		local -i partitions=
398
+
399
+		# Check here to see if a device such as /dev/sdb has partitions. If there
400
+		# are partitions, such as /dev/sdb1, then hide /dev/sdb from being shown.
401
+		if [[ "${devname}" =~ ^/dev/mmcblk[0-9]+p*[0-9]* ]]; then
402
+			devmajor="${devname%%p[0-9]*}"
403
+			if [[ "${devname}" = "${devmajor}" ]]; then
404
+				partitions="$(lsblk -l -n | grep "part" | awk '{print "/dev/"$1}' \
405
+					| grep -ow -E ^${devname}p[0-9]+ -c)"
406
+				if (( partitions > 0 )); then
407
+					continue
408
+				fi
409
+			fi
410
+		else
411
+			devmajor="${devname%%[0-9]*}"
412
+			if [[ "${devname}" = "${devmajor}" ]]; then
413
+				partitions="$(lsblk -l -n | grep "part" | awk '{print "/dev/"$1}' \
414
+					| grep -ow -E ^${devname}[0-9]+ -c)"
415
+				if (( partitions > 0 )); then
416
+					continue
417
+				fi
418
+			fi
419
+		fi
420
+
421
+		info_internal="$(info_internal "${devmajor}")"
422
+
423
+		if (( info_internal == 1 )) && (( show_internal == 0 )); then
424
+			continue
425
+		fi
426
+
427
+		if (( info_internal == 0 )) || (( show_internal == 1 )); then
428
+		
429
+			total_removable=$((++total_removable))
430
+			
431
+			info_label="$(info_label "${devname}")"
432
+			# If no label is present, then use information about the device
433
+			# instead.
434
+			if [[ -z "${info_label}" ]]; then
435
+				info_label="$(info_label "${devmajor}")"
436
+				[[ -z "${info_label}" ]] && info_label="$(info_model "${devmajor}")"
437
+				[[ -z "${info_label}" ]] && info_label="$(info_vendor "${devmajor}")"
438
+				if [[ -z "${info_label}" ]]; then
439
+					info_label="No label"
440
+				else
441
+					info_label="No label (${info_label})"
442
+				fi
443
+			fi
444
+
445
+			mounted="$(info_mounted "${devname}")"
446
+			if (( mounted == 0 )); then
447
+				if (( show_removable_device_filename == 1 )); then
448
+					printf '%s' "<menu id=\"mount${devname}\" "
449
+					printf '%s' "label=\"${devname#/dev/}: ${info_label}\" "
450
+					printf '%s' "execute=\"$0 --mount-menu removable "
451
+					printf '%s' "${devname}\" />"
452
+					printf '\n'
453
+				else
454
+					printf '%s' "<menu id=\"mount${devname}\" "
455
+					printf '%s' "label=\"${info_label}\" "
456
+					printf '%s' "execute=\"$0 --mount-menu removable "
457
+					printf '%s' "${devname}\" />"
458
+					printf '\n'
459
+				fi
460
+			else
461
+				if (( show_removable_device_filename == 1 )); then
462
+					printf '%s' "<menu id=\"mount${devname}\" "
463
+					printf '%s' "label=\"${devname#/dev/}: "
464
+					printf '%s' "${info_label} (mounted)\" "
465
+					printf '%s' "execute=\"$0 --mount-menu removable "
466
+					printf '%s' "${devname}\" />"
467
+					printf '\n'
468
+				else
469
+					printf '%s' "<menu id=\"mount${devname}\" "
470
+					printf '%s' "label=\"${info_label} (mounted)\" "
471
+					printf '%s' "execute=\"$0 --mount-menu removable "
472
+					printf '%s' "${devname}\" />"
473
+					printf '\n'
474
+				fi
475
+				mounted_removable[${#mounted_removable[*]}]=${devname}
476
+			fi
477
+		fi
478
+	done
479
+
480
+	if (( total_removable == 0 )); then
481
+		printf '%s\n' "<item label=\"None\" />"
482
+	elif (( ${#mounted_removable[*]} > 0 )); then
483
+		printf '%s\n' "<item label=\"Unmount all\">"
484
+		printf '%s\n' "<action name=\"Execute\">"
485
+		printf '%s\n' "<command>$0 --unmount-all-removable \
486
+			${mounted_removable[*]}</command>"
487
+		printf '%s\n' "<prompt>Unmount all removable devices?</prompt>"
488
+		printf '%s\n' "</action>"
489
+		printf '%s\n' "</item>"
490
+	fi
491
+
492
+	# Here we list devices matched by the "optical_devices" regex specified in
493
+	# the configuration file.
494
+	printf '%s\n' "<separator label=\"Optical media\" />"
495
+
496
+	optical=( $(lsblk -l -n | grep -v "part" | awk '{print "/dev/"$1}' \
497
+		| grep -ow ${optical_devices} | sort) )
498
+
499
+	if (( ${#optical[*]} == 0 )); then
500
+		printf '%s\n' "<item label=\"None\" />"
501
+		printf '%s\n' "</openbox_pipe_menu>"
502
+		return 0
503
+	fi
504
+
505
+	for devname in ${optical[@]}; do
506
+		local info_label=
507
+		local -i info_blank=0
508
+		local -i info_has_media=0
509
+		local -i mounted=0
510
+
511
+		info_has_media="$(info_has_media "${devname}")"
512
+		if (( info_has_media == 0 )); then
513
+			printf '%s\n' "<item label=\"${devname#/dev/}: None\" />"
514
+		else
515
+			info_blank="$(info_blank "${devname}")"
516
+			if (( info_blank == 1 )); then
517
+				info_label="Blank media"
518
+			else
519
+				info_label="$(info_label ${devname})"
520
+				[[ -z "${info_label}" ]] && info_label="$(info_model "${devname}")"
521
+				[[ -z "${info_label}" ]] && info_label="No label"
522
+			fi
523
+
524
+			mounted="$(info_mounted "${devname}")"
525
+			if (( mounted == 0 )); then
526
+				if (( show_optical_device_filename == 1 )); then
527
+					printf '%s' "<menu id=\"mount${devname}\" "
528
+					printf '%s' "label=\"${devname#/dev/}: ${info_label}\" "
529
+					printf '%s' "execute=\"$0 --mount-menu optical "
530
+					printf '%s' "${devname}\" />"
531
+					printf '\n'
532
+				else
533
+					printf '%s' "<menu id=\"mount${devname}\" "
534
+					printf '%s' "label=\"${info_label}\" "
535
+					printf '%s' "execute=\"$0 --mount-menu optical "
536
+					printf '%s' "${devname}\" />"
537
+					printf '\n'
538
+				fi
539
+			else
540
+				if (( show_optical_device_filename == 1 )); then
541
+					printf '%s' "<menu id=\"mount${devname}\" "
542
+					printf '%s' "label=\"${devname#/dev/}: "
543
+					printf '%s' "${info_label} (mounted)\" "
544
+					printf '%s' "execute=\"$0 --mount-menu optical "
545
+					printf '%s' "${devname}\" />"
546
+					printf '\n'
547
+				else
548
+					printf '%s' "<menu id=\"mount${devname}\" "
549
+					printf '%s' "label=\"${info_label} (mounted)\" "
550
+					printf '%s' "execute=\"$0 --mount-menu optical "
551
+					printf '%s' "${devname}\" />"
552
+					printf '\n'
553
+				fi
554
+				mounted_optical[${#mounted_optical[*]}]=${devname}
555
+			fi
556
+		fi
557
+	done
558
+	
559
+	if (( ${#mounted_optical[*]} > 0 )); then
560
+		printf '%s\n' "<item label=\"Unmount all\">"
561
+		printf '%s\n' "<action name=\"Execute\">"
562
+		printf '%s\n' "<command>$0 --unmount-all-optical \
563
+			${mounted_optical[*]}</command>"
564
+		printf '%s\n' "<prompt>Unmount all optical devices?</prompt>"
565
+		printf '%s\n' "</action>"
566
+		printf '%s\n' "</item>"
567
+	fi
568
+
569
+	printf '%s\n' "</openbox_pipe_menu>"
570
+}
571
+# Here we provide a submenu for each device, which displays the available
572
+# actions that can be performed.
573
+mount_menu() {
574
+	local media_type="${1}"
575
+	local devname="${2}"
576
+	local info_label="${3}"
577
+	local devname_short="${devname##*/}"
578
+	local -i mounted=0
579
+
580
+	printf '%s\n' "<openbox_pipe_menu>"
581
+
582
+	if [[ "${media_type}" = "removable" ]]; then
583
+		if (( show_removable_device_filename == 1 )); then
584
+			printf '%s\n' "<separator label=\"${devname}\" />"
585
+		else
586
+			printf '%s\n' "<separator label=\"${devname}\" />"
587
+		fi
588
+	elif [[ "${media_type}" = "optical" ]]; then
589
+		if (( show_optical_device_filename == 1 )); then
590
+			printf '%s\n' "<separator label=\"${devname}\" />"
591
+		else
592
+			printf '%s\n' "<separator label=\"${info_label}\" />"
593
+		fi
594
+	fi
595
+
596
+	mounted="$(info_mounted "${devname}")"
597
+
598
+	if (( mounted == 0 )); then
599
+		printf '%s\n' "<item label=\"Open\">"
600
+		printf '%s\n' "<action name=\"Execute\">"
601
+        printf '%s\n' "<command>$0 --mount-and-open ${devname}</command>"
602
+		printf '%s\n' "</action>"
603
+		printf '%s\n' "</item>"
604
+
605
+		printf '%s\n' "<item label=\"Mount\">"
606
+		printf '%s\n' "<action name=\"Execute\">"
607
+		printf '%s\n' "<command>$0 --mount-device ${devname}</command>"
608
+		printf '%s\n' "</action>"
609
+		printf '%s\n' "</item>"
610
+	else
611
+		printf '%s\n' "<item label=\"Open\">"
612
+		printf '%s\n' "<action name=\"Execute\">"
613
+		printf '%s\n' "<command>$0 --open-directory ${devname}</command>"
614
+		printf '%s\n' "</action>"
615
+		printf '%s\n' "</item>"
616
+
617
+		printf '%s\n' "<item label=\"Unmount\">"
618
+		printf '%s\n' "<action name=\"Execute\">"
619
+		printf '%s\n' "<command>$0 --unmount-device ${devname}</command>"
620
+		printf '%s\n' "</action>"
621
+		printf '%s\n' "</item>"
622
+	fi
623
+
624
+	printf '%s' "<menu id=\"showinfo${devname##*/}\" "
625
+	printf '%s' "label=\"Info\" "
626
+	printf '%s' "execute=\"$0 --show-info ${devname}\" />"
627
+	printf '\n'
628
+
629
+	printf '%s\n' "</openbox_pipe_menu>"
630
+}
631
+# }}}
632
+
633
+#-------------------------------------#
634
+#              INT MAIN               #
635
+#-------------------------------------#
636
+
637
+if (( $# == 0 )); then
638
+	device_menu
639
+	exit 0
640
+fi
641
+
642
+# The script calls itself with different options in order to get nested pipe
643
+# menus.
644
+case "${1}" in
645
+	"--mount-menu")
646
+		mount_menu ${2} ${3}
647
+		;;
648
+	"--mount-device")
649
+		action_mount "${2}"
650
+		;;
651
+	"--unmount-device")
652
+		action_unmount "${2}"
653
+		;;
654
+	"--open-directory")
655
+		action_open "${2}"
656
+		;;
657
+	"--mount-and-open")
658
+		action_mount "${2}" && action_open "${2}"
659
+		;;
660
+	"--show-info")
661
+		action_info "${2}"
662
+		;;
663
+	"--unmount-all-removable")
664
+		shift 1 && action_unmount_all $@
665
+		;;
666
+	"--unmount-all-optical")
667
+		shift 1 && action_unmount_all $@
668
+    	;;
669
+esac
670
+
671
+# vim: set ts=4 sw=4 noet foldmethod=marker :