#!/sbin/sh
#
# Copyright (c) 1997,1998,1999 by Sun Microsystems, Inc.
# All Rights Reserved
#
# @(#)proxy	3.8 04/18/00 Sun Microsystems
#
# The start-up file for all SunScreen proxies

# maximum amount of time to wait for a change to 'inetd' listeners to take
# effect before going on or aborting
INWAIT=30

read SUNSCREEN_BASE <${SUNSCREEN_ETC:-/etc/opt/SUNWicg/SunScreen}/location
. $SUNSCREEN_BASE/bin/.ssenv.profile

PATH=/usr/bin:/bin
ADIR=$ETC_DIR/.active
PDIR=$SUNSCREEN_BASE/proxies
JAVALIBDIR=/usr/java/lib

# commands used
CHMOD=/usr/bin/chmod
CP=/usr/bin/cp
GREP=/usr/bin/grep
EXPR=/usr/bin/expr
MV=/usr/bin/mv
NETSTAT=/usr/bin/netstat
PS=/usr/bin/ps
RM=/usr/bin/rm
SED=/usr/bin/sed
SLEEP=/usr/bin/sleep
SS_SECURID=$LIB_DIR/ss_securid
TR=/usr/bin/tr
# pseudo-command: allows debugging
RUN=
#"echo NO-RUN"

# this is what '$PS -e' sees for some things:
SS_SECUR=ss_secur

# N.B.: /etc/inetd.conf is a symlink to /etc/inet/inetd.conf
IND=/etc/inet
INETD=inetd
INCFG=$IND/$INETD.conf
# N.B.: /etc/rc2.d/S88sendmail is hard-linked to /etc/init.d/sendmail
# and some number of other "/etc/rc?.d" things
SMD=/etc/rc2.d
SMRC=$SMD/S88sendmail

NEW=.$$.ssproxytmp

# port numbers and service names
FTP=21
FTPN=ftp
HTTP=80
SMTP=25
TELNET=23
TELNETN=telnet

VSN=
	# sendmail interface change w/ Solaris 8
VSNSM=0	
	# Java lib/ & JRE interface change w/ Solaris 8
VSNJX=0

PROXY=`$LIB_DIR/strs 1 1675 "proxy"`
STARTING=`$LIB_DIR/strs 1 1960 "starting"`

copyit () {
	trap "" 1 2 3 15	# ignore signals
	(umask 0; $CP -f $1 $2)
	$RM -f $1
	trap 1 2 3 15		# revive signals
}

moveit () {
	trap "" 1 2 3 15	# ignore signals
	$MV -f $1 $2
	trap 1 2 3 15		# revive signals
}

# version/platform-specific hacks
uvsn () {
	VSN=`uname -r`
	PLT=`uname -p`
	[ `expr $VSN : '5\.[8]'` -ne 0 ] && VSNSM=1
	[ $VSNSM -eq 1 ] && VSNJX=1
}

# check for a particular service as being active ('in') or commented out
# EFS-style ('out')
# $1 == service name (per 'inetd.conf')
in_chk () {
	ININ=0 INEFS=0
	if [ -x $INCFG ] ; then
		S=`$LIB_DIR/strs 1 1320 "missing file"`
		echo "$S '$INCFG'" 1>&2
		exit
	fi
	INCi=`$GREP -c "^$1[ 	]" <$INCFG`
	INCo=`$GREP -c "^#efs#$1[ 	]" <$INCFG`
	INC=`$EXPR $INCi + $INCo`
	if [ $INC -ne 1 ] ; then
		S=`$LIB_DIR/strs 1 1322 "missing inetd service entry"`
		echo "$S: '$1'" 1>&2
		exit
	fi
	if [ $INCi -ne 0 ] ; then
		ININ=1
	else
		INEFS=1
	fi
}

