#!/bin/bash
# Copyright (C) 2008 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 nfsserver
# Required-Stop:  $network $syslog $remote_fs
# Should-Stop:    $portmap ypbind keyserv ldap gssd nfsserver
# 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

# autofs misc driver not yet supported in our kernel
# so don't allow this for now
USE_MISC_DEVICE=''

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

    # Check misc device
    if [ -n "$USE_MISC_DEVICE" -a "$USE_MISC_DEVICE" = "yes" ]; 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 ]; 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 $DAEMON -p $PIDFILE $AUTOFS_OPTIONS

    return $?
}

clearautomnt()
{
    local map mnt fstype options dummy
    local path dtype
    local opt=$1
    test "$opt" = "before" && opt=continue || opt=:
    while read map mnt fstype options dummy; do
	test "$fstype" = "autofs" || continue
	case ",$options," in
	*,indirect,*)
	    for path in $mnt/* ; do
		test "$path" = "$mnt/*"  && continue
		test -e $path            || continue
		dtype=$(stat -f -c '%T' "$path" 2>/dev/null)
		test "$dtype" = "autofs" && continue
		if test "$opt" = "continue" ; then
		    mkill  -TERM $path
		else
		    echo "$path still busy...unmounting lazy"
		    umount -l    $path
		fi
	    done
	    $opt
	    test -e $mnt || continue
	    echo "$mnt still busy...unmounting lazy"
	    umount -l $mnt
            ;;
	*,direct,*)
            # umount 2 times: one for the real fs, one for autofs
            # because mountpoint and autofs mp are identical here!
	    $opt
	    test -e $mnt || continue
	    echo "$mnt still busy...unmounting lazy"
	    umount -l $mnt
	    umount -l $mnt
	    ;;
        *)
	    ;;
	esac
    done < /proc/mounts
}
force_stop()
{
    local -i i
    # Terminate all processes making automounted file systems busy
    clearautomnt before

    # First send USR2 signal, automount will expire all non-busy
    # filesystems and then terminate.
    # Busy filesystems will be left mounted
    /sbin/killproc -USR2 $DAEMON

    # Let's wait a while for the daemon to really shut down
    # in case of debug and browsable maps enabled this could take a while
    for i in {0..90}; do
        /sbin/checkproc $DAEMON || break
        sleep 1
    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)
    clearautomnt after

    return 0
}

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
