
#!/bin/sh

# pvmcleanup

# Usage: pvmcleanup [-f filename | [-pvmhosts] host ...]

# Pvmcleanup kills pvm daemons and removes pvm's files from /tmp on each
# machine specified.
  
# Pvmcleanup looks first for command line arguments: -f expects a file
# specifying the hosts to clean up (a normal pvm hosts file will work).
# The arguments could also be the hosts to clean up on, optionally
# preceded by -pvmhosts.
  
# If there are no arguments to pvmcleanup it checks for a PVM_HOSTS
# variable (set by DQS 3). If that is not set, it checks for a JOB_NAME
# variable and $JOB_NAME.HOSTS file (set up by pre-3 DQS).

# This script depends on the user being able to rsh from the machine on
# which the job is started to every other host to be cleaned. It depends
# on the output format of the id command. And it depends on uname and a
# switch/if construct to use the right switches for th eps command on
# each machine (so far it understands IRIX, AIX, HP-UX, and SunOS).

# Variables:

#   hostfile - file of hosts to clean
#   hostlist - list of hosts to clean
#   host - loop variable, machine to clean up 
#   pids - loop variable, pvm dameon pids
#   ps_switches - ps command switches to use for getting pvm daemon pids
#   name - uname output for determining ps_switches
#   return_value - the pvmcleanup script's return value

usage()
{
  echo ''
  echo 'Usage: pvmcleanup [-f filename | [-pvmhosts] host ...]'

  echo ''
  echo 'Pvmcleanup looks first for command line arguments: -local means'
  echo 'only clean up on the machine where pvmcleanup is run, -f expects'
  echo 'a file specifying the hosts to clean up. A normal pvm hosts file'
  echo 'will work. The arguments could also be the hosts to clean up on,'
  echo 'optionally preceded by -pvmhosts.'

  echo ''
  echo 'If there are no arguments to pvmcleanup it checks for a PVM_HOSTS'
  echo 'variable (set by DQS 3). If that is not set, it checks for a'
  echo 'JOB_NAME variable and $JOB_NAME.HOSTS file (set up by pre-3 DQS).'
  echo ''

  exit $return_value
}

pvmgetarch()
{
#
# pvmgetarch.sh
#
# Generate PVM architecture string.
#
# This is a heuristic thing that may need to be tuned from time
# to time.  I don't know of a real solution to determining the
# machine type.
#
# Notes:
#   1. Local people mess with things.
#   2. It's good to try a few things for robustness.
#   3. Don't use test -x
#
# 08 Apr 1993  Robert Manchek  manchek@CS.UTK.EDU.
# 24 Aug 1994  last revision
# 28 Jul 1995  release 3.3.8
#

#
# begin section that may need to be tuned.
#
ARCH=UNKNOWN

#
# determine the machine type from scratch
#
if [ -f /bin/uname -o -f /usr/bin/uname ]; then
	if [ -f /bin/uname ]; then
		os="`/bin/uname -s`"
		ht="`/bin/uname -m`"
	else
		os="`/usr/bin/uname -s`"
		ht="`/usr/bin/uname -m`"
	fi

	case "$os,$ht" in
	SunOS,sun3* )           ARCH=SUN3 ;;
	SunOS,sun4* )           ARCH=SUN4 ;;
	SunOS,i86pc )           ARCH=X86SOL2 ;;
	ULTRIX,RISC )           ARCH=PMAX ;;
	ULTRIX,VAX )            ARCH=UVAX ;;
	AIX*,* )                ARCH=RS6K ;;
	*HP*,9000/[2345]* )     ARCH=HP300 ;;
	*HP*,9000/[78]* )       ARCH=HPPA ;;
	IRIX,* )                ARCH=SGI ;;
	*,alpha )               ARCH=ALPHA ;;
	CRSOS,smp )             ARCH=CRAYSMP ;;
	*,paragon )             ARCH=PGON ;;
	dgux,AViiON )           ARCH=DGAV ;;
	*,88k )                 ARCH=E88K ;;
	*,mips )                ARCH=MIPS ;;
	*,CRAY-2 )              ARCH=CRAY2 ;;
	Linux,i[345]86 )        ARCH=LINUX ;;
	BSD/OS,i[345]86 )       ARCH=BSD386 ;;
	FreeBSD,i386 )          ARCH=FREEBSD ;;
	SUPER-UX,SX-3 )         ARCH=SX3 ;;
	uts,* )                 ARCH=UTS2 ;;
	realix,M88* )           ARCH=M88K ;;
	DomainOS,DN* )          ARCH=APOLLO ;;
	esac
