# Author: Martin Matusiak <numerodix@gmail.com>
# Licensed under the GNU Public License, version 3
#
# <desc> Find packages by binary or process pid </desc>
#
# <usage>
# source this file in bash, then run `findpkgs`
# </usage>


function _findpkgfor() {
	local file="$1";shift;

	if which paludis &>/dev/null; then
		paludis -o "$file" 2>/dev/null | grep '::installed' \
			| sed "s/::installed//g" | tr -d ' '
	elif which qfile &>/dev/null; then
		qfile "$file" 2>/dev/null | awk '{print $1}'
	elif which equery &>/dev/null; then
		equery belongs "$file" 2>/dev/null | awk '{print $1}'
	elif which dpkg &>/dev/null; then
		dpkg -S "$file" 2>/dev/null | awk '{print $1}' | tr -d ':'
	elif which rpm &>/dev/null; then
		rpm -qf "$file" 2>/dev/null | grep -v "not owned"
	else
		echo "No known package manager found"
	fi
}

function findpkgs() {
	local arg="$1";shift;

	if [ ! "$arg" ]; then
		echo "Usage:  findpkgs [ pid | /path/to/binary ]"
		return
	fi

	local pid=
	local arg_new=
	local bin=
	if echo "$arg" | grep "^[0-9]*$" &>/dev/null; then
		pid="$arg"
	else
		arg_new=$(which "$arg" 2>/dev/null)
		[ "$arg_new" ] && arg="$arg_new"
		if ! echo "$arg" | grep '^/' &>/dev/null; then
			echo "Can't find absolute path (or not a binary) for: $arg" >&2
			return
		fi
		arg=$(readlink -f "$arg")
		if ! file "$arg" | grep 'ELF' &>/dev/null; then
			echo "Not a binary: $arg" >&2
			return
		fi
		bin="$arg"
	fi


	local fst=
	local fst_new=
	local files=
	if [ "$pid" ]; then
		fst=$(ps aux \
					| sed "s/^[^ ]* *//g" \
					| grep "^$pid " \
					| awk '{print $10}' \
					| tr -d ':')
		fst_new=$(which "$fst" 2>/dev/null)
		[ "$fst_new" ] && fst="$fst_new"
		if ! echo "$fst" | grep '^/' &>/dev/null; then
			echo "Can't find absolute path for: $fst" >&2
			unset fst
		fi

		if $(which lsof &>/dev/null); then
			files=$(lsof \
						| sed "s/^[^ ]* *//g" \
						| grep "^$pid " \
						| awk '{print $8}' \
						| grep '^/' \
						| sort \
						| uniq)
		else
			files=$(cat "/proc/$pid/maps" \
						| awk '{print $6}' \
						| grep '^/' \
						| sort \
						| uniq)
		fi

		files="$fst $files"
		for file in `echo $files`; do
			_findpkgfor "$file"
		done | sort | uniq

	elif [ "$bin" ]; then
		files=$(ldd "$bin" \
					| awk '{print $3}' \
					| grep '^/' \
					| sort \
					| uniq)
		files="$bin $files"
		for file in `echo $files`; do
			_findpkgfor "$file"
		done | sort | uniq
	fi
}

