#! /bin/sh
##########################################################################
# Myricom GM networking software and documentation			 #
# Copyright (c) 2001 by Myricom, Inc.					 #
# All rights reserved.	 See the file `COPYING' for copyright notice.	 #
##########################################################################

# This file outputs as much useful information about the user's GM 
# configuration as it can harvest.
#
# The basic model here is to create a temporary directory full of files,
# tar it up, uuencode it, and have the user send the results to
# help@myri.com.  The files included include the results of running various
# GM tests and copies of system files revealing the system configuration.

# This is the directory to store all temporary files for easy cleanup
tmp="/tmp/gm_config_info.$$"

# This is the directory in which to store all files to be archived.
archive_dir="" # TBD

# This is the file in which to store the log (must be in archive_dir)
log="" # TBD

# The name used to invoke this script, without prepended path
invocation_basename=`echo $0 | sed -e 's@.*/@@'`

################################################################
# Useful functions
################################################################

# Clean up all temporary files

cleanup ()
{
    rm -rf ${tmp}
}

# Append a string to the log

gm_log ()
{
    # Log if the logfile is known, else just echo.
    if [ -r "/${log}" ]
    then
	echo "$*" | tee -a ${log}
    else
	echo "$*"
    fi
}

# Print a nicely formatted warning

warn ()
{
    stars=`echo $* | sed -e 's/./#/g'`
    gm_log ${stars}
    gm_log $*
    gm_log ${stars}
}

# Print a warning and exit

gm_die ()
{
    warn $*
    cleanup
    exit 1
}

# Print a usage summary

usage ()
{
    echo "Usage: ${invocation_basename} HELP_NUMBER"
    echo "    HELP_NUMBER must be the help number assigned to your incident."
    echo "    If a help number has not been assigned, use 0."
}

# Log the results of a command to a separate file, with a brief synopsis
# logged to the global log.  Add the file to the list of files to be
# archived.

fake_prompt_for_log="?"
log_cmd () {
    # Verify that this function is not called before the log exists.
    if [ ! -f "/${log}" -o ! -d "/${archive_dir}" ]
    then
	gm_die "Cannot log commands this early in the script."
    fi

    # Make the filename be the filename without the path and with
    # all dangerous characters cleaned up.
    filename=`echo $* | sed -e 's@^[^ ]*/@@' | sed -e 's/[^A-Za-z-]/_/g'`

    # Record the results of the program the command log
    echo "${fake_prompt_for_log} $*" >> ${archive_dir}/${filename}
    eval "$*" 2>&1 >> ${archive_dir}/${filename}
    
    # Record a brief synopsis to the log
    gm_log ""
    head -n 4 ${archive_dir}/${filename} | tee -a ${log}
    wc=`wc -l < ${archive_dir}/${filename} || 0`
    if [ ${wc} -gt 4 ]
    then
	 gm_log "[See file ${filename} for additional output.]"
    fi
    gm_log ""
}

# Schedule a file to be archived
archive ()
{
    # Verify that this function is not called before the log exists.
    test -f "/${log}" -a -d "/${archive_dir}" \
    || gm_die "Cannot archive files this early in the script."

    target_dirname=`echo $1 | sed -e 's@/[^/]*$@@'`
    mkdir -p "${archive_dir}/.${target_dirname}" \
    || gm_die Could not create "${archive_dir}/.${target_dirname}".
    
    gm_log "[archiving $1]"
    cp -p "$1" "${archive_dir}/.$1" || warn "Could not archive $1."
}

try_to_archive ()
{
    if [ -f "$1" -a -r "$1" ]
    then
	archive $1
    else
	gm_log "[Could not archive $1]"
    fi
}

################################################################
# implementation
################################################################

# Arange to cleanup when exitting due to a signal

interrupt_cleanup ()
{
  cleanup
  exit 1
}
trap interrupt_cleanup EXIT

# Check that the user passed in a help number on the command line

