#!/bin/sh
#
# This script prints everything engineering might need to debug a problem.
PATH=$PATH:/usr/local/bin

running_cmd=""
# this next command says remove the leading path from $0 (${0##*/}), 
# append that to /tmp, then append the pid if the
# current process ($$)
export iopipe=/tmp/${0##*/}.$$
mknod ${iopipe} p

# this string indicates the reader thread can stop
# we write this into the reader's input stream, because
# we don't have very sophisticated IPC in bash 
# and we have a blocking read that we need to supply some 
# input to "unblock" and terminate.
export endofinput="!--@@EOF@@--!"

#
# determine how long we can run
#    we'll use the default of 25 seconds if the user doesn't say otherwise
# burt 426203 complains this is too short for serial console users, change so that non-ssh users have a longer timeout
#for the ssh case the value of 120 is iapproximately double the time it takes the script to complete 

let maxruntime=${1:-0}*1
if [ "0" -eq "${maxruntime}" ] ; then
    if [ -n "${SSH_TTY}" ] ; then
        maxruntime=120
    else
        maxruntime=9999
    fi
fi

#
# this is the list of commands to run
# to add a command, make sure that it has a newline (\n) before the next command
# and the end, the extra \ is to continue the string to the next line
#
cmds="get_version\n \
get_fw_revision\n \
show_crc_errs\n \
uptime\n \
ipmi_sensors\n \
ifconfig\n \
/usr/local/bin/rlm_stats -p\n \
/usr/local/bin/ecc_stats \n \
/usr/local/bin/dump-i2c-statistics.sh\n \
cat /etc/network/interfaces\n \
route -n\n \
ip route show table 16\n \
ip route show table 64\n \
ip rule show\n \
cat /var/log/network-conf\n \
route -n -A inet6\n \
ip -6 addr\n \
cat /var/run/spiflash\n \
fru_list\n \
cat /var/log/messages\n \
cat /var/log/messages.1\n \
cat /mnt/logs/etc/fifo\n \
cat /mnt/logs/etc/fifo.1\n \
cat /mnt/logs/etc/fpga_events\n \
cat /mnt/logs/etc/fpga_events.1\n \
cat /mnt/logs/etc/sp_persistent_log\n \
cat /mnt/logs/etc/sp_persistent_log.1\n \
cat /mnt/logs/ipmi_debug_logs\n \
cat /mnt/logs/ipmi_debug_logs.1\n \
uptime\n \
/usr/local/bin/rlm_stats -p\n \
get_leds\n \
plat_dependent\n \
pstree_wrapper\n \
/usr/bin/top -n 1\n \
mount\n \
date\n \
whoami\n \
free\n \
cat /etc/build.ident\n \
cat /mnt/logs/sp_startup\n \
cat /mnt/logs/sp_startup.1\n \
cat /proc/meminfo\n \
cat /var/log/debug\n \
cat /var/log/debug.1\n \
cat /var/log/authlog\n \
cat /var/log/authlog.1\n \
cat /var/log/blocked_ip\n \
cat /var/log/environ\n \
cat /mnt/logs/etc/rlm_config_from_filer\n \
cat /mnt/logs/etc/rlm_config_to_filer\n \
cat /mnt/logs/etc/rlm_config_xtd_info\n \
cat /mnt/logs/etc/interfaces\n \
cat /mnt/logs/etc/trap_conf\n \
cat /mnt/logs/etc/takeover_conf\n \
cat /tmp/rlm_runtime_registry\n \
cat /etc/resolv.conf\n \
show_hw_info\n \
check_fw_revision\n \
hsamcmd --fault-show-all\n \
environ -show_all"


#
# we don't have a whole lot of control over the read process
# so we send some magic charaters to terminate the reading
#
reader_eof() {
	echo "${endofinput}" > ${iopipe}
}

reader() {
local read_line

	read_line=""
	while true ; do
		while read read_line ; do
			if [ "${endofinput}" != "${read_line}" ] ; then 
				echo "$read_line"
			else
				return
			fi
		done < ${iopipe}
	done

}

# 
# nixes the processes that this shell script starts
#
cleanup_processes() {

	[ -d "/proc/${loop_pid}" ] && kill ${loop_pid} &> /dev/null
	[ -d "/proc/${ioreader_pid}" ] && kill ${ioreader_pid} &> /dev/null
	[ -d "/proc/${timeout_pid}" ] && kill ${timeout_pid} &> /dev/null

}

#
# Signal handler, for when the user presses ctrl-c or the process gets a shutdown signal
#
handlesignal() {

    echo "**ctrl-c pressed, stopping**" 
	cleanup_processes

	trap "echo ctrl-c already pressed, stopping in progress " SIGHUP SIGINT SIGTERM
}

# enable the above signalhander
trap handlesignal SIGHUP SIGINT SIGTERM 

#
# runs some command, printing out the command and a
# header string of equals signs, the same number of characters as the
# command
#
runner() {
local cmd

   cmd=$*

   echo ${cmd} &> ${iopipe}
   echo ${cmd//?/=} &> ${iopipe}

   ${cmd} &> ${iopipe}
}

#
# waits $maxruntime seconds, then kills the data collection process
# so that ontap doesn't timeout waiting for data
#
timeout_kill() {

    sleep ${maxruntime}

    echo "**timeout of ${maxruntime} seconds, stopping data collection**" 

	cleanup_processes

}

get_fw_revision() {
/usr/local/bin/collect_fw_vers.sh
}

show_crc_errs() {
crc_errs=$(fw_printenv | grep crcerr)
if [ -n "$crc_errs" ] ; then
    echo "CRC Errors Detected"
    for x in $crc_errs
    do
        echo "  $x"
    done
fi
}



ipmi_sensors() {
  /usr/local/bin/ipmi sensors
}

fru_list() {
  FRU_TFILE="/tmp/tempFru"

  /usr/local/bin/fruprog list
  count=`/usr/local/bin/fruprog list | wc -l`
  count=`expr $count \- 4`
  iFru=0
  while [ $iFru -lt $count ]
  do
    echo FRU $iFru
    echo ==================
    /usr/local/bin/fruprog show $iFru > $FRU_TFILE
    cat $FRU_TFILE
    if grep -q "checksum error" $FRU_TFILE
    then
      /usr/local/bin/fruprog show $iFru -d
    fi

    iFru=`expr $iFru + 1`
  done
  rm -f $FRU_TFILE
}

plat_dependent() {
if [ -f "/var/run/RazorS" -o -f "/var/run/RazorM" ] ; then
    echo ACP info
    echo ========
    /usr/local/bin/oem_ipmi acp show

    echo Model Name details
    echo ==================
    /usr/local/bin/oem_ipmi acp model_show

    echo ACP sensors
    echo ==================
    /usr/local/bin/oem_ipmi acp sensors
fi
}

# version is a bit of a finky command, we need to run it like this
# capture the output then put it into a memory location then echo that out
# you may find a better way, there was much experimentation before arriving at this solution
get_version() {
local result

	result=""
	result=`/usr/local/bin/version.sh -a`
    echo -e "${result}"
}

#
show_hw_info() {
	show_hw_info.sh
}

check_fw_revision() {
	collect_fw_vers.sh
}

# report the FRU LED states
get_leds() {
	get_leds.sh
}

#pstree command requires us to disable TERM temporarily if we
#run directly, so hide in this local function
pstree_wrapper() {
    TERM="" pstree -a -p -c
}


#
# this is the loop that runs the command from the array
#  forking the task and waiting for it to complete.
#
# by putting the command into the background, the current shell
#  keeps control of the signals so ctrl-c can be trapped, terminating the parent
#  which will then terminate any children, thus ending the script :(
#
# the loop itself is put into a seperate task, as we may need to 
#  kill it if it does not finish in a certain number of seconds
#
execute_commands() {

	echo -e ${cmds} | while read running_cmd ; do
    	if [ -n "${running_cmd}" ] && [ -e "/proc/${ioreader_pid}/cmdline" ] ; then
        	(runner $running_cmd)&
        	running_pid=$!
        	wait ${running_pid}
   		fi
	done

	# signal to the reader thread we're done
	reader_eof
}

# start reading from io buffer
reader & 
ioreader_pid=$!

# start executing commands
execute_commands &
loop_pid=$!

# this must be started after execute_commands
# because it needs the pid of the loop process
timeout_kill & 
timeout_pid=$!

# this is where the program waits for the execute_commands loop to finish running or get terminated
wait ${loop_pid}

# belt and suspenders! send eof just in case so we don't block on the ioreader pid
reader_eof

# the loop pid gets terminated, but the reader may sill have data,
# so wait for it to complete, signal to tickle the process & get in going a little sooner
kill -CONT ${ioreader_pid} &> /dev/null
wait ${ioreader_pid}

cleanup_processes
[ -e "${iopipe}" ] && rm -f ${iopipe}

# fin!
echo -e "."

exit 0
