#!/bin/bash
# Copyright (C) 2011 SUSE Linux Products GmbH, Nuernberg, Germany.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

### BEGIN INIT INFO
# Provides:       autofs
# Required-Start: $network $syslog $remote_fs
# Should-Start:   $portmap ypbind keyserv ldap gssd
# Required-Stop:  $network $syslog $remote_fs
# Should-Stop:    $portmap ypbind keyserv ldap gssd
# Default-Start:  3 5
# Default-Stop:
# Short-Description: automatic mounting of filesystems
# Description:    Start the autofs daemon for automatic mounting of filesystems.
### END INIT INFO

#
# Location of the automount daemon and the init directory
#
DAEMON=/usr/sbin/automount
prog=`basename $DAEMON`
MODULE="autofs4"
DEVICE="autofs"
confdir=/etc/sysconfig
PIDFILE=/var/run/automount.pid

test -x $DAEMON || exit 5

PATH=/sbin:/usr/sbin:/bin:/usr/bin
export PATH

. /etc/rc.status

#
# load customized configuation settings
#
if [ -r $confdir/autofs ]; then
	. $confdir/autofs
fi

function start() {
    # Make sure autofs4 module is loaded
    if ! grep -q autofs /proc/filesystems; then
	# Try load the autofs4 module fail if we can't
	modprobe -q $MODULE >/dev/null 2>&1
	if [ $? -eq 1 ]; then
	    echo "Error: failed to load autofs4 module."
	    return 1
	fi
    elif ([ -f /proc/modules ] && lsmod) | grep -q autofs[^4]; then
	# wrong autofs filesystem module loaded
	echo
	echo "Error: autofs kernel module is loaded, autofs4 required"
	return 1
    fi

    # Use the AutoFS misc device unless it is explicitly disabled
    if [ -z "$USE_MISC_DEVICE" -o "x$USE_MISC_DEVICE" = "xyes" ]; then
	sleep 1
	if [ -e "/proc/misc" ]; then
	    MINOR=`awk "/$DEVICE/ {print \\$1}" /proc/misc`
	    if [ -n "$MINOR" -a ! -c "/dev/$DEVICE" ]; then
		mknod -m 0600 /dev/$DEVICE c 10 $MINOR
	    fi
	fi
	if [ -x /sbin/restorecon -a -c /dev/$DEVICE ]; then
	    /sbin/restorecon /dev/$DEVICE
	fi
    else
	if [ -c /dev/$DEVICE ]; then
	    rm /dev/$DEVICE
	fi
    fi

    if [ "$LOCAL_OPTIONS" ]; then
        AUTOFS_OPTIONS="-O $LOCAL_OPTIONS $AUTOFS_OPTIONS"
    fi
    /sbin/startproc -w $DAEMON -p $PIDFILE $AUTOFS_OPTIONS

    return $?
}

function force_stop() {
    # Send an USR2 signal and wait for the automounter to expire
    # all non-busy file systems and then terminate. This is normally
    # enough, but there's a corner case: it's possible that a
    # concurrent mount request will prevent the daemon from exiting.
    # To workaround this, send SIGUSR2 again on each iteration.
    # Busy file systems are left mounted and will be handled later.
    for i in {0..90}; do
        /sbin/killproc -USR2 $DAEMON
        sleep 1
        /sbin/checkproc $DAEMON || break
    done
    echo ""
    # Coup de grace if it has not died yet
    /sbin/checkproc $DAEMON && /sbin/killproc -KILL $DAEMON

    # At this point there should not be any busy autofs filesystems mounted.
    # To ensure that there are no leftovers, we lazy umount any remaining
    # autofs filesystems which have been still kept busy for some reason
    # (this should have been done by the USR2 signal but currently this
    # does not work)
    while read map mnt fstype options dummy; do
        test "$fstype" = "autofs" || continue
        case "$options" in
        *indirect*)
            for path in $mnt/* ; do
                test "$path" = "$mnt/*" && break
                test -e $path && umount -l $path
                echo "$path still busy...unmounting lazy"
            done
            echo "$mnt still busy...unmounting lazy"
            test -e $mnt && umount -l $mnt
            ;;
        *[^i][^n]direct*)
            # umount 2 times: one for the real fs, one for autofs
            # because mountpoint and autofs mp are identical here!
            echo "$mnt still busy...unmounting lazy"
            test -e $mnt && umount -l $mnt
            test -e $mnt && umount -l $mnt
            ;;
        *) ;;
        esac
    done < /proc/mounts

    return 0
}

function stop() {
    # Normal stop, terminate daemon, we don't care about busy leftovers here
    /sbin/killproc -p $PIDFILE -TERM $DAEMON
}

RETVAL=0

case "$1" in
    start)
	echo -n "Starting $prog "
	# Check if already running
	if ! /sbin/checkproc $DAEMON; then
	    start
	fi

	rc_status -v
	;;
    stop)
	echo -n "Shutting down $prog "
        case "$RUNLEVEL" in
        [016sS])
	    echo -n "(force) "
            force_stop
            ;;
        *)
            stop
	    ;;
        esac

	rc_status -v
	;;
    force-stop)
	echo -n "Shutting down $prog (force) "
        force_stop

	rc_status -v
        ;;
    try-restart|condrestart)
	## Do a restart only if the service was active before.
	## Note: try-restart is now part of LSB (as of 1.9).
	## RH has a similar command named condrestart.
	if test "$1" = "condrestart"; then
	    echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
	fi
	$0 status
	if test $? = 0; then
	    $0 restart
	else
	    rc_reset	# Not running is not a failure.
	fi
	# Remember status and be quiet
	rc_status
	;;
    restart)
	$0 stop
	$0 start

	rc_status
	;;
    force-reload)
	echo -n "Reload service $prog "
	/sbin/killproc -HUP $DAEMON
	rc_status -v

	;;
    reload)
	echo -n "Reload service $prog "
	/sbin/killproc -HUP $DAEMON
	rc_status -v

	;;
    force-expire)
	# forcing expire of mounted filesystems
	echo -n "$prog: force expire"
	/sbin/killproc -USR1 $DAEMON

	rc_status -v
	;;
    status)
	echo -n "Checking for service $prog "
	/sbin/checkproc $DAEMON
	# NOTE: rc_status knows that we called this init script with
	# "status" option and adapts its messages accordingly.
	rc_status -v
	;;
    *)
	echo "Usage: $0 {start|stop|force-stop|status|try-restart|restart|force-reload|reload|force-expire}"
	exit 1
	;;
esac
rc_exit
