#!/pkg/bin/ksh
#
# Take a pidin snapshot and store it in the sysmgr_debug directory
# If we have 10 or more snaps, delete all but the 5 oldest and 4 newest snaps.
#
# August 2003, Tim LaBerge 
# 
#  Copyright (c) 2003-2014 by cisco Systems, Inc.
#  All rights reserved.

usage=" [-C console_node] [-p pid_to_trace] [-D debug_cmd] [-r reason] [-b pid_list] [-a proc_name]pid_of_caller calling_process calling_function line_number"

# Move forward in the argument list
shift $(($OPTIND - 1))


# Cope with slight differences in shell syntax
setarray ()
{
    local _varname
    _varname="$1"
    shift

    if [ -n "$BASH_VERSION" ]; then
        # Set the variable as an array using bash syntax.  The "eval"
        # here is not actually need for bash, but it hides the ()
        # syntax from ksh which otherwise gets confused.
        eval "$_varname=("'"$@")'
    else
        # Set the variable as an array using ksh syntax. Again, the
        # "eval" isn't needed for ksh, but hides the ksh syntax from
        # bash.
        eval "set -A $_varname "'"$@"'
    fi
}

unset CONSOLE_NODE
unset pid
unset debug_cmd
unset reason
unset pid_array
unset proc_array
unset debug_array
unset array_size 
pid_array=0
debug_array_elems=0
unset calling_process
unset node_name
num_of_elems=$#
pid_array_set=0
while getopts C:p:D:r:P:b:a:n:f:x:c:l:k:d: g 
do
    case $g in
    C) CONSOLE_NODE=$OPTARG;;
    p) pid=$OPTARG;;
    D) debug_cmd=$OPTARG;;
    r) reason=$OPTARG;;
    b) pid_array_set=1;;
    a) proc_array=$OPTARG;;
    f) function=$OPTARG;;
    x) line=$OPTARG;;
    n) node_name=$OPTARG;;
    c) caller_pid=$OPTARG;;
    l) current_level=$OPTARG;;
    k) sysmgr_dlrsc_nodeid=$OPTARG;;
    d) calling_process=$OPTARG;;
    *) echo "Usage: $0 $usage" >&2; exit 1;;
    esac
done
#((num_of_elems=num_of_elems+1))
if [[ -z $4 && -z $pid_array_set ]]
then
    echo "Usage: $0 $usage" >&2
    exit 1
fi

DEBUG_DIR=/var/log/sysmgr_debug
#if [ -n "$CONSOLE_NODE" ]; then
#BOOTDEV=`/pkg/sbin/getappmedia -C $CONSOLE_NODE showtech`
#else
#BOOTDEV=`/pkg/sbin/getappmedia showtech`
#fi

# "/net" and harddisk is not supproted yet.
#if [ -z $sysmgr_dlrsc_nodeid ]
#then
#HARDDISKDEV=harddisk:
#else
#HARDDISKDEV=/net/sysmgr_dlrsc_nodeid/harddisk:
#fi

for device in $HARDDISKDEV $BOOTDEV bootflash: 
do

    if [ -e $device ]; then
        SHUTDOWN_DEV=$device; break;
    fi
done

if [ -z $SHUTDOWN_DEV ]; then
#    echo "Logging device is not available; exiting..." >&2; exit 1
    echo "Logging device is not available; setting to /var/log/..." >&2; 
    SHUTDOWN_DEV=/var/log
fi

DEBUG_DIR=$SHUTDOWN_DEV/sysmgr_debug

if [ ! -d $DEBUG_DIR ]; then
    mkdir $DEBUG_DIR
    if [ $? -ne 0 ]; then
        exit 1
    fi
fi


if [[ -n "$5" && -z $pid_array_set ]]
then
    echo "Usage: $0 $usage" >&2
    exit 1
fi

if [[ $pid_array_set -eq 0 ]]
then
    shift $(($OPTIND - 1))
    calling_pid=$1
    calling_process=$2
    function=$3
    line=$4
