#!/bin/sh
###############################################################################
# stacktrace
#
# Shell wrapper to simplify 'stacktrace.so' usage.
#
# ---------------------------------------------------------------------------
# stacktrace - Stacktrace printer.
#   (C) 2008-2009 Gerardo García Peña <gerardo@kung-foo.net>
#
#   This program is free software; you can redistribute it and/or modify it
#   under the terms of the GNU General Public License as published by the Free
#   Software Foundation; either version 2 of the License, or (at your option)
#   any later version.
#
#   This program is distributed in the hope that it will be useful, but WITHOUT
#   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
#   more details.
#
#   You should have received a copy of the GNU General Public License along
#   with this program; if not, write to the Free Software Foundation, Inc., 51
#   Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
#
###############################################################################

log()
{
  echo "$0:$@" 1>&2
}

error()
{
  echo "$0:error:$@" 1>&2
  exit 1
}

usage()
{
  echo "$0:error:$@" 1>&2
  log "Usage:"
  log "  $0 {program_name} [args ...]"
  exit 1
}

SO="stacktrace.so"

# check params
if [ -z "$1" ]; then
  usage "At least you must provide the program to execute."
fi
if ! which "$1" > /dev/null 2>&1; then
  usage "'$1' is not a valid executable program."
fi

# select the best IFS
SEP=""
for i in "\r" "\n" "\t" ":" " "; do
  if ! ( echo "$@" | grep "$i" > /dev/null 2>&1 ); then
    SEP="$i"
  fi
done
[ -n "$SEP" ] || error "Cannot find a suitable field separator (IFS)."

# build params
PROG="$1"
PARAMS=""
shift
while test "$1"; do
  if [ -n "$PARAMS" ]; then
    PARAMS="$PARAMS$SEP"
  fi
  PARAMS="$PARAMS$1"
  shift
done

# search stacktrace.so
STACKTRACE=""
LPATH=`(
         echo "."
         ldconfig -p \
         | sed -e 's#^.* => ##' -e 's#/[^/]*$##' \
         | grep '^/' \
         | sort -u
       )`
for P in $LPATH; do
  if [ -z "$STACKTRACE" -a -e "$P/$SO" ]; then
    STACKTRACE="$P/$SO"
    log "Using stacktrace located at '$STACKTRACE'"
  fi
done
[ -n "$STACKTRACE" ] || error "Cannot find $SO."

# launch program
IFS="$SEP"
LD_PRELOAD="$STACKTRACE" "$PROG" $PARAMS

# finishing
STATUS="$?"
log "$PROG finished with status $STATUS."
exit $STATUS
