#!/bin/bash

### BEGIN INIT INFO
# Provides:          nfs-common
# Required-Start:    $portmap $time
# Required-Stop:     $time
# Default-Start:     S
# Default-Stop:      0 1 6
# Short-Description: NFS support files common to client and server
# Description:       NFS is a popular protocol for file sharing across
#		     TCP/IP networks. This service provides various
#                    support functions for NFS mounts.
### END INIT INFO

# What is this?
DESC="NFS common utilities"

# Read config
DEFAULTFILE=/etc/default/nfs-common
NEED_STATD=
NEED_GSSD=
PIPEFS_MOUNTPOINT=/run/rpc_pipefs
RPCGSSDOPTS=
if [ -f $DEFAULTFILE ]; then
    . $DEFAULTFILE
fi

. /lib/lsb/init-functions

# Exit if required binaries are missing.
[ -x /sbin/rpc.statd ] || exit 0

#
# Parse the fstab file, and determine whether we need gssd. (The
# /etc/defaults settings, if any, will override our autodetection.) This code
# is partially adapted from the mountnfs.sh script in the sysvinit package.
#
AUTO_NEED_GSSD=no

if [ -f /etc/fstab ]; then
    exec 9<&0 </etc/fstab

    while read DEV MTPT FSTYPE OPTS REST
    do
	case $DEV in
	    ''|\#*)
		continue
		;;
	esac
	OLDIFS="$IFS"
	IFS=","
	for OPT in $OPTS; do
	    case "$OPT" in
		sec=krb5|sec=krb5i|sec=krb5p)
		    AUTO_NEED_GSSD=yes
		;;
	    esac
	done
	IFS="$OLDIFS"
    done

    exec 0<&9 9<&-
fi

case "$NEED_STATD" in
    yes|no)
        ;;
    *)
        NEED_STATD=yes
        ;;
esac

case "$NEED_IDMAPD" in
    yes|no)	
        ;;
    *)
        NEED_IDMAPD=yes
	;;
esac

case "$NEED_GSSD" in
    yes|no)	
        ;;
    *)
        NEED_GSSD=$AUTO_NEED_GSSD
	;;
esac

do_modprobe() {
    if [ -x /sbin/modprobe -a -f /proc/modules ]
    then
        modprobe -q "$1" || true
    fi
}

do_mount() {
    if ! grep -E -qs "$1\$" /proc/filesystems
    then
	return 1
    fi
    if ! mountpoint -q "$2"
    then
	mount -t "$1" "$1" "$2"
	return
    fi
    return 0
}

do_umount() {
    if mountpoint -q "$1"
    then
	umount "$1"
    fi
    return 0
}

# See how we were called.
case "$1" in
  start)
	log_daemon_msg "Starting $DESC"

	if [ "$NEED_STATD" = yes ]; then
	    log_progress_msg "statd"
	    
	    # See if rpcbind is running
	    if [ -x /usr/sbin/rpcinfo ]; then
		/usr/sbin/rpcinfo -p >/dev/null 2>&1
		RET=$?
		if [ $RET != 0 ]; then
		   echo
		   log_warning_msg "Not starting: portmapper is not running"
		   exit 0
		fi
	    fi
	    start-stop-daemon --start --oknodo --quiet \
		--pidfile /run/rpc.statd.pid \
	        --exec /sbin/rpc.statd -- $STATDOPTS
	    RET=$?
	    if [ $RET != 0 ]; then
	        log_end_msg $RET
	        exit $RET
	    else
		if [ -d /run/sendsigs.omit.d ]; then
		    rm -f /run/sendsigs.omit.d/statd
		    ln -s /run/rpc.statd.pid /run/sendsigs.omit.d/statd
		fi
	    fi
	fi

	# Don't start idmapd and gssd if we don't have them (say, if /usr is not
	# up yet).
	[ -x /usr/sbin/rpc.idmapd ] || NEED_IDMAPD=no
	[ -x /usr/sbin/rpc.gssd   ] || NEED_GSSD=no

	if [ "$NEED_IDMAPD" = yes ] || [ "$NEED_GSSD" = yes ]
	then
	    do_modprobe sunrpc
	    do_modprobe nfs
	    do_modprobe nfsd
	    mkdir -p "$PIPEFS_MOUNTPOINT"
	    if do_mount rpc_pipefs $PIPEFS_MOUNTPOINT
	    then
	    	if [ "$NEED_IDMAPD" = yes ]
		then
	            log_progress_msg "idmapd"
		    start-stop-daemon --start --oknodo --quiet \
			    --exec /usr/sbin/rpc.idmapd
		    RET=$?
	            if [ $RET != 0 ]; then
        	        log_end_msg $RET
        	        exit $RET
                    fi
		fi
		if [ "$NEED_GSSD" = yes ]
		then
		    do_modprobe rpcsec_gss_krb5
	            log_progress_msg "gssd"

	            # we need this available; better to fail now than
		    # mysteriously on the first mount
		    if ! grep -q -E '^nfs[	 ]' /etc/services; then
		    	log_action_end_msg 1 "broken /etc/services, please see /usr/share/doc/nfs-common/README.Debian.nfsv4"
			exit 1
		    fi

		    start-stop-daemon --start --oknodo --quiet \
			    --exec /usr/sbin/rpc.gssd -- $RPCGSSDOPTS
		    RET=$?
	            if [ $RET != 0 ]; then
        	        log_end_msg $RET
        	        exit $RET
                    fi
		fi
	    fi
	fi
	log_end_msg 0
	;;

  stop)
	log_daemon_msg "Stopping $DESC"

	if [ "$NEED_GSSD" = yes ]
	then
	    log_progress_msg "gssd"
	    start-stop-daemon --stop --oknodo --quiet \
		    --name rpc.gssd
	    RET=$?
	    if [ $RET != 0 ]; then
                log_end_msg $RET
                exit $RET
            fi
	fi
	if [ "$NEED_IDMAPD" = yes ]
	then
	    log_progress_msg "idmapd"
	    start-stop-daemon --stop --oknodo --quiet \
		--name rpc.idmapd
            RET=$?
	    if [ $RET != 0 ]; then
                log_end_msg $RET
                exit $RET
            fi
	fi
	if [ "$NEED_STATD" = yes ]
	then
	    log_progress_msg "statd"
	    start-stop-daemon --stop --oknodo --quiet \
	        --name rpc.statd
	    RET=$?
	    if [ $RET != 0 ]; then
                log_end_msg $RET
                exit $RET
            fi
	fi
	do_umount $PIPEFS_MOUNTPOINT 2>/dev/null || true
	log_end_msg 0
	;;

  status)
	if [ "$NEED_STATD" = yes ]
	then
	    if ! pidof rpc.statd >/dev/null
	    then
	        echo "rpc.statd not running"
	        exit 3
	    fi
	fi

	if [ "$NEED_GSSD" = yes ]
	then
            if ! pidof rpc.gssd >/dev/null
	    then
		echo "rpc.gssd not running"
		exit 3
	    fi
	fi

	if [ "$NEED_IDMAPD" = yes ]
	then
            if ! pidof rpc.idmapd >/dev/null
	    then
		echo "rpc.idmapd not running"
		exit 3
	    fi
	fi

	echo "all daemons running"
	exit 0
	;;

  restart | force-reload)
	$0 stop
	sleep 1
	$0 start
	;;

  *)
	log_success_msg "Usage: nfs-common {start|stop|status|restart}"
	exit 1
	;;
esac

exit 0
