Subject: Re: pkg/15358: SUBMISSION: new pkgsrc module for security/ssh2-3.1.0
To: NetBSD GNATS submissions and followups <gnats-bugs@gnats.netbsd.org>
From: Greg A. Woods <woods@weird.com>
List: netbsd-bugs
Date: 07/05/2002 01:43:08
here's an updated and more widely tested rc.d script...  though it still
requires a posix-ish shell and the keygen command-line option isn't
directly supported on non-rc.subr machines (it didn't seem that useful
to worry about).

(I've been wondering if maybe it wouldn't be a good idea to have an
rc.subr support package that older systems and non-NetBSD systems could
install so all this code duplication could be eliminated....)

-- 
								Greg A. Woods

+1 416 218-0098;            <g.a.woods@ieee.org>;           <woods@robohack.ca>
Planix, Inc. <woods@planix.com>; VE3TCP; Secrets of the Weird <woods@weird.com>

#! /bin/sh
#
#ident "@(#)$NetBSD$"
#
# This script is designed primarily for the NetBSD system startup
# scripts (/etc/rc et al), but has compatability to work on other
# systems (including older NetBSD systems) with no additional outside
# support functionality.

# PROVIDE: sshd
# REQUIRE: LOGIN

name="sshd2"
rcvar=$name
command="@PREFIX@/sbin/${name}"
required_files="@PKG_SYSCONFDIR@/${name}_config"
PORT=$(grep Port ${required_files} | awk '{ x = $2 } END {print x}' -)
pidfile="/var/run/${name}_${PORT}.pid"

sshd_keygen2()
{
	if [ -f @PKG_SYSCONFDIR@/hostkey ]; then
		echo "You already have a DSA host key in @PKG_SYSCONFDIR@/hostkey"
		echo "Skipping DSA Key Generation"
	else
		umask 022
		@PREFIX@/bin/ssh-keygen2 -P -t dsa -c "1024-bit dsa hostkey" @PKG_SYSCONFDIR@/hostkey
	fi

}

sshd_precmd2()
{
	if [ ! -f @PKG_SYSCONFDIR@/hostkey ]; then
		sshd_keygen2
	fi
}

# is this NetBSD (1.4V|1.5) [2000/03/10] or newer?
# 
if [ -f /etc/rc.subr -a -f /etc/rc.conf -a -d /etc/rc.d -a -f /etc/rc.d/DAEMON ]; then

	. /etc/rc.subr

	extra_commands="keygen reload"
	keygen_cmd=sshd_keygen2
	start_precmd=sshd_precmd2

	# is this NetBSD 1.4Z [2000/05/13] or newer?
	# 
	if type load_rc_config > /dev/null 2>&1 ; then
		load_rc_config ${name}
	else
		. /etc/rc.conf
		if [ -f /etc/rc.conf.d/${name} ]; then
			. /etc/rc.conf.d/${name}
		fi
		if [ -f @PREFIX@/etc/rc.conf.d/${name} ]; then
			. @PREFIX@/etc/rc.conf.d/${name}
		fi
	fi
	run_rc_command "$1"

