#!/bin/sh

# live_ast: run asterisk from a newly-built copy with minimal changes.

# Copyright (C) 2007 Tzafrir Cohen <tzafrir.cohen@xorcom.com>
#
# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
# USA

# This script allows you to install Asterisk into a subdirectory of
# your source distribution and run it from there.
#
# Example usage:
#
#   contrib/scripts/live_ast conf-file # optionally. and now edit live/live.conf
#   # edit live/live.conf
#   contrib/scripts/live_ast configure
#   make
#   contrib/scripts/live_ast install
#   contrib/scripts/live_ast samples
#   contrib/scripts/live_ast run
#   contrib/scripts/live_ast run -r
#   ./live/asterisk -r                 # Same as run -r
#
# A standard debugging cycle of a code in a module:
#
#   # edit apps/app_skel.c
#   contrib/scripts/live_ast install
#   contrib/scripts/live_ast run -r
#   # and in the CLI:
#   module unload app_skel.so
#   module load app_skel.so
#
# If you have external scripts that run asterisk, use the script
# live/asterisk that is generated by the 'samples' command. In this case you
# should probably also rem-out the line 'astvarrundir' and maybe also
# 'astetcdir' in live/etc/asterisk.conf .
#
####################### Begin Samples
# optional environment variables. Set those in live/live.conf or in
# your envirnment.
#
# LIVE_AST_LIBPRI_PATH:
# To use a libpri SVN directory (without running 'make install': make include
# a symlink to the current directory:
#   ln -s . /path/to/checkout/of/libpri/include
# Be sure to run there 'make'. Then set in live.conf:
#LIVE_AST_LIBPRI_PATH="/path/to/checkout/of/libpri"
#
# LIVE_AST_ZAPTEL_PATH:
# Likewise, the same trick can be used to build vs. a local copy of zaptel:
#   ln -s /path/to/checkout/of/zaptel/include .
#   ln -s /path/to/checkout/of/zaptel/zaptel .
#LIVE_AST_ZAPTEL_PATH="/path/to/checkout/of/zaptel"
#
#LIVE_AST_DAHDI_PATH="/path/to/dahdi-linux/dir"
#LIVE_AST_DAHDITOOLS_PATH="/path/to/dahdi-tools/dir"
#
# Another alternative for Zaptel is to use the live_zap script included
# with the Zaptel distribution. The following should work after you used
# './live_zap install' or even with a copy generated with
# './live_zap rsync' . '/apth/to/zaptel' is the directory containing the
# live/ subdirectory:
#
#LIVE_AST_ZAPLIVE_PATH="/path/to/zaptel"
#
# LIVE_AST_LD_PATH_EXTRA:
# space-separated or colon-separated directories to add to
# LD_LIBRARY_PATH. It is added before any existing components of
# LD_LIBRARY_PATH.
#LIVE_AST_LD_PATH_EXTRA="$HOME/lib:$HOME/libtest /opt/testapp"
#
# LIVE_AST_CONFIGURE_PARAMS:
# Extra parameters to pass to ./configure.
#LIVE_AST_CONFIGURE_PARAMS="--enable-dev-mode"
#
# LIVE_AST_FORCE_DEF_CONF:
# If set to a non-empty value, always regenerate menuselect config.
# This avoids emenselect's nag about "configuration has changed" that
# happens occasionally after an svn update.
#LIVE_AST_FORCE_DEF_CONF=yes
#
# LIVE_AST_BRISTUFFED_LIBPRI
# A hack to use the second, "bristuffed" copy of libpri that exists
# e.g. in the Debian libpri-dev package. If set to a non-empty value,
# live_ast will edit makeopts to use that second copy after ./configure
# is run.
#LIVE_AST_BRISTUFFED_LIBPRI=yes
#
# LIVE_AST_VALGRIND_ARGS:
# Parameters to pass to valgrind if using the 'valgrind' command.
#LIVE_AST_VALGRIND_ARGS="-v --leak-check=full --suppressions=contrib/valgrind.supp --log-file=valgrind.log"
#
# LIVE_AST_FOR_SYSTEM
# When generating asterisk.conf, use most components from the installed
# system. Also provide a sane var-run directory for those of us who want
# to do the right thing and run asterisk as non-root.
#LIVE_AST_FOR_SYSTEM=yes
####################### End Samples

