#! /bin/bash
#
# $Id: //depot/autofs-4.0/samples/rc.autofs.in#4 $
#
# rc file for automount using a Sun-style "master map".
# We first look for a local /etc/auto.master, then a YP
# map with that name
#
# On most distributions, this file should be called:
# /etc/rc.d/init.d/autofs or /etc/init.d/autofs
#

# For Redhat-ish systems
#
# chkconfig: 345 15 85
# description: Automounts filesystems on demand

# This is used in the Debian distribution to determine the proper
# location for the S- and K-links to this init file.
# The following value is extracted by debstd to figure out how to
# generate the postinst script. Edit the field to change the way the
# script is registered through update-rc.d (see the manpage for
# update-rc.d!)
#
FLAGS="defaults 21"

#
# Location of the automount daemon and the init directory
#
DAEMON=/usr/sbin/automount
initdir=/etc/init.d

#
# Determine which kind of configuration we're using
#
system=unknown
if [ -f /etc/debian_version ]; then
    system=debian
elif [ -f /etc/redhat-release ]; then
    system=redhat
else
    echo "$0: Unknown system, please port and contact autofs@linux.kernel.org" 1>&2
    exit 1
fi

if [ $system = redhat ]; then
    . $initdir/functions
fi

test -e $DAEMON || exit 0
thisscript="$0"
if [ ! -f "$thisscript" ]; then
    echo "$0: Cannot find myself" 1>&2
    exit 1
fi

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

#
# We can add local options here
# e.g. localoptions='rsize=8192,wsize=8192'
#
localoptions=''

#
# Daemon options
# e.g. --timeout 60
#
daemonoptions=''

#
# 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()
{
    if ! getmounts_file /etc/auto.master; then
	if ! getnismounts auto.master; then
	    echo "no autofs mounts configured!" 1>&2
	fi
    fi
}

function getmounts_file()
{
    #
    # Check for local maps to be loaded
    #
    local map="$1"
    shift
    if [ -f "$map" ]
    then
	cat "$map" | sed -e '/^#/d' -e '/^$/d' | process_master_file "$@"
    else
	return 1
    fi
}

function process_master_file()
{
    local line_options="$@" daemon_options
    while read dir map options
    do
	options="$line_options $options"
	case "$dir" in
	    +*)	getnismounts "${dir/+/}" $map $options
		continue;
	esac
	if [ ! -z "$dir" -a ! -z "$map" \
		-a x`echo "$map" | cut -c1` != 'x-' ]
	then
	    type=""
	    if [ -x $map ]; then
		type=program
	    elif [ -f $map ]; then
		type=file
	    elif [ x`echo "$map" | cut -c1` == 'x/' ]; then
		# Starts with '/', thus a file, but doesn't exist
		# so leave it out, leaving 'type=""' (hro)
		type=""
	    elif [ -f /etc/$map ]; then
		type=file
		map=/etc/$map
	    elif [ $map == hesiod ]; then
		type=hesiod
		map=""
	    elif [ $map == ldap ]; then
		type=ldap
		map=""
	    else
		case "$map" in
		    !*)	type=program map="${map/!/}";;
		    *)	type=yp;;
		esac
	    fi
	    daemon_options=`munge_options daemon $daemonoptions $options`
	    options=`munge_options mount $options`

	    if [ "$type" ]; then
		echo "$DAEMON $daemon_options -- $dir $type $map $localoptions $options"
	    fi
	fi
    done
}

function getnismounts()
{
    #
    # Check for YellowPage maps to be loaded
    #
    local map="$1"
    shift
    if [ -e /usr/bin/ypcat ] && [ `ypcat -k "$map" 2>/dev/null | wc -l` -gt 0 ]
    then
	ypcat -k "$map" | process_master_file "$@"
    else
	return 1
    fi
}

#
# List active mounts
#
function active()
{
    ps ax|grep "[0-9]:[0-9][0-9] $DAEMON " |
	while read pid tt stat time command
	do
	    echo $command
	done
}

#
# Status lister.
#
function status()
{
	echo "Configured Mount Points:"
	echo "------------------------"
	getmounts | sed 's/ -- / /'
	echo ""
	echo "Active Mount Points:"
	echo "--------------------"
	active
}

function munge_options()
{
	local which="$1"
	shift
	echo "$@" | awk -v which="$which" '
BEGIN {
	RS="[, \n-]"
	FS="="
	daemon_opts[ "timeout" ] = "timeout"
	daemon_opts[ "t" ] = "timeout"
}
{
	if ( $0 ~ /^$/ )
		next
	if ( $1 in daemon_opts ) {
		daemon[ daemon_opts[ $1 ] ] = $2
	} else {
		mount[$0] = 1
	}
}
END {
	if ( which ~ "^daemon$" ) {
		if ( "timeout" in daemon ) {
			printf "--timeout=%s\n", daemon["timeout"]
		}
	} else {
		for ( a in mount ) {
			if ( length( out ) )
				out=out "," a
			else
				out=a
		}
		printf "%s\n", out
	}
}
'
}

