#!/bin/sh
#
# ufdb-pstack: print a stack dump
# based upon pstack of the gdb package, Copyright by FSF
# minor modifications by Marcus Kool
#
# RCS: $Id: ufdb-pstack.in,v 1.15 2015/08/20 13:16:52 root Exp root $

trap "echo ignoring signals" 1 2 3 4 5 6 7 8 10 11 12 13 14 15 20

unset MALLOC_CHECK_  # glibc
unset MALLOC_OPTIONS # BSD
unset MALLOCTYPE     # AIX
unset MALLOCOPTIONS  # AIX
unset MALLOCDEBUG    # AIX
unset UMEM_DEBUG     # Solaris
unset MALLOC_DEBUG   # Solaris

umask 022

PATH=/bin:/usr/bin:$PATH
export PATH

if [ -d /opt/csw/bin ]
then
   PATH=/opt/csw/bin:$PATH
   export PATH
fi

if [ -d /usr/xpg4/bin ]
then
   PATH=/usr/xpg4/bin:$PATH
   export PATH
fi

R=${RANDOM:-$PPID}
CRASHREPORT=/tmp/urlfilterdb.crashreport.$$.$R


(  
   echo "ufdb-pstack version" 1.31-14 "was called for pid $1"
   echo
) > $CRASHREPORT

echo "ufdb-pstack version" 1.31-14 "was called for pid $1"

if test $# -lt 1; then
    echo "Usage: `basename $0 .sh` <process-id>" 1>&2
    exit 1
fi


KERNEL=`uname -s`
case "$KERNEL" in
   Linux)
      if test ! -d /proc ; then
	 echo "ufdb-pstack: no /proc directory: cannot print stack dump"
	 exit 0
      fi

      corefile="none"
      backtrace="bt"

      if test ! -r /proc/$1
      then
	 if test -f $1
	 then
	    exe=icapd
	    corefile=$1
	    backtrace="thread apply all bt"
	 else
	    echo "Process $1 not found."
	    tail -n 100 /var/log/messages | grep ufdbguardd
	    ps -ef | grep ufdbguardd
	    swapon -s
	    exit 1
	 fi
      else
	 exe="/proc/$1/exe"
	 corefile="$1"

	 # GDB doesn't allow "thread apply all bt" when the process isn't
	 # threaded; need to peek at the process to determine if that or the
	 # simpler "bt" should be used.

	 if test -d /proc/$1/task ; then
	     # Newer kernel; has a task/ directory.
	     if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then
		 backtrace="thread apply all bt"
	     fi
	 elif test -f /proc/$1/maps ; then
	     # Older kernel; go by it loading libpthread.
	     if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
		 backtrace="thread apply all bt"
	     fi
	 fi
      fi
      ;;
   *)
      # just assume that $1 has the correct PID and ufdbguardd is in /usr/bin
      exe=/usr/bin/ufdbguardd
      corefile="$1"
      backtrace="thread apply all bt"
      ;;
esac


PSTACK=/usr/bin/pstack
GDB=/usr/bin/gdb

if [ -x "$GDB" ]
then

   # if $GDB -nx --quiet --batch --readnever > /dev/null 2>&1; then
   #     readnever=--readnever
   # else
   #     readnever=
   # fi

   readnever=
   interpreter="--interpreter=console"

   $GDB --version
   echo "executing $GDB --quiet $interpreter $readnever -nx $exe  $corefile"
   # Run gdb and strip out unwanted noise.
   (
   $GDB --quiet $interpreter $readnever -nx $exe  $corefile  2>&1 <<EOF
   set interactive-mode off
   set confirm off
   set print null-stop on
   set print object on
   set print array on
   set print frame-arguments all
   set width 0
   set height 0
   set pagination no
   p UFDBglobalReconfig
   p UFDBglobalStatus
   p UFDBglobalDatabaseStatus
   p UFDBglobalFatalError
   p UFDBglobalUserName
   bt full
   thread apply all bt full
   quit
EOF
   ) |
   sed -n \
       -e 's/^\((gdb) \)*//' \
       -e '/^#0 .* __kernel_vsyscall/d' \
       -e '/ in clone /d' \
       -e '/No symbol table info available/d' \
       -e '/Loaded symbols for/d' \
       -e '/Reading symbols from/d' \
       -e '/^\[New Thread /d' \
       -e 's/^No locals./        &/' \
       -e '/^Backtrace stopped: Not enough registers or memory available to unwind further/d'  \
       -e 's/signal handler called.*/&     ====================================================================/' \
       -e 'p'  \
   >> $CRASHREPORT

elif [ -x "$PSTACK" ]
then
   $PSTACK $1 |
   sed -n \
       -e '/BadSignalCaught/s/$/     =====/'  \
       -e '/called from signal handler/s$/    =============================================================/'   \
       -e 'p'  \
   >> $CRASHREPORT
else
   echo "gdb nor pstack is installed on this system so a crash report cannot be generated ..."
fi

echo "This crash report is also saved in $CRASHREPORT"

(
   uname -a
   echo
   lscpu
   echo
   gdb --version
   echo
   gcc --version
   echo
   date
   echo
) >> $CRASHREPORT

cat $CRASHREPORT