# if not then it must be old NetBSD, Solaris, Linux, etc...
# 
else

	if [ -f /etc/rc.subr ] ; then
		. /etc/rc.subr	# NetBSD-1.3 has older checkyesno variant
	fi

	if expr "$(type warn)" : '.* is a shell function$' >/dev/null 2>&1 ; then
		:
	else
		warn ()
		{
			if expr "$(type logger)" : '.* is .*/logger$' >/dev/null 2>&1 ; then
				logger -s -p daemon.warning -t rc "$0: WARNING: $*"
			else
				echo "$0: WARNING: $*" 1>&2
			fi
		}
	fi

	# XXX we may not have/want to be so paranoid of overriding 'checkyesno'...
	#
	if expr "$(type warn)" : '.* is a shell function$' >/dev/null 2>&1 ; then
		:
	else
		# Test contents of $1, as a variable, for on or off values;
		# and warn if not set appropriately.
		#
		checkyesno ()
		{
			eval _value=\${${1}}
			case ${_value} in
			[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
				return 0
				;;
			[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
				return 1
				;;
			*)
				_rcconf=""
				if [ -f /etc/rc.conf ]; then
					_rcconf="in /etc/rc.conf"
				fi
				warn "\${${1}} is not configured properly${_rcconf}."
				return 1
				;;
			esac
		}
	fi

	# wait_for_pids pid [pid ...]
	#	spins until none of the pids exist
	#
	wait_for_pids()
	{
		_list=$*
		if [ -z "$_list" ]; then
			return
		fi
		_prefix=
		while true; do
			_nlist="";
			for _j in $_list; do
				if kill -0 $_j 2>/dev/null; then
					_nlist="${_nlist}${_nlist:+ }$_j"
				fi
			done
			if [ -z "$_nlist" ]; then
				break
			fi
			_list=$_nlist
			echo -n ${_prefix:-"Waiting for PIDS: "}$_list
			_prefix=", "
			sleep 2
		done
		if [ -n "$_prefix" ]; then
			echo "."
		fi
	}

	# On systems without an /etc/rc.conf the default action must
	# be to start the daemon....
	#
	if [ -f /etc/rc.conf ] ; then
		. /etc/rc.conf
		cmd=${1}
	else
		eval ${rcvar}="YES"

		# strictly maybe the rule should also be if $0 ends in ".sh"?
		#
		case ${1} in
		"")
			cmd="start"
			;;
		esac
	fi

	case ${cmd} in
	force*)
		cmd=${cmd#force}
		_rc_force_run=YES
		eval ${rcvar}="YES"
		;;
	esac

	eval _precmd=\$${cmd}_precmd

	case ${cmd} in
	start)
		if checkyesno ${rcvar}; then
			if [ -f ${pidfile} ] ; then
				read _pid _junk < ${pidfile}
				if kill -0 ${_pid}; then
					warn "${name} is already running as ${_pid}!"
					exit 0
				fi
			fi
			for _f in $required_files; do
				if [ ! -r "${_f}" ]; then
					warn "${_f} is not readable."
				fi
			done
			# if the precmd failed and force
			# isn't set, exit
			#
			if ! eval $_precmd && [ -z "$_rc_force_run" ]; then
				exit 1
			fi
			if [ -x ${command} ] ; then
				eval ${command} \${${name}_flags} && echo "${name} started."
			fi
		fi
		;;
	stop)
		if [ -f ${pidfile} ] ; then
			if ! eval $_precmd && [ -z "$_rc_force_run" ]; then
				return 1
			fi
			read _pid _junk < ${pidfile}
			kill -15 ${_pid} && echo "Stopping ${name}."
			wait_for_pids ${_pid}
			rm -f ${pidfile}
		elif checkyesno ${rcvar}; then
			warn " (${pidfile} does not exist; not stopping ${name})"
		fi
		;;
	status)
		if [ -f ${pidfile} ] ; then
			read _pid _junk < ${pidfile}
			# -p and -l are nearly universal these days....
			ps -p ${_pid} -l
		elif checkyesno ${rcvar}; then
			warn "${pidfile} does not exist."
		fi
		;;
	reload)
		if [ -f ${pidfile} ] ; then
			if ! eval $_precmd && [ -z "$_rc_force_run" ]; then
				return 1
			fi
			read _pid _junk < ${pidfile}
			kill -1 ${_pid}
		elif checkyesno ${rcvar}; then
			warn "${pidfile} does not exist; not reloading ${name}."
		fi
		;;
	restart)
		if ! eval $_precmd && [ -z "$_rc_force_run" ]; then
			exit 1
		fi
		# prevent restart being called more
		# than once by any given script
		#
		if [ -n "$_rc_restart_done" ]; then
			exit 0
		fi
		_rc_restart_done=YES
		( $0 ${_rc_force_run:+force}stop )
		$0 ${_rc_force_run:+force}start
		;;
	rcvar)
		echo "# $name"
		if [ -n "$rcvar" ]; then
			if checkyesno ${rcvar}; then
				echo "\$${rcvar}=YES"
			else
				echo "\$${rcvar}=NO"
			fi
		fi
		;;
	*)
		echo "Usage: $0 {start|stop|restart|status|reload}" 1>&2
		exit 64
		;;
	esac
fi

exit 0