# put the named service back 'in' (running as per normal Solaris)
# $1 == service name (per 'inetd.conf')
in_in () {
	(umask 0; $CP -f $INCFG $IND/$NEW)
	$CHMOD u+w $IND/$NEW
	$SED <$INCFG >$IND/$NEW -e 's=^#efs#\('$1'[ 	].*\)=\1='
	if [ $? -ne 0 -o ! -s $IND/$NEW ] ; then
		S=`$LIB_DIR/strs 1 920 \
		  "inetd edit (in) failed for service entry"`
		echo "$S: '$1'" 1>&2
		$RM -f $IND/$NEW
	else
		copyit $IND/$NEW $INCFG
	fi
}

# comment the named service 'out' EFS-style
# $1 == service name (per 'inetd.conf')
in_out () {
	(umask 0; $CP -f $INCFG $IND/$NEW)
	$CHMOD u+w $IND/$NEW
	$SED <$INCFG >$IND/$NEW -e 's=^'$1'[ 	].*=#efs#&='
	if [ $? -ne 0 -o ! -s $IND/$NEW ] ; then
		S=`$LIB_DIR/strs 1 922 \
		  "inetd edit (out) failed for service entry"`
		echo "$S: '$1'" 1>&2
		$RM -f $IND/$NEW
	else
		copyit $IND/$NEW $INCFG
	fi
}

# pop 'inetd' with SIGHUP, causing it to reparse and update listeners
in_reparse () {
	PID=`$PS -e | $GREP $INETD | $SED -e 's/^  *//' -e 's/ .*//'`
	[ "$PID" ] && $RUN kill -HUP $PID
}

# check for sendmail running as an active daemon ('in') or commented 'out'
# EFS-style (which is still: running queues but not listening for inbound
# SMTP on port 25)
sendmail_chk () {
	SMIN=0 SMEFS=0
	if [ ! -x $SMRC ] ; then
		S=`$LIB_DIR/strs 1 1320 "missing file"`
		echo "$S '$SMRC'" 1>&2
		exit
	fi
	case $VSNSM in
	1)
		SMPAT='[^#]*MODE=\".*-bd'
		SMINPAT='[^#]*MODE=[^#]*-bd'
		SMOUTPAT='[^#]*MODE=.*# efs{-bd}'
		;;
	*)
		SMPAT='[^#]*sendmail[	 ].*-bd'
		SMINPAT='[^#]*sendmail [^#]*-bd'
		SMOUTPAT='[^#]*sendmail .* #efs{-bd}'
		;;
	esac
	SMC=`$GREP -c "$SMPAT" <$SMRC`
	if [ $SMC -ne 1 ] ; then
		S=`$LIB_DIR/strs 1 1324 "missing sendmail daemon entry in"`
		echo "$S '$SMRC'" 1>&2
		exit
	fi
	SMLN=`$GREP "$SMPAT" <$SMRC | $TR ' 	' '  '`
	SMIN=`expr "$SMLN" : "$SMINPAT"`
	if [ $SMIN -eq 0 ] ; then
		SMEFS=`expr "$SMLN" : "$SMOUTPAT"`
		if [ $SMEFS -eq 0 ] ; then
			S=`$LIB_DIR/strs 1 2156 \
			  "unexpected sendmail daemon entry"`
			echo "$S: '$SMLN'" 1>&2
		fi
	fi
}

# put sendmail back 'in' as a daemon (running as per normal Solaris)
sendmail_in () {
	$RUN $SMRC stop
	(umask 0; $CP -f $SMRC $SMD/$NEW)
	$CHMOD u+w $SMD/$NEW
	case $VSNSM in
	1)
		SMPAT='s=\([^#]*MODE\="\)\(.*\)# efs{-bd}\(.*\)=\1-bd\2\3='
		;;
	*)
		SMPAT='s=\([^#]*sendmail\)\(.*\) #efs{-bd}\(.*\)=\1 -bd\2\3='
		;;
	esac
	$SED <$SMRC >$SMD/$NEW -e "$SMPAT"
	if [ $? -ne 0 -o ! -s $SMD/$NEW ] ; then
		S=`$LIB_DIR/strs 1 1930 "sendmail daemon edit (in) failed"`
		echo "$S" 1>&2
		$RM -f $SMD/$NEW
	else
		copyit $SMD/$NEW $SMRC
	fi
	$RUN $SMRC start
}

