#!/bin/sh
#
# chkconfig: 345 48 52
# description: Automounts filesystems on demand
# processname: /usr/sbin/automount
# config: /etc/auto.master
# pidfile: /var/run/automount.xxx.pid

WITHOUT_RC_COMPAT=1

# Source function library.
. /etc/init.d/functions

# Get config.
SourceIfNotEmpty /etc/sysconfig/autofs

PIDFILE=/var/run/automount
LOCKFILE=/var/lock/subsys/autofs
SKIPFILE=/var/lock/subsys/autofs.skip
DAEMON=/usr/sbin/automount
CONFIGFILE=/etc/auto.master
TABFILE=/etc/auto.tab
RETVAL=0

LDAPAUTOMASTER=/usr/lib/autofs/autofs-ldap-auto-master

[ -x "$DAEMON" ] || exit 0

function skip()
{
    [ -s "$CONFIGFILE" ] && [ -s "$TABFILE" ] || return 0
    return 1
}

#
# Check for all maps that are to be loaded
#
function getschemes()
{
    local schemes
    schemes=$(echo $(grep ^automount: /etc/nsswitch.conf |\
	sed -e 's/^.\+:[[:space:]]*//' \
	    -e 's/\[[^]]\+\]//g' \
	    -e 's/[[:space:]]\+/\
/g' |sort -u))
    if [ -z "$schemes" ]; then
	echo files
    else
	echo $schemes
    fi
}

function getfilemounts()
{
    [ -f "$CONFIGFILE" ] && \
	sed '/^\(#\|\+\|$\)/d' $CONFIGFILE
}

function getldapmounts()
{
    [ -x "$LDAPAUTOMASTER" ] || return 0
    "$LDAPAUTOMASTER" 2> /dev/null
}

function getrawmounts()
{
    local scheme
    for scheme in $(getschemes) ; do
	case "$scheme" in
            files)
		getfilemounts
                ;;
            ldap)
		getldapmounts
                ;;
	     yp|nis*)
		# unsupported
		;;
        esac
    done
}

#
# This function will build a list of automount commands to execute in
# order to activate all the mount points. It is used to figure out
# the difference of automount points in case of a reload
#
function getmounts()
{
    #
    # Check for local maps to be loaded
    #
    local knownmaps=" "
    local dir map options maptype mapoptions startupoptions pidtail
    getrawmounts | while read dir map options; do
	# absolute paths please
	[ -z "${dir%%/*}" ] || continue
	# normalize
	dir=$(readlink -m $dir)

	# We can't do empty or direct host maps, so don't bother trying.
	[ -n "$map" -a "$map" = "-hosts" ] && continue

	# filter out duplicate or nested maps
	echo $dir |grep -qF "$knownmaps" && continue
	echo "$knownmaps" |grep -q "^$dir/" && continue

	# handle options
	startupoptions=

	if echo "$options" | grep -qE -- '\B-(t\b|-timeout\b=)'; then
	    startupoptions="--timeout=$(echo $options |\
		sed 's/.*-\(t[^0-9]*\|-timeout\)[ \t=]*\([0-9][0-9]*\).*$/\2/g')"
	elif echo "$DAEMONOPTIONS" | grep -q -- '-t'; then
	    # It's okay to be sloppy with DAEMONOPTIONS as there is no
	    # possibility of conflicting with mount or map options.
	    startupoptions="--timeout=$(echo $DAEMONOPTIONS | \
	      sed 's/.*--*t\(imeout\)*[ \t=]*\([0-9][0-9]*\).*$/\2/g')"
	fi

	# Check for the ghost option
	if echo "$DAEMONOPTIONS $options" | grep -qE -- '\B-(g\b|-ghost\b)'; then
	    startupoptions="$startupoptions --ghost"
	fi

	# Dont even deal with conflicts between --ghost and [no]browse
	# Its just insane to configure things like that.
	if echo "$options" | grep -qE -- '\B-browse\b'; then
	    startupoptions="$startupoptions --ghost"
	fi

	# Check for verbose
	if echo "$DAEMONOPTIONS $options" | grep -qE -- '\B-(v\b|-verbose\b)'; then
	    startupoptions="$startupoptions --verbose"
	fi

	# Check for debug
	if echo "$DAEMONOPTIONS $options" | grep -qE -- '\B-(d\b|-debug\b)'; then
	    startupoptions="$startupoptions --debug"
	fi

	# Other option flags are intended for maps.
	mapoptions="$(echo "$DAEMONOPTIONS $options" |\
	        sed   's/-\(t[^0-9]*\|-timeout\)[ \t=]*\([0-9][0-9]*\)//g' |
	        sed   's/-\(g\b\|-ghost\b\)//g' |
	        sed   's/-\(v\b\|-verbose\b\)//g' |
	        sed   's/-\(d\b\|-debug\b\)//g')"

	# Break up the maptype and map, if the map type is specified
	maptype=${map%:*}
	# Handle degenerate map specifiers
	if [ "$maptype" = "$map" ] ; then
	    if [ -x "$map" ]; then
	        maptype=program
	    elif [ -x "/etc/$map" ]; then
	        maptype=program
	        map=$(readlink -m "/etc/$map")
	    elif [ -f "$map" ]; then
	        maptype=file
	    elif [ "$map" = "hesiod" -o "$map" = "userhome" ] ; then
	        maptype=$map
	        map=
	    elif [ "$map" = "multi" ] ; then
	        maptype=$map
	        map=
	    else
		# no yp support, sorry.
		continue
	    fi
	fi

	map=${map##*:}
	pidtail=`echo $dir | sed 's/\//./g'`
	startupoptions="--pid-file $PIDFILE$pidtail.pid $startupoptions"
	echo "$DAEMON $startupoptions $dir $maptype $map $mapoptions $LOCALOPTIONS" |\
	    sed -e 's/[[:space:]]\+/ /g'

	knownmaps="$knownmaps
$dir"
    done
}

