#!/bin/bash

ME=${0##*/}

PROG_PATH="/usr/local/bin /usr/sbin /usr/bin /sbin /bin"

usage() {
    cat <<Usage
usage: $ME [options] <program>

Create a \$program-libs directory in the CWD and copy all libs
needed to run the program into that directory.  If an absolute
path to the program is not included then we search for the
program on a reasonable path:

    $PROG_PATH

Options:
   -h --help         Show this help
   -f --force        Overwrite \$program-libs directory
   -p --prefix       Directory prefix for grabbing libs
   -o --output=<dir> Directory to put libs in
   -v --verbose      Print more

Short options can be stacked.  Example:

    $ME -fvp <directory> <program>

The --prefix option allows you to grab libraries from, for
example, a mounted squashfs file even if the architecture (64 or
32 bit) does not match that of the host system.
Usage

    exit ${1:-0}
}

main() {

    [ $# -eq 0 ] && usage 0

    local short_stack="hfopv"

    while [ $# -gt 0 -a -n "$1" -a -z "${1##-*}" ]; do
        local arg=${1#-}; shift

        case $arg in
            [$short_stack][$short_stack]*)
                if echo "$arg" | grep -q "^[$short_stack]\+$"; then
                    set -- $(echo $arg | sed -r 's/([a-zA-Z])/ -\1 /g') "$@"
                    continue
                fi;;
        esac

        case $arg in
            -help|h) usage 0           ;;
           -force|f) FORCE=true        ;;
         -verbose|v) VERBOSE=true      ;;
      -prefix=*|p=*) PREFIX=${arg#*=}  ;;
      -output=*|o=*) TARGET=${arg#*=}  ;;

          -prefix|p) [ $# -gt 0 ] || fatal "Expected argument after: -$arg"
                     PREFIX=$1; shift  ;;

          -output|o) [ $# -gt 0 ] || fatal "Expected argument after: -$arg"
                     TARGET=$1; shift  ;;

                  *) fatal "Unknown argment: -$arg" ;;
        esac
    done

    [ -n "$TARGET" -a -n "$FORCE" ] && fatal "Can't use --force with --output"

    case $# in
        0) fatal "Missing program parameter" ;;
        1) prog=$1                           ;;
        *) fatal "Extra parameters: $*"      ;;
    esac

    local orig_prog=$prog
    test -e $prog || prog=$(which $prog 2>/dev/null)
    test -e $prog || fatal "Could not find program %s" $orig_prog

    targ="$(basename $prog)-libs"
    [ -n "$TARGET" ] && targ=$TARGET

    local preprog=$PREFIX$prog

    if [ ! -e "$preprog" -a -n "${prog##/*}" ]; then
        local path
        for path in $PROG_PATH; do
            [ -e $PREFIX$path/$prog ] || continue
            prog=$path/$prog
            preprog=$PREFIX$prog
            vsay "Found program at: $prog"
            break
        done
    fi
    [ -e $preprog ] || fatal "Could not find program: $prog"

    [ "$FORCE" ] && rm -r $targ
    [ -z "$TARGET" -a -e "$targ" ] && fatal "Use -f option to overwrite $targ directory"

    mkdir -p $targ
    [ -e "$targ" ] || fatal "Could not create $targ directory"


    local libs raw_libs
    if [ "$PREFIX" ]; then
        [ -d "$PREFIX" ] || fatal "Prefix: $PREFIX is not a directory"

        local sudo
        [ "$UID" = 1 ] || sudo=sudo

        local need_64 new_arch=linux32
        if file $preprog | grep -q x86.64; then
            need_64=true
            new_arch=linux64
        fi
        local have_64
        uname -m | grep -q x86.64 && have_64=true
        local linux_arg
        [ "$need_64" != "$have_64" ] && linux_arg=$new_arch

        raw_libs=$($sudo $linux_arg chroot $PREFIX /usr/bin/ldd $prog)

    else
        raw_libs=$(ldd $prog)
    fi

    [ "$raw_libs" ] || fatal "The ldd program found no libraries"

    vsay "Raw libraries:\n$raw_libs\n"

    libs=$(echo "$raw_libs" | grep "=> /" | sed 's/.*=> //' | sed 's/ .*//' ) 

    libs="$libs $(ls $PREFIX/lib/ld-linux.* | sed "s=^$PREFIX==" )"

    vsay "Libraries:\n$libs\n"

    for lib in $libs; do
        lib=$PREFIX$lib
        real_lib=$(readlink -f $lib)
        if [ "$real_lib" -a "$real_lib" != "$lib" ]; then
            vsay "Real lib: $real_lib"
            cp -a $real_lib $targ
            sym_sorc=$targ/$(basename $lib)
            sym_dest=$(basename $real_lib)
            [ -e "$sym_sorc" ] || ln -s $sym_dest $sym_sorc
        else
            cp $lib $targ
        fi
    done
}

vsay() {
    [ "$VERBOSE" ] && echo -e "$*"
}

fatal() {
    echo "$ME fatal error: $@"
    exit 1
}

main "$@"