if [ $# != 1 ]
then
    usage
    gm_die "Too few parameters."
fi

# Check that the help number is really a number

help_number="${1-invalid}"
help_number_stripped=`echo ${help_number} | sed -e 's/[^0-9]/0/g'`
if [ x"${help_number}" != x"${help_number_stripped}" ]
then
    usage
    gm_die "'${help_number}' is not a number."
fi

# Check that the help number is not in a known-invalid range.

if [ ${help_number} -lt 1000 -a ${help_number} != 0 ]
then
    usage
    gm_die "Help number is invalid."
fi

################
# Determine the tempfile tree structure
################

# The name of the host, if available
hostname=`hostname || echo hostname`

# The date in a highly compact form, usable as a unique identifier in a 
# filename
date=`date +%y%m%d_%H%M || echo date`

# Create the archive directory
archive_dir_basename="${date}_${USER}@${hostname}"
archive_dir="${tmp}/${archive_dir_basename}"
mkdir -p ${archive_dir} || gm_die "Could not create archive directory."

# Create the empty log file.  It must exist since the log() function
# does not actually log until it sees this file.
log="${archive_dir}/00_LOG"
touch ${log} || gm_die "Could not create log file."

tarfile="${help_number}-${date}_${USER}@${hostname}.tar.gz"

################
# Compute prompt for command logging
#
# This is first so any warning will be first in the ${log} file.
################

whoami="$GM_WHOAMI"
if [ "x${whoami}" = "xroot" ]
then
    fake_prompt_for_log="${whoami}@${hostname}#"
else
    warn "${invocation_basename} was not run as root."
    fake_prompt_for_log="${whoami}@${hostname}>"
fi

################
# Report the help number
################

if [ ${help_number} = 0 ]
then
    gm_log User claims not to know the help number.
else
    gm_log User says help number is ${help_number}.
fi

################
# Locate the install directory
################

# Is the script being run with a full path?

first_char=`echo "$0" | sed -e 's/\(.\).*/\1/'`
if [ x${first_char} != x/ ]
then
    gm_die You must run this script using a full pathname.
fi

# Extract the install directory from the path

install_dir=`echo "$0" | sed -e 's@/[^/]*/[^/]*$@@'`
test "x${install_dir}" != "x$0" -a "x${install_dir}" != "x" \
|| gm_die "Invalid installation. ($0)"

gm_log "GM is installed in ${install_dir}."

PATH="${install_dir}/bin:$PATH"
export PATH

################################################################
# Modify here
################################################################

################
# archive files that may be missing, but we want if they are available.
################

# GM

try_to_archive ${install_dir}/.gm_install_log
try_to_archive ${install_dir}/.gm_install_log_for_${HOSTNAME}

# Linux

try_to_archive /proc/cmdline
try_to_archive /proc/cpuinfo
try_to_archive /proc/devices
try_to_archive /proc/dma
try_to_archive /proc/interrupts
try_to_archive /proc/iomem
try_to_archive /proc/meminfo
try_to_archive /proc/modules
try_to_archive /proc/net/route
try_to_archive /proc/pci
try_to_archive /proc/uptime
try_to_archive /proc/version
try_to_archive /var/log/messages

# Tru64

try_to_archive /var/adm/messages

################
# run tests and archive the results
################

####
# GM
####

log_cmd gm_counters
log_cmd gm_board_info
log_cmd gm_allsize -g -u -bw
log_cmd gm_allsize -g -b -bw
log_cmd gm_allsize -g -u -lat
log_cmd gm_allsize -g -b -lat
log_cmd gm_allsize -v -g -u -bw
log_cmd gm_allsize -v -g -b -bw
log_cmd gm_allsize -v -g -u -lat
log_cmd gm_allsize -v -g -b -lat
log_cmd gm_allsize -v -f -e -g
log_cmd gm_debug
log_cmd gm_debug -l
log_cmd gm_debug --internal-info --no-counters

####
# Fairly common system tests
####

log_cmd uname -a
log_cmd gcc --version
log_cmd cc -V
log_cmd cxx -V
log_cmd netstat -r
log_cmd ifconfig -a

####
# Shared library tests
####

# Log the dynamic dependencies of each installed application
for app in ${install_dir}/bin/*
do
    log_cmd ldd ${app}
done

####
# Linux
####

log_cmd dmesg
log_cmd lsmod

####
# Tru64
####

log_cmd sizer -c
log_cmd sizer -implver
log_cmd sizer -p
log_cmd hwmgr -show component
log_cmd uerf -R

################################################################
# Create archive
################################################################

# Tar up all of the results.  This is not logged because the log
# is included in the tarfile.

(cd ${tmp} && tar cf ${tarfile} ${archive_dir_basename}) \
|| gm_die Could not create tarball of results.
uuencode ${tmp}/${tarfile} ${tarfile}

################
# Filter out unreadable files
################

echo 
echo "Please email this output to help@myri.com."

################
# Make sure the user notices if they did not run the script as root.
################

if [ "x${whoami}" != "xroot" ]
then
  warn "You did not ${invocation_basename} as root.  Please do so if possible."
fi

################
# Cleanup and exit
################

trap cleanup EXIT

exit 0
