#!/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 18 82
# processname: /usr/sbin/automount
# config: /etc/auto.master
# 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/rc.d/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=''

#
# Check for all maps that are to be loaded
#
function getrawmounts()
{
    if [ -f /etc/auto.master ]; then
        cat /etc/auto.master | sed -e '/^#/d' -e '/^$/d'
    fi
    if [ -x /usr/bin/ypcat ] ; then
        /usr/bin/ypcat -k auto.master 2>/dev/null|sed -e '/^#/d' -e '/^$/d'
    fi
#
# check for LDAP maps to be loaded
#
 if [ -x /usr/bin/ldapsearch ] && \
       ldapsearch -x "(&(ou=auto.master)(objectclass=automountmap))" "dn" | \
       grep "dn:.*ou=auto.master" > /dev/null 2>&1;
 then
   		ldapbase=`ldapsearch -x "(&(ou=auto.master)(objectclass=automountmap))" "ou" \
               | grep "^dn:" | sed 's/^dn: ou=auto.master,\(.*\)/\1/' \
               | sed 's/ //g'`
       ldapsearch -u -x -b "ou=auto.master,$ldapbase"  \
               "(&(objectclass=automount)(cn=*))" -s one \
	       | awk ' \
	       /^automountInformation: / { sub($1,""); AUTOINFO=$0 }
	       /^cn: / { sub($1,""); CN=$0 }
	       END { print CN AUTOINFO } '
 fi

}


#
# 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
#
knownmaps=" "
getrawmounts | (
	while read dir map options
	do
            # These checks screen out duplicates and skip over directories
            # where the map is '-'.
	    if [ ! -z "$dir" -a ! -z "$map" \
			-a x`echo "$map" | cut -c1` != 'x-' \
                        -a "`echo "$knownmaps" | grep $dir/`" = "" ]
	    then
                # Break up the maptype and map, if the map type is specified
                maptype=`echo $map | cut -f1 -d:`
                # Handle degenerate map specifiers
                if [ "$maptype" = "$map" ] ; then
			ldapmap=""
			ldapmap=`ldapsearch -x "(&(ou=$map)(objectclass=automountmap))" "dn" 2>/dev/null | grep "^dn:" |  sed 's/dn: \(.*\)/\1/' `
			if [ ! -z "$ldapmap" ]; then
				maptype="ldap"
				map=$ldapmap
                        elif [ -x "$map" ]; then
                                maptype=program
                        elif [ -f "$map" ]; then
                                maptype=file
                        elif [ -f "/etc/$map" ]; then
                                maptype=file
                                map=`echo /etc/$map | sed 's^//^/^g'`
                        elif [ "$map" = "hesiod" -o "$map" = "userhome" ] ; then
                                maptype=$map
                                map=
                        else
                                maptype=yp
                                map=`basename $map`
                        fi
                fi
                if echo $options | grep -- '-t' >/dev/null 2>&1 ; then
                    thisdaemonoptions="$(echo "$daemonoptions $options" |\
                      sed 's/--*t\(imeout\)*[ \t=]*\([0-9][0-9]*\).*$/--timeout \2/g')"
                fi
                # Collect all other options, converting -rwsize, et al to rwsize
                options=`echo "$options" | sed -e '
                  s/[ \t]*--*t\(imeout\)*[ \t=]*[0-9][0-9]*//g'`
                map=`echo "$map" | cut -f2- -d:`
                if [ "$maptype" = "file" ] ; then
                        if [ -f "/etc/$map" ]; then
                                map=`echo /etc/$map | sed 's^//^/^g'`
                        fi
                fi

		echo "$DAEMON $thisdaemonoptions $dir $maptype $map $options $localoptions" | sed 's/  / /g'
	    fi
            knownmaps=" $dir/ $knownmaps"
	done
    )
}

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

# 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 start()
{
  RETVAL=0
  # Make sure the autofs filesystem type is available.
  (grep -q autofs /proc/filesystems || /sbin/modprobe -k autofs) 2> /dev/null
  # Check if the automounter is already running?
  if [ ! -f /var/lock/subsys/autofs ]; then
    echo -n 'Starting automounter: '
    getmounts | sh && success "autofs startup" || failure "autofs startup"
    echo
    touch /var/lock/subsys/autofs
  fi
  return $RETVAL
}

function stop()
{
  echo -n "Stopping automounter:"
  pids=$(/sbin/pidof $DAEMON)
  kill -TERM $pids 2> /dev/null && sleep 1
  RETVAL=$?
  count=1
  while alive $pids; do
    sleep 5
    count=$(expr $count + 1)
    if [ $count -gt 10 ]; then
      echo "Giving up on automounter"
      break;
    fi
    echo "Automounter not stopped yet: retrying... (attempt $count)"
  done
  if [ $count -ge 1 -a $count -le 10 ]; then
    success "autofs shutdown"
    RETVAL=0
  else
    failure "autofs shutdown"
  fi
  echo
  rm -f /var/lock/subsys/autofs
  umount -a -f -t autofs
  return $RETVAL
}

function redhat()
{

#
# See how we were called.
#
case "$1" in
  start)
        start    
	;;
  stop)
        stop
	;;
  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 >$TMP1
	ps axwww|grep "[0-9]:[0-9][0-9] $DAEMON " | (
	    while read pid tt stat time command; do
		echo "$command" >>$TMP2
		if ! grep -q "^$command" $TMP1; 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
	;;
  condrestart)
 	if [ -f /var/lock/subsys/autofs ] ; then
 		stop
 		start
 	fi
 	;;
  status)
	status
	;;
  *)
	echo "Usage: $initdir/autofs {start|stop|restart|reload|status}"
	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 mnt rest
	do
		echo -n " $mnt"
		pidfile=/var/run/autofs`echo $mnt | sed 's/\//./'`.pid
		start-stop-daemon --start --pidfile $pidfile --quiet \
			--exec $DAEMON $daemonoptions -- $mnt $rest
	done
	echo "."
	;;
    stop)
	echo 'Stopping automounter.'
	start-stop-daemon --stop --quiet --signal USR2 --exec $DAEMON
	;;
    reload|restart)
	echo "Reloading automounter: checking for changes ... "
	TMP=/var/run/autofs.tmp
	getmounts >$TMP
	for i in /var/run/autofs.*.pid
	do
		pid=`head -n 1 $i 2>/dev/null`
		[ "$pid" = "" ] && continue
		command=`tail +2 $i`
		if ! grep -q "^$command" $TMP
		then
			echo "Stopping automounter: $command"
			kill -USR2 $pid
		fi
	done
	rm -f $TMP
	$thisscript start
	;;
    status)
	status
	;;
    *)
	echo "Usage: $initdir/autofs {start|stop|restart|reload|status}" >&2
	exit 1
	;;
esac
}

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

exit 0
