#!/bin/bash
#
# bug 3.2.10: Generates a bug report (needs bash >=2.0)
#
# Christoph Lameter, October 26, 1996
#
# Modified by Nicols Lichtmaier
#
set -e

# Compat tests
if [ "$BASH_VERSION" \< "2.01.1" ] ; then
	echo "$0: Needs Bash >= 2.01.1" >&2
	exit 1
fi

export TEXTDOMAIN=bug
YESNO=$"yYnN"

if [ -z "$EMAIL" ] ; then
	if  [ ! -r /etc/mailname ] ; then
		echo $"$0: Please set the environment variable EMAIL to contain your fully qualified e-mail address and try again." >&2
		exit 1
	fi
	FROM="`id -un`"
	FROM=`sed -ne "s/^$FROM:[^:]*:[^:]*:[^:]*:\\([^,:]*\\),\\?.*:.*/\\1/p" \
		< /etc/passwd`" <$FROM@`cat /etc/mailname`>"
else
	FROM="$EMAIL"
fi

if [ "$(type -t realpath 2> /dev/null)" = "" ]; then REALPATH=realp; else REALPATH=realpath ; fi

# Wait for a keypress and put it in $KEY
getkey()
{
	stty -icanon min 1 || true 2> /dev/null
	KEY=$(dd bs=1 count=1 2> /dev/null)
	stty icanon || true 2> /dev/null
	KEY="${KEY:0:1}"
	echo
}

# Usage: yesno <prompt> "yep"|"nop" (<- default)
#	output: REPLY
yesno()
{
	while true; do
		echo -n "$1"

		getkey

		# if 'n'
		if [ "$KEY" = "${YESNO:2:1}" -o "$KEY" = "${YESNO:3:1}" ]; then
			REPLY=nop
			return
		fi

		# if 'y'
		if [ "$KEY" = "${YESNO:0:1}" -o "$KEY" = "${YESNO:1:1}" ]; then
			REPLY=yep
			return
		fi

		# if \n
		if [ "$KEY" = "" ]; then
			REPLY=$2
			return
		fi
	done
}

realp()
{
	fname=${1%/}	# strips trailing '/'
	while [ -L "$fname" ]; do
		oldfname="$fname"
		fname="$(command ls -l $fname)"
		fname="${fname#*\> }"
		if [ "$fname" = . ] ; then
			fname="$(dirname $oldfname)"
		elif echo $fname | grep -vq '^/' - ; then
			fname="$(dirname $oldfname)/$fname"
		fi
	done
	pushd $(dirname $fname) > /dev/null
	fname=$(pwd -P)/$(basename $fname)
	popd > /dev/null
	echo $fname
}

createfile()
{
	for i in $1 $1.{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; do
		if [ ! -r $i ]; then
			tempfile --name $i && return
		fi
	done
	echo $"$0: could not create temp file!" >&2
	exit 1
}

sendhelp()
{
echo "bug v3.2.10"
echo $"Usage: $1 [options] <packagename> [<text>]
A script to ease the reporting of bugs.

Options:
    -c          Do  not  include  configuration  files  in  the bug
                report.
    -d          Debug.  Don't send the mail to the bug tracking sys
                tem, send it to the current user instead.
    -f          <packagename> is a file belonging to the package
                and bug will search for it.
    -L          When used with -f prevents bug from following
                symlinks.
    -H special_header
                Adds  a  custom  header  to  generated mail. Can be
                repeated to add multiple custom headers.
    -m          Submit a \"maintonly\" bug report. Only sent  to  the
                maintainer not to the mailing list.
    -p          print. Do not send the bug report instead output it
                on stdout so that it can be redirected into a file.
    -q          Submit a quiet bug report (Just register. No e-mail
                forwarding to anyone)
    -s text     Set the Subject of the bug  report.  Otherwise  bug
                will ask for a short description of the problem.
    -S severity Set the severity level of the bug report.
    -x          Do not send a CC to the submitter of the bugreport
    -z          Do not compress the configfiles by  removing  empty
                lines and comments.
    -h          Shows this text.

Please don't report several unrelated bugs - especially ones in
different packages - in one message."
	exit 0
}

if [ "$1" = "--help" ]; then sendhelp ; fi

if [ "$UID" = "0" ] ; then
	echo $"Filing bug reports with system users is insecure and not supported."
	read -p $"Who are you? Enter a non-system user: " -er U
	echo $"Reporting bug as user $U."
	bugrp=$($REALPATH "$0")
	su - $U -c "$bugrp $*"
	exit 0
fi

if grep -q "^$(id -un):" /usr/share/base-passwd/passwd.master ; then
	echo $0: $"Filing bug reports with system users is insecure and not supported." >&2
	exit 1
fi

while getopts "cdfhH:Lmpqs:S:vzx-" OPT; do
	case $OPT in
		c)	NOCONFIG=1;;
		d)	DEBUG=1;;
		f)	SEARCH=1;;
		h)	sendhelp $0;;
		H)	CUSTOM_HEADER[${#CUSTOM_HEADER[*]}]=$OPTARG;;
		L)	NODEREFERENCESYMLINKS=1;;
		m)	MAINT=1;;
		p)	PRINT=1;;
		q)	QUIET=1;;
		s)	SUBJECT="$OPTARG"
			if [ -z "$SUBJECT" ]; then
				NOSUBJECT=yep
			fi
			;;
		S)	SEVERITY="$OPTARG";;
		v)	echo "bug 3.2.10" >&2
			exit 1;;
		x)	DONTCCSUBMITTER=1;;
		z)	NOZAP=1;;
	        -)	break;;
	  	*)	echo $"Usage: $0 [options] <packagename> [<text>] .." >&2
		    	exit 1;;
        esac
