diff --git a/ChangeLog b/ChangeLog index bb36773..917a0ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 0.2.1 log error msgs when parsing network url + added devmon 1.1.0 automounting script to udevil distribution 0.2.0 2012-05-22: initial test release diff --git a/README b/README index d11f1ba..6e1a7eb 100644 --- a/README +++ b/README @@ -34,7 +34,8 @@ DESCRIPTION Mounts and unmounts optical and removable devices without a password (set suid), shows device info, monitors device changes. Emulates mount's and - udisks's command line usage and udisks v1's output. + udisks's command line usage and udisks v1's output. Includes the devmon + automounting daemon. Run 'udevil --help' for usage. See /etc/udevil/udevil.conf for config. http://ignorantguru.github.com/udevil/udevil--help.html @@ -99,6 +100,8 @@ BUILD libglib2.0-0 libglib2.0-dev libudev0 (>=143) libudev-dev autotools-dev build-essential fakeroot intltool pkg-config + Also recommended if using devmon: eject zenity + configure will report anything missing when you run it as shown below. 2) Use these commands to download the udevil tarball and build: diff --git a/debian/control b/debian/control index 62d6267..409d011 100644 --- a/debian/control +++ b/debian/control @@ -12,8 +12,10 @@ Package: udevil Architecture: any Depends: libc6, libglib2.0-0, libudev0 (>=143) Recommends: -Suggests: -Conflicts: +Suggests: eject +Conflicts: devmon +Provides: devmon Description: Mounts and unmounts optical and removable devices without a - password (set suid), shows device info, monitors device changes. + password (set suid), shows device info, monitors device changes. Includes the + devmon automounting script. diff --git a/src/Makefile.am b/src/Makefile.am index b6b458b..fdedb85 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,8 @@ noinst_PROGRAMS = udevil udevil_SOURCES = udevil.c device-info.c realpath.c +bin_SCRIPTS = devmon + INSTALL_DIR = $(DESTDIR)/$(prefix)/bin INSTALL_SRC = $(top_builddir)/src diff --git a/src/Makefile.in b/src/Makefile.in index 5cc5833..dbccd78 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -15,6 +15,7 @@ @SET_MAKE@ + VPATH = @srcdir@ am__make_dryrun = \ { \ @@ -71,6 +72,35 @@ udevil_DEPENDENCIES = $(am__DEPENDENCIES_1) udevil_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(udevil_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(bindir)" +SCRIPTS = $(bin_SCRIPTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -247,6 +277,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ udevil_SOURCES = udevil.c device-info.c realpath.c +bin_SCRIPTS = devmon INSTALL_DIR = $(DESTDIR)/$(prefix)/bin INSTALL_SRC = $(top_builddir)/src udevil_CFLAGS = \ @@ -305,6 +336,41 @@ clean-noinstPROGRAMS: udevil$(EXEEXT): $(udevil_OBJECTS) $(udevil_DEPENDENCIES) $(EXTRA_udevil_DEPENDENCIES) @rm -f udevil$(EXEEXT) $(udevil_LINK) $(udevil_OBJECTS) $(udevil_LDADD) $(LIBS) +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -469,8 +535,11 @@ distdir: $(DISTFILES) done check-am: all-am check: check-am -all-am: Makefile $(PROGRAMS) +all-am: Makefile $(PROGRAMS) $(SCRIPTS) installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done install: install-am install-exec: install-exec-am install-data: install-data-am @@ -531,7 +600,7 @@ install-dvi: install-dvi-am install-dvi-am: -install-exec-am: +install-exec-am: install-binSCRIPTS install-html: install-html-am @@ -571,7 +640,7 @@ ps: ps-am ps-am: -uninstall-am: +uninstall-am: uninstall-binSCRIPTS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: install-am install-data-am install-strip uninstall-am @@ -580,15 +649,16 @@ uninstall-am: clean-libtool clean-noinstPROGRAMS ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am \ - install-data-hook install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ + install install-am install-binSCRIPTS install-data \ + install-data-am install-data-hook install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-hook + tags uninstall uninstall-am uninstall-binSCRIPTS \ + uninstall-hook install-data-hook: diff --git a/src/devmon b/src/devmon new file mode 100755 index 0000000..a07da8e --- /dev/null +++ b/src/devmon @@ -0,0 +1,1163 @@ +#!/bin/bash +# Script Name: devmon http://igurublog.wordpress.com/downloads/script-devmon/ +# Requires: udevil bash>=4 Recommended: eject zenity +# Optional: udisks v1 may be substituted for udevil +# If udevil is not set suid, udisks v1/v2 or pmount is required +# License: GNU GENERAL PUBLIC LICENSE Version 3 http://www.gnu.org/licenses/gpl-3.0.txt +# Thanks to Bernard Baeyens (berbae) for code from udisksvm script + +#========================================================================= + +defaultmountoptions="noexec,nosuid,nodev,noatime" + +#========================================================================= + +help() +{ + cat << EOF +devmon version 1.1.0 (distributed with udevil) +Automounts and unmounts optical and removable drives +Requires: udevil bash>=4 Also Recommended: eject zenity +Optional: udisks v1 may be substituted for udevil + If udevil is not set suid, udisks v1/v2 or pmount is required +Usage: devmon [AUTOMOUNT-OPTIONS] # Run as daemon to automount + devmon [MOUNT-OPTIONS] # Or run as client to manually un/mount +AUTOMOUNT-OPTIONS: (these can be used only in daemon mode) +--exec-on-device DEVICE "COMMAND" Execute COMMAND after mounting DEVICE +--exec-on-label "LABEL" "COMMAND" Execute COMMAND after mounting LABEL +--exec-on-video "COMMAND" Execute COMMAND after video DVD mount +--exec-on-audio "COMMAND" Execute COMMAND after audio CD insertion +--exec-on-disc "COMMAND" Execute COMMAND after data CD/DVD mount +--exec-on-drive "COMMAND" Execute COMMAND after drive mount +--exec-on-unmount "COMMAND" Execute COMMAND after unmount +--exec-on-remove "COMMAND" Execute COMMAND after drive removal + Where the following in COMMAND will be replaced with: + %d mount point directory (eg /media/cd) + %f device name (eg /dev/sdd1) + %l label of mounted volume + Multiple --exec-on-XXX options may be used to execute multiple commands. + Other exec-on-XXX commands are ignored if exec-on-device or -label executed. +--mount-options "OPTIONS" Default: $defaultmountoptions +--info-on-mount Show mounted drive info in a zenity dialog +--no-mount Don't mount anything, just exec (disables + --exec-on-video) +--no-unmount Don't unmount all removable drives on exit + +MOUNT-OPTIONS: (these can be used only in client mode) +--unmount-removable | -r Sync and unmount all removable drives and show + pop-up dialog (zenity installation required) +--unmount-recent | -c Unmount most recently mounted removable drive +--unmount-optical | -o Unmount all optical drives (error pop-up only) +--unmount-all | -u Same as --unmount-removable --unmount-optical +--unmount DIR|DEVICE Unmount DEVICE or mount point DIR +--eject DIR|DEVICE Unmount and eject DEVICE or mount point DIR +--mount-all | -a Mount all removable and optical drives +--mount DEVICE Mount DEVICE +--mount-options|--mount-fstype|--eject-options "OPTIONS" + These options will be passed to mount or eject + +UNIVERSAL OPTIONS: (these can be used in both daemon and client modes) +--ignore-device DEVICE Ignore DEVICE (eg /dev/sdd1) +--ignore-label "LABEL" Ignore volume with LABEL +--sync | -s Add sync mount option for ext2-4 ntfs ufs, or + flush for fat & vfat (slower writing but safer) +--internal Also attempt to un/mount internal system drives + (this is mostly a fix for esata issues) +--no-gui | -g Do not show zenity pop-up dialogs +Instructions and updates: + http://igurublog.wordpress.com/downloads/script-devmon/ +EOF + exit +} + +test2() +{ + if [ "${2:0:1}" = "-" ] || [ "$2" = "" ]; then + echo "devmon: Option $1 requires an argument" 1>&2 + exit 1 + fi +} + +test3() +{ + if [ "${2:0:1}" = "-" ] || [ "$2" = "" ] || \ + [ "${3:0:1}" = "-" ] || [ "$3" = "" ]; then + echo "devmon: Option $1 requires two arguments" 1>&2 + exit 1 + fi +} + +unknown() +{ + echo "devmon: Unknown option $1" 1>&2 + echo " For help use: devmon --help" 1>&2 + exit 1 +} + +# parse command line +execoix=0 +execomx=0 +execovx=0 +execoax=0 +execodx=0 +execolx=0 +execoux=0 +execorx=0 +umntx=0 +mntx=0 +ejx=0 +igdevx=0 +iglabx=0 +while [ "$1" != "" ]; do + if [ "${1:0:1}" = "-" ]; then + case "$1" in + --help ) + help + exit + ;; + # don't use eval on these to preserve command strings + --exec-on-drive ) + test2 "$1" "$2" + execoi[$execoix]="$2" + (( execoix++ )) + shift + ;; + --exec-on-disc ) + test2 "$1" "$2" + execom[$execomx]="$2" + (( execomx++ )) + shift + ;; + --exec-on-video ) + test2 "$1" "$2" + execov[$execovx]="$2" + (( execovx++ )) + shift + ;; + --exec-on-audio ) + test2 "$1" "$2" + execoa[$execoax]="$2" + (( execoax++ )) + shift + ;; + --exec-on-device ) + test3 "$1" "$2" "$3" + execod1[$execodx]="$2" + execod2[$execodx]="$3" + (( execodx++ )) + shift 2 + ;; + --exec-on-label ) + test3 "$1" "$2" "$3" + execol1[$execolx]="$2" + execol2[$execolx]="$3" + (( execolx++ )) + shift 2 + ;; + --exec-on-unmount ) + test2 "$1" "$2" + execou[$execoux]="$2" + (( execoux++ )) + shift + ;; + --exec-on-remove ) + test2 "$1" "$2" + execor[$execorx]="$2" + (( execorx++ )) + shift + ;; + --info-on-mount ) + infomount=1 + ;; + --no-mount ) + nomount=1 + ;; + --sync ) + syncopt=1 + ;; + --unmount-on-exit ) + # leave for usage compat with versions prior to 1.0.1 + ;; + --no-unmount ) + nounmount=1 + ;; + --unmount-all ) + unmountrem=1 + unmountoptical=1 + ;; + --unmount-removable ) + unmountrem=1 + ;; + --unmount-optical ) + unmountoptical=1 + ;; + --unmount-recent ) + unmountrecent=1 + ;; + --unmount ) + test2 "$1" "$2" + umnt[$umntx]="$2" + (( umntx++ )) + shift + ;; + --mount-all ) + mountall=1 + ;; + --mount ) + test2 "$1" "$2" + mnt[$mntx]="$2" + (( mntx++ )) + shift + ;; + --eject ) + test2 "$1" "$2" + ej[$ejx]="$2" + (( ejx++ )) + shift + ;; + --mount-options ) + test2 "$1" "$2" + mountoptions="$2" + shift + ;; + --mount-fstype ) + test2 "$1" "$2" + mountfstype="$2" + shift + ;; + --eject-options ) + test2 "$1" "$2" + ejectoptions="$2" + shift + ;; + --internal ) + internal=1 + ;; + --nogui | --no-gui ) + nogui=1 + ;; + --ignore-device ) + test2 "$1" "$2" + igdev[$igdevx]="$2" + (( igdevx++ )) + shift + ;; + --ignore-label ) + test2 "$1" "$2" + iglab[$iglabx]="$2" + (( iglabx++ )) + shift + ;; + --* ) + unknown "$1";; + -* ) + o="${1:1}" + while [ "$o" != "" ]; do + case "${o:0:1}" in + r ) + unmountrem=1;; + o ) + unmountoptical=1;; + u ) + unmountrem=1 + unmountoptical=1 + ;; + a ) + mountall=1;; + s ) + syncopt=1;; + c ) + unmountrecent=1;; + g ) + nogui=1;; + h ) + help + exit + ;; + * ) + unknown "-${o:0:1}";; + esac + o="${o:1}" + done + ;; + esac + else + unknown "$1" + fi + shift +done +(( mountmode = umntx + mntx + ejx + unmountrem + unmountoptical + mountall + unmountrecent )) + +# Warnings +if [ "$(whoami)" = "root" ]; then + echo "WARNING: running devmon as root is usually not required or recommended" 1>&2 +fi + +if (( execoix + execomx + execovx + execoax + execodx + execolx + execoux + execorx \ + + nounmount + infomount != 0 )) && (( mountmode != 0 )); then + echo "WARNING: devmon automount options ignored in mount mode" 1>&2 +fi + +# Discovery +udevil=`which udevil` +udisks1=`which udisks` +udisks2=`which udisksctl` +pmount=`which pmount` + +if [ "$udevil" != "" ]; then + info_cmd="$udevil" +elif [ "$udisks1" != "" ]; then + info_cmd="$udisks1" +else + echo "WARNING: devmon can't find udevil or udisks v1 for device monitoring" 1>&2 + info_cmd="udevil" +fi + +if [ "$udevil" != "" ]; then + if [ -u "$udevil" ] || [ "$(whoami)" = "root" ]; then + mount_cmd="$udevil" + fi +fi + +if [ "$mount_cmd" = "" ] && [ "$udisks1" != "" ]; then + mount_cmd="$udisks1" +fi + +if [ "$mount_cmd" = "" ] && [ "$udisks2" != "" ]; then + mount_cmd="$udisks2" +fi + +if [ "$mount_cmd" = "" ] && [ "$pmount" != "" ]; then + if [ -u "$pmount" ] || [ "$(whoami)" = "root" ]; then + mount_cmd="$pmount" + fi +fi + +if [ "$mount_cmd" = "" ]; then + echo "WARNING: devmon can't run udevil, udisks, or pmount for mounting" 1>&2 + mount_cmd="udevil" +fi + + +driveinfo() #$1=dev #Optional $2=quiet +{ + unset systeminternal usage ismounted presentationnopolicy hasmedia \ + opticaldisc numaudiotracks type partition media blank label + uinfos=`$info_cmd --show-info $1 2> /dev/null` + label=`echo "$uinfos" | grep -m 1 "^ label:" | sed 's/ *label: *\(.*\)/\1/'` + listinfos=`echo "$uinfos" | grep \ + -e "^ system internal:" \ + -e "^ usage:" \ + -e "^ type:" \ + -e "^ is mounted:" \ + -e "^ presentation nopolicy:" \ + -e "^ has media" \ + -e "^ optical disc:" \ + -e " blank:" \ + -e " num audio tracks:" \ + -e "^ partition:" \ + -e " media:"` + # The change for type= is to take only its first value in listinfos + listinfos=$(echo "$listinfos" | sed 's/ //g + s/:/=/ + s/opticaldisc=/&1/ + s/type=\(.*\)/type=${type:-\1}/ + s/[()]//g + s/partition=/&1/') + eval "$listinfos" + if (( internal == 1 )); then + systeminternal="ignored" + fi + # Take only the first character + hasmedia=${hasmedia:0:1} + # If "partition:" not find in listinfos, should mean it is not a partition + partition=${partition:-0} + nopolicy="$presentationnopolicy" + if (( mountmode == 0 )) && [ "$systeminternal" != "1" ] && [ "$2" != "quiet" ]; then + if [ "$usage" = "filesystem" ] || [ "$opticaldisc" = "1" ]; then + echo "device: [$1]" + echo " systeminternal: [$systeminternal]" + echo " usage: [$usage]" + echo " type: [$type]" + echo " label: [$label]" + echo " ismounted: [$ismounted]" + echo " nopolicy: [$nopolicy]" + echo " hasmedia: [$hasmedia]" + echo " opticaldisc: [$opticaldisc]" + echo " numaudiotracks: [$numaudiotracks]" + echo " blank: [$blank]" + echo " media: [$media]" + echo " partition: [$partition]" + fi + fi +} + +ignoredevice() +{ + idx=0 + while (( idx < igdevx )); do + if [ "$1" = "${igdev[$idx]}" ]; then + echo "devmon: ignored device $1" + return 0 + fi + (( idx++ )) + done + return 1 +} + +ignorelabel() +{ + ilx=0 + while (( ilx < iglabx )); do + if [ "$1" = "${iglab[$ilx]}" ]; then + echo "devmon: ignored label $1" + return 0 + fi + (( ilx++ )) + done + return 1 +} + +execcommands() # $exectype "${exec[@]}" +{ + exectype="$1" + shift + while [ "$1" != "" ]; do + usercmd="$1" + usercmd="${usercmd//%f/$dv}" + usercmd="${usercmd//%l/'$lb'}" + usercmd="${usercmd//%d/'$point'}" + if [ "$usercmd" != "" ]; then + echo "devmon: [$exectype] eval $usercmd &" + eval $usercmd & + fi + shift + done +} + +mountdev() # $1=device [$2=label] [$3=devtype or fstype] +{ + # set label comment + if [ "$2" = "" ]; then + lblcmt="" + else + lblcmt="# ($2)" + fi + # set mount-fstype option + if [ "$mountfstype" != "" ]; then + if [ "$mount_cmd" = "$udisks2" ] || [ "$mount_cmd" = "$pmount" ]; then + fst="-t" + else + fst="--mount-fstype" + fi + else + fst="" + fi + # set default mount options + if [ "$mountoptions" != "" ]; then + mopts="$mountoptions" + else + mopts="$defaultmountoptions" + fi + # set sync mount options + if (( syncopt == 1 )); then + case "$3" in + ext2 | ext3 | ext4 | ufs | ntfs ) + mopts="$mopts,sync";; + fat | vfat ) + mopts="$mopts,flush";; + esac + fi + + if [ "$mount_cmd" = "$udisks2" ]; then + mntmsg="devmon: $mount_cmd mount -b $1 -o \"$mopts\" $fst $mountfstype $lblcmt" + elif [ "$mount_cmd" = "$pmount" ]; then + mntmsg="devmon: $mount_cmd $fst $mountfstype $1 $lblcmt" + else + mntmsg="devmon: $mount_cmd --mount $1 --mount-options \"$mopts\" $fst $mountfstype $lblcmt" + fi + if [ "$3" != "nofs" ]; then + echo "$mntmsg" + fi + + # mount + if [ "$mount_cmd" = "$udisks2" ]; then + umsg=`$mount_cmd mount -b $1 -o "$mopts" $fst $mountfstype 2>&1` + elif [ "$mount_cmd" = "$pmount" ]; then + umsg=`$mount_cmd $fst $mountfstype $1 2>&1` + else + umsg=`$mount_cmd --mount $1 --mount-options "$mopts" $fst $mountfstype 2>&1` + fi + mounterr="$?" + # get mount point + point=`echo "$umsg" | grep "^Mounted " | sed 's/^Mounted .* at \(.*\)/\1/'` + + if [ "$mount_cmd" = "$pmount" ] && [ "$point" = "" ]; then + # pmount doesn't output the mount point + point=" " + fi + if [ "$mounterr" != "0" ] || [ "$point" = "" ]; then + # if $3=nofs then there was no apparent filesystem but we tried to mount it + # anyway in case it didn't report the filesystem accurately, so ignore the + # error + if [ "$3" != "nofs" ]; then + echo "$umsg" 1>&2 + echo "devmon: error mounting $1 ($mounterr)" 1>&2 + if [ "$mount_cmd" = "$udisks1" ] || [ "$mount_cmd" = "$udisks2" ]; then + if (( mountmode == 0 )) && (( polkiterrgiven != 1 )) && \ + [ "$(echo "$umsg" | grep 'Not *Authorized')" != "" ]; then + if (( nogui != 1 )); then + ( sleep 3 && WINDOWID="" zenity --error --no-wrap --title="devmon error" \ + --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 ) & + fi + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2 + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2 + echo "udisks functions are not authorized through policykit," 1>&2 + echo "so devmon cannot automount drives." 1>&2 + echo "Please see devmon's consolekit installation instructions:" 1>&2 + echo "http://igurublog.wordpress.com/downloads/script-devmon/#install" 1>&2 + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2 + echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 1>&2 + polkiterrgiven=1 + fi + fi + fi + uerr=3 + return 3 + elif [ "$3" = "nofs" ]; then + # no filesystem reported but successful mount + echo "$mntmsg" + fi + echo "$umsg" + if [ "$point" = " " ]; then + # pmount doesn't output the mount point + point="" + fi +} + +unmountdev() # $1=device +{ + if [ "$mount_cmd" = "$udisks2" ]; then + uerrmsg=`$mount_cmd unmount -b $1 2>&1` + echo "devmon: $mount_cmd unmount -b $1" + elif [ "$mount_cmd" = "$pmount" ]; then + uerrmsg=`pumount $1 2>&1` + echo "devmon: pumount $1" + else + uerrmsg=`$mount_cmd --unmount $1 2>&1` + echo "devmon: $mount_cmd --unmount $1" + fi + umounterr="$?" + if [ "$mount_cmd" = "$udisks1" ] && [ "$uerrmsg" != "" ]; then + # bug: udisks v1 returns $?==0 when unmount fails + umounterr=1 + fi + if [ "$uerrmsg" != "" ]; then + echo "$uerrmsg" + fi + if [ $umounterr -ne 0 ]; then + uerr=3 + return 3 + fi +} + +ejectdev() +{ + echo "devmon: eject $ejectoptions $1" + eject $ejectoptions $1 + if [ "$?" != "0" ]; then + uerr=3 + return 3 + fi +} + +mountdrive() # $1=device $2=label [$3=devtype or fstype] +{ + dv="$1" + lb="$2" + tp="$3" + unset point + + if ( ignoredevice "$dv" ) || ( ignorelabel "$lb" ); then + return + fi + + # mount + if [ "$tp" != "audiocd" ] && (( nomount != 1 )); then + mountdev $dv "$lb" "$tp" + if [ "$?" != "0" ]; then + return + fi + fi + + # exec on device + unset execdone + x=0 + while (( x < execodx )); do + if [ "${execod1[$x]}" = "$dv" ]; then + usercmd="${execod2[$x]}" + usercmd="${usercmd//%f/$dv}" + usercmd="${usercmd//%l/'$lb'}" + usercmd="${usercmd//%d/'$point'}" + if [ "$usercmd" != "" ]; then + echo "devmon: [exec on device] eval $usercmd" + eval $usercmd & + execdone=1 + fi + fi + (( x++ )) + done + if (( execdone == 1 )); then return; fi + + # exec on label + x=0 + while (( x < execolx )); do + if [ "${execol1[$x]}" = "$lb" ]; then + usercmd="${execol2[$x]}" + usercmd="${usercmd//%f/$dv}" + usercmd="${usercmd//%l/'$lb'}" + usercmd="${usercmd//%d/'$point'}" + if [ "$usercmd" != "" ]; then + echo "devmon: [exec on label] eval $usercmd" + eval $usercmd & + execdone=1 + fi + fi + (( x++ )) + done + if (( execdone == 1 )); then return; fi + + # exec on video + if [ "$tp" = "dvd" ] && [ "$point" != "" ] && [ -d "$point/VIDEO_TS" ]; then + echo "devmon: videodvd $dv ($lb) on $point" + if (( execovx != 0 )); then + execcommands "exec on video" "${execov[@]}" + fi + return + fi + + # exec on audio + if [ "$tp" = "audiocd" ]; then + echo "devmon: audiocd $dv ($lb)" + if (( execoax != 0 )); then + execcommands "exec on audio" "${execoa[@]}" + fi + return + fi + + # exec on disc + if [ "$tp" = "optical" ] || [ "$tp" = "dvd" ]; then + if [ "$point" != "" ] || (( nomount == 1 )); then + if (( execomx != 0 )); then + execcommands "exec on disc" "${execom[@]}" + fi + fi + return + fi + + # exec on drive + if [ "$point" != "" ] || (( nomount == 1 )); then + if (( execoix != 0 )); then + execcommands "exec on drive" "${execoi[@]}" + fi + fi + + # info on mount + if [ "$point" != "" ] && (( infomount == 1 )) && (( nomount != 1 )); then + sleep .5 + echo "devmon: [info on mount] $dv" + if (( nogui != 1 )); then + WINDOWID="" zenity --info --text="The following device has been mounted:\n\n$(df -hT "$dv" \ + | 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" & + fi + df -hT "$dv" + fi +} + +mountalldrives() +{ + # Mount all optical drives, no exec + x=0 + while [ -e /dev/sr$x ]; do + driveinfo /dev/sr$x + if [ "$numaudiotracks" = "" ]; then + numaudiotracks=0 + fi + if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \ + [ "$ismounted" != "1" ] && [ "$hasmedia" != "0" ] && \ + [ "$blank" != "1" ] && (( numaudiotracks == 0 )) && \ + [ "$nopolicy" != "1" ]; then + if ( ignoredevice "/dev/sr$x" ) || ( ignorelabel "$label" ); then + (( x++ )) + continue + fi + mountdev /dev/sr$x "$label" + eval notejectedsr$x=1 + fi + (( x++ )) + done + # Mount removable drives, no exec + IFSOLD="$IFS" + IFS=$'\n' + partlist=`grep " sd[a-z0-9]*$" /proc/partitions | sed 's/.* \(sd[a-z0-9]*\)/\1/'` + for p in $partlist; do + if ( ignoredevice "/dev/$p" ); then + continue + fi + driveinfo /dev/$p + if ( ignorelabel "$label" ); then + continue + else + if [ "$systeminternal" != "1" ] && [ "$opticaldisc" != "1" ] && \ + [ "$ismounted" = "0" ] && [ "$nopolicy" != "1" ]; then + if [ "$usage" = "filesystem" ]; then + mountdev /dev/$p "$label" "$type" + else + mountdev /dev/$p "$label" nofs + fi + fi + fi + done + IFS="$IFSOLD" +} + +trapexit() +{ + kill $COPROC_PID 2> /dev/null + + # prevent trap code from executing multiple times on different signals + if (( trapdone != 1 )); then + trapdone=1 + # Unmount All + if (( nounmount != 1 )); then + IFSOLD="$IFS" + IFS=$'\n' + uerr=0 + partlist=`grep " sd[a-z0-9]*$" /proc/partitions | \ + sed 's/.* \(sd[a-z0-9]*\)/\1/'` + for p in $partlist; do + if ( ignoredevice "/dev/$p" ); then + continue + fi + driveinfo /dev/$p + if ( ignorelabel "$label" ); then + continue + else + if [ "$systeminternal" != "1" ] && [ "$opticaldisc" != "1" ] && \ + [ "$usage" = "filesystem" ] && [ "$ismounted" = "1" ]; then + if [ "$mount_cmd" = "$udisks2" ]; then + echo "devmon: [on exit] $mount_cmd unmount -b /dev/$p &" + $mount_cmd unmount -b /dev/$p & + elif [ "$mount_cmd" = "$pmount" ]; then + echo "devmon: [on exit] pumount /dev/$p &" + pumount /dev/$p & + else + echo "devmon: [on exit]$mount_cmd --unmount /dev/$p &" + $mount_cmd --unmount /dev/$p & + fi + if [ "$?" != "0" ]; then + uerr=3 + fi + fi + fi + done + IFS="$IFSOLD" + fi + echo 'devmon: stopped' + exit $uerr + fi +} + +# Client Mode +if (( mountmode != 0 )); then + uerr=0 + if (( unmountrem == 1 )) || (( unmountrecent == 1 )); then + y=0 + unset udrive zpid + IFSOLD="$IFS" + IFS=$'\n' + if (( unmountrem == 1 )); then + # Unmount All Removable Drives + partlist=`grep " sd[a-z0-9]*$" /proc/partitions | sed 's/.* \(sd[a-z0-9]*\)/\1/'` + msgtitle="devmon unmount" + else + # Unmount Recent + partlist=`mount | grep "^/dev/.* on " | sed 's/^\/dev\/\(.*\) on .*/\1/' \ + | grep -v -e "null" -e "shm" -e "mapper" -e "snd" \ + -e "video" -e "random" | tac` + msgtitle="devmon unmount recent" + fi + for p in $partlist; do + if ( ignoredevice "/dev/$p" ); then + continue + fi + driveinfo /dev/$p + if ( ignorelabel "$label" ); then + continue + else + if [ "$systeminternal" != "1" ] && [ "$opticaldisc" != "1" ] \ + && [ "$ismounted" = "1" ]; then + udrive[$y]="/dev/$p" + (( y++ )) + if (( unmountrem != 1 )); then break; fi + fi + fi + done + IFS="$IFSOLD" + if (( y == 0 )); then + msg="No removable drives are mounted" + echo "$msg" + else + msg="Unmounting ${udrive[@]}...\n\n(This dialog will close when the devices are unmounted)" + echo "Preparing to unmount ${udrive[@]}" + fi + if (( nogui != 1 )); then + WINDOWID="" zenity --info --title="$msgtitle" --text="$msg" &> /dev/null & + zpid=$! + fi + if (( y > 0 )); then + echo "devmon: sync" + sync + for d in ${udrive[@]}; do + unmountdev $d + if [ "$?" != "0" ] && (( nogui != 1 )); then + driveinfo "$d" quiet + if [ "$label" = "" ]; then + lb="" + else + lb=" ($label)" + fi + msg="Unmount error on $d$lb:\n\n$uerrmsg" + WINDOWID="" zenity --error --title="$msgtitle" --text="$msg" &> /dev/null & + fi + done + echo "devmon: sync" + sync + fi + if [ "$zpid" != "" ]; then + sleep 2 + kill $zpid 2> /dev/null + fi + fi + + # Unmount Optical + if (( unmountoptical == 1 )); then + x=0 + while [ -e "/dev/sr$x" ]; do + if ( ignoredevice "/dev/sr$x" ); then + (( x++ )) + continue + fi + driveinfo /dev/sr$x + if ( ignorelabel "$label" ); then + (( x++ )) + continue + else + if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \ + [ "$ismounted" = "1" ]; then + unmountdev /dev/sr$x + if [ "$?" != "0" ] && (( nogui != 1 )); then + if [ "$label" = "" ]; then + lb="" + else + lb=" ($label)" + fi + msg="Unmount error on /dev/sr$x$lb:\n\n$uerrmsg" + WINDOWID="" zenity --error --title="devmon unmount optical" \ + --text="$msg" &> /dev/null & + fi + fi + fi + (( x++ )) + done + fi + + # Unmount DIR|DEVICE + if (( umntx > 0 )); then + x=0 + while (( x < umntx )); do + d="${umnt[$x]}" + # remove trailing slash + if [ "$d" != "/" ]; then + d="${d%/}" + fi + if [ "${d:0:5}" = "/dev/" ]; then + # Unmount DEVICE + unmountdev "$d" + else + # Unmount DIR + if [ "$(dirname "$d")" = "." ]; then + if [ -d "$(pwd)/$d" ]; then + d="$(pwd)/$d" + elif [ -d "/media/$d" ]; then + d="/media/$d" + elif [ -e "/dev/$d" ] && [ "$(mount | grep "^/dev/$d on ")" != "" ]; then + unmountdev "/dev/$d" + (( x++ )) + continue + fi + fi + if [ ! -d "$d" ]; then + echo "devmon: No such directory or mounted device $d" 1>&2 + uerr=3 + else + dv=`mount | grep -m 1 " on $d type " | awk '{print $1}'` + if [ "$dv" = "" ]; then + echo "devmon: Nothing mounted on $d (mtab)" 1>&2 + uerr=3 + else + unmountdev "$dv" + fi + fi + fi + (( x++ )) + done + fi + + # Eject DIR|DEVICE + if (( ejx > 0 )); then + x=0 + while (( x < ejx )); do + d="${ej[$x]}" + # remove trailing slash + if [ "$d" != "/" ]; then + d="${d%/}" + fi + dv="" + if [ "${d:0:5}" = "/dev/" ]; then + # Eject DEVICE + dv="$d" + else + # Eject DIR + if [ "$(dirname "$d")" = "." ]; then + if [ -d "$(pwd)/$d" ]; then + d="$(pwd)/$d" + elif [ -d "/media/$d" ]; then + d="/media/$d" + elif [ -e "/dev/$d" ] && [ "$(mount | grep "^/dev/$d on ")" != "" ]; then + dv="/dev/$d" + fi + fi + if [ "$dv" = "" ]; then + if [ ! -d "$d" ]; then + echo "devmon: No such directory or mounted device $d" 1>&2 + uerr=3 + else + dv=`mount | grep -m 1 " on $d type " | awk '{print $1}'` + if [ "$dv" = "" ]; then + echo "devmon: Nothing mounted on $d (mtab)" 1>&2 + uerr=3 + fi + fi + fi + fi + if [ "$dv" != "" ]; then + driveinfo "$dv" + if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \ + [ "$ismounted" = "1" ]; then + unmountdev "$dv" + fi + ejectdev "$dv" + fi + (( x++ )) + done + fi + + # Mount DEVICE + if (( mntx > 0 )); then + x=0 + while (( x < mntx )); do + d="${mnt[$x]}" + # remove trailing slash + if [ "$d" != "/" ]; then + d="${d%/}" + fi + if [ "$(dirname "$d")" = "." ] && [ "${d:0:5}" != "/dev/" ]; then + d="/dev/$d" + fi + driveinfo "$d" quiet + if [ "$opticaldisc" = "1" ]; then + mountdev $d "$label" + else + mountdev $d "$label" "$type" + fi + (( x++ )) + done + fi + + # Mount All Unmounted + if (( mountall == 1 )); then + mountalldrives + fi + + exit $uerr +fi + +# Daemon Mode +if [ "$mountfstype" != "" ]; then + echo "WARNING: --mount-fstype ignored in daemon mode" 1>&2 + mountfstype="" +fi +if [ "$ejectoptions" != "" ]; then + echo "WARNING: --eject-options ignored in daemon mode" 1>&2 + ejectoptions="" +fi +pidcount=`ps h -C "${0//*\//}" -o pid | wc -l` +if (( pidcount > 2 )); then + echo + echo "WARNING: multiple instances of devmon appear to be running (my pid=$$):" + ps h -C "${0//*\//}" + echo +fi + +if [ "$mount_cmd" = "$udisks1" ] || [ "$info_cmd" = "$udisks1" ]; then + # Trigger udisks daemon start two ways + if [ -e /dev/sr0 ]; then + udisks --poll-for-media /dev/sr0 + fi + udisks --show-info /dev/sda > /dev/null +fi +sleep 2 # helps successful sr0 startup mount on reboot + + +# Startup Mounting +if (( nomount != 1 )); then + mountalldrives +fi + +# Start monitoring +coproc $info_cmd --monitor +err=$? +trap trapexit EXIT SIGINT SIGTERM SIGQUIT +trap "echo devmon: ignored HUP" SIGHUP + +if [ $err != "0" ] || [ ! ps -p $COPROC_PID &>/dev/null ]; then + echo "devmon: unable to start $info_cmd --monitor" 1>&2 + exit 2 +fi + + +# Monitoring Loop +while ps -p $COPROC_PID &>/dev/null; do + read -u ${COPROC[0]} + echo "===========================================" + echo "$REPLY" + event="${REPLY%:*}" + devpath="${REPLY#*:}" + devpath="/dev/${devpath##*/}" + if [ "$event" != "" ] && [ "$devpath" != "/dev/" ] && [ -e "$devpath" ]; then + case $event in + added ) + driveinfo $devpath + if [ "$systeminternal" != "1" ] && [ "$ismounted" = "0" ] && \ + [ "$nopolicy" != "1" ]; then + if [ "$usage" = "filesystem" ]; then + mountdrive $devpath "$label" "$type" + else + mountdrive $devpath "$label" nofs + fi + fi + ;; + job-changed ) + ;; + removed ) + ;; + changed ) + driveinfo $devpath + eval notejected=\$notejected${devpath#/dev/} + eval devmounted=\$devmounted${devpath#/dev/} + eval devmounted${devpath#/dev/}="$ismounted" + # If notejected==1 then cd has not been ejected and was probably + # manually unmounted, so don't automount it. Otherwise + # devmon will instantly mount any manual unmount. + if [ "$systeminternal" != "1" ] && [ "$opticaldisc" = "1" ] && \ + [ "$ismounted" != "1" ] && [ "$hasmedia" != "0" ] && \ + [ "$blank" != "1" ] && (( notejected != 1 )) && \ + [ "$nopolicy" != "1" ]; then + if [ "$media" = "optical_dvd" ]; then + mountdrive $devpath "$label" dvd + elif (( numaudiotracks > 0 )); then + mountdrive $devpath "$label" audiocd + else + mountdrive $devpath "$label" optical + fi + eval notejected${devpath#/dev/}=1 + else + if [ "$systeminternal" != "1" ] && \ + [ "$ismounted" != "1" ] && [ "$hasmedia" = "0" ]; then + # disc ejected + echo "devmon: $devpath eject detected" + eval notejected${devpath#/dev/}=0 + fi + if [ "$systeminternal" != "1" ] && [ "$ismounted" != "1" ] && \ + [ "$nopolicy" != "1" ] && [ "$devmounted" = "1" ]; then + # exec-on-unmount + if (( execoux != 0 )); then + if ( ! ignoredevice "$devpath" ) && ( ! ignorelabel "$label" ); then + dv="$devpath" + execcommands "exec on unmount" "${execou[@]}" + fi + fi + fi + fi + ;; + esac + elif [ "$event" = "removed" ]; then + eval unset devmounted${devpath#/dev/} + # exec-on-remove + if (( execorx != 0 )); then + if ( ! ignoredevice "$devpath" ); then + unset lb point + dv="$devpath" + execcommands "exec on remove" "${execor[@]}" + fi + fi + fi +done + +exit + +# CHANGELOG +# 1.1.0: added support for udevil, udisks2, pmount +# 1.0.5: --exec-on-unmount now executes only once per unmount +# 1.0.4: added --exec-on-unmount, --exec-on-remove +# added multiple instance warning +# %f device spec no longer passed in quotes to commands +# 1.0.3: help updated for sync +# corrected exec-on-drive bug introduced in 1.0.1 +# 1.0.2: --sync adds sync for ntfs +# 1.0.1: added --sync +# added --no-unmount; unmount-on-exit is now default +# obey UDISKS_PRESENTATION_NOPOLICY to inhibit automount +# added unmount-all error pop-ups +# 1.0.0: added --unmount-recent +# improved udisks mount info to stdout +# improved mount/unmount without apparent filesystem +# 0.9.5: ignore trailing slash in un/mount dir/dev specs +# attempt to mount no filesystem in case there is one +# 0.9.4: polkit error more selective +# 0.9.3: corrected problems with spaces in volume labels +# corrected un/mounting of partitionless devices +# corrected --ignore-devices problem +# added not authorized pop-up error +# 0.9.2: added --internal +# 0.9.1: corrected --unmount-on-removable not recognized +# 0.9.0: changed --unmount-all to --unmount-removable +# added --unmount-all (now includes optical) +# added --unmount-optical +# added --unmount DIR|DEVICE +# added --eject DIR|DEVICE +# added --mount-all +# added --mount DEVICE +# added --info-on-mount +# added pass options to udisks +# better error msg from udisks +# individual drive eject detection +# no limit on number of optical drives +# 0.8.2: more verbose errors +# run as root changed to warning +# 0.8.1: added --unmount-on-exit +# adjusted start daemon trigger, timing +# added 'do not run as root' catcher +# added trap to ignore SIGHUP + diff --git a/src/udevil.c b/src/udevil.c index 2222c39..10fae04 100644 --- a/src/udevil.c +++ b/src/udevil.c @@ -128,7 +128,7 @@ void parse_mounts( gboolean report ) gchar **lines; GError *error; guint n; -//printf("\n@@@@@@@@@@@@@ parse_mounts %s\n\n", report ? "TRUE" : "FALSE" ); +//fprintf( stderr, "\n@@@@@@@@@@@@@ parse_mounts %s\n\n", report ? "TRUE" : "FALSE" ); contents = NULL; lines = NULL; @@ -219,7 +219,7 @@ void parse_mounts( gboolean report ) } g_free( contents ); g_strfreev( lines ); -//printf("\nLINES DONE\n\n"); +//fprintf( stderr, "\nLINES DONE\n\n"); // translate each mount points list to string gchar *points, *old_points; GList* m; @@ -240,7 +240,7 @@ void parse_mounts( gboolean report ) g_list_free( devmount->mounts ); devmount->mounts = NULL; devmount->mount_points = points; -//printf( "translate %d:%d %s\n", devmount->major, devmount->minor, points ); +//fprintf( stderr, "translate %d:%d %s\n", devmount->major, devmount->minor, points ); } // compare old and new lists @@ -252,16 +252,16 @@ void parse_mounts( gboolean report ) for ( l = newmounts; l; l = l->next ) { devmount = (devmount_t*)l->data; -//printf("finding %d:%d\n", devmount->major, devmount->minor ); +//fprintf( stderr, "finding %d:%d\n", devmount->major, devmount->minor ); found = g_list_find_custom( devmounts, (gconstpointer)devmount, (GCompareFunc)cmp_devmounts ); - if ( found ) + if ( found && found->data ) { -//printf(" found\n"); +//fprintf( stderr, " found\n"); if ( !g_strcmp0( ((devmount_t*)found->data)->mount_points, devmount->mount_points ) ) { -//printf(" freed\n"); +//fprintf( stderr, " freed\n"); // no change to mount points, so remove from old list devmount = (devmount_t*)found->data; g_free( devmount->mount_points ); @@ -272,7 +272,7 @@ void parse_mounts( gboolean report ) else { // new mount -//printf(" new mount %d:%d\n", devmount->major, devmount->minor ); +//fprintf( stderr, " new mount %d:%d\n", devmount->major, devmount->minor ); dev = makedev( devmount->major, devmount->minor ); udevice = udev_device_new_from_devnum( udev, 'b', dev ); if ( udevice ) @@ -280,12 +280,12 @@ void parse_mounts( gboolean report ) } } } -//printf( "\nREMAINING\n\n"); +//fprintf( stderr, "\nREMAINING\n\n"); // any remaining devices in old list have changed mount status for ( l = devmounts; l; l = l->next ) { devmount = (devmount_t*)l->data; -//printf("remain %d:%d\n", devmount->major, devmount->minor ); +//fprintf( stderr, "remain %d:%d\n", devmount->major, devmount->minor ); if ( report ) { dev = makedev( devmount->major, devmount->minor ); @@ -313,6 +313,7 @@ void parse_mounts( gboolean report ) { char* bdev = g_path_get_basename( devnode ); printf( "changed: /org/freedesktop/UDisks/devices/%s\n", bdev ); + fflush( stdout ); g_free( bdev ); g_free( devnode ); } @@ -333,8 +334,11 @@ static void free_devmounts() for ( l = devmounts; l; l = l->next ) { devmount = (devmount_t*)l->data; - g_free( devmount->mount_points ); - g_slice_free( devmount_t, devmount ); + if ( devmount ) + { + g_free( devmount->mount_points ); + g_slice_free( devmount_t, devmount ); + } } g_list_free( devmounts ); devmounts = NULL; @@ -432,6 +436,8 @@ if ( !( cond & G_IO_NVAL ) ) else if ( !strcmp( action, "move" ) ) printf( "moved: /org/freedesktop/UDisks/devices/%s\n", bdev ); g_free( bdev ); + fflush( stdout ); + fflush( stderr ); } g_free( devnode ); udev_device_unref( udevice ); @@ -3157,7 +3163,7 @@ _get_type: if ( mount_knows( type == MOUNT_NET ? netmount->url : data->device_file ) ) { // mount knows (in fstab) so mount as normal user with only specified opts - wlog( "udevil: '%s' is known to mount - running mount as normal user\n", + wlog( "udevil: %s is known to mount - running mount as normal user\n", data->device_file, 1 ); if ( data->fstype ) wlog( "udevil: warning: fstype ignored for device in fstab (or specify mount point)\n", @@ -3605,6 +3611,8 @@ static int command_info( CommandData* data ) device_free( device ); udev_device_unref( udevice ); udev_unref( udev ); + fflush( stdout ); + fflush( stderr ); return ret; } @@ -3805,7 +3813,7 @@ static void show_help() printf( " udevil help|--help|-h\n" ); printf( "\n" ); printf( "http://ignorantguru.github.com/udevil/ See /etc/udevil/udevil.conf for config.\n" ); - //printf( "For automounting with udevil run 'devmon --help'\n" ); + printf( "For automounting with udevil run 'devmon --help'\n" ); printf( "\n" ); }