fi

if [ "$ARCH" = UNKNOWN ]; then
	if [ -f /bin/arch ]; then
		case "`/bin/arch`" in
		ksr1 ) ARCH=KSR1 ;;
		sun2 ) ARCH=SUN2 ;;
		sun3 ) ARCH=SUN3 ;;
		sun4 ) ARCH=SUN4 ;;
		esac
	fi
fi

if [ "$ARCH" = UNKNOWN ]; then

	if [ -f /usr/etc/RELDEF ]; then ARCH=ATT; fi

	if [ -f /ultrixboot ]; then
		if [ -f /pcs750.bin ]; then
			ARCH=UVAX
		else
			ARCH=PMAX
		fi
	else
		if [ -f /pcs750.bin ]; then ARCH=VAX; fi
	fi

	if [ -d /usr/alliant ]; then ARCH=AFX8; fi
	if [ -f /usr/bin/cluster ]; then ARCH=BFLY; fi
	if [ -d /usr/convex ]; then ARCH=CNVX; fi
	if [ -f /unicos ]; then ARCH=CRAY; fi
	if [ -f /hp-ux ]; then ARCH=HP300; fi
	if [ -f /usr/bin/getcube ]; then ARCH=I860; fi
	if [ -f /usr/bin/asm56000 ]; then ARCH=NEXT; fi
	if [ -f /etc/vg ]; then ARCH=RS6K; fi
	if [ -d /usr/include/caif ]; then ARCH=RT; fi
	if [ -f /bin/4d ]; then ARCH=SGI; fi
	if [ -f /dynix ]; then ARCH=SYMM; fi
	if [ -f /bin/titan ]; then ARCH=TITN; fi

	if [ -f /netbsd ]; then
		case "`/usr/bin/machine`" in
		i386)   ARCH=NETBSDI386 ;;
		amiga)  ARCH=NETBSDAMIGA ;;
		hp300)  ARCH=NETBSDHP300 ;;
		mac68k) ARCH=NETBSDMAC68K ;;
		pmax)   ARCH=NETBSDPMAX ;;
		sparc)  ARCH=NETBSDSPARC ;;
		sun3)   ARCH=NETBSDSUN3 ;;
		esac
	elif [ -f /usr/bin/machine ]; then
		case "`/usr/bin/machine`" in
		i386 ) ARCH=BSD386 ;;
		esac
	fi
	if [ -f /usr/bin/uxpm ] && /usr/bin/uxpm ; then
		ARCH=UXPM
	fi
fi

if [ "$ARCH" = UNKNOWN ]; then
	if [ -f /bin/uname -o -f /usr/bin/uname ]; then
		if [ -f /bin/uname ]; then
			os="`/bin/uname -s`"
			ht="`/bin/uname -m`"
		else
			os="`/usr/bin/uname -s`"
			ht="`/usr/bin/uname -m`"
		fi

		case "$os,$ht" in
		*,i[345]86 )            ARCH=SCO ;;
		esac
	fi
fi

#
# update the machine type to derive subclasses
#
if [ "$ARCH" = SUN4 ]; then
	rel="`/bin/uname -r`"
	case "$rel" in
	5.* )   ARCH=SUN4SOL2 ;;
	esac
fi
if [ "$ARCH" = SUN4SOL2 ]; then
	nproc="`/bin/mpstat | wc -l`"
	if [ $nproc -gt 2 ]; then ARCH=SUNMP; fi
fi
if [ "$ARCH" = ALPHA ]; then
	rel="`/usr/bin/uname -r`"
	case "$rel" in
	*3.*)
		nproc="`/usr/sbin/sizer -p`"
		if [ $nproc -gt 1 ]; then ARCH=ALPHAMP; fi ;;
	esac
fi
if [ "$ARCH" = SGI ]; then
	rel="`/bin/uname -r`"
	case "$rel" in
	5.* )   ARCH=SGI5 ;;
	6.* )   ARCH=SGI64 ;;
	esac
