Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1266 lines
34 KiB

4 years ago
  1. #!/bin/bash
  2. # Script Name: devmon http://igurublog.wordpress.com/downloads/script-devmon/
  3. # Requires: udevil bash>=4 Recommended: eject spacefm|zenity
  4. # Optional: udisks v1 may be substituted for udevil
  5. # If udevil is not set suid, udisks v1/v2 or pmount is required
  6. # License: GNU GENERAL PUBLIC LICENSE Version 3 http://www.gnu.org/licenses/gpl-3.0.txt
  7. # Thanks to Bernard Baeyens (berbae) for code from udisksvm script
  8. #=========================================================================
  9. defaultmountoptions="noexec,nosuid,nodev,noatime"
  10. #=========================================================================
  11. help()
  12. {
  13. cat << EOF
  14. devmon version 1.1.8 (distributed with udevil)
  15. Automounts and unmounts optical and removable drives
  16. Requires: udevil bash>=4 Also Recommended: eject spacefm|zenity
  17. Optional: udisks v1 may be substituted for udevil
  18. If udevil is not set suid, udisks v1/v2 or pmount is required
  19. Usage: devmon [AUTOMOUNT-OPTIONS] # Run as daemon to automount
  20. devmon [MOUNT-OPTIONS] # Or run as client to manually un/mount
  21. AUTOMOUNT-OPTIONS: (these can be used only in daemon mode)
  22. --exec-on-device DEVICE "COMMAND" Execute COMMAND after mounting DEVICE
  23. --exec-on-label "LABEL" "COMMAND" Execute COMMAND after mounting LABEL
  24. --exec-on-video "COMMAND" Execute COMMAND after video DVD mount
  25. --exec-on-audio "COMMAND" Execute COMMAND after audio CD insertion
  26. --exec-on-disc "COMMAND" Execute COMMAND after data CD/DVD mount
  27. --exec-on-drive "COMMAND" Execute COMMAND after drive mount
  28. --exec-on-unmount "COMMAND" Execute COMMAND after unmount
  29. --exec-on-remove "COMMAND" Execute COMMAND after drive removal
  30. Where the following in COMMAND will be replaced with:
  31. %d mount point directory (eg /media/cd)
  32. %f device name (eg /dev/sdd1)
  33. %l label of mounted volume
  34. Multiple --exec-on-XXX options may be used to execute multiple commands.
  35. Other exec-on-XXX commands are ignored if exec-on-device or -label executed.
  36. --mount-options "OPTIONS" Default: $defaultmountoptions
  37. --info-on-mount Show mounted drive info in a popup dialog
  38. --no-mount Don't mount anything, just exec (disables
  39. --exec-on-video)
  40. --no-unmount Don't unmount all removable drives on exit
  41. MOUNT-OPTIONS: (these can be used only in client mode)
  42. --unmount-removable | -r Sync and unmount all removable drives and show
  43. pop-up dialog (spacefm or zenity required)
  44. --unmount-recent | -c Unmount most recently mounted removable drive
  45. --unmount-optical | -o Unmount all optical drives (error pop-up only)
  46. --unmount-all | -u Same as --unmount-removable --unmount-optical
  47. --unmount DIR|DEVICE Unmount DEVICE or mount point DIR
  48. --eject DIR|DEVICE Unmount and eject DEVICE or mount point DIR
  49. --mount-all | -a Mount all removable and optical drives
  50. --mount DEVICE Mount DEVICE
  51. --mount-options|--mount-fstype|--eject-options "OPTIONS"
  52. These options will be passed to mount or eject
  53. --enumerate-device-files List known devices
  54. UNIVERSAL OPTIONS: (these can be used in both daemon and client modes)
  55. --ignore-device DEVICE Ignore DEVICE (eg /dev/sdd1)
  56. --ignore-label "LABEL" Ignore volume with LABEL
  57. --sync | -s Add sync mount option for ext2-4 ntfs ufs, or
  58. flush for fat & vfat (slower writing but safer)
  59. --internal Also attempt to un/mount internal system drives
  60. (this is mostly a fix for esata issues)
  61. --no-gui | -g Do not show spacefm/zenity pop-up dialogs
  62. Instructions and updates:
  63. http://igurublog.wordpress.com/downloads/script-devmon/
  64. EOF
  65. exit
  66. }
  67. test2()
  68. {
  69. if [ "${2:0:1}" = "-" ] || [ "$2" = "" ]; then
  70. echo "devmon: Option $1 requires an argument" 1>&2
  71. exit 1
  72. fi
  73. }
  74. test3()
  75. {
  76. if [ "${2:0:1}" = "-" ] || [ "$2" = "" ] || \
  77. [ "${3:0:1}" = "-" ] || [ "$3" = "" ]; then
  78. echo "devmon: Option $1 requires two arguments" 1>&2
  79. exit 1
  80. fi
  81. }
  82. unknown()
  83. {
  84. echo "devmon: Unknown option $1" 1>&2
  85. echo " For help use: devmon --help" 1>&2
  86. exit 1
  87. }
  88. # parse command line
  89. execoix=0
  90. execomx=0
  91. execovx=0
  92. execoax=0
  93. execodx=0
  94. execolx=0
  95. execoux=0
  96. execorx=0
  97. umntx=0
  98. mntx=0
  99. ejx=0
  100. igdevx=0
  101. iglabx=0
  102. while [ "$1" != "" ]; do
  103. if [ "${1:0:1}" = "-" ]; then
  104. case "$1" in
  105. --help )
  106. help
  107. exit
  108. ;;
  109. # don't use eval on these to preserve command strings
  110. --exec-on-drive )
  111. test2 "$1" "$2"
  112. execoi[$execoix]="$2"
  113. (( execoix++ ))
  114. shift
  115. ;;
  116. --exec-on-disc )
  117. test2 "$1" "$2"
  118. execom[$execomx]="$2"
  119. (( execomx++ ))
  120. shift
  121. ;;
  122. --exec-on-video )
  123. test2 "$1" "$2"
  124. execov[$execovx]="$2"
  125. (( execovx++ ))
  126. shift
  127. ;;
  128. --exec-on-audio )
  129. test2 "$1" "$2"
  130. execoa[$execoax]="$2"
  131. (( execoax++ ))
  132. shift
  133. ;;
  134. --exec-on-device )
  135. test3 "$1" "$2" "$3"
  136. execod1[$execodx]="$2"
  137. execod2[$execodx]="$3"
  138. (( execodx++ ))
  139. shift 2
  140. ;;
  141. --exec-on-label )
  142. test3 "$1" "$2" "$3"
  143. execol1[$execolx]="$2"
  144. execol2[$execolx]="$3"
  145. (( execolx++ ))
  146. shift 2
  147. ;;
  148. --exec-on-unmount )
  149. test2 "$1" "$2"
  150. execou[$execoux]="$2"
  151. (( execoux++ ))
  152. shift
  153. ;;
  154. --exec-on-remove )
  155. test2 "$1" "$2"
  156. execor[$execorx]="$2"
  157. (( execorx++ ))
  158. shift
  159. ;;
  160. --info-on-mount )
  161. infomount=1
  162. ;;
  163. --no-mount )
  164. nomount=1
  165. ;;
  166. --sync )
  167. syncopt=1
  168. ;;
  169. --unmount-on-exit )
  170. # leave for usage compat with versions prior to 1.0.1
  171. ;;
  172. --no-unmount )
  173. nounmount=1
  174. ;;
  175. --unmount-all )
  176. unmountrem=1
  177. unmountoptical=1
  178. ;;
  179. --unmount-removable )
  180. unmountrem=1
  181. ;;
  182. --unmount-optical )
  183. unmountoptical=1
  184. ;;
  185. --unmount-recent )
  186. unmountrecent=1
  187. ;;
  188. --unmount )
  189. test2 "$1" "$2"
  190. umnt[$umntx]="$2"
  191. (( umntx++ ))
  192. shift
  193. ;;
  194. --mount-all )
  195. mountall=1
  196. ;;
  197. --mount )
  198. test2 "$1" "$2"
  199. mnt[$mntx]="$2"
  200. (( mntx++ ))
  201. shift
  202. ;;
  203. --eject )
  204. test2 "$1" "$2"
  205. ej[$ejx]="$2"
  206. (( ejx++ ))
  207. shift
  208. ;;
  209. --mount-options )
  210. test2 "$1" "$2"
  211. mountoptions="$2"
  212. shift
  213. ;;
  214. --mount-fstype )
  215. test2 "$1" "$2"
  216. mountfstype="$2"
  217. shift
  218. ;;
  219. --eject-options )
  220. test2 "$1" "$2"
  221. ejectoptions="$2"
  222. shift
  223. ;;
  224. --internal )
  225. internal=1
  226. ;;
  227. --nogui | --no-gui )
  228. nogui=1
  229. ;;
  230. --ignore-device )
  231. test2 "$1" "$2"
  232. igdev[$igdevx]="$2"
  233. (( igdevx++ ))
  234. shift
  235. ;;
  236. --ignore-label )
  237. test2 "$1" "$2"
  238. iglab[$iglabx]="$2"
  239. (( iglabx++ ))
  240. shift
  241. ;;
  242. --enumerate-device-files )
  243. all=`grep " [ms]d[a-z0-9]*$" /proc/partitions | \
  244. sed 's/.* \([ms]d[a-z0-9]*\)/\/dev\/\1/'`
  245. n=$'\n'
  246. if [ "$all" != "" ]; then
  247. all="$all$n"
  248. fi
  249. for f in /dev/mapper/*; do
  250. if [ -h "$f" ]; then
  251. name="$(basename "$f")"
  252. target="$(readlink "$f")"
  253. target="$(basename "$target")"
  254. if [ "$target" != "" ]; then
  255. all="$all/dev/$target$n"
  256. if [ "${name:0:4}" = "loop" ]; then
  257. all="$all/dev/$name$n"
  258. fi
  259. fi
  260. fi
  261. done
  262. # add mounted loop devices (attached requires losetup as root)
  263. loop=`cat /proc/self/mountinfo 2>/dev/null | grep ' /dev/loop[0-9]* ' | cut -f9 -d ' ' 2>/dev/null`
  264. if [ "$loop" != "" ]; then
  265. loop="$loop$n"
  266. fi
  267. other=`/bin/ls -1 /dev/md[0-9]* /dev/dm-* /dev/sr* 2>/dev/null`
  268. if [ "$other" != "" ]; then
  269. other="$other$n"
  270. fi
  271. all="$all$loop$other"
  272. echo -n "$all" | sort | uniq
  273. exit
  274. ;;
  275. --* )
  276. unknown "$1";;
  277. -* )
  278. o="${1:1}"
  279. while [ "$o" != "" ]; do
  280. case "${o:0:1}" in
  281. r )
  282. unmountrem=1;;
  283. o )
  284. unmountoptical=1;;
  285. u )
  286. unmountrem=1
  287. unmountoptical=1
  288. ;;
  289. a )
  290. mountall=1;;
  291. s )
  292. syncopt=1;;
  293. c )
  294. unmountrecent=1;;
  295. g )
  296. nogui=1;;
  297. h )
  298. help
  299. exit
  300. ;;
  301. * )
  302. unknown "-${o:0:1}";;
  303. esac
  304. o="${o:1}"
  305. done
  306. ;;
  307. esac
  308. else
  309. unknown "$1"
  310. fi
  311. shift
  312. done
  313. (( mountmode = umntx + mntx + ejx + unmountrem + unmountoptical + mountall + unmountrecent ))
  314. # Warnings
  315. if [ "$(whoami)" = "root" ]; then
  316. echo "WARNING: running devmon as root is usually not required or recommended" 1>&2
  317. fi
  318. if (( execoix + execomx + execovx + execoax + execodx + execolx + execoux + execorx \
  319. + nounmount + infomount != 0 )) && (( mountmode != 0 )); then
  320. echo "WARNING: devmon automount options ignored in mount mode" 1>&2
  321. fi
  322. # Discovery
  323. udevil=`which udevil 2>/dev/null`
  324. udisks1=`which udisks 2>/dev/null`
  325. udisks2=`which udisksctl 2>/dev/null`
  326. pmount=`which pmount 2>/dev/null`
  327. zenity=`which zenity 2>/dev/null`
  328. spacefm=`which spacefm 2>/dev/null`
  329. if [ "$udevil" != "" ] && [ -x "$udevil" ]; then
  330. info_cmd="$udevil"
  331. elif [ "$udisks1" != "" ] && [ -x "$udisks1" ]; then
  332. info_cmd="$udisks1"
  333. else
  334. echo "WARNING: devmon can't run udevil or udisks v1 for device monitoring" 1>&2
  335. info_cmd="udevil"
  336. fi
  337. if [ "$udevil" != "" ] && [ -x "$udevil" ]; then
  338. if [ -u "$udevil" ] || [ "$(whoami)" = "root" ]; then
  339. mount_cmd="$udevil"
  340. fi
  341. fi
  342. if [ "$mount_cmd" = "" ] && [ "$pmount" != "" ] && [ -x "$pmount" ]; then
  343. if [ -u "$pmount" ] || [ "$(whoami)" = "root" ]; then
  344. mount_cmd="$pmount"
  345. fi
  346. fi
  347. if [ "$mount_cmd" = "" ] && [ "$udisks1" != "" ] && [ -x "$udisks1" ]; then
  348. mount_cmd="$udisks1"
  349. fi
  350. if [ "$mount_cmd" = "" ] && [ "$udisks2" != "" ] && [ -x "$udisks2" ]; then
  351. mount_cmd="$udisks2"
  352. fi
  353. if [ "$mount_cmd" = "" ]; then
  354. echo "WARNING: devmon can't run udevil, pmount, or udisks for mounting" 1>&2
  355. mount_cmd="udevil"
  356. fi
  357. driveinfo() #$1=dev #Optional $2=quiet
  358. {
  359. unset systeminternal usage ismounted presentationnopolicy hasmedia \
  360. opticaldisc numaudiotracks type partition media blank label
  361. uinfos=`$info_cmd --show-info $1 2> /dev/null`
  362. label=`echo "$uinfos" | grep -m 1 "^ label:" | sed 's/ *label: *\(.*\)/\1/'`
  363. listinfos=`echo "$uinfos" | grep \
  364. -e "^ system internal:" \
  365. -e "^ usage:" \
  366. -e "^ type:" \
  367. -e "^ is mounted:" \
  368. -e "^ presentation nopolicy:" \
  369. -e "^ has media" \
  370. -e "^ optical disc:" \
  371. -e " blank:" \
  372. -e " num audio tracks:" \
  373. -e "^ partition:" \
  374. -e " media:"`
  375. # The change for type= is to take only its first value in listinfos
  376. listinfos=$(echo "$listinfos" | sed 's/ //g
  377. s/:/=/
  378. s/opticaldisc=/&1/
  379. s/type=\(.*\)/type=${type:-\1}/
  380. s/[()]//g
  381. s/partition=/&1/')
  382. eval "$listinfos"
  383. if (( internal == 1 )); then
  384. systeminternal="ignored"
  385. fi
  386. # Take only the first character
  387. hasmedia=${hasmedia:0:1}
  388. # If "partition:" not find in listinfos, should mean it is not a partition
  389. partition=${partition:-0}
  390. nopolicy="$presentationnopolicy"
  391. if (( mountmode == 0 )) && [ "$systeminternal" != "1" ] && [ "$2" != "quiet" ]; then
  392. if [ "$usage" = "filesystem" ] || [ "$opticaldisc" = "1" ]; then
  393. echo "device: [$1]"
  394. echo " systeminternal: [$systeminternal]"
  395. echo " usage: [$usage]"
  396. echo " type: [$type]"
  397. echo " label: [$label]"
  398. echo " ismounted: [$ismounted]"
  399. echo " nopolicy: [$nopolicy]"
  400. echo " hasmedia: [$hasmedia]"
  401. echo " opticaldisc: [$opticaldisc]"
  402. echo " numaudiotracks: [$numaudiotracks]"
  403. echo " blank: [$blank]"
  404. echo " media: [$media]"
  405. echo " partition: [$partition]"
  406. fi
  407. fi
  408. }
  409. ignoredevice()
  410. {
  411. idx=0
  412. while (( idx < igdevx )); do
  413. if [ "$1" = "${igdev[$idx]}" ]; then
  414. echo "devmon: ignored device $1"
  415. return 0
  416. fi
  417. (( idx++ ))
  418. done
  419. return 1
  420. }
  421. ignorelabel()
  422. {
  423. ilx=0
  424. while (( ilx < iglabx )); do
  425. if [ "$1" = "${iglab[$ilx]}" ]; then
  426. echo "devmon: ignored label $1"
  427. return 0
  428. fi
  429. (( ilx++ ))
  430. done
  431. return 1
  432. }
  433. execcommands() # $exectype "${exec[@]}"
  434. {
  435. exectype="$1"
  436. shift
  437. while [ "$1" != "" ]; do
  438. usercmd="$1"
  439. usercmd="${usercmd//%f/$dv}"
  440. usercmd="${usercmd//%l/$lb}"
  441. usercmd="${usercmd//%d/$point}"
  442. if [ "$usercmd" != "" ]; then
  443. echo "devmon: [$exectype] eval $usercmd &"
  444. eval $usercmd &
  445. fi
  446. shift
  447. done
  448. }
  449. mountdev() # $1=device [$2=label] [$3=devtype or fstype]
  450. {
  451. # set label comment
  452. if [ "$2" = "" ]; then
  453. lblcmt=""
  454. else
  455. lblcmt="# ($2)"
  456. fi
  457. # set mount-fstype option
  458. if [ "$mountfstype" != "" ]; then
  459. if [ "$mount_cmd" = "$udisks2" ] || [ "$mount_cmd" = "$pmount" ]; then
  460. fst="-t"
  461. else
  462. fst="--mount-fstype"
  463. fi
  464. else
  465. fst=""
  466. fi
  467. # set default mount options
  468. if [ "$mountoptions" != "" ]; then
  469. mopts="$mountoptions"
  470. else
  471. mopts="$defaultmountoptions"
  472. fi
  473. # set sync mount options
  474. if (( syncopt == 1 )); then
  475. case "$3" in
  476. ext2 | ext3 | ext4 | ufs | ntfs )
  477. mopts="$mopts,sync";;
  478. fat | vfat )
  479. mopts="$mopts,flush";;
  480. esac
  481. fi
  482. if [ "$mount_cmd" = "$udisks2" ]; then
  483. mntmsg="devmon: $mount_cmd mount -b $1 -o \"$mopts\" $fst $mountfstype $lblcmt"
  484. elif [ "$mount_cmd" = "$pmount" ]; then
  485. mntmsg="devmon: $mount_cmd $fst $mountfstype $1 $lblcmt"
  486. else
  487. mntmsg="devmon: $mount_cmd --mount $1 --mount-options \"$mopts\" $fst $mountfstype $lblcmt"
  488. fi
  489. if [ "$3" != "nofs" ]; then
  490. echo "$mntmsg"
  491. fi
  492. # mount
  493. if [ "$mount_cmd" = "$udisks2" ]; then
  494. umsg=`$mount_cmd mount -b $1 -o "$mopts" $fst $mountfstype 2>&1`
  495. elif [ "$mount_cmd" = "$pmount" ]; then
  496. umsg=`$mount_cmd $fst $mountfstype $1 2>&1`
  497. else
  498. umsg=`$mount_cmd --mount $1 --mount-options "$mopts" $fst $mountfstype 2>&1`
  499. fi
  500. mounterr="$?"
  501. # get mount point
  502. point=`echo "$umsg" | grep "^Mounted " | sed 's/^Mounted .* at \(.*\)/\1/'`
  503. if [ "$mount_cmd" = "$pmount" ] && [ "$point" = "" ]; then
  504. # pmount doesn't output the mount point - get it below
  505. point=" "
  506. fi
  507. if [ "$mounterr" != "0" ] || [ "$point" = "" ]; then
  508. # if $3=nofs then there was no apparent filesystem but we tried to mount it
  509. # anyway in case it didn't report the filesystem accurately, so ignore the
  510. # error
  511. if [ "$3" != "nofs" ]; then
  512. echo "$umsg" 1>&2
  513. echo "devmon: error mounting $1 ($mounterr)" 1>&2
  514. if [ "$mount_cmd" = "$udisks1" ] || [ "$mount_cmd" = "$udisks2" ]; then
  515. if (( mountmode == 0 )) && (( polkiterrgiven != 1 )) && \
  516. [ "$(echo "$umsg" | grep 'Not *Authorized')" != "" ]; then
  517. if (( nogui != 1 )); then
  518. if [ "$spacefm" != "" ]; then
  519. ( sleep 3 && $spacefm -g --title "devmon error" --window-icon error --label "udisks functions are not authorized through policykit,\nso devmon cannot automount drives.\nPlease install udevil or see devmon's consolekit installation instructions:\n\nhttp://igurublog.wordpress.com/downloads/script-devmon/#install\n\n(To silence this pop-up add --no-gui to devmon's command line.)" --button "Open Website" xdg-open "http://igurublog.wordpress.com/downloads/script-devmon/#install" --button ok &> /dev/null ) &
  520. else
  521. ( sleep 3 && WINDOWID="" $zenity --error --no-wrap --title="devmon error" \
  522. --text="udisks functions are not authorized through policykit,\nso devmon cannot automount drives.\nPlease install udevil or see devmon's consolekit installation instructions:\n\nhttp://igurublog.wordpress.com/downloads/script-devmon/#install\n\n(To silence this pop-up add --no-gui to devmon's command line.)" &> /dev/null ) &
  523. fi
  524. fi
  525. echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2
  526. echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2
  527. echo "udisks functions are not authorized through policykit," 1>&2
  528. echo "so devmon cannot automount drives." 1>&2
  529. echo "Please see devmon's consolekit installation instructions:" 1>&2
  530. echo "http://igurublog.wordpress.com/downloads/script-devmon/#install" 1>&2
  531. echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2
  532. echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2
  533. polkiterrgiven=1
  534. fi
  535. fi
  536. fi
  537. uerr=3
  538. return 3
  539. elif [ "$3" = "nofs" ]; then
  540. # no filesystem reported but successful mount
  541. echo "$mntmsg"
  542. fi
  543. # set devtag for recognizing mounted by devmon
  544. devpath="$1"
  545. devtag="${devpath#/dev/}"
  546. devtag="${devtag//-/_}"
  547. eval devmounted${devtag}=1
  548. echo "$umsg"
  549. if [ "$point" = " " ]; then
  550. # pmount doesn't output the mount point - get it now
  551. sleep 1
  552. point=`$info_cmd --show-info $1 2>/dev/null | grep "^ mount paths:" | sed 's/.*: *\(.*\)/\1/'`
  553. point="${point%%, *}"
  554. fi
  555. }
  556. unmountdev() # $1=device
  557. {
  558. if [ "$mount_cmd" = "$udisks2" ]; then
  559. echo "devmon: $mount_cmd unmount -b $1"
  560. uerrmsg=`$mount_cmd unmount -b $1 2>&1`
  561. elif [ "$mount_cmd" = "$pmount" ]; then
  562. echo "devmon: pumount $1"
  563. uerrmsg=`pumount $1 2>&1`
  564. else
  565. echo "devmon: $mount_cmd --unmount $1"
  566. uerrmsg=`$mount_cmd --unmount $1 2>&1`
  567. fi
  568. umounterr="$?"
  569. if [ "$mount_cmd" = "$udisks1" ] && [ "$uerrmsg" != "" ]; then
  570. # bug: udisks v1 returns $?==0 when unmount fails
  571. umounterr=1
  572. fi
  573. if [ "$uerrmsg" != "" ]; then
  574. echo "$uerrmsg"
  575. fi
  576. if [ $umounterr -ne 0 ]; then
  577. uerr=3
  578. return 3
  579. fi
  580. }
  581. ejectdev()
  582. {
  583. echo "devmon: eject $ejectoptions $1"
  584. eject $ejectoptions $1
  585. if [ "$?" != "0" ]; then
  586. uerr=3
  587. return 3
  588. fi
  589. }
  590. mountdrive() # $1=device $2=label [$3=devtype or fstype]
  591. {
  592. dv="$1"
  593. lb="$2"
  594. tp="$3"
  595. unset point
  596. if ( ignoredevice "$dv" ) || ( ignorelabel "$lb" ); then
  597. return
  598. fi
  599. # mount
  600. if [ "$tp" != "audiocd" ] && (( nomount != 1 )); then
  601. mountdev $dv "$lb" "$tp"
  602. if [ "$?" != "0" ]; then
  603. return
  604. fi
  605. fi
  606. # exec on device
  607. unset execdone
  608. x=0
  609. while (( x < execodx )); do
  610. if [ "${execod1[$x]}" = "$dv" ]; then
  611. usercmd="${execod2[$x]}"
  612. usercmd="${usercmd//%f/$dv}"
  613. usercmd="${usercmd//%l/$lb}"
  614. usercmd="${usercmd//%d/$point}"
  615. if [ "$usercmd" != "" ]; then
  616. echo "devmon: [exec on device] eval $usercmd"
  617. eval $usercmd &
  618. execdone=1
  619. fi
  620. fi
  621. (( x++ ))
  622. done
  623. if (( execdone == 1 )); then return; fi
  624. # exec on label
  625. x=0
  626. while (( x < execolx )); do
  627. if [ "${execol1[$x]}" = "$lb" ]; then
  628. usercmd="${execol2[$x]}"
  629. usercmd="${usercmd//%f/$dv}"
  630. usercmd="${usercmd//%l/$lb}"
  631. usercmd="${usercmd//%d/$point}"
  632. if [ "$usercmd" != "" ]; then
  633. echo "devmon: [exec on label] eval $usercmd"
  634. eval $usercmd &
  635. execdone=1
  636. fi
  637. fi
  638. (( x++ ))
  639. done
  640. if (( execdone == 1 )); then return; fi
  641. # exec on video
  642. if [ "$tp" = "dvd" ] && [ "$point" != "" ] && [ -d "$point/VIDEO_TS" ]; then
  643. echo "devmon: videodvd $dv ($lb) on $point"
  644. if (( execovx != 0 )); then
  645. execcommands "exec on video" "${execov[@]}"
  646. fi
  647. return
  648. fi
  649. # exec on audio
  650. if [ "$tp" = "audiocd" ]; then
  651. echo "devmon: audiocd $dv ($lb)"
  652. if (( execoax != 0 )); then
  653. execcommands "exec on audio" "${execoa[@]}"
  654. fi
  655. return
  656. fi
  657. # exec on disc
  658. if [ "$tp" = "optical" ] || [ "$tp" = "dvd" ]; then
  659. if [ "$point" != "" ] || (( nomount == 1 )); then
  660. if (( execomx != 0 )); then
  661. execcommands "exec on disc" "${execom[@]}"
  662. fi
  663. fi
  664. return
  665. fi
  666. # exec on drive
  667. if [ "$point" != "" ] || (( nomount == 1 )); then
  668. if (( execoix != 0 )); then
  669. execcommands "exec on drive" "${execoi[@]}"
  670. fi
  671. fi
  672. # info on mount
  673. if [ "$point" != "" ] && (( infomount == 1 )) && (( nomount != 1 )); then
  674. sleep .5
  675. echo "devmon: [info on mount] $dv"
  676. if (( nogui != 1 )); then
  677. if [ "$spacefm" != "" ]; then
  678. $spacefm -g --title "devmon mount" --window-icon drive-removable-media --label \
  679. "The following device has been mounted:\n\n$(df -hT "$dv" | grep "$dv" | \
  680. awk '{print "Device:\\t"$1"\x0AType:\\t"$2"\nSize:\\t\\t"$3"\nUsed:\\t"$4"\n""Avail:\\t"$5"\nUse%:\\t"$6"\nMount:\\t"$7,$8,$9,$10}')\nLabel:\\t$lb" \
  681. --button open spacefm "$point" --button ok &>/dev/null &
  682. else
  683. WINDOWID="" $zenity --info --text="The following device has been mounted:\n\n$(df -hT "$dv" \
  684. | grep "$dv" | awk '{print "Device:\\t"$1"\x0AType:\\t"$2"\nSize:\\t\\t"$3"\nUsed:\\t"$4"\n""Avail:\\t"$5"\nUse%:\\t"$6"\nMount:\\t"$7,$8,$9,$10}')\nLabel:\\t$lb" --title="devmon mount" &
  685. fi
  686. fi
  687. df -hT "$dv"
  688. fi
  689. }
  690. mountalldrives()
  691. {
  692. # Mount all optical drives, no exec
  693. x=0
  694. while [ -e /dev/sr$x ]; do
  695. driveinfo /dev/sr$x
  696. if [ "$numaudiotracks" = "" ]; then
  697. numaudiotracks=0
  698. fi
  699. if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \
  700. [ "$ismounted" != "1" ] && [ "$hasmedia" != "0" ] && \
  701. [ "$blank" != "1" ] && (( numaudiotracks == 0 )) && \
  702. [ "$nopolicy" != "1" ]; then
  703. if ( ignoredevice "/dev/sr$x" ) || ( ignorelabel "$label" ); then
  704. (( x++ ))
  705. continue
  706. fi
  707. mountdev /dev/sr$x "$label"
  708. eval notejectedsr$x=1
  709. fi
  710. (( x++ ))
  711. done
  712. # Mount removable drives, no exec
  713. IFSOLD="$IFS"
  714. IFS=$'\n'
  715. partlist=`grep " [ms]d[a-z0-9]*$" /proc/partitions | sed 's/.* \([ms]d[a-z0-9]*\)/\1/'`
  716. for p in $partlist; do
  717. if ( ignoredevice "/dev/$p" ); then
  718. continue
  719. fi
  720. driveinfo /dev/$p
  721. if ( ignorelabel "$label" ); then
  722. continue
  723. else
  724. if [ "$systeminternal" != "1" ] && [ "$opticaldisc" != "1" ] && \
  725. [ "$ismounted" = "0" ] && [ "$nopolicy" != "1" ]; then
  726. if [ "$usage" = "filesystem" ]; then
  727. mountdev /dev/$p "$label" "$type"
  728. else
  729. mountdev /dev/$p "$label" nofs
  730. fi
  731. fi
  732. fi
  733. done
  734. IFS="$IFSOLD"
  735. }
  736. trapexit()
  737. {
  738. kill $COPROC_PID 2> /dev/null
  739. # prevent trap code from executing multiple times on different signals
  740. if (( trapdone != 1 )); then
  741. trapdone=1
  742. # Unmount All
  743. if (( nounmount != 1 )); then
  744. IFSOLD="$IFS"
  745. IFS=$'\n'
  746. uerr=0
  747. partlist=`grep " [ms]d[a-z0-9]*$" /proc/partitions | \
  748. sed 's/.* \([ms]d[a-z0-9]*\)/\1/'`
  749. for p in $partlist; do
  750. if ( ignoredevice "/dev/$p" ); then
  751. continue
  752. fi
  753. driveinfo /dev/$p
  754. if ( ignorelabel "$label" ); then
  755. continue
  756. else
  757. if [ "$systeminternal" != "1" ] && [ "$opticaldisc" != "1" ] && \
  758. [ "$usage" = "filesystem" ] && [ "$ismounted" = "1" ]; then
  759. if [ "$mount_cmd" = "$udisks2" ]; then
  760. echo "devmon: [on exit] $mount_cmd unmount -b /dev/$p &"
  761. $mount_cmd unmount -b /dev/$p &
  762. elif [ "$mount_cmd" = "$pmount" ]; then
  763. echo "devmon: [on exit] pumount /dev/$p &"
  764. pumount /dev/$p &
  765. else
  766. echo "devmon: [on exit]$mount_cmd --unmount /dev/$p &"
  767. $mount_cmd --unmount /dev/$p &
  768. fi
  769. if [ "$?" != "0" ]; then
  770. uerr=3
  771. fi
  772. fi
  773. fi
  774. done
  775. IFS="$IFSOLD"
  776. fi
  777. echo 'devmon: stopped'
  778. exit $uerr
  779. fi
  780. }
  781. # Client Mode
  782. if (( mountmode != 0 )); then
  783. uerr=0
  784. if (( unmountrem == 1 )) || (( unmountrecent == 1 )); then
  785. y=0
  786. unset udrive zpid
  787. IFSOLD="$IFS"
  788. IFS=$'\n'
  789. if (( unmountrem == 1 )); then
  790. # Unmount All Removable Drives
  791. partlist=`grep " [ms]d[a-z0-9]*$" /proc/partitions | sed 's/.* \([ms]d[a-z0-9]*\)/\1/'`
  792. msgtitle="devmon unmount"
  793. else
  794. # Unmount Recent
  795. partlist=`mount | grep "^/dev/.* on " | sed 's/^\/dev\/\(.*\) on .*/\1/' \
  796. | grep -v -e "null" -e "shm" -e "mapper" -e "snd" \
  797. -e "video" -e "random" | tac`
  798. msgtitle="devmon unmount recent"
  799. fi
  800. for p in $partlist; do
  801. if ( ignoredevice "/dev/$p" ); then
  802. continue
  803. fi
  804. driveinfo /dev/$p
  805. if ( ignorelabel "$label" ); then
  806. continue
  807. else
  808. if [ "$systeminternal" != "1" ] && [ "$opticaldisc" != "1" ] \
  809. && [ "$ismounted" = "1" ]; then
  810. udrive[$y]="/dev/$p"
  811. (( y++ ))
  812. if (( unmountrem != 1 )); then break; fi
  813. fi
  814. fi
  815. done
  816. IFS="$IFSOLD"
  817. if (( y == 0 )); then
  818. msg="No removable drives are mounted"
  819. echo "$msg"
  820. else
  821. msg="Unmounting ${udrive[@]}...\n\n(This dialog will close when the devices are unmounted)"
  822. echo "Preparing to unmount ${udrive[@]}"
  823. fi
  824. if (( nogui != 1 )); then
  825. if [ "$spacefm" != "" ]; then
  826. spacefm -g --title "$msgtitle" --label "$msg" --button close &> /dev/null &
  827. else
  828. WINDOWID="" zenity --info --title="$msgtitle" --text="$msg" &> /dev/null &
  829. fi
  830. zpid=$!
  831. fi
  832. if (( y > 0 )); then
  833. echo "devmon: sync"
  834. sync
  835. for d in ${udrive[@]}; do
  836. unmountdev $d
  837. if [ "$?" != "0" ] && (( nogui != 1 )); then
  838. driveinfo "$d" quiet
  839. if [ "$label" = "" ]; then
  840. lb=""
  841. else
  842. lb=" ($label)"
  843. fi
  844. msg="Unmount error on $d$lb:\n\n$uerrmsg"
  845. if [ "$spacefm" != "" ]; then
  846. spacefm -g --title "$msgtitle" --window-icon error \
  847. --label "$msg" --button close &> /dev/null &
  848. else
  849. WINDOWID="" zenity --error --title="$msgtitle" --text="$msg" &> /dev/null &
  850. fi
  851. fi
  852. done
  853. echo "devmon: sync"
  854. sync
  855. fi
  856. if [ "$zpid" != "" ]; then
  857. sleep 2
  858. kill $zpid 2> /dev/null
  859. fi
  860. fi
  861. # Unmount Optical
  862. if (( unmountoptical == 1 )); then
  863. x=0
  864. while [ -e "/dev/sr$x" ]; do
  865. if ( ignoredevice "/dev/sr$x" ); then
  866. (( x++ ))
  867. continue
  868. fi
  869. driveinfo /dev/sr$x
  870. if ( ignorelabel "$label" ); then
  871. (( x++ ))
  872. continue
  873. else
  874. if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \
  875. [ "$ismounted" = "1" ]; then
  876. unmountdev /dev/sr$x
  877. if [ "$?" != "0" ] && (( nogui != 1 )); then
  878. if [ "$label" = "" ]; then
  879. lb=""
  880. else
  881. lb=" ($label)"
  882. fi
  883. msg="Unmount error on /dev/sr$x$lb:\n\n$uerrmsg"
  884. if [ "$spacefm" != "" ]; then
  885. spacefm -g --title "devmon unmount optical" \
  886. --window-icon error \
  887. --label "$msg" --button close &> /dev/null &
  888. else
  889. WINDOWID="" zenity --error --title="devmon unmount optical" \
  890. --text="$msg" &> /dev/null &
  891. fi
  892. fi
  893. fi
  894. fi
  895. (( x++ ))
  896. done
  897. fi
  898. # Unmount DIR|DEVICE
  899. if (( umntx > 0 )); then
  900. x=0
  901. while (( x < umntx )); do
  902. d="${umnt[$x]}"
  903. # remove trailing slash
  904. if [ "$d" != "/" ]; then
  905. d="${d%/}"
  906. fi
  907. if [ "${d:0:5}" = "/dev/" ]; then
  908. # Unmount DEVICE
  909. unmountdev "$d"
  910. else
  911. # Unmount DIR
  912. if [ "$(dirname "$d")" = "." ]; then
  913. if [ -d "$(pwd)/$d" ]; then
  914. d="$(pwd)/$d"
  915. elif [ -d "/media/$d" ]; then
  916. d="/media/$d"
  917. elif [ -e "/dev/$d" ] && [ "$(mount | grep "^/dev/$d on ")" != "" ]; then
  918. unmountdev "/dev/$d"
  919. (( x++ ))
  920. continue
  921. fi
  922. fi
  923. if [ ! -d "$d" ]; then
  924. echo "devmon: No such directory or mounted device $d" 1>&2
  925. uerr=3
  926. else
  927. dv=`mount | grep -m 1 " on $d type " | awk '{print $1}'`
  928. if [ "$dv" = "" ]; then
  929. echo "devmon: Nothing mounted on $d (mtab)" 1>&2
  930. uerr=3
  931. else
  932. unmountdev "$dv"
  933. fi
  934. fi
  935. fi
  936. (( x++ ))
  937. done
  938. fi
  939. # Eject DIR|DEVICE
  940. if (( ejx > 0 )); then
  941. x=0
  942. while (( x < ejx )); do
  943. d="${ej[$x]}"
  944. # remove trailing slash
  945. if [ "$d" != "/" ]; then
  946. d="${d%/}"
  947. fi
  948. dv=""
  949. if [ "${d:0:5}" = "/dev/" ]; then
  950. # Eject DEVICE
  951. dv="$d"
  952. else
  953. # Eject DIR
  954. if [ "$(dirname "$d")" = "." ]; then
  955. if [ -d "$(pwd)/$d" ]; then
  956. d="$(pwd)/$d"
  957. elif [ -d "/media/$d" ]; then
  958. d="/media/$d"
  959. elif [ -e "/dev/$d" ] && [ "$(mount | grep "^/dev/$d on ")" != "" ]; then
  960. dv="/dev/$d"
  961. fi
  962. fi
  963. if [ "$dv" = "" ]; then
  964. if [ ! -d "$d" ]; then
  965. echo "devmon: No such directory or mounted device $d" 1>&2
  966. uerr=3
  967. else
  968. dv=`mount | grep -m 1 " on $d type " | awk '{print $1}'`
  969. if [ "$dv" = "" ]; then
  970. echo "devmon: Nothing mounted on $d (mtab)" 1>&2
  971. uerr=3
  972. fi
  973. fi
  974. fi
  975. fi
  976. if [ "$dv" != "" ]; then
  977. driveinfo "$dv"
  978. if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \
  979. [ "$ismounted" = "1" ]; then
  980. unmountdev "$dv"
  981. fi
  982. ejectdev "$dv"
  983. fi
  984. (( x++ ))
  985. done
  986. fi
  987. # Mount DEVICE
  988. if (( mntx > 0 )); then
  989. x=0
  990. while (( x < mntx )); do
  991. d="${mnt[$x]}"
  992. # remove trailing slash
  993. if [ "$d" != "/" ]; then
  994. d="${d%/}"
  995. fi
  996. if [ "$(dirname "$d")" = "." ] && [ "${d:0:5}" != "/dev/" ]; then
  997. d="/dev/$d"
  998. fi
  999. driveinfo "$d" quiet
  1000. if [ "$opticaldisc" = "1" ]; then
  1001. mountdev $d "$label"
  1002. else
  1003. mountdev $d "$label" "$type"
  1004. fi
  1005. (( x++ ))
  1006. done
  1007. fi
  1008. # Mount All Unmounted
  1009. if (( mountall == 1 )); then
  1010. mountalldrives
  1011. fi
  1012. exit $uerr
  1013. fi
  1014. # Daemon Mode
  1015. if [ "$mountfstype" != "" ]; then
  1016. echo "WARNING: --mount-fstype ignored in daemon mode" 1>&2
  1017. mountfstype=""
  1018. fi
  1019. if [ "$ejectoptions" != "" ]; then
  1020. echo "WARNING: --eject-options ignored in daemon mode" 1>&2
  1021. ejectoptions=""
  1022. fi
  1023. pidcount=`ps h -C "${0//*\//}" -o pid | wc -l`
  1024. if (( pidcount > 2 )); then
  1025. echo
  1026. echo "WARNING: multiple instances of devmon appear to be running (my pid=$$):"
  1027. ps h -C "${0//*\//}"
  1028. echo
  1029. fi
  1030. if [ "$mount_cmd" = "$udisks1" ] || [ "$info_cmd" = "$udisks1" ]; then
  1031. # Trigger udisks daemon start two ways
  1032. if [ -e /dev/sr0 ]; then
  1033. udisks --poll-for-media /dev/sr0
  1034. fi
  1035. udisks --show-info /dev/sda > /dev/null
  1036. fi
  1037. sleep 2 # helps successful sr0 startup mount on reboot
  1038. # Startup Mounting
  1039. if (( nomount != 1 )); then
  1040. mountalldrives
  1041. fi
  1042. # Start monitoring
  1043. coproc $info_cmd --monitor
  1044. err=$?
  1045. trap trapexit EXIT SIGINT SIGTERM SIGQUIT
  1046. trap "echo devmon: ignored HUP" SIGHUP
  1047. if [ $err != "0" ] || [ ! ps -p $COPROC_PID &>/dev/null ]; then
  1048. echo "devmon: unable to start $info_cmd --monitor" 1>&2
  1049. exit 2
  1050. fi
  1051. # Monitoring Loop
  1052. while ps -p $COPROC_PID &>/dev/null; do
  1053. read -u ${COPROC[0]}
  1054. echo "==========================================="
  1055. echo "$REPLY"
  1056. event="${REPLY%:*}"
  1057. devpath="${REPLY#*:}"
  1058. devpath="/dev/${devpath##*/}"
  1059. devtag="${devpath#/dev/}"
  1060. devtag="${devtag//-/_}"
  1061. if [ "$event" != "" ] && [ "$devpath" != "/dev/" ] && [ -e "$devpath" ]; then
  1062. case $event in
  1063. added )
  1064. driveinfo $devpath
  1065. if [ "$systeminternal" != "1" ] && [ "$ismounted" = "0" ] && \
  1066. [ "$nopolicy" != "1" ]; then
  1067. if [ "$usage" = "filesystem" ]; then
  1068. mountdrive $devpath "$label" "$type"
  1069. else
  1070. mountdrive $devpath "$label" nofs
  1071. fi
  1072. fi
  1073. ;;
  1074. job-changed )
  1075. ;;
  1076. removed )
  1077. ;;
  1078. changed )
  1079. driveinfo $devpath
  1080. eval notejected=\$notejected${devtag}
  1081. eval devmounted=\$devmounted${devtag}
  1082. eval devmounted${devtag}="$ismounted"
  1083. # If notejected==1 then cd has not been ejected and was probably
  1084. # manually unmounted, so don't automount it. Otherwise
  1085. # devmon will instantly mount any manual unmount.
  1086. if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \
  1087. [ "$ismounted" != "1" ] && [ "$hasmedia" != "0" ] && \
  1088. [ "$blank" != "1" ] && (( notejected != 1 )) && \
  1089. [ "$nopolicy" != "1" ]; then
  1090. if [ "$media" = "optical_dvd" ]; then
  1091. mountdrive $devpath "$label" dvd
  1092. elif (( numaudiotracks > 0 )); then
  1093. mountdrive $devpath "$label" audiocd
  1094. else
  1095. mountdrive $devpath "$label" optical
  1096. fi
  1097. eval notejected${devtag}=1
  1098. else
  1099. if [ "$systeminternal" != "1" ] && \
  1100. [ "$hasmedia" = "0" ]; then
  1101. if (( notejected == 1 )) || [ "$notejected" == "" ]; then
  1102. # disc ejected
  1103. echo "devmon: $devpath eject detected"
  1104. eval notejected${devtag}=0
  1105. fi
  1106. if [ "$ismounted" != "0" ]; then
  1107. # unmount if ejected disc still mounted
  1108. unmountdev "$devpath"
  1109. fi
  1110. fi
  1111. if [ "$systeminternal" != "1" ] && [ "$ismounted" != "1" ] && \
  1112. [ "$nopolicy" != "1" ] && [ "$devmounted" = "1" ]; then
  1113. # exec-on-unmount
  1114. if (( execoux != 0 )); then
  1115. if ( ! ignoredevice "$devpath" ) && \
  1116. ( ! ignorelabel "$label" ); then
  1117. unset lb point
  1118. dv="$devpath"
  1119. execcommands "exec on unmount" "${execou[@]}"
  1120. fi
  1121. fi
  1122. # remove udevil mount point in case unmounted by other
  1123. if [ "$mount_cmd" = "$udevil" ]; then
  1124. echo "devmon: $udevil clean"
  1125. $udevil clean
  1126. fi
  1127. fi
  1128. fi
  1129. ;;
  1130. esac
  1131. elif [ "$event" = "removed" ]; then
  1132. eval unset devmounted${devtag}
  1133. # unmount if removed device is still mounted
  1134. grep -qs "^${devpath} " /proc/mounts &> /dev/null
  1135. mounterr=$?
  1136. if [ $mounterr -ne 0 ]; then
  1137. grep -qs "^${devpath} " /etc/mtab &> /dev/null
  1138. mounterr=$?
  1139. fi
  1140. if [ $mounterr -eq 0 ]; then
  1141. unmountdev "${devpath}"
  1142. elif [ "$mount_cmd" = "$udevil" ]; then
  1143. # remove udevil mount point in case unmounted by other
  1144. echo "devmon: $udevil clean"
  1145. $udevil clean
  1146. fi
  1147. # exec-on-remove
  1148. if (( execorx != 0 )); then
  1149. if ( ! ignoredevice "$devpath" ); then
  1150. unset lb point
  1151. dv="$devpath"
  1152. execcommands "exec on remove" "${execor[@]}"
  1153. fi
  1154. fi
  1155. fi
  1156. done
  1157. exit
  1158. # CHANGELOG
  1159. # For changes after version 1.1.0, see udevil ChangeLog
  1160. #
  1161. # 1.1.0: added support for udevil, udisks2, pmount
  1162. # 1.0.5: --exec-on-unmount now executes only once per unmount
  1163. # 1.0.4: added --exec-on-unmount, --exec-on-remove
  1164. # added multiple instance warning
  1165. # %f device spec no longer passed in quotes to commands
  1166. # 1.0.3: help updated for sync
  1167. # corrected exec-on-drive bug introduced in 1.0.1
  1168. # 1.0.2: --sync adds sync for ntfs
  1169. # 1.0.1: added --sync
  1170. # added --no-unmount; unmount-on-exit is now default
  1171. # obey UDISKS_PRESENTATION_NOPOLICY to inhibit automount
  1172. # added unmount-all error pop-ups
  1173. # 1.0.0: added --unmount-recent
  1174. # improved udisks mount info to stdout
  1175. # improved mount/unmount without apparent filesystem
  1176. # 0.9.5: ignore trailing slash in un/mount dir/dev specs
  1177. # attempt to mount no filesystem in case there is one
  1178. # 0.9.4: polkit error more selective
  1179. # 0.9.3: corrected problems with spaces in volume labels
  1180. # corrected un/mounting of partitionless devices
  1181. # corrected --ignore-devices problem
  1182. # added not authorized pop-up error
  1183. # 0.9.2: added --internal
  1184. # 0.9.1: corrected --unmount-on-removable not recognized
  1185. # 0.9.0: changed --unmount-all to --unmount-removable
  1186. # added --unmount-all (now includes optical)
  1187. # added --unmount-optical
  1188. # added --unmount DIR|DEVICE
  1189. # added --eject DIR|DEVICE
  1190. # added --mount-all
  1191. # added --mount DEVICE
  1192. # added --info-on-mount
  1193. # added pass options to udisks
  1194. # better error msg from udisks
  1195. # individual drive eject detection
  1196. # no limit on number of optical drives
  1197. # 0.8.2: more verbose errors
  1198. # run as root changed to warning
  1199. # 0.8.1: added --unmount-on-exit
  1200. # adjusted start daemon trigger, timing
  1201. # added 'do not run as root' catcher
  1202. # added trap to ignore SIGHUP