function get_command_from_pid()
{
    ps ax | grep "[0-9]:[0-9][0-9] $DAEMON " | (
        while read pid tt stat time command; do
            if [ "$pid" = "$1" ] ; then
	        echo `echo "$command" | sed 's/--pid-file.*\.pid/ /'`
		return 0
	    fi
	done
    )

    return 0
}

# return true if at least one pid is alive
function alive()
{
    if [ -z "$*" ]; then
	return 1
    fi
    for i in $*; do
	if kill -0 $i 2> /dev/null; then
	    return 0
	fi
    done

    return 1
}

#
# Redhat start/stop function.
#
function redhat()
{

#
# See how we were called.
#
case "$1" in
  start)
	# Check if the automounter is already running?
	if [ ! -f /var/lock/subsys/autofs ]; then
	    echo 'Starting automounter: '
	    getmounts | sed 's/ -- / /' | sh
	    touch /var/lock/subsys/autofs
	fi
	;;
  stop)
	pids=$(/sbin/pidof $DAEMON)
	kill -TERM $pids 2> /dev/null && sleep 1
	count=1
	while alive $pids; do
	    sleep 5
	    count=$(expr $count + 1)
	    if [ $count -gt 5 ]; then
		echo "Giving up on automounter"
		break;
	    fi
	    echo "Automounter not stopped yet: retrying... (attempt $count)"
	done
	if [ $count -gt 1 -a $count -le 5 ]; then
	    echo "Automounter stopped"
	fi
	rm -f /var/lock/subsys/autofs
	;;
  reload|restart)
	if [ ! -f /var/lock/subsys/autofs ]; then
		echo "Automounter not running"
		exit 1
	fi
	echo "Checking for changes to /etc/auto.master ...."
        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 | sed 's/ -- / /' >$TMP1
	ps ax|grep "[0-9]:[0-9][0-9] $DAEMON " | (
	    while read pid tt stat time command; do
		echo "$command" >>$TMP2
		if ! grep -q "^$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
	;;
  status)
	status
	;;
  getmounts)
	getmounts
	;;
  active)
	active
	;;

  *)
	echo "Usage: $initdir/autofs {start|stop|restart|reload|status|getmounts|active}"
	exit 1
esac
}

#
# Debian start/stop functions.
#
function debian()
{
#
# See how we were called.
#
case "$1" in
    start)
	echo -n 'Starting automounter:'
	getmounts | while read cmd args
	do
		opt=${args%%-- *}
		rest=${args#*-- }
		mnt=${rest%% *}
		rest=${rest#* }
		echo -n " $mnt"
		if [ ! -d /var/run/autofs ]; then
			mkdir /var/run/autofs
		fi
		pidfile=/var/run/autofs/`echo $mnt | sed 's,_,__,g;s,/,_:,g'`.pid
		start-stop-daemon --start --pidfile $pidfile --quiet \
			--exec $DAEMON -- --pid-file=$pidfile $opt $mnt $rest
	done
	echo "."
	;;
    stop)
	echo -n 'Stopping automounter: '
	start-stop-daemon --stop --quiet --signal USR2 --exec $DAEMON
	any=0
	for file in /var/run/autofs/*.pid
	do
	    if [ -e "$file" ]
	    then
	    	any=1
		pid=`head -n 1 $file`
		command=`get_command_from_pid $pid`
		if [ -z "`ps --no-heading $pid`" ]
		then
		    echo -n -e "\n  Stopped $pid($command)"
		    rm -f $file
		else
		    echo -n -e "\n  Couldn't stop $pid($command)"
		fi
	    fi
	done
        if [ $any -eq 1 ]; then
		echo
        fi
	echo "done."
	;;
    reload)
	echo -n "Reloading automounter: checking for changes..."
	TMP=/var/run/autofs.tmp
	getmounts | sed 's/ -- / /' | sed 's/  / /g' >$TMP

	any=0
	for i in /var/run/autofs/*.pid
	do
		pid=`head -n 1 $i 2>/dev/null`
		[ "$pid" = "" ] && continue
		command=`get_command_from_pid $pid`
		if ! grep -q "^$command" $TMP
		then
	                any=1
			echo -n -e "\n  Stopping automounter: $command"
			kill -USR2 $pid
			rm -f $i
		fi
	done
	if [ $any -eq 1 ]; then
		echo
	fi
	echo "done."
	rm -f $TMP
	$thisscript start
	;;
    force-reload|restart)
	$0 stop
	$0 start
	;;
    status)
	status
	;;
    getmounts)
	getmounts | sed 's/ -- / /'
	;;
    active)
	active
	;;
    *)
	echo "Usage: $initdir/autofs {start|stop|restart|reload|force-reload|status|getmounts|active}" >&2
	exit 1
	;;
esac
}

if [ $system = debian ]; then
	debian "$@"
elif [ $system = redhat ]; then
	redhat "$@"
fi

exit 0