fi
if [ "$ARCH" = SGI64 ]; then
	nproc="`/usr/sbin/mpadmin -n | wc -w`"
	if [ $nproc -gt 1 -a "$SGIMP" = ON ]; then ARCH=SGIMP64; fi
fi
if [ "$ARCH" = SGI5 ]; then
	nproc="`/usr/sbin/mpadmin -n | wc -w`"
	if [ $nproc -gt 1 -a "$SGIMP" = ON ]; then ARCH=SGIMP; fi
fi
if [ "$ARCH" = SUN4 -a -f /dev/cm ]; then ARCH=CM2; fi
if [ "$ARCH" = SUN4 -a -f /dev/cmni ]; then ARCH=CM5; fi
if [ "$ARCH" = CNVX ]; then
	if /usr/convex/getsysinfo -f native_default; then
		ARCH=CNVXN
	fi
fi
if [ "$ARCH" = PMAX -a -d /usr/maspar ]; then ARCH=MASPAR; fi
if [ "$ARCH" = RS6K ]; then 
	nproc="`/usr/sbin/lsdev -C -c processor | wc -l`"
	if [ $nproc -gt 1 ]; then ARCH=RS6KMP; fi
fi
if [ "$ARCH" = HPPA -a -f /bin/sysinfo ]; then ARCH=CSPP; fi
if [ "$ARCH" = HPPA ]; then
	nproc="`/usr/bin/vmstat -n | wc -l`"
	if [ $nproc -gt 8 ]; then ARCH=HPPAMP; fi
fi

#
# ugh, done.
#

echo $ARCH

}	# End pvmgetarch() Function


hostlist=
hostfile=

if test "$#" -gt 0 ; then

# Process the command line arguments

  if test X"$1" = X"-usage" ; then
    return_value=0
    usage
  elif test X"$1" = X"-f" ; then
    if test "$#" -lt 2 ; then
      echo pvmcleanup: no file specified with -f
      return_value=1
      usage
    else
      hostfile="$2"
    fi
  elif test X"$1" = X"-pvmhosts" ; then
    hostlist=`echo $* | sed s/-pvmhosts//`
  else
    hostlist="$*"
  fi
elif test -n "$PVM_HOSTS" ; then

# Try the DQS 3 pvm hosts variable

  hostlist=`echo $PVM_HOSTS | sed s/-pvmhosts//`

elif test -n "$JOB_NAME" ; then

# Try the pre DQS 3 pvm hosts variable

  hostfile=${JOB_NAME}.HOSTS

else
  echo pvmcleanup: no host list or file specified
  return_value=1
  usage
fi

#
#  Determine local machine architecture, "LOCAL_ARCH".
LOCAL_ARCH="`pvmgetarch`"

#
#  Oh, to "awk" or to "nawk"?  That is the question.
AWK="/usr/bin/awk"
case "${LOCAL_ARCH}" in			# SUN4 has "nawk" bug where "END"
    SUN2|SUN3|SUN4|SunOS)  : ;;		# causes nawk to fail. Use awk.
    *)	if [ -s /usr/bin/nawk ] ; then
	    AWK="/usr/bin/nawk"
	fi ;;
esac

# Try to get hosts from a file

if test -n "$hostfile" ; then
  if test ! -r "$hostfile" ; then
    echo pvmcleanup: hostfile $hostfile does not exist
    return_value=1
    usage
  else
    hostlist=`cat $hostfile | ${AWK} '!/^\*|#/ {print $1}'`
  fi
fi

if test -z "$hostlist" ; then
  echo pvmcleanup: no hosts specified
  return_value=1
  usage
fi

#
#  Identify which Remote Shell Command to use for this specific system.
#  Using excerpts from "~/pvm3.3.11/lib/pvmgetarch".