BASE_DIR="${AST_LIVE_BASE_DIR:-$PWD/live}"
AST_CONF_DIR="$BASE_DIR/etc/asterisk"
AST_CONF="$AST_CONF_DIR/asterisk.conf"
AST_BIN="$BASE_DIR/usr/sbin/asterisk"
GDB_INIT="$BASE_DIR/gdbinit"
LIVE_CONF="$BASE_DIR/live.conf"
DISABLED_MODS="chan_h323 pbx_dundi"
DISABLED_MODS_FILE="modules-disabled.conf"

if [ -r "$LIVE_CONF" ]; then . "$LIVE_CONF"; fi

if [ "$LIVE_AST_LIBPRI_PATH" != '' ]; then
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-pri=$LIVE_AST_LIBPRI_PATH"
  LIVE_AST_LD_PATH_EXTRA="$LIVE_AST_LD_PATH_EXTRA $LIVE_AST_LIBPRI_PATH"
fi

if [ "$LIVE_AST_ZAPTEL_PATH" != '' ]; then
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-tonezone=$LIVE_AST_ZAPTEL_PATH"
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-zaptel=$LIVE_AST_ZAPTEL_PATH"
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-zaptel_transcode=$LIVE_AST_ZAPTEL_PATH"
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-zaptel_vldtmf=$LIVE_AST_ZAPTEL_PATH"
  LIVE_AST_LD_PATH_EXTRA="$LIVE_AST_LD_PATH_EXTRA $LIVE_AST_ZAPTEL_PATH"
fi

if [ "$LIVE_AST_DAHDI_PATH" != '' ]; then
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-dahdi=$LIVE_AST_DAHDI_PATH"
fi

if [ "$LIVE_AST_DAHDITOOLS_PATH" != '' ]; then
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-tonezone=$LIVE_AST_DAHDITOOLS_PATH"
  LIVE_AST_LD_PATH_EXTRA="$LIVE_AST_LD_PATH_EXTRA $LIVE_AST_DAHDITOOLS_PATH"
fi

if [ "$LIVE_AST_ZAPLIVE_PATH" != '' ]; then
  ZAPLIVE_USR_DIR="$LIVE_AST_ZAPLIVE_PATH/live/usr"
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-tonezone=$ZAPLIVE_USR_DIR"
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-zaptel=$ZAPALIVE_USR_DIR"
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-zaptel_transcode=$ZAPALIVE_USR_DIR"
  LIVE_AST_CONFIGURE_PARAMS="$LIVE_AST_CONFIGURE_PARAMS --with-zaptel_vldtmf=$ZAPALIVE_USR_DIR"
  LIVE_AST_LD_PATH_EXTRA="$LIVE_AST_LD_PATH_EXTRA $ZAPLIVE_USR_DIR/lib"
fi

# gets rid of excessive spaces. Leves nothing if there were only white spaces:
LIVE_AST_LD_PATH_EXTRA=`echo $LIVE_AST_LD_PATH_EXTRA | tr ' ' :`
LIVE_AST_LD_PATH_EXTRA="$BASE_DIR/usr/lib:$LIVE_AST_LD_PATH_EXTRA"

set_ld_env() {
  if [ "$LD_LIBRARY_PATH" = '' ]; then
    LD_LIBRARY_PATH="$LIVE_AST_LD_PATH_EXTRA"
  else
    LD_LIBRARY_PATH=`echo $LD_LIBRARY_PATH | tr ' ' :`
    LD_LIBRARY_PATH="$LIVE_AST_LD_PATH_EXTRA:$LD_LIBRARY_PATH"
  fi
  export LD_LIBRARY_PATH
}

# if live.conf does not exist, generate it from the sample
gen_live_conf() {
  if [ -r $LIVE_CONF ]; then return; fi
  # TODO: `dirname $LIVE_CONF` in case someone redefines it?
  mkdir -p $BASE_DIR
  sed -n -e '/^#* Begin Samples/,/^#* End Samples/p' "$0" \
  | sed  -e '/^#* \(Begin\|End\) Samples/d' >"$LIVE_CONF"
}