else
    j=0
    while [[ $num_of_elems -gt 1 ]]
    do
        if [[ $1 = -n ]]
        then
           shift
           node_name=$1
           ((num_of_elems=num_of_elems-2))
           shift
           continue
        fi
        if [[ $1 = -c ]]
        then
            shift
            calling_pid=$1
            ((num_of_elems=num_of_elems-2))
            shift
            continue
        fi
        if [[ $1 = -d ]]
        then
            shift 2
            ((num_of_elems=num_of_elems-2))
            continue
        fi
        if [[ $1 = -p ]]
        then
            shift 2
            ((num_of_elems=num_of_elems-2))
            continue
        fi
        if [[ $1 = -k ]]
        then
            shift 2
            ((num_of_elems=num_of_elems-2))
            continue
        fi
        if [[ $1 = -f ]]
        then
            shift 2
            ((num_of_elems=num_of_elems-2))
            continue
        fi
        if [[ $1 = -x ]]
        then
            shift 2
            ((num_of_elems=num_of_elems-2))
            continue
        fi
        if [[ $1 = -b ]]
        then
            shift
            ((num_of_elems=num_of_elems-1))
            continue
        fi
        if [[ $1 = -D ]] 
        then
           shift
           debug_array[$debug_array_elems]=$1
           ((debug_array_elems=debug_array_elems+1))
           ((num_of_elems=num_of_elems-2))
           shift
           continue
        fi
        if [[ $1 = -l ]]
        then
            shift
            current_level=$1
            ((num_of_elems=num_of_elems-2))
            shift
            continue
        fi
        if [[ $1 = -r ]]
        then
            shift
            reason=$1
            ((num_of_elems=num_of_elems-2))
            shift
            continue
        fi
    pid_array[$j]=$1
    shift
    ((j+=1))
    ((num_of_elems-=1))
    done
    pid_array[$j]=$1
    array_size=${#pid_array[*]}
    ((array_size-=1))
fi

DEBUG_FILE="$DEBUG_DIR/debug.$node_name.$$.log"

# Define an array of debug files, sorted in time increasing order
setarray debug_files `ls -tr $DEBUG_DIR/debug.* 2>/dev/null`

# 'i' is the index of the last array element
i=${#debug_files[*]} 

# If 10 or more files in the directory...
if [ $i -ge 200 ]
then
    # Keep the 5 oldest and 4 newest
    k=$(($i-50))
    j=150
    while [ $j -lt $k ]
    do
        rm ${debug_files[$j]} 2>/dev/null
	j=$(($j+1))
    done
fi

if [ -z "$reason" ]; then
    sysmgr_log "$0 invoked by ($calling_process) for pid ($pid). Output is in $DEBUG_FILE"
else
    if [ -z "$current_level" ]; then
        sysmgr_log "$0 invoked for : $reason  Output is in $DEBUG_FILE"
    else
        sysmgr_log "$0 invoked for: $reason and for level:$current_level . Output is in $DEBUG_FILE"
    fi
fi
num_of_elems=${#pid_array[*]}
((num_of_elems=num_of_elems-1))
# Generate the snap
(
echo "Script invoked at `date`"

if [ ! -z "$reason" ]; then
echo "Problem detected, Reason: $reason"
fi
echo "$0 invoked by ($calling_process) for level :$current_level
 `date`." 

# If we have a pid_array, get the attach_process output of each process
i=0
while [[ $i -lt $num_of_elems ]]
do
   echo "------------------------------------------------------------"
    echo "Output of: attach_process -A -p ${pid_array[$i]} -i 1"
    attach_process -A -p ${pid_array[$i]} -i 1
    echo "----------------------------------------------------------------"
    echo "Output of: lwm_debug_proc -b -p ${pid_array[$i]}"
    NO_DLLMAIN=1 /pkg/bin/lwm_debug_proc -b -p ${pid_array[$i]}
   ((i=i+1))
   pid=0
done  

# If we have a pid, get the attach_process output
if [ $pid -gt 0 ]
then
    echo "------------------------------------------------------------"
    echo "Output of: attach_process -A -p $pid -i 1"
    attach_process -A -p $pid -i 1
    echo "----------------------------------------------------------------"
    echo "Output of: lwm_debug_proc -b -p $pid"
    NO_DLLMAIN=1 /pkg/bin/lwm_debug_proc -b -p $pid
fi

echo "------------------------------------------------------------"
echo "Output of: top"
ps -auxw | sort -k 3 -r


if [ ! -z "$debug_cmd" ]
then
    echo "------------------------------------------------------------"
    echo "Output of: $debug_cmd"
    eval $debug_cmd
fi

if [ ! -x $debug_array_elems ]
then
    ((debug_array_elems=debug_array_elems+1))
    i=0
    while [[ $i -lt $debug_array_elems ]]
    do
        echo "------------------------------------------------------------"
        echo "Output of: ${debug_array[$i]}"
        eval ${debug_array[$i]}
        ((i=i+1))
    done
fi
if [ -e /pkg/sbin/show_mirror ]; then
    echo "------------------------------------------------------------"
    echo "Output of show mirror performance" 
    /pkg/sbin/show_mirror -p -c4
fi
echo "Exiting script at `date`."

) > $DEBUG_FILE 2>&1