case "${LOCAL_ARCH}" in		# ~/pvm3.3.11/conf/${LOCAL_ARCH}.def
	APOLLO)	RSH="/usr/bin/remsh" ;;
	ATT)	RSH="/usr/bin/remsh" ;;
	BSD386)	RSH="/usr/bin/rsh" ;;
	CRAY)	RSH="/usr/ucb/remsh" ;;
	CRAY2)	RSH="/usr/ucb/remsh" ;;
	CSPP)	RSH="/usr/bin/remsh" ;;
	DGAV)	RSH="/usr/ucb/remsh" ;;
	HP300)	RSH="/usr/bin/remsh" ;;
	HPPA)	RSH="/usr/bin/remsh" ;;
	I860)	RSH="/usr/ucb/rcmd" ;;
	I860I860)	RSH="/usr/ucb/rcmd" ;;
	I860SGI)	RSH="/usr/bsd/rsh" ;;
	IPSC2)	RSH="/usr/ucb/rcmd" ;;
	LINUX)	RSH="/usr/bin/rsh" ;;
	NETBSDAMIGA)	RSH="/usr/bin/rsh" ;;
	NETBSDHP300)	RSH="/usr/bin/rsh" ;;
	NETBSDI386)	RSH="/usr/bin/rsh" ;;
	NETBSDMAC68K)	RSH="/usr/bin/rsh" ;;
	NETBSDPMAX)	RSH="/usr/bin/rsh" ;;
	NETBSDSPARC)	RSH="/usr/bin/rsh" ;;
	NETBSDSUN3)	RSH="/usr/bin/rsh" ;;
	RS6K)	RSH="/usr/bin/rsh" ;;
	RS6KMP)	RSH="/usr/bin/rsh" ;;
	SCO)	RSH="/usr/bin/rcmd" ;;
	SGI)	RSH="/usr/bsd/rsh" ;;
	SGI5)	RSH="/usr/bsd/rsh" ;;
	SGI64)	RSH="/usr/bsd/rsh" ;;
	SGIMP)	RSH="/usr/bsd/rsh" ;;
	SGIMP64)	RSH="/usr/bsd/rsh" ;;
	SP2MPI)	RSH="/usr/bin/rsh" ;;
	SUN4SOL2)	RSH="/usr/bin/rsh" ;;
	SUNMP)	RSH="/usr/bin/rsh" ;;
	UXPM)	RSH="/usr/bin/rsh" ;;
	X86SOL2)	RSH="/usr/bin/rsh" ;;
	*)	RSH="/usr/ucb/rsh" ;;
esac	# pvmgetarch

# Rsh to each host and clean up

for host in $hostlist 
do

# Figure out ps_switches

  name=`$RSH $host uname -a`

  case "`echo $name | ${AWK} '{print $1}'`" in

    IRIX)  ps_switches="-aef";;
    AIX)   ps_switches="-aef";;
    HP-UX) ps_switches="-aef";;

    SunOS)
      case "`echo $name | ${AWK} '{print $3}'`" in
        5*) ps_switches="-aef";;
        *) ps_switches="-auxw";;
      esac ;;
    *)	   ps_switches="-aef" ;;
  esac

#
#  Extract the user's UID, Username and pvmd PID from remote target host
#  Need to perform in 2 segments, to keep it simple.
  RMT_STUFF="`(${RSH} ${host} id) | ${AWK} \
	'BEGIN { UID = "UNKNOWN"; USER_NAME = "UNKNOWN" }
	{ start = index($1, "\=")+1 	# rec contains results of "id" command.
	  end = index($1, "\(" )	# uid=xxxx(user_id) gid=xxx(group_name)
	  end2 = index($1, "\)" )
	  UID = substr($1, start, end-start )
	  USER_NAME = substr($1, end+1, end2-end-1 )
	} END { printf ("%s\;%s\;", UID, USER_NAME) }' `"
  RMT_UID="`(echo ${RMT_STUFF}) | ${AWK} 'BEGIN { FS = "\;" } {print $1}'`"
  RMT_USER="`(echo ${RMT_STUFF}) | ${AWK} 'BEGIN { FS = "\;" } {print $2}'`"

  PVMD_PID="`(${RSH} ${host} /bin/ps ${ps_switches}) | ${AWK} \
	'BEGIN { PID = "" }
	  { if ( $1 ~ /^'${RMT_USER}'$/ && /pvmd/ )	# output of ps.
	      { PID = PID $2\" \" }			# any lines w/ "pvmd"
	  } END { print PID }' `"

  case "${PVMD_PID}" in
    '') ;;			# Non-existent "pvmd" process
     *)	${RSH} ${host} "kill -9 ${PVMD_PID}";
	${RSH} ${host} "\rm -r /tmp/pvm[dlu].${RMT_UID} /tmp/pvmd.${RMT_USER}"
	;;
  esac				# Check for non-empty "PVMD_PID" string

done

