#!/bin/sh

# -----------------------------------------------------------------------------
print_usage_and_exit() {
    echo
    echo "Usage: $this_script <exec-name> <pid> <timestamp>"
    echo
    echo -e "\tThis script will accept a core file on stdin and save it in"
    echo -e "\tgzip format to $CORE_FINAL_PATH."
    echo
    exit 1
}

# - MAIN ----------------------------------------------------------------------

# pick up some helper functions
source /ciena/scripts/fault.sh

# Take note of our name as invoked
this_script=$(basename $0)

# Fill variables such as $CORE_FINAL_PATH
#get_core_paths
CORE_INITIAL_PATH=/tmp
CORE_FINAL_PATH=/tmp/corefiles

# check for various help incarnations
case "$1" in
    "-h"|"--help"|"-?") print_usage_and_exit ;;
esac

# Verify that the correct number of parameters were provided
if [ "$#" -ne 3 ] ; then
    echo
    echo "ERROR: missing parameters"
    print_usage_and_exit
fi

# Grab the parameters provided by the kernel.  These are defined by the
# parameters included in /proc/sys/kernel/core_pattern.
#
thread_name=$1
pid=$2
timestamp=$3

# Use the exe entry in proc to determine the real name of the binary.  This
# allows the correct name to be attached to commands that soft link to a
# binary or change their name using prctl().
#
real_name=$(readlink /proc/$pid/exe)
if [ "$?" -eq "0" ] ; then
    real_name=$(basename $real_name)
else
    real_name=$thread_name
fi

core_initial_file=$CORE_INITIAL_PATH/core.$pid
core_lock_file=$CORE_INITIAL_PATH/core.in.progress
core_final_file=$CORE_FINAL_PATH/core-$real_name-$pid-$timestamp.gz

source /sbin/krn getenv
family=$(cat /family)
if [ "$KRN_MODE" != "debug" ]; then
    case "$family" in
        "artamir") NCORES=2 ;;
        "brego")   NCORES=5 ;;
        *)         NCORES=1 ;;
    esac
else
    NCORES=5
fi

# We now make the core file in its final place (flash) so as to reduce
# the temporary RAM needs while coring.  (The original architecture
# kept all cores in RAM disk, and the two-stage process kept
# incomplete cores from being processed too early.)  Core-making is
# slightly faster this way, but you'll have to figure out whether
# they're done yet on your own.  (As a hint, owner-read permission
# will be withheld until the core is completed.)

# First advertise to the world that we're trying to make a core.
# Processes can know that if there is a core file in $CORE_INITIAL_PATH
# that it's not finished yet, and they can react accordingly.  We try to
# mimic the 6.3 core behavior to minimize compatibility problems.

touch $core_initial_file

# Serialize the making of core files.  Eliminates situations where
# flash fills up and _all_ paralleled core files end up truncated and
# thus corrupt.  Done this way all that will fit intact will be so,
# and only the extras are truncated/corrupt.  (We keep them anyway
# because a truncated core file still has useful information in it.)
# The hard-link is used as an atomic test-and-set mutex, this is
# standard Unix script practice for the last thirty years.

waitcount=180	# Three minutes.
while ! ln $core_initial_file $core_lock_file 2>/dev/null; do
    sleep 1
    waitcount=$(expr $waitcount - 1)
    if [ $waitcount -eq 0 ]; then
	echo "Too busy, can't make core file $core_final_file"
	rm -f $core_initial_file
	exit
    fi
done

# Do not use nice on the gzip call below if associated corefile is from a 
# SAOS server process crash.  Use of nice on SAOS server crash in the first
# minute of operation was found to result in >10mins to gzip corefile,
# resulting in watchdog expiry and reboot.  This defeats config revert-to-
# defaults defense mechanism.
unset NICE SPID
FIFO=/tmp/fifo/leos/LEOS_IPC_PID

if [ -r "$FIFO" ]; then
    SPID=`cat $FIFO`
fi

if [ "$SPID" -ne $2 ]; then
    NICE=nice
fi

zipcount=$(ls -1 $CORE_FINAL_PATH/core-* 2>/dev/null | wc -l)
if [ "$zipcount" -lt $NCORES ]; then

    # Start the watchdog.  The kernel will reboot us if we do not kick or
    # disable the watchdog in time (the timeout is set by the soft_margin
    # parameter when the watchdog module is loaded).
    echo 1 > /dev/watchdog

    echo "Core file for $pid ($(xargs -0 </proc/$pid/cmdline)) being generated..." >/dev/console
    # Make the final file with the special 'incomplete' access permissions.
    mkdir -p -m 0775 $CORE_FINAL_PATH
    umask u-r

    # Run gzip with input from stdin, and send the output to $core_final_file.
    # We choose speed rather than compression density; the size
    # difference is small but the speed difference is immense.
    $NICE gzip -1fc > $core_final_file || echo "Error making $core_final_file, it may be corrupt."
    
    # Ensure group accessibility, and mark as 'complete'.
    chmod u+r,g=u $core_final_file
    umask u+r

    # Disable the watchdog.
    echo 'V' > /dev/watchdog

else
    echo "maximum number ($NCORES) of core files reached"
fi

# Finished, release interlocks.
rm -f $core_initial_file $core_lock_file

generate_core_log $real_name $pid $timestamp $core_final_file $thread_name