# comment sendmail 'out' of daemon mode, EFS-style
sendmail_out () {
	$RUN $SMRC stop
	(umask 0; $CP -f $SMRC $SMD/$NEW)
	$CHMOD u+w $SMD/$NEW
	case $VSNSM in
	1)
		SMPAT='s=\([^#]*MODE\=.*\)-bd\(.*\)=\1\2# efs{-bd}='
		;;
	*)
		SMPAT='s=\([^#]*sendmail.*\)[ 	]-bd\(.*\)=\1\2 #efs{-bd}='
		;;
	esac
	$SED <$SMRC >$SMD/$NEW -e "$SMPAT"
	if [ $? -ne 0 -o ! -s $SMD/$NEW ] ; then
		S=`$LIB_DIR/strs 1 1932 "sendmail daemon edit (out) failed"`
		echo "$S" 1>&2
		$RM -f $SMD/$NEW
	else
		copyit $SMD/$NEW $SMRC
	fi
	$RUN $SMRC start
}

tcp_listener () {
	if [ ! -x $NETSTAT ] ; then
		TLISTEN=-1
	else
		TLISTEN=`$NETSTAT -an | $TR ' 	' '  ' \
		  | $GREP -c " *\*\.$1 .* LISTEN *"`
	fi
}

# finalize prestart, by bouncing 'inetd' if needed
prefinal () {
  if [ $BOUNCEPORT -ne 0 ] ; then
    in_reparse
    I=$INWAIT
    while [ $I -gt 0 ] ; do
      tcp_listener $BOUNCEPORT
      if [ $TLISTEN -eq $BOUNCELISTEN -o $TLISTEN -eq -1 ] ; then
	TLISTEN=$BOUNCELISTEN
	I=0
      else
	$SLEEP 1
	I=`$EXPR $I - 1`
      fi
    done
    if [ $TLISTEN -ne $BOUNCELISTEN ] ; then
      S=`$LIB_DIR/strs 1 924 "inet failed to reconfigure"`
      echo "$S" 1>&2
    fi
    BOUNCEPORT=0
  fi
}

# prepare for configured proxies to start; this was done here rather
# than in the 'start' proc below because we want to avoid bouncing
# 'inetd' more than once
prestart () {
  if [ -s $ADIR/$1.conf ] ; then
    case $1 in
    httpp)
      # all we can do is complain if there's a listener
      tcp_listener $HTTP
      if [ $TLISTEN -eq 1 ] ; then
	S=`$LIB_DIR/strs 1 870 "HTTP server already exists"`
	echo "$S" 1>&2
      fi
      ;;
    ftpp)
      # if 'inetd's in there, take it out
      in_chk $FTPN
      if [ $ININ -eq 1 ] ; then
	in_out $FTPN
	BOUNCEPORT=$FTP
	BOUNCELISTEN=0
      fi
      ;;
    telnetp)
      # if 'inetd's in there, take it out
      in_chk $TELNETN
      if [ $ININ -eq 1 ] ; then
	in_out $TELNETN
	BOUNCEPORT=$TELNET
	BOUNCELISTEN=0
      fi
      ;;
    smtpp)
      # if 'sendmail's in there, take it out
      sendmail_chk
      if [ $SMIN -ne 0 ] ; then
	sendmail_out
	tcp_listener $SMTP
	if [ $TLISTEN -eq 1 ] ; then
	    S=`$LIB_DIR/strs 1 1936 "sendmail daemon still running"`
	    echo "$S '$SMRC'" 1>&2
	fi
      fi
      ;;
    esac
  fi
}

start () {
  if [ -f $PDIR/$1 -a -s $ADIR/$1.conf ] ; then
    echo "$STARTING $1 $PROXY."
    # check for http proxy
    if [ "$1" = httpp ] ; then
	LD_LIBRARY_PATH="$JAVALIBDIR:$LD_LIBRARY_PATH" $PDIR/$1 &
    else 
	$PDIR/$1 &
    fi
  fi
}

