#!/bin/sh
# ltspfs_entry
# place in /lib/udev
# $1 = mode (add/remove)
# $2 = devicename
# $3 = fstype (optional)

ROOT=/var/run/drives
FSTAB=/var/run/ltspfs_fstab

# get default configuration:
if [ -f /etc/ltspfs/ltspfsd.conf ]; then
    . /etc/ltspfs/ltspfsd.conf
fi

# get ltsp configuration:
if [ -f /usr/share/ltsp/ltsp_config ]; then
    . /usr/share/ltsp/ltsp_config
fi

boolean_is_true(){
    case $1 in
       # match all cases of true|y|yes
       [Tt][Rr][Uu][Ee]|[Yy]|[Yy][Ee][Ss]) return 0 ;;
       *) return 1 ;;
    esac
}

if ! boolean_is_true "$LOCALDEV" ; then
    exit 0
fi

call_ltspfsmounter()
{
    action="$1"
    MOUNTPOINT=$2
    for LDM_SOCKET in /var/run/ldm_socket_*; do
        if [ -S ${LDM_SOCKET} ]; then
            SERVER=${LDM_SOCKET##*_}
            SSH_OPTS="-X"
            # see if we have a command with DISPLAY matching our socket
            IS_DIRECTX=$(pgrep -f -l ${LDM_SOCKET}.*DISPLAY)

            unset DISPLAY_INFO
            # get the DISPLAY info for ltspfsmounter
            if [ -n "${IS_DIRECTX}" ];then
                unset SSH_OPTS
                for line in $IS_DIRECTX ; do
                    case $line in
                        DISPLAY*)
                            DISPLAY_INFO="${line}"
                        ;;
                    esac
                done
            fi

            /usr/bin/ssh $SSH_OPTS -S ${LDM_SOCKET} ${SERVER} \
                "$DISPLAY_INFO /usr/sbin/ltspfsmounter ${MOUNTPOINT} $action"
        fi
    done

    if [ -x "/usr/sbin/ltspfsmounter" ]; then
        # Also call local ltspfsmounter if installed
        # ltspfs needs DISPLAY to do Xatom authentication.
        # For this rev, lets use the first Xserver running
        for f in $(ls /tmp/.X*lock); do
            export DISPLAY=:$(echo $f|sed -e 's/^.*\.X//' -e 's/-lock$//')
            break
        done 
        XAUTHORITY=$(find /tmp -maxdepth 1 -mindepth 1 -type f -name xauth-$DISPLAY-*)
        export XAUTHORITY

        HOMEDIR=$(cat /proc/mounts|grep sshfs|awk '{print $2}'|head -1)
        USER=${HOMEDIR##*/}
        export USER=${USER:-root}

        su ${USER} -c "/usr/sbin/ltspfsmounter ${MOUNTPOINT} $action"
    fi
}

remove_device()
{
    DEVICENAME="$1"
    while read DEV MOUNTPOINT TYPE OPTIONS DUMP PASS; do
        if [ "${DEV}" = "/dev/${DEVICENAME}" ]; then
            umount -l ${MOUNTPOINT}
            rmdir ${MOUNTPOINT}
            call_ltspfsmounter remove ${MOUNTPOINT}
            sed -i -e "\@ ${MOUNTPOINT} @d" ${FSTAB}
            exit 0
        fi
    done < ${FSTAB}
}

start_ltspfsd()
{
    if [ -z "$(pgrep ltspfsd)" ]; then
        # Make this sessions secret auth cookie for ltspfs
        if [ ! -f /var/run/ltspfs_token ]; then
            mcookie > /var/run/ltspfs_token
        fi
        # start up the ltspfsd daemon
        /usr/bin/ltspfsd
    fi
}

call_cdpinger(){
    if [ -z $(pgrep -f -l "/usr/sbin/cdpinger $1") ]; then
        /usr/sbin/cdpinger $1 &
        return 0
    else
        # already running cdpinger for this device
        return 1
    fi
}

add_device() {
    DEVICENAME="$1"
    if [ -x /sbin/udevadm ]; then
        udevinfo="/sbin/udevadm info"
    else
        udevinfo=udevinfo
    fi

    eval "export $($udevinfo -qenv -n ${DEVICENAME}|sed -e 's/=/="/' -e 's/$/"/')"
    if [ -z "$ID_TYPE" ]; then
        # set an ID type for known devices
        case $DEVICENAME in
            fd?) # internal floppy drives don't set any information
                ID_TYPE=floppy ;;
        esac
    fi

    # set devices to be denied based on simple booleans:
    if boolean_is_true "$LOCALDEV_DENY_FLOPPY" ; then
        LOCALDEV_DENY="ID_TYPE:floppy,$LOCALDEV_DENY"
    fi

    if boolean_is_true "$LOCALDEV_DENY_USB" ; then
        LOCALDEV_DENY="ID_BUS:usb,$LOCALDEV_DENY"
    fi

    if boolean_is_true "$LOCALDEV_DENY_CD" ; then
        LOCALDEV_DENY="ID_TYPE:cd,$LOCALDEV_DENY"
    fi

    # default to not allowing internal disks, as it gives write access to root
    # filesystems:
    test -z "$LOCALDEV_DENY_INTERNAL_DISKS" && LOCALDEV_DENY_INTERNAL_DISKS=True
    if boolean_is_true "$LOCALDEV_DENY_INTERNAL_DISKS" ; then
        # IDE, SCSI (which should catch sata)
        LOCALDEV_DENY="ID_BUS:ata+ID_TYPE:disk,ID_BUS:scsi+ID_TYPE:disk,$LOCALDEV_DENY"
    fi

    # Deny mounting by sysfs attribute from udevinfo (in environment)
    # LOCALDEV_DENY is a comma-separated list of var=val pairs
    if [ -n "${LOCALDEV_DENY}" ]; then
        oldifs=$IFS
        IFS=,
        for deny_ruleset in ${LOCALDEV_DENY}; do
            count=0
            IFS=+
            for deny_rule in $deny_ruleset; do
                var=$(echo $deny_rule|cut -d: -f1)
                val=$(echo $deny_rule|cut -d: -f2)
                eval test="\${$var}" 2>/dev/null
                # If $test (the value of the udevinfo var) equals $val
                # (the value from LOCALDEV_DENY), then increment count of
                # matches
                if [ "$test" = "$val" ]; then
                    count=$(($count+1))
                else
                    count=0
                    break
                fi
            done
            [ $count -gt 0 ] && exit 1
        done
        unset IFS
        if [ -n "$oldifs" ]; then
            IFS=$oldifs
        fi
    fi

    # handle CDROM devices, which do not produce udev add/remove events
    if [ "${ID_TYPE}" = "cd" ]; then
        cd_device="$DEVICENAME"
        for link in $($udevinfo -q symlink -n ${DEVICENAME}) ; do
            case $link in
                cdrom*) 
                    cd_device="$link"
                    break
                    ;;
            esac
        done

        if call_cdpinger $cd_device ; then
            # started new cdpinger, which will handle the rest
            exit 0
        fi
    fi

    # Make sure we have a valid FSTYPE
    [ -z "${FSTYPE}" ] && FSTYPE="${ID_FS_TYPE}"   # Use udevinfo ID_FS_TYPE
    [ "${FSTYPE}" = "swap" ] && exit 1             # Don't mount swap partitions
    [ -z "${FSTYPE}" ] && exit 1                   # That's empty too, die.
    
    case $DEVICENAME in
        fd*) 
            LABEL="floppy${DEVICENAME##fd}"
            ;;
        cdrom*)
            LABEL="${DEVICENAME}"
            ;;
    esac

    [ -z "${LABEL}" ] && LABEL=${ID_FS_LABEL_SAFE}
    [ -z "${LABEL}" ] && LABEL="${ID_BUS}${ID_TYPE}-${DEVICENAME}"

    # Check for existing label with same name
    if [ -r ${FSTAB} ]; then
        while read DEV MOUNTPOINT TYPE OPTIONS DUMP PASS; do
            if [ "${MOUNTPOINT##*/}" = "${LABEL}" ]; then
                # Seems we already have a mountpoint with this name
                # Let's change the label
                LABEL="${LABEL}-${DEVICENAME}"
            fi
        done < ${FSTAB}
    fi
 
    # Invent $MOUNTPOINT
    MOUNTPOINT=$ROOT/$LABEL
    mkdir -p ${MOUNTPOINT}

    # Set "utf8" option if volume is vfat, iso9660, or ntfs (which support it)
    # This fixes filenames with international characters
    case ${FSTYPE} in
        vfat|iso9660|ntfs) LOCALDEV_MOUNT_OPTIONS=${LOCALDEV_MOUNT_OPTIONS:-"defaults,utf8"} ;;
    esac     

    echo "/dev/${DEVICENAME} ${MOUNTPOINT} ${FSTYPE} ${LOCALDEV_MOUNT_OPTIONS:-defaults} 0 0" >> ${FSTAB}
    
    start_ltspfsd

    call_ltspfsmounter add ${MOUNTPOINT}
}

if [ "$1" = "add" ] || [ "$1" = "remove" ]; then
    MODE=$1
    shift
else
    # backwards compatibility:
    # called as add_fstab_entry or remove_fstab_entry
    MODE=$(basename $0)
fi

DEVICENAME=$(basename $1)
FSTYPE=$2

case $MODE in
    add*) add_device $DEVICENAME ;;
    remove*) remove_device $DEVICENAME ;;
    *) exit 1 ;;
esac