done
shift $(($OPTIND - 1))

PACKAGE="$1"
shift || :
#if [ "$1" != "" ]; then
#	echo $"$0: Wrong number of arguments" >&2
#	exit 1
#fi

if [ "$SEARCH" ]; then
	if [ -z "$PACKAGE" ]; then
		echo $"$0: Must specify file name when using -f." 2>&2
		exit 1
	fi
	FILE="$PACKAGE"
	if [ ! -e "$FILE" ]; then
		OLDIFS="$IFS"
		IFS=":$IFS"
		fnfound=""
		for dir in /sbin:/usr/sbin:$PATH; do
			if [ -e "$dir/$FILE" ]; then
				fnfound=yep
				FILE="$dir/$FILE"
				break;
			fi
		done
		IFS="$OLDIFS"
		if [ -z "$fnfound" ]; then
			echo
			echo $"$0: File \`$FILE' not found." 2>&2
			exit 1	
		fi
	fi
	if [ ! "$NODEREFERENCESYMLINKS" ]; then
		FILE=$($REALPATH "$FILE")
	fi
	test "$PRINT" || echo -n $"Searching for package containing ${FILE}..."
	if [ "$FILE" = "" ]; then
		echo
		echo $"$0: Must include parameter when using -f." 2>&2
		exit 1
	fi
	PACKAGE=$(grep -l ^${FILE}\$ /var/lib/dpkg/info/*.list | head -1)
	if [ -z "$PACKAGE" ]; then
		echo
		echo $"$0: File \`$FILE' can't be found in any installed package." >&2
		exit 1
	fi
	PACKAGE=${PACKAGE##*/}
	PACKAGE=${PACKAGE%%.list}
	test "$PRINT" || echo $"done."
	if [ -z "$PRINT" ]; then
		echo $"\`$FILE' found in package \`$PACKAGE'"
		yesno $"Submit bug for this package? [Y|n] " yep
		if [ $REPLY = nop ]; then
			exit 0
		fi
	fi
fi

if [ "$PACKAGE" = "" ]; then
	echo -----------------------------------------------------------------------------
	echo $"Please state in which package you have found a problem, or...
type one of these bug categories:

base             General bugs in the base system
boot-floppies    Bugs in the installation discs
bugs.debian.org  The bug tracking system, @bugs.debian.org
ftp.debian.org   Problems with the FTP site
nonus.debian.org Problems with the non-us FTP site
www.debian.org   Problems with the WWW site
manual           Bugs in the manual
project          Problems related to Project administration
general          General problems (e.g., that many manpages are mode 755)
kernel           Problems with the Linux kernel, or that shipped with Debian
lists.debian.org The mailing lists debian-*@lists.debian.org."
	echo
	read -p $"package? " -er PACKAGE
	if [ "$PACKAGE" = "" ]; then
		echo $"Canceled!"
		exit 0
	fi
fi