# (re?)generate the ./live/asterisk wrapper script
gen_live_asterisk() {
  cat <<EOF >"$BASE_DIR/asterisk"
#!/bin/sh
# a wrapper to run asterisk from the "live" copy:
EOF
  if realpath $0 >/dev/null 2>&1; then
    cat <<EOF >>"$BASE_DIR/asterisk"
export AST_LIVE_BASE_DIR="$PWD/live"
real_me='`realpath $0`'
exec "\$real_me" run "\$@"
EOF
  else # No realpath. Fall back to change working directory:
    cat <<EOF >>"$BASE_DIR/asterisk"
cd "$PWD"
exec "$0" run "\$@"
EOF
  fi
}

command="$1"
if [ $# -gt 0 ]; then
  shift
fi

case "$command" in
configure)
  ./configure $LIVE_AST_CONFIGURE_PARAMS "$@"
  if [ "$LIVE_AST_FORCE_DEF_CONF" != '' ]; then
    rm -f menuselect.makeopts
  fi
  if [ "$LIVE_AST_BRISTUFFED_LIBPRI" != '' ]; then
    sed -i \
      -e 's|^\(PRI_INCLUDE=\).*|\1-I/usr/include/bristuffed|' \
      -e 's|^\(PRI_LIB=\).*|\1-lpri-bristuffed|' \
      makeopts
  fi
  ;;
install)
  make install DESTDIR="$BASE_DIR" "$@"
  ;;
samples)
  make samples DESTDIR="$BASE_DIR" "$@"
  sed -r -i \
    -e '/^\[directories\]\(!\)/s/\(!\).*//' \
    -e "/^\[directories\]/a; rem-out any of the following to use Asterisk's defaults:" \
    -e "/^ast(cache|etc|mod|varlib|data|agi|run|spool|log|db|key)dir\>/s| /| $BASE_DIR/|" \
    "$AST_CONF"
  if [ "$LIVE_AST_FOR_SYSTEM" != '' ]; then
    sed -r -i \
      -e "/^ast(etc|varlib|data|agi|run|spool|log|db|key)dir\>/s|^|;|" \
      -e "/^;astrundir\>/aastrundir    => /var/run/asterisk" \
      "$AST_CONF"
  fi
  # disable some modules that bind on a port that is already in use by a
  # main Asterisk copy, and would crash asterisk in failing:
  rm -f "$AST_CONF_DIR/$DISABLED_MODS_FILE"
  for mod in $DISABLED_MODS; do
    echo "noload => $mod.so" >> "$AST_CONF_DIR/$DISABLED_MODS_FILE"
  done
  echo "#include $DISABLED_MODS_FILE" >> "$AST_CONF_DIR/modules.conf"

  cat <<EOF >"$GDB_INIT"
set args -C "$AST_CONF" -c
EOF
  gen_live_asterisk
  chmod +x "$BASE_DIR/asterisk"
  # Generate a sample config file for live_ast itself:
  gen_live_conf
  ;;
conf-file)
  # Just regenerate live.conf from the sample if it does not already exist:
  gen_live_conf
  ;;
run)
  set_ld_env
  exec $AST_BIN -C $AST_CONF "$@"
  ;;
valgrind)
  set_ld_env
  exec valgrind $LIVE_AST_VALGRIND_ARGS $AST_BIN -C $AST_CONF "$@"
  ;;
rsync)
  remote_host="$1"
  remote_dir="$2"
  me=`basename $0`
  # FIXME: assumes varrundir is /var/run/asterisk
  rsync -ai "$0" \
    --exclude '/live/asterisk' \
    --exclude '/live/var/run/asterisk/*' --exclude '/live/var/log/asterisk/*' \
    live "$remote_host:$remote_dir/"
  ssh $remote_host "cd '$remote_dir' && ./$me gen-live-asterisk"
  ;;
gen-live-asterisk)
  gen_live_asterisk
  ;;
gdb)
  set_ld_env
  exec gdb -x $GDB_INIT $AST_BIN
  ;;
*)
  echo "$0: Unknown command '$command'. Aborting"
  echo
  echo "$0: Usage:              Equivalent of:"
  echo "$0 configure [params]   ./configure [params]"
  echo "$0 install              make install"
  echo "$0 samples              make samples"
  echo "$0 run [params]         asterisk [params]"
  echo "$0 gdb                  gdb asterisk"
  echo "$0 valgrind             valgrind asterisk"
  echo "$0 rsync [user@]host dir  copy files over to [user@]host:dir"
  echo "$0 gen-live-asterisk    regenerate the wrapper ./live/asterisk"
  echo "$0 conf-file            create live.conf if it does not exist"
  exit 1
  ;;
esac