#!/bin/sh

# Copyright (c) 2003-2013 Aleksey Cheusov <vle@gmx.net>
# 
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# 
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

set -e

libdir=/usr/pkg/lib
sysconfdir=/usr/pkg/etc

LMDBG_SOEXT=${LMDBG_SOEXT:=so}
LMDBG_LIB=${LMDBG_LIB:=$libdir/liblmdbg.$LMDBG_SOEXT}

usage () {
    cat <<'EOF'
lmdbg-run is intended to run your program with
liblmdbg.$LMDBG_SOEXT LD_PRELOAD-ed in order to log
the calls of the following functions:
malloc, free, realloc, aligned_alloc and memalign.
Set LMDBG_LIB environment variable to liblmdbg.$LMDBG_SOEXT
The default is $libdir/liblmdbg.$LMDBG_SOEXT.

usage: lmdbg-run [OPTIONS] <progname> [args...]
OPTIONS:
  -h                     display this screen
  -V                     display version
  -v                     verbose mode
  -o <filename>          set a filename for logging
  -f|-p <filter>         save filter's output to log file
  -n                     do not enable logging on startup, SIGUSR1 enables it
  -N <pidfile>           save pid of progname to pidfile
  -T <stacktrace-skip>   addresses to skip in the top of stacktrace
  -B <stacktrace-skip>   addresses to skip in the bottom of stacktrace
  -M <stacktrace-max>    limit for a number of addresses in a stacktrace

EOF
}

version (){
cat <<'EOF'
lmdbg-run 1.3.0
EOF
}

while getopts hVvo:f:p:nS:M:T:B:N: f; do
    case $f in
	h)
	    usage
	    exit 0;;
	V)
	    version
	    exit 0;;
	v)
	    LMDBG_VERBOSE=1;
	    export LMDBG_VERBOSE;;
	o)
	    ofile="$OPTARG";;
        f|p)
	    pipe="$OPTARG";;
	n)
	    LMDBG_TIMEOUT=-1;;
	N)
	    LMDBG_PIDFILE="$OPTARG";;
        S|T)
	    LMDBG_ST_SKIP_TOP="$OPTARG";;
        B)
	    LMDBG_ST_SKIP_BOTTOM="$OPTARG";;
        M)
	    LMDBG_ST_COUNT="$OPTARG";;
	'?')
	    usage 1>&2
	    exit 1;;
    esac
done
shift $(expr $OPTIND - 1)

progname=`echo $1`
if test $# -eq 0 -o "$progname" = ''; then
    echo 'Progname should not be empty, run '"'"'lmdbg-run -h'"'"' for details' 1>&2
    exit 1
fi

TMPDIR=${TMPDIR:=/tmp}

if test "$pipe"; then
    fifo_file=`mktemp -u $TMPDIR/lmdbg-run.XXXXXX` || {
	exit 2
    }

    trap 'rm -f "$fifo_file"' 0 1 2 3 5 15

    mkfifo -m 600 "$fifo_file" || {
	exit 3
    }

    eval "$pipe" < "$fifo_file" > "$ofile" 2>/dev/null &
    ofile="$fifo_file"
fi

if test "$LMDBG_VERBOSE"; then
    echo Running "$* with LD_PRELOAD=$LMDBG_LIB" 1>&2
fi

LMDBG_LOGFILE="$ofile"
LMDBG_PROGNAME="$1"

export LMDBG_LOGFILE LMDBG_PIDFILE LMDBG_PROGNAME LMDBG_TIMEOUT
export LMDBG_ST_SKIP_TOP LMDBG_ST_SKIP_BOTTOM LMDBG_ST_COUNT

set +e
export LD_PRELOAD="$LMDBG_LIB"
"$@"
ex=$?
unset LD_PRELOAD
set -e

wait

if test "$LMDBG_VERBOSE"; then
    echo Done. 1>&2
fi

exit $ex
