Subject: Re: OPSYS specific MESSAGEs
To: Jeremy C. Reed <reed@reedmedia.net>
From: Greg A. Woods <woods@weird.com>
List: tech-pkg
Date: 03/27/2003 11:15:58
--/vkwb553kg
Content-Type: text/plain; charset=us-ascii
Content-Description: message body and .signature
Content-Transfer-Encoding: 7bit

[ On Wednesday, March 26, 2003 at 18:09:02 (-0800), Jeremy C. Reed wrote: ]
> Subject: Re: OPSYS specific MESSAGEs
>
> p.s. By the way, I have noticed that some rc scripts work a little without
> the rc.subr or rc.conf (because they check if the files exist).

Speaking of that you might be interested in the complete and portable
template RC script I use.  The one for Smail-3 is attached....

-- 
								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>



--/vkwb553kg
Content-Type: text/plain
Content-Description: rc.d template script
Content-Disposition: inline;
	filename="init.sh"
Content-Transfer-Encoding: 7bit

#! /bin/sh
#
#	init.sh - a sample init control script for smail
#
#ident "@(#)smail/util:$Name:  $:$Id: init.sh,v 1.8 2003/02/27 20:03:58 woods Exp $"

# PROVIDE: mail
# REQUIRE: LOGIN
# KEYWORD: shutdown

# This script is designed primarily for the NetBSD system startup
# scripts (/etc/rc et al), but has basic compatability to work on other
# systems (including older NetBSD systems) with no additional outside
# support functionality.
# 
# It is easily tailored to support any basic daemon which writes its
# PID to a file specified by $pidfile.
#
#	The following globals are used to tailor it:
#
#	name		needed	function
#	----		------	--------
#	name		y	Name of script.
#
#	command		n	Full path to command.
#				Not needed if ${arg}_cmd is set for
#				each keyword.
#
#	command_args	n	Optional parameters for command
#				(used after ${name}_flags).
#
#	extra_commands	n	List of extra commands supported.
#
#	pidfile		n	If set, use check_pidfile $pidfile, else if
#				$command is set, use check_process $command.
#
#	rcvar		n	This is checked with checkyesno to determine
#				if the action should be run.
#
#	sig_reload	n	signal to send for the "reload" command. (def=1)
#
#	sig_stop	n	signal to send for the "stop" command. (def=15)
#
#	${name}_chdir	n	Directory to cd to before running ${command}
#
#	${name}_flags	n	Arguments to call ${command} with.
#
#				NOTE:	$flags from the environment
#					can be used to override this.
#
#	${_arg}_cmd	n	If set, use this as the action when invoked;
#				$_arg is available for the action to use.
#				Otherwise, use default command (see below)
#
#	${_arg}_precmd	n	If set, run just before performing the main
#				action in the default command (i.e, after
#				checking for required bits and process
#				(non)existance).
#
#				If this completes with a non-zero exit code,
#				don't run ${_arg}_cmd.
#
#	required_dirs	n	If set, check for the existence of the given
#				directories before running the default
#				(re)start command.
#
#	required_files	n	If set, check for the readability of the given
#				files before running the default (re)start
#				command.
#
#	required_vars	n	If set, perform checkyesno on each of the
#				listed variables before running the default
#				(re)start command.

#### start of local configuration section ####

command="X_SMAIL_NAME_X"
conf_file="X_LIB_DIR_X/config"
aliases_file="X_ALIASES_FILE_X"
forcepaths_file="X_PATH_FORCE_PATHS_FILE_X"
forcesmtp_file="X_PATH_FORCE_SMTP_FILE_X"
paths_file="X_PATH_PATHS_FILE_X"
rewrite_file="X_PATH_REWRITE_FILE_X"
pidfile="X_DAEMON_PIDFILE_X"

#### end of local configuration section ####

#### start of package-specific section ####

name="smail"
rcvar="smail"
smail_flags="-bd -q15m"		# default settings -- override in /etc/rc.conf
#required_files="${conf_file} ${aliases_file} ${forcepaths_file} ${forcesmtp_file} ${paths_file} ${rewrite_file}"
required_files="${aliases_file} ${rewrite_file}"
sig_reload="1"

#### end of package-specific section -- the rest is 100% generic ####

# 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

	# some older versions need this enabled...
	#
	extra_commands="${extra_commands} reload"

	# 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

	# don't override any warn function already provided in /etc/rc.subr
	#
	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 checkyesno)" : '.* 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
	}

	_arg=${1}

	# 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
	else
		eval ${rcvar}="YES"

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

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

	if [ -n "${rcvar}" -a "${_arg}" != "rcvar" -a "${_arg}" != "status" ]; then
		if ! checkyesno ${rcvar}; then
			exit 0
		fi
	fi

	# eval $foo when $foo is unset returns true so we can blindly
	# "eval $_precmd" and check for failures without having to set
	# it to true...
	#
	eval _precmd=\$${cmd}_precmd
	eval _cmd=\$${_arg}_cmd

	# handle custom FOO_cmd setting...
	#
	if [ -n "$_cmd" ]; then
		if ! eval $_precmd && [ -z "$_rc_force_run" ]; then
			exit 1
		fi
		eval $_cmd
		exit 0
	fi

	if [ -n "$flags" ]; then	# allow override from environment $flags
		_flags=$flags
	else
		eval _flags=\$${name}_flags
	fi

	eval _chdir=\$${name}_chdir

	case ${_arg} in
	start)
		if [ ! -x $command ]; then
			exit 0
		fi
		if [ -s ${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_vars; do
			if ! checkyesno $_f; then
				warn "\$${_f} is not set."
				if [ -z "$_rc_force_run" ]; then
					exit 1
				fi
			fi
		done
		for _f in $required_dirs; do
			if [ ! -d "${_f}/." ]; then
				warn "${_f} is not a directory."
				if [ -z "$_rc_force_run" ]; then
					exit 1
				fi
			fi
		done
		for _f in $required_files; do
			if [ ! -r "${_f}" ]; then
				warn "${_f} is not readable."
				if [ -z "$_rc_force_run" ]; then
					exit 1
				fi
			fi
		done
		#
		# run the precmd and if it fails, and force, isn't
		# set, then error out
		#
		if ! eval $_precmd && [ -z "$_rc_force_run" ]; then
			exit 1
		fi
		if [ -n "$_chdir" ] ; then
			cd $_chdir
		fi
		eval ${command} \${${name}_flags} ${command_args} && eval echo "${name} started using '${command} ${command_args} \${${name}_flags}'."
		;;
	stop)
		if [ -s ${pidfile} ] ; then
			if ! eval $_precmd && [ -z "$_rc_force_run" ]; then
				exit 1
			fi
			read _pid _junk < ${pidfile}
			kill -${sig_stop:-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 [ -s ${pidfile} ] ; then
			if ! eval $_precmd && [ -z "$_rc_force_run" ]; then
				exit 1
			fi
			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 [ -s ${pidfile} ] ; then
			if ! eval $_precmd && [ -z "$_rc_force_run" ]; then
				exit 1
			fi
			read _pid _junk < ${pidfile}
			kill -${sig_reload:-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|rcvar}" 1>&2
		exit 1
		;;
	esac
fi

exit 0

--/vkwb553kg--