#!/usr/bin/sh
# dd/rsync/cmp/... progress - find output[/input] offset
case "$#" in
	0|1)
		case "$#" in
			0)
				set -- "$(basename "$0" | sed -e 's/P$//')"
			;;
		esac
		p="$(
			type "$1" |
			sed -ne '
				s/is \(\/.*\)$/is \
\1/
				tf
				q
				:f
				s/^.*\
//
				p
				q
			'
		)"
		[ -n "$p" ] || {
			1>&2 printf '%s\n' "$0: failed to find $1, aborting"
			exit 1
		}
		case "$p" in
			/usr/bin/cp|/bin/cp|/usr/bin/dd|/bin/dd|/usr/bin/rsync|/bin/rsync)
				rw=w
			;;
			/usr/bin/cmp|/bin/cmp)
				rw=r
			;;
			*)
				rw='[ruw]'
			;;
		esac
	;;
	*)
		printf '%s\n' "usage: $0: [program]"
		exit 1
	;;
esac
while :
do
	PIDs="$(fuser "$p" 2>>/dev/null)"
	[ -n "$PIDs" ] || exit
	set -- $PIDs
	for PID in $PIDs
	do
		lsof -o -p "$PID" 2>>/dev/null |
		while read -r line
		do
			set -- $line
			if [ $# -ne 9 ]; then
				continue
			fi
			COMMAND="$1"; PID="$2"; USER="$3"; FD="$4"; TYPE="$5";
			DEVICE="$6"; OFFSET="$7"; NODE="$8"; NAME="$9"
			expr match "$FD" '[0-9]\{1,\}'"$rw"'$' >>/dev/null 2>&1 || continue
			case "$TYPE" in
				BLK|CHR|REG) :;;
				*) break;;
			esac
			doffset=$(
				printf '%s\n' "$OFFSET" |
				sed -e '
					s/^0x//
					/^[0-9a-f]\{1,\}$/!d
					s/[a-f]/\u&/g
					s/^/ibase=16;/
				' |
				bc -l
			)
			[ -n "$doffset" ] || continue
			printf '%s\n' "$NAME $doffset"
		done
	done
	sleep 1
done