#
# Status lister.
#
function status()
{
    echo "Configured Mount Points:"
    echo "------------------------"
    getmounts
    echo ""
    echo "Active Mount Points:"
    echo "--------------------"
    ps --no-headers axwww |grep "[0-9]:[0-9][0-9] $DAEMON " |\
	while read pid tt stat time command; do echo $command; done
}

function start()
{
    if skip; then
	touch "$SKIPFILE"
	RETVAL=0
	return $RETVAL
    fi
	
    # Make sure the autofs filesystem type is available.
    if ! fgrep -qs autofs /proc/filesystems; then
	if ! action "Loading autofs support:" modprobe -k autofs4 2>/dev/null; then
	    RETVAL=1
	    return $RETVAL
	fi
    fi

    echo -n 'Starting automounter: '
    getmounts |sh &&
    {
	RETVAL=0
	success "automounter startup"
    } || {
	failure "automounter startup"
	RETVAL=1
    }

    echo
    rm -f "$SKIPFILE"
    [ $RETVAL -eq 0 ] && touch "$LOCKFILE"
    return $RETVAL
}

function stop()
{
    RETVAL=0
    if ! action "Stopping automounter:" \
	/sbin/start-stop-daemon --stop --quiet --oknodo \
		--signal USR2 --retry 5 --exec $DAEMON; then
	RETVAL=1
	return $RETVAL
    fi

    umount -a -f -l -t autofs ||:
    [ $RETVAL -eq 0 ] && rm -f "$LOCKFILE"
    return $RETVAL
}

function restart()
{
    stop
    start
}

function reload()
{
    if [ ! -f $LOCKFILE ]; then
	echo "Automounter not running"
	RETVAL=1
	return $RETVAL
    fi
    echo "Checking for changes to $CONFIGFILE ...."
    TMP1=`mktemp /tmp/autofs.XXXXXX` || { echo "could not make temp file" >& 2; exit 1; }
    TMP2=`mktemp /tmp/autofs.XXXXXX` || { echo "could not make temp file" >& 2; exit 1; }
    getmounts >$TMP1
    ps --no-headers axwww |grep "[0-9]:[0-9][0-9] $DAEMON " |\
	while read pid tt stat time command; do
	    echo "$command" >>$TMP2
	if ! grep -qs "^$command" $TMP2; then
		while kill -USR2 $pid; do
		    sleep 3
		done
	    echo "Stop $command"
	fi
    done

    while read x; do
	if ! grep -q "^$x" $TMP2; then
		$x
		echo "Start $x"
	fi
    done  <$TMP1
    rm -f $TMP1 $TMP2
}

# See how we were called.
case "$1" in
	start)
		start
		;;
	stop)
		stop
		;;
	status)
		status
		;;
	reload)
		reload
		;;
	restart)
		restart
		;;
	condstop)
		if [ -e "$LOCKFILE" ]; then
			stop
		fi
		;;
	condrestart)
		if [ -e "$LOCKFILE" ]; then
			restart
		fi
		;;
	skipstart)
		if [ -e "$SKIPFILE" -a ! -e "$LOCKFILE" ]; then
			start
		fi
		;;
	*)
		# echo "Usage: ${0##*/} {start|stop|status|reload|restart|condstop|condrestart}"
		# RETVAL=1
esac

# exit $RETVAL
