#!/bin/csh -f

# hierarchical ps

# give this script a PID and it'll do a ps on that process and all its
# children.

# daw, 11/19/03

# enable this to run using a different tmp filesystem if /tmp is
# unusable (eg, no space or inodes)

# daw; 12/9/12

switch (`uname -s``uname -r`)
case SunOS5*:
    set TPLUS = "+"
	breaksw
case Linux[2-5]*:
    set TPLUS = "--lines=+"
	breaksw
default:
	exec echo ${0}: does not run on `uname -s` `uname -r`
endsw

unsetenv PID			# just in case
set LOG = "cat"

while($#argv)
	switch ("$1")
	case -d:
		set DEBUG
#		shift
#		breaksw
# fall through to verbose
	case -v:
		set VERBOSE
		shift
		breaksw
	case -nh:
		set NOHEADER
		shift
		breaksw
	case -i:
		set INDENT = "$2"
		shift ; shift
		breaksw
	case -f:
		set FILE = $2
		shift ; shift
		breaksw
	case -l:
#		set LOG = ( "tee" "-a" /tmp/`basename $0.``date +%y%m%d.%H%M%S` )
		set DOLOG
		shift
		breaksw
	case -t:
		set TMP = $2
		shift ; shift
		breaksw
	case -u:
		if (! $?UP) @ UP = 0
		@ UP++
		shift 
		breaksw
	default:
		if (! $?PID) then
		    set PID = $1
		    shift
		    breaksw
		else
		    if (! $?PID2) then
			set PID2 = $1
			shift
			breaksw
		    endif
		endif
		set DQ = '"'
		exec echo ${0}: "What do I do with $DQ$1$DQ?"
	endsw
end

if ($?DEBUG) then
    set DVSW = "-d"
else if ($?VERBOSE) then
    set DVSW = "-v"
else
    set DVSW
endif

if (! $?TMP) set TMP = /tmp
if ($?DOLOG) set LOG = ( "tee" "-a" $TMP/`basename $0.``date +%y%m%d.%H%M%S` )

if (! $?FILE) then
    if ($?VERBOSE) echo `date +%T` /bin/ps -eaf
#    set FILE = /tmp/`basename $0`.$$
    set FILE = $TMP/`basename $0`.$$
    /bin/ps -eaf > $FILE
    set RMFILE
endif
set INDENT

if (! $?PID) set PID = 1
    
# program name => PID code
echo $PID | grep -v "[0-9]" > /dev/null
if (! $status) then
#    set PID = `/bin/ps -eaf | grep "$PID" | egrep -v "$0 $PID|grep $PID" | awk '{print $2}'`
#echo \$PID = $PID
    set TARGET = "`echo $PID | sed 's;\(.\);\[\1\];'`"
#echo TARGET = "$TARGET"
#    set PID = `ps auxwww | grep "$TARGET" | tee $FILE.$$  | grep -vw $0 | awk '{print $2}'`
    set MASK = "`echo $0 | sed 's;.;\[&\];'`"
#    set PID = `ps auxwww | grep "$TARGET" | tee $FILE.$$  | grep -v "$MASK" | awk '{print $2}'`
    set PID = `grep "$TARGET" $FILE | tee $FILE.$$  | grep -v "$MASK" | awk '{print $2}'`
    if ($#PID > 1) then
	if ($?PID2) then
#	    set PID2 = `grep -w $PID2 $FILE.$$ | grep -v "$MASK" | awk '{print $2}'`
	    set PID2 = `awk '{if($2=='$PID2')print}' $FILE.$$ | awk '{print $2}'`
	    if ($#PID2 == 1) then
		set PID = $PID2
		goto gotpid
	    endif
	endif
	if ($#PID == 2) then
	    set PIDS = `grep "$TARGET" $FILE.$$  | grep -v "$MASK" | awk '{print $2,$3}'`
	    if ($?DEBUG) echo PIDS = $PIDS
	    if ($PIDS[1] == $PIDS[4]) then
		set PID = $PIDS[1]
		goto gotpid
	    endif
	    if ($PIDS[2] == $PIDS[3]) then
		set PID = $PIDS[2]
		goto gotpid
	    endif
	endif
echo PID = "$PID"
#	grep -vw $0 $FILE.$$
	grep -v "$MASK" $FILE.$$
	exec echo Which one\?
    else if ($#PID == 0) then
	exit
    endif
endif

gotpid:

# Look at parent of PID (more than one possible)
if ($?UP) then
    while ($UP)
#	set PID = `awk '{if ($2=='$PID')print $3}' $FILE`
# don't trip over PIDs that are not there.
	set NPID = `awk '{if ($2=="'$PID'")print $3}' $FILE`
	if ($NPID) set PID = $NPID
	@ UP--
    end
endif

if ($?VERBOSE) echo `date +%T` Printing PID and descendents
if ($?RMFILE && ! $?NOHEADER) head -1 $FILE | $LOG
awk '{if ($2=='$PID')print"'"$INDENT"'",$0}' $FILE | $LOG
# Too many words from ``; 6/3/07
goto skipold
if ($?DEBUG) then
    echo DEBUG: awk '{if ($3=='$PID')print $2}' $FILE
    awk '{if ($3=='$PID')print $2}' $FILE
endif
set CHILDREN = ( `awk '{if ($3=='$PID')print $2}' $FILE` )
if ($?DEBUG) then
    echo CHILDREN = $CHILDREN
endif
foreach CHILD ( $CHILDREN )
    $0 -f $FILE -i " $INDENT" $CHILD | $LOG
end
goto skipnew
skipold:
awk '{if ($3=='$PID')print $2}' $FILE > $FILE.$$
@ OFFSET = 1
@ NOPERLOOP = 10
set NOCHILDREN = `cat $FILE.$$ | wc -l`
while ($OFFSET <= $NOCHILDREN)
    if ($?DEBUG) echo OFFSET = $OFFSET\; NOPERLOOP = $NOPERLOOP\; NOCHILDREN = $NOCHILDREN
#    foreach CHILD ( `tail +$OFFSET $FILE.$$ | head -$NOPERLOOP` )
    foreach CHILD ( `tail $TPLUS$OFFSET $FILE.$$ | head -$NOPERLOOP` )
	# see if we need to recurse on this child
	@ NOGCHILDREN = `awk '{if ($3=='$CHILD')print $2}' $FILE | wc -l`
	if ($NOGCHILDREN) then
	    if ($?DEBUG) echo $0 $DVSW -f $FILE -i " $INDENT" $CHILD \| $LOG
#echo $0 $DVSW -f $FILE -i " $INDENT" $CHILD \| $LOG
	    $0 $DVSW -f $FILE -i " $INDENT" $CHILD | $LOG
	else
	    if ($?DEBUG) echo DEBUG awk '{if ($2=='$CHILD')print"'" $INDENT"'",$0}' $FILE \| $LOG
	    awk '{if ($2=='$CHILD')print"'" $INDENT"'",$0}' $FILE | $LOG
	endif
    end
    @ OFFSET += $NOPERLOOP
end
skipnew:

if ($?RMFILE) /bin/rm -f $FILE
/bin/rm -f $FILE.$$

if ($#LOG > 1) then
    echo ""
    echo "To see this again, "
    echo " " more $LOG[$#LOG]
endif