stop () {
  pid=`$PS -e | $GREP $1 | $SED -e 's/^  *//' -e 's/ .*//'`
  [ "$pid" ] && kill -TERM $pid

  # deal with restoring prior (standard Solaris) service entry;
  # because this looks at the current state of the .conf file, it
  # avoids putting the prior service back, then turning right around
  # and taking them back out (which would create a small but succulent
  # security hole)
  if [ ! -s $ADIR/$1.conf ] ; then
    case $1 in
    httpp)
	# there shouldn't have been a prior listener; in any case, we
	# can't do anything about one anyway
	;;
    ftpp)
	# if this was commented out, put it back to stock
	in_chk $FTPN
	if [ $INEFS -eq 1 ] ; then
		in_in $FTPN
		BOUNCEPORT=$FTP
		BOUNCELISTEN=1
	fi
	;;
    telnetp)
	# if this was commented out, put it back to stock
	in_chk $TELNETN
	if [ $INEFS -eq 1 ] ; then
		in_in $TELNETN
		BOUNCEPORT=$TELNET
		BOUNCELISTEN=1
	fi
	;;
    smtpp)
	# if this was commented out, put it back to stock
	sendmail_chk
	if [ $SMEFS -ne 0 ] ; then
	  sendmail_in
	  tcp_listener $SMTP
	  if [ $TLISTEN -eq 0 ] ; then
	    S=`$LIB_DIR/strs 1 1934 "sendmail daemon failed to run"`
	    echo "$S '$SMRC'" 1>&2
	  fi
	fi
	;;
    esac
  fi
}

start_sid () {
    pid=`$PS -e | $GREP $SS_SECUR | $SED -e 's/^  *//' -e 's/ .*//'`
    if [ -z "$pid" -a -r /etc/sdace.txt -a -x $SS_SECURID ] ; then
      echo "$STARTING SecurID PIN daemon."
      $SS_SECURID -p 3855 &
    fi
}

uvsn
[ $VSNJX -eq 1 -a \( ! -d $JAVALIBDIR -o ! -x $JAVALIBDIR/libjava.so \) ] \
  && JAVALIBDIR=/usr/java/jre/lib/$PLT

# stop and start procs tell us if we need to bounce 'inetd' and if so,
# what we can listen for to see if it worked
BOUNCEPORT=0

case $1 in
'start')
    for proxy in httpp telnetp smtpp ftpp ; do
      prestart $proxy
    done
    prefinal
    for proxy in httpp telnetp smtpp ftpp ; do
      start $proxy
    done
    start_sid
    ;;

'stop')
    for proxy in httpp telnetp smtpp ftpp ; do
      stop $proxy
    done
    prefinal

    pid=`$PS -e | $GREP $SS_SECUR | $SED -e 's/^  *//' -e 's/ .*//'`
    [ "$pid" ] && kill $pid
    ;;

## msd: restarting proxies doesn't work 
##'reconfig')
##    restart httpp
##
##    for proxy in telnetp smtpp ftpp ; do
##      pid=`$PS -e | $GREP $proxy | $SED -e 's/^  *//' -e 's/ .*//'`
##      if [ "$pid" ] ; then
##        if [ -s $ADIR/$proxy.conf ] ; then
##	  kill -HUP $pid
##	else
##	  kill -9 $pid
##	fi
##     else
##       start $proxy
##     fi
##    done
##    ;;

'restart')
    for proxy in httpp telnetp smtpp ftpp ; do
      stop $proxy
      prestart $proxy
    done
    prefinal
    for proxy in httpp telnetp smtpp ftpp ; do
      start $proxy
    done
    start_sid
    ;;    

*)
    U=`$LIB_DIR/strs 1 2180 "usage"`
    echo "$U: /etc/init.d/proxy {start|stop|restart|reconfig}" 1>&2
    exit 1
    ;;
esac

exit 0

# eof