# Checking for valid package name
i=$((${#PACKAGE}-1))
while [ $i -gt 0 -o $i -eq 0 ]; do
	case ${PACKAGE:$i:1} in
		" ")
			echo $"$0: Package name goes first, bug report last." >&2
			exit 1
			;;
		[[:upper:]])
			echo $"$0: Packages names are formed with lower case letters." >&2
			exit 1
			;;
		[^-a-z0-9.+])
			echo $"$0: Invalid package name." >&2
			exit 1
			;;
	esac
	i=$(($i - 1))
done


#shift || true

if [ "$EDITOR" = "" ]; then
	EDITOR="$VISUAL"
	if [ "$EDITOR" = "" ]; then
		if [ -x /usr/bin/editor ]; then
			EDITOR="$($REALPATH /usr/bin/editor)"
		else
			if [ ! -x /bin/ae ]; then
				echo $"$0: Cannot locate a texteditor." >&2
				exit 1
			fi
			EDITOR="ae"
		fi
	fi
fi


checkconf()
{ 
# Takes two parameters filename and md5sum and checks if the file was modified
# If so outputs the filename
	if [ "$1" = "/etc/passwd" ]; then exit; fi
	if [ -r "$1" ]; then
		SUM=`md5sum $1`
		if [ "${SUM:0:32}" != "$2" ]; then
			echo "$1"
		fi
	else
		echo $1
	fi
}

checkconfs()
{
	read X
	while [ "$X" ]; do
		checkconf $X
		if ! read X ; then
			return
		fi
	done
}

pinfo()
{
	sed -n </var/lib/dpkg/status -e "/^Package: $1$/,/^Description: /p"
}

setsubject()
{
	if [ "$NOSUBJECT" != "yep" -a "$SUBJECT" = "" ]; then
		while [ "$SUBJECT" = "" ]; do
#			dialog --backtitle "Bug Reporting Tool - Debian/GNU Linux" \
#				--inputbox "Please describe your problems using $PACKAGE" \
#				8 78 2> /tmp/bugtmp...
#			SUBJECT=`cat /tmp/bugtmp...`
			echo $"Please describe your problems using $PACKAGE in one line."
			read -er SUBJECT ;
		done
		SUBJECT="$PACKAGE: $SUBJECT"
	fi
}

setseverity()
{
	local o="cCgGiInNwWhH"

	if [ -z "$SEVERITY" -a ! -z "$PRINT" ]; then
		SEVERITY=normal
	fi

	while [ "$SEVERITY" = "" ]; do
		echo
		echo -----------------------------------------------------------------------------
		echo $"Which should be the severity for this bug report? "
		echo $"
       0) Feature request, or maybe a bug which is very difficult to
       fix due to major design considerations.

       1) The package fails to perform correctly on some conditions, or
       in some systems, or fails to comply current policy documents. Most
       bugs are in this category.

       2) This bug makes the package unsuitable for a stable Debian release.
       The package should be removed from a stable distribution if this
       bug is not fixed.

       3) Dangerous bug. Makes the package in question unusable by anyone or
       mostly so, or causes data loss, or introduces a security hole allowing
       access to the accounts of users who use the package.

       4) Critical bug. Makes unrelated software on the system (or the whole
       system) break, or causes serious data loss, or introduces a security
       hole on systems where you install the package."
       		echo
		echo -n $"Severity? [01234] "
		getkey
		if [ "$KEY" = "4" ]; then
			SEVERITY=critical
		fi
		if [ "$KEY" = "3" ]; then
			SEVERITY=grave
		fi
		if [ "$KEY" = "2" ]; then
			SEVERITY=important
		fi
		if [ "$KEY" = "" -o "$KEY" = "1" ]; then
			SEVERITY=normal
		fi
		if [ "$KEY" = "0" ]; then
			SEVERITY=wishlist
		fi
	done
}

template()
{
	if [ "$SUBJECT" ]; then
		echo "Subject: $SUBJECT"
	fi
 	cat <<-EOF
		Package: $PACKAGE
		Version: $VERSION
		Severity: $SEVERITY

		$*

		-- System Information
		Debian Release: `cat /etc/debian_version`
		Kernel Version: `uname -a`

	EOF
}

trap 'echo $"$0 interrupted." ; rm -f $TEMPS ; exit 0' SIGINT

