#!/bin/sh

# Mounts and explores pendrives
#
# Based on Eko M. Budi's excellent script, copyright 2004
# Extensions and refinements by Hanu-mizzle, 2005
#
# License: GNU GPL

MNT_PENDRIVE=${MNT_PENDRIVE:-/mnt/pendrive}
MNT_USB_STORAGE=${MNT_USB:-/mnt/usb-storage}
MNT_VLHOT=${MNT_VLHOT:-/media}

# Check for existing vl-hot , which we will prefer
if mount | grep -q "^.* on $MNT_VLHOT"; then
  echo "vl-hot handled it, exploring..."
  for DIR in $(ls $MNT_VLHOT); do
    explorer $MNT_VLHOT/$DIR &
  done
  exit 0
fi

# Check for existing usb-mount points, which we will prefer
if mount | grep -q "^.* on $MNT_USB_STORAGE"; then
  echo "usb-mount handled it, exploring..."
  for DIR in $(ls $MNT_USB_STORAGE); do
    explorer $MNT_USB_STORAGE/$DIR &
  done
  exit 0
fi

# Load modules if necessary and wait for them to register
if ! /sbin/lsmod | grep -q "^usb_storage"; then
  /sbin/modprobe usb-storage &> /dev/null
  WAIT=yes
fi
if ! /sbin/lsmod | grep -q "^sg"; then
  /sbin/modprobe sg &> /dev/null
  WAIT=yes
fi

# Wait for new modules to register
if [ $WAIT ]; then
  sleep 5
fi

# Determine user through ownership of console
USB_USER=$(ls -l /dev/console | perl -e \
'local $_ = <>; split / +/; print $_[2], "\n";')
# This should work OK
USB_GROUP=users

# If we are running a 2.6 series kernel, we can take advantage of the dmask
# option to mount. Otherwise we have to settle for just umask. Boo!
case $(uname -r) in
  2.6*) MASK="umask=117,dmask=007" ;;
  *) MASK="umask=007" ;;
esac

# Options for all file systems
OPT_COMMON="sync,dirsync"
# Options for all MS file systems; file systems like FAT have to be
# assimilated to Unix style permissions with these options
OPT_WIN="uid=$USB_USER,gid=$USB_GROUP,$MASK"

# This function determines the options that need to be passed to mount
# for a given device
mount_options () {
  local FS=`sudo disktype $1 | grep -m 1 "file system" | perl -e 'local $_ = <>; split / +/; print $_[0], "\n";'`

  case $FS in
    Ext2)
      MOUNT_OPTIONS="-t ext2 -o noatime,$OPT_COMMON" ;;
    Ext3)
      MOUNT_OPTIONS="-t ext3 -o noatime,$OPT_COMMON" ;;
    ReiserFS)
      MOUNT_OPTIONS="-t reiserfs -o noatime,$OPT_COMMON" ;;
    NTFS)
      MOUNT_OPTIONS="-t ntfs -o quiet,noatime,$OPT_WIN,$OPT_COMMON" ;;
    FAT16|FAT32)
      MOUNT_OPTIONS="-t vfat -o shortname=mixed,quiet,noatime,$OPT_WIN,$OPT_COMMON" ;;
    "")
      echo "Something is wrong with this partition!"
      return 1 ;;
    *)
      # Assume FAT filesystem
      MOUNT_OPTIONS="-t vfat -o shortname=mixed,quiet,noatime,$OPT_WIN,$OPT_COMMON" ;;
  esac
}

# Find all devices that are usb-storage. If there are none, then the script
# quits after notifying the user of this condition. The way this works is by
# finding all the SCSI hosts which are in /proc/scsi/usb-storage. Then the
# devices are found by association through the use of sg_map, whose output
# looks like this:

# /dev/sg0  3 0 0 0  0  /dev/sda
# /dev/sg1  4 0 0 0  0  /dev/sdb

# Where the second field is the virtual host (each mass storage device has
# its own) and the last field is the device. I ASSume there is only one
# partition on the device, which is probably true 99.9999% of the time. This
# was also the behavior of the old script, so I'm not going to make things
# needlessly complicated

# The old version used the output of dmesg. It was really ugly. :D

DEVS=$(sudo /usr/bin/sg_map -x | perl -e \
'while (<>) {
   chomp;
   split / +/;
   if (-f "/proc/scsi/usb-storage/$_[1]") { print "$_[$#_]1", " "; }
  }
  print "\n";')

echo "Devices=$DEVS"

if [ ! "$DEVS" ]; then
  echo "No pendrives found"
  message "ERROR" "No pendrives found"
else
  # Mount each device
  for DEV in $DEVS; do
    # This is if the device is already mounted; the loop continues to the next
    # device
    if mount | grep -q "^$DEV"; then
      continue;
    fi
    # This function will set the variable MOUNT_OPTIONS globally. I really
    # wish functions could return strings. What a hack :evil:
    mount_options $DEV
    # Export the options so that they apply to each subshell
    export MOUNT_OPTIONS
    # Export DEV to each subshell as well
    export DEV
    # This tells the subshell where to mount an individual drive
    export MOUNT_ID=$(sudo /usr/X11/bin/mkpdmount $MNT_PENDRIVE);
    # Here the subshell is run. Because it runs in the background,
    # multiple flash drives can be used, and their associated
    # explorer can be closed out
    (sudo /bin/mount $DEV "$MNT_PENDRIVE/$MOUNT_ID" $MOUNT_OPTIONS &&
     explorer "$MNT_PENDRIVE/$MOUNT_ID" &&
     sudo /bin/umount "$MNT_PENDRIVE/$MOUNT_ID" &&
     sudo /usr/X11/bin/rmpdmount $MNT_PENDRIVE $MOUNT_ID) &
  done
fi

exit 0