TEMP1=$(tempfile -pbug)
TEMPS=$TEMP1
if [ -f /var/lib/dpkg/info/$PACKAGE.list ]; then
	test "$PRINT" || echo -n $"Getting package's info..."
	pinfo $PACKAGE >$TEMP1
	VERSION=`grep ^Version: $TEMP1`
	VERSION=${VERSION#Version: }
	DEPS=`grep Depends: $TEMP1` || DEPS=""
	if [ "$NOCONFIG" = "" ]; then
		if grep -q "Conffiles:" $TEMP1; then
			MODCONF=`sed -n <$TEMP1  -e '/Conffiles:/,/^[^ ].*\|^$/p'| egrep -v :\|^$ | checkconfs`
		fi
	fi
	test "$PRINT" || echo $"done."
	setsubject
	setseverity
	template "$*" >$TEMP1

	if [ "$DEPS" != "" ]; then
		test "$PRINT" || echo -n $"Checking ${PACKAGE}'s dependencies..."
		echo "Versions of the packages $PACKAGE depends on:" >>$TEMP1
		DEPS=`echo "$DEPS"|tr "|,\n" "  "|sed -e "s/ ([^)]*)//g" -e "s/Pre-Depends://g" -e "s/Depends://g" -e "s/  / /g" `
		pkgs=""
		vpkgs=""
		
		# See which packages are real and which are virtual
		for i in $DEPS; do
			if [ -f /var/lib/dpkg/info/$i.list ]; then
				pkgs="$pkgs $i"
			else
				vpkgs="$vpkgs $i"
			fi
		done
		test "$pkgs" && dpkg -l $pkgs | tail +6 | sort -u >>$TEMP1
		unset pkgs

		# Now let's search for virtual packages
		for i in $vpkgs; do
			X=${i//+/\\\\+}
			TEMP2=$(tempfile -pbug)
			TEMPS="$TEMPS $TEMP2"
			perl -n000e "print if /^Provides:.* $X\b[^-+]/mo && !/^Status: +[^ ]+ +[^ ]+ +config-files/mo" \
				/var/lib/dpkg/status >$TEMP2
			if [ -s $TEMP2 ]; then
				REALPACKAGE=`head -1 $TEMP2`
				REALPACKAGE=${REALPACKAGE#Package: }
#				echo "$REALPACKAGE	$(grep '^Version:' $TEMP2) (Provides virtual package $i)" >>$TEMP1
				dpkg -l "$REALPACKAGE" | tail +6 >>$TEMP1
				echo "	^^^ (Provides virtual package $i)" >>$TEMP1
			else
				echo "$i	Not installed or no info" >>$TEMP1
			fi
			rm $TEMP2
		done
		unset vpkgs
		test "$PRINT" || echo $"done."
	fi

	if [ "$MODCONF" != "" ]; then
		test "$PRINT" || echo -n $"Including modified configuration files..."
		for i in $MODCONF; do
			if ls -lL "$i" | grep -qv ^.......r ; then
				continue
			fi
			echo -e "\n--- Begin $i (modified conffile)" >>$TEMP1
			if [ -r $i ]; then
				if file -L $i | grep -q "text"; then
					if [ "$NOZAP" ]; then
						cp $i $TEMP1
					else
						sed -e '/^#[^!]/d' -e '/^$/d' <$i >>$TEMP1
					fi
				else
					echo "*** Contents not text ***" >>$TEMP1
				fi
			else
				echo "Config file not present or no permissions for access" >>$TEMP1
			fi
			echo -e "\n--- End $i" >>$TEMP1
		done
		test "$PRINT" || echo $"done."
	fi
else
	VERSION="N/A"
	for i in base bootdisk rootdisk bugs.debian.org ftp.debian.org www.debian.org manual project general kernel lists.debian.org ; do
		if [ "$PACKAGE" = "$i" ]; then
			PSEUDO=yep
			VERSION=$(date -u +"%Y%m%d")
		fi
	done
	if [ "$PSEUDO" != "yep" ] && ! grep -q "^Package: $PACKAGE\>" /var/lib/dpkg/available; then
		echo $"Package $PACKAGE doesn't seem to exist!"
		yesno $"Submit bug anyway? [y|N] " nop
		if [ $REPLY = nop ]; then
			echo $"Bug report not sent"
			exit 1
		fi
	fi
	setsubject
	setseverity
	template "$*" >$TEMP1
fi

if [ -z "$1" -a -z "$PRINT" ]; then
	X=""
	while [ "$X" = "" ]; do
		TEMPBACKUP=$(tempfile -pbug)
		TEMPS="$TEMPS $TEMPBACKUP"
		cp $TEMP1 $TEMPBACKUP
		EDNAME="${EDITOR%% *}"
		EDNAME="${EDNAME##*/}"
		if [ "$EDNAME" = "joe" ]; then
			IFJOE="-skiptop 1"
			echo $"Reporting bug for package: $PACKAGE $VERSION"
			echo -ne \\033[2J\\033[1\;1H
		fi
		if [ "$EDNAME" = "joe" -o \
			"$EDNAME" = "jed" -o \
			"$EDNAME" = "emacs" -o \
			"$EDNAME" = "ae" -o \
			"$EDNAME" = "gnuclient" -o \
			"$EDNAME" = "elvis" -o \
			"$EDNAME" = "elvisnox" -o \
			"$EDNAME" = "nvi" -o \
			"$EDNAME" = "vim" -o \
			"$EDNAME" = "gvim" -o \
			"$EDNAME" = "vi" ]; then
			EDITARGS="+6"
		fi

		do_edit=yep

		while [ "$do_edit" = yep ]; do

			$EDITOR $IFJOE $EDITARGS $TEMP1 || true

			if cmp $TEMP1 $TEMPBACKUP >/dev/null; then
				echo $"Report unmodified, it won't be sent."
				rm $TEMP1 $TEMPBACKUP
				exit 1;
			fi

			while true; do
				echo -n $"Do you really want to submit this bug report? [y|n|E=edit] "

				getkey

				# if 'n'
				if [ "$KEY" = "${YESNO:2:1}" -o "$KEY" = "${YESNO:3:1}" ]; then
					REPLY=nop
					do_edit=nop
					break
				fi

				# if 'y'
				if [ "$KEY" = "${YESNO:0:1}" -o "$KEY" = "${YESNO:1:1}" ]; then
					REPLY=yep
					do_edit=nop
					break
				fi

				# if \n
				if [ "$KEY" = "" -o "$KEY" = $"e" \
						-o "$KEY" = $"E" ]; then
					REPLY=edit
					do_edit=yep
					break
				fi
			done
		done

		if [ $REPLY = nop ]; then
			SAVEFILE=$(createfile /var/tmp/bug.dead )
			cat "$TEMP1" >> $SAVEFILE
			echo $"Bug report cancelled (report text left in $SAVEFILE)."
			exit 0
		fi
		rm $TEMPBACKUP
		X="`head -1 $TEMP1`"
		X=${X#Subject: }
	done
	SUBJECT=$X
else
	if [ "$SUBJECT" = "" -a "$NOSUBJECT" != "yep" ]; then
		SUBJECT="$PACKAGE $VERSION"
	fi
fi

if [ "$PRINT" ]; then
	cat $TEMP1
	rm $TEMP1
	exit 0
fi

MADDR="submit@bugs.debian.org"

if [ "$QUIET" ]; then
	MADDR="quiet@bugs.debian.org"
fi

if [ "$MAINT" ]; then
	MADDR="maintonly@bugs.debian.org"
fi

if [ "$DEBUG" ]; then
	MADDR="$FROM"
else
	if [ ! "$DONTCCSUBMITTER" ]; then
		CC="$FROM"
	fi
fi

{
	echo "From: $FROM"
	echo "Subject: $SUBJECT"
	echo "To: $MADDR"
	test "$CC" && echo "Bcc: $CC"
	echo "X-Mailer: bug 3.2.10"
	test "$REPLYTO" && echo "Reply-To: $REPLYTO"
	i=0
	while [ $i -lt ${#CUSTOM_HEADER[*]} ] ; do
		echo ${CUSTOM_HEADER[$i]}
		i=$((i+1))
	done
	echo
	if [ -z "$1" ]; then
		sed <$TEMP1 -e "1d"
	else
		echo $@
	fi
} |
{
	{
		test -x /usr/sbin/sendmail && /usr/sbin/sendmail -oi -t
	} ||
	{
		SAVEFILE=$( createfile /var/tmp/${PACKAGE}.bug )
		tee "$SAVEFILE" > /dev/null
		echo
		echo $"Error while sending bug report. Not sent."
		echo $"Bug report saved in $SAVEFILE"
		false
	}
} || SAVED=true

rm $TEMP1
if [ "$SAVED" = "" ]; then
	echo $"Bug Report submitted to $MADDR $CC"
	echo $"If you want to submit further information about this bug please wait
to receive the bug number by e-mail. Then mail any extra information to
nnnnn@bugs.debian.org, where nnnnn is the bug number."
else
	exit 1
fi
