Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Sat, 2 Jun 2012 01:42:00 +0200
From: Frank Dittrich <frank_dittrich@...mail.com>
To: john-dev@...ts.openwall.com
Subject: Re: New version of john.bash_completion

On 06/01/2012 05:12 PM, Frank Dittrich wrote:
> Hi magnum,
> 
> here is an enhanced version of the bash completion script (diff against
> current git version attached).

Since apparently this version has not yet been pushed to git, I just
continued working on it.

Changes:
-cosmetic cleanups
-minor bug fixes
-completion support for -opt:val

If $COMP_WORDBREAKS does not contain a colon,
$ ./john -fo:a[tab]
becomes:
$ ./john -fo=a

Otherwise,
$ ./john -fo:a[tab]
becomes
$ ./john -fo:afs

All other options should work as well, at least those options with
useful completions, not just usage hints, e.g., there's no completion
for --users:

Please test to check if I missed something.
Otherwise, enjoy the new functionality.

Frank

--- john.bash_completion.orig	2012-06-01 15:15:05.479095570 +0000
+++ john.bash_completion	2012-06-01 23:28:41.110661714 +0000
@@ -35,10 +35,9 @@
 #
 #
 # The code is still ugly, many things can probably be done more efficiently.
-# Currently, grep and sed are the only external commands used.
-#
-#
+# Currently, grep, tr, and sed are the only external commands used.
 # Trying to build a perfect completion script will be hard.
+#
 # If possible, I'd like to avoid the need to maintain this script whenever
 # john gets a new option.
 #
@@ -72,36 +71,42 @@
 #         but pressing [tab] expands this to something useful
 #         Where to fix this? In john? Some bash config option?
 #
-#       --external should use names of [List.External:..-.] sections
-#         (Just sections without a generate() function, if --wordlist, --incremental or --single
-#         is present on the command line; with a generate() function, if none of these
-#         options is used - WHAT IF the user adds a --wordlist option later?)
-#       --restore= and --status= completion should search for existing .rec files 
-#	  in the correct directory, instead of $PWD.
-#       --mkpc and other options which are not mentioned in the usage output are currently ignored
-#
-#       Should I support -option instead of --option? (currently -option (or -opt) gets replaced 
-#	with --option during completion.
-#	Should I support --option:val, -option:val, or even -opt:val instead of just --option=val?
+#       --external should not use all names of [List.External:..-.] sections, but
+#         just sections without a generate() function, if --wordlist, --incremental or --single
+#         is present on the command line; and just those with a generate() function,
+#         if none of these options is used - WHAT IF the user adds a --wordlist option later?
+#
 #	Should expanding an abbreviated option to its long form also be done by john itself
 #	(requires new john option)?
 
-
-# grep and sed are used to process john's usage info the list of .rec files...
-
 # different implementations for completion logic for these options:
 # --rules --single --incremental --restore --status
 # for __john_completion=[2|any other value]
 #
 # john
 ## on my system, have() is a dummy function which always return "yes", so get rid of calling it... 
-## have grep && have sed && 
+## have grep && have sed && have tr 
 _john()
 {
-	local first cur options valopts compreplya compreplyb encodings formats subformats list hidden dir cmd i ver ver1 ver2 ver3 prev
-
+	local first cur options valopts compreplya compreplyb encodings formats subformats list hidden dir cmd i ver ver1 ver2 ver3 prev words
 	COMPREPLY=()
-	_get_comp_words_by_ref -n = cur
+
+	if [[ "${COMP_WORDBREAKS}" == *:* ]] ; then
+		_get_comp_words_by_ref -n := cur prev words
+	else
+		_get_comp_words_by_ref -n = cur prev words
+		# If the colon is not part of COMP_WORDBREAKS, e.g., due to
+		# including this line into your ~/.bashrc, as mentioned in
+		# /etc/bash_completion ...
+		# 	export COMP_WORDBREAKS="${COMP_WORDBREAKS//:}"
+		# just replace : with = in -opt:val
+		if [[ "${cur}" == -*:* ]] ; then
+			cur="${cur//:/=}"
+			COMPREPLY=( $(compgen -W "${cur}" -- ${cur}) )
+			compopt -o nospace
+			return 0
+		fi
+	fi
 
 #	We need to make sure we run the correct program, not some other program 
 #	called john which is located somewhere in $PATH
@@ -133,29 +138,34 @@ _john()
 	hidden=`${first} --list=hidden-options 2>/dev/null|sed 's#^\(--[a-z-]*=\?\).*$#\1#'`
 
 	case "${cur}" in
-		-?(-)fo?(r|rm|rma|rmat)=dynamic*)
-			if echo "${options}" | grep "^--subformat" > /dev/null ; then
+		-?(-)fo?(r|rm|rma|rmat)+(=|:)dynamic*)
+			if [[ "${options}" == *--subformat* ]] ; then
 				 subformats=`${first} --subformat=LIST|sed 's#^\(User\)\?Format = \(dynamic_[0-9]*\).*$#\2#'`
-				cur=${cur#*=}
+				cur=${cur#*[=:]}
 				COMPREPLY=( $(compgen -W "${subformats}" -- ${cur}) )
 			fi
 			return 0
 			;;
-		-?(-)fo?(r|rm|rma|rmat)=dy?(n|na|nam|nami))
-			if echo "${options}" | grep "^--subformat" > /dev/null ; then
-				cur=${cur#*=}
+		-?(-)fo?(r|rm|rma|rmat)+(=|:)dy?(n|na|nam|nami))
+			if [[ "${options}" == *--subformat* ]] ; then
+				if [[ "${cur#*f}" == o[=:]* || "${cur#*f}" == or[=:]* ]] ; then
+					if [[ `echo "${valopts}"|grep -c "^-*${cur%[=:]*}"` -ne 1 ]] ; then
+						return 0
+					fi
+				fi
+				cur=${cur#*[=:]}
 				COMPREPLY=( $(compgen -W "dynamic" -- ${cur}) )
 				compopt -o nospace
 			fi
 			return 0
 			;;
-		-?(-)fo?(r|rm|rma|rmat)=*)
-			if [[ "_${cur#*o}" == "_=" || "_${cur#*o}" == "_r=" ]] ; then
-				if [[ `echo "${valopts}"|grep -c "^-*${cur%=}"` -ne 1 ]] ; then
+		-?(-)fo?(r|rm|rma|rmat)+(=|:)*)
+			if [[ "${cur#*f}" == o[=:]* || "${cur#*f}" == or[=:]* ]] ; then
+				if [[ `echo "${valopts}"|grep -c "^-*${cur%[=:]*}"` -ne 1 ]] ; then
 					return 0
 				fi
 			fi
-			cur=${cur#*=}
+			cur=${cur#*[=:]}
 			formats=`${first} |sed -n '/^--format/,$ { s#^--format=[ A-Za-z]*:##; /^--/ b; s#^ *##; s#\<dynamic_n\>#dynamic#; s#[/ ]#\n#g; p }'`
 			COMPREPLY=( $(compgen -W "${formats}" -- ${cur}) )
 			return 0
@@ -176,15 +186,15 @@ _john()
 			fi
 			return 0
 			;;
-		-?(-)re?(s|st|sto|stor|store)=*|-?(-)sta?(t|tu|tus)=*)
-			if [[ "_${cur}" == "_-re=" || "_${cur}" == "_--re=" ]] ; then
+		-?(-)re?(s|st|sto|stor|store)+(=|:)*|-?(-)sta?(t|tu|tus)+(=|:)*)
+			if [[ "${cur}" == -re[=:]* || "${cur}" == --re[=:]* ]] ; then
 				if [[ `echo "${valopts}"|grep -c "^--re"` -ne 1 ]] ; then
 					return 0
 				fi
 			fi
 # If there is no .rec file in the current directory, the old completion logic will show all files:
 ##echo _`for f in *.rec; do echo ${f%.rec};done`_
-			cur=${cur#*=}
+			cur=${cur#*[=:]}
 # cd $JOHN/ or Private home for system-wide builds, if ./john --list=build-info works?
 # NO, this would be wrong!
 # .rec files are stored in the current directory (or a subdirectory if the session name contains a slash)
@@ -197,14 +207,14 @@ _john()
 			done
 			return 0
 			;;
-		-?(-)w?(o|or|ord|ordl|ordli|ordlis|ordlist)=*)
-			cur=${cur#*=}
+		-?(-)w?(o|or|ord|ordl|ordli|ordlis|ordlist)+(=|:)*)
+			cur=${cur#*[=:]}
 			 __expand_tilde_by_ref cur 2>/dev/null
 			_filedir
 			return 0
 			;;
  		--rules|--single)
-			if echo "${valopts}" | grep "^${cur}$" > /dev/null ; then
+			if [[ "${valopts}" == *${cur}* ]] ; then
 				if [[ "_${__john_completion}" == "_2" ]] ; then
 					COMPREPLY=( $(compgen -W "${cur}=" -- ${cur}) )
 					compopt -o nospace
@@ -226,26 +236,26 @@ _john()
 			fi
 			return 0
 			;;
-		-?(-)ru?(l|le|les)=*|-?(-)si?(n|ng|ngl|ngle)=*)
+		-?(-)ru?(l|le|les)+(=|:)*|-?(-)si?(n|ng|ngl|ngle)+(=|:)*)
 			# let's assume every john version which supports --single= 
 			# also supports --rules=, and vice versa
-			if echo "${valopts}" | grep "^--rules$" > /dev/null ; then
+			if [[ "${valopts}" == *--rules* ]] ; then
 				cmd=`echo ${COMP_LINE}|sed "s# ${cur}# --list=rules #"`
 				list=`${cmd} 2>/dev/null`
 				if [[ $? -ne 0 ]] ; then
 					list=`${first} --list=rules 2>/dev/null`
 				fi
 				if [[ $? -eq 0 ]] ; then
-					cur=`echo ${cur#*=}|LC_ALL=C tr [A-Z] [a-z]`
+					cur=`echo ${cur#*[=:]}|LC_ALL=C tr A-Z a-z`
 					COMPREPLY=( $(compgen -W "${list}" -- ${cur}) )
 				else
-					cur=${cur#*=}
+					cur=${cur#*[=:]}
 					COMPREPLY=( $(compgen -W "NT single wordlist" -- ${cur}) )
 				fi
 			fi
 			return 0
 			;;
-		-?(-)ex?(t|te|ter|tern|terna|ternal)=*)
+		-?(-)ex?(t|te|ter|tern|terna|ternal)+(=|:)*)
 			cmd=`echo ${COMP_LINE}|sed "s# ${cur}# --list=externals #"`
 			list=`${cmd} 2>/dev/null`
 			if [[ $? -ne 0 ]] ; then
@@ -278,9 +288,9 @@ _john()
 						list="${list} DumbForce KnownForce DateTime Repeats Subsets AtLeast1-Simple AtLeast1-Generic Policy AppendLuhn AutoAbort AutoStatus"
 					fi
 				fi
-				cur=${cur#*=}
+				cur=${cur#*[=:]}
 			else
-				cur=`echo ${cur#*=}|LC_ALL=C tr [A-Z] [a-z]`
+				cur=`echo ${cur#*[=:]}|LC_ALL=C tr A-Z a-z`
 			fi
 			COMPREPLY=( $(compgen -W "${list}" -- ${cur}) )
 			return 0
@@ -304,23 +314,23 @@ _john()
 			fi
 			return 0
 			;;
-		-?(-)i?(n|nc|ncr|ncre|ncrem|ncreme|ncremen|ncrement|ncrementa|ncremental)=*)
+		-?(-)i?(n|nc|ncr|ncre|ncrem|ncreme|ncremen|ncrement|ncrementa|ncremental)+(=|:)*)
 			cmd=`echo ${COMP_LINE}|sed "s# ${cur}# --list=inc-modes #"`
 			list=`${cmd} 2>/dev/null`
 			if [[ $? -ne 0 ]] ; then
 				list=`${first} --list=inc-modes 2>/dev/null`
 			fi
 			if [[ $? -eq 0 ]] ; then
-				cur=`echo ${cur#*=}|LC_ALL=C tr [A-Z] [a-z]`
+				cur=`echo ${cur#*[=:]}|LC_ALL=C tr A-Z a-z`
 				COMPREPLY=( $(compgen -W "${list}" -- ${cur}) )
 			else
-				cur=${cur#*=}
+				cur=${cur#*[=:]}
 				COMPREPLY=( $(compgen -W "All Alpha Digits Alnum LanMan" -- ${cur}) )
 			fi
 			return 0
 			;;
-		-?(-)mak?(e|e-|e-c|e-ch|e-cha|e-char|e-chars|e-charse|e-charset)=*)
-			cur=${cur#*=}
+		-?(-)mak?(e|e-|e-c|e-ch|e-cha|e-char|e-chars|e-charse|e-charset)+(=|:)*)
+			cur=${cur#*[=:]}
 			#redirect stderr just in case __expand_tilde_by_ref
 			#doesn't exist everywhere
 			#(I'm a bit worried because of the __ at the begin.
@@ -331,21 +341,18 @@ _john()
 			_filedir "chr"
 			return 0
 			;;
-		--stdout=*|--markov=*)
-			return 0
-			;;
 		--stdout)
 			COMPREPLY=( $(compgen -W "--stdout --stdout=LENGTH" -- ${cur}) )
 			return 0
 			;;
 		--markov)
-			if echo "${options}" | grep "^${cur}$" > /dev/null ; then
+			if [[ "${valopts}" == *${cur}* ]] ; then
 				COMPREPLY=( $(compgen -W "--markov --markov=LEVEL[:START[:END[:LENGTH]]]" -- ${cur}) )
 			fi
 			return 0
 			;;
 		--test)
-			if echo "${valopts}" | grep "^${cur}$" > /dev/null ; then
+			if [[ "${valopts}" == *${cur}* ]] ; then
 				COMPREPLY=( $(compgen -W "--test --test=SECONDS" -- ${cur}) )
 			else
 				COMPREPLY=( $(compgen -W "${cur}" -- ${cur}) )
@@ -353,31 +360,31 @@ _john()
 			return 0
 			;;
 		--show)
-			if echo "${valopts}" | grep "^--show$" > /dev/null ; then
+			if [[ "${valopts}" == *${cur}* ]] ; then
 				COMPREPLY=( $(compgen -W "--show --show=LEFT" -- ${cur}) )
 			else
 				COMPREPLY=( $(compgen -W "--show" -- ${cur}) )
 			fi
 			return 0
 			;;
-		-?(-)sho?(w)=l*)
-			if echo "${valopts}" | grep "^--show$" > /dev/null ; then
-				cur=${cur#*=}
+		-?(-)sho?(w)+(=|:)l*)
+			if [[ "${valopts}" == *--show* ]] ; then
+				cur=${cur#*[=:]}
 				COMPREPLY=( $(compgen -W "left" -- ${cur}) )
 			fi
 			return 0
 			;;
-		-?(-)sho?(w)=*)
-			if echo "${valopts}" | grep "^--show$" > /dev/null ; then
-				cur=${cur#*=}
+		-?(-)sho?(w)+(=|:)*)
+			if [[ "${valopts}" == *--show* ]] ; then
+				cur=${cur#*[=:]}
 				COMPREPLY=( $(compgen -W "LEFT" -- ${cur}) )
 			fi
 			return 0
 			;;
-		--users=L*|--users=U*|--users=-*|--groups=G*|--groups=-*|--shells=S*|--shells=-*|--salts=C*|--salts=-*)
+		--users=?(-)+(L|U)*|--groups=+(-|G)*|--shells=+(-|S)*|--salts=+(-|C)*)
 			return 0
 			;;
-		--users=*)
+		--users=?(-))
 			cur=${cur#*=}
 			COMPREPLY=( $(compgen -W "LOGIN,... UID,... -LOGIN,... -UID,..." -- ${cur}) )
 			return 0
@@ -397,11 +404,11 @@ _john()
 			COMPREPLY=( $(compgen -W "COUNT -COUNT" -- ${cur}) )
 			return 0
 			;;
-		-?(-)en?(c|co|cod|codi|codin|coding)=*)
-			if  echo "${valopts}" | grep "^--encoding=" > /dev/null ; then
+		-?(-)en?(c|co|cod|codi|codin|coding)+(=|:)*)
+			if [[ "${valopts}" == *--encoding=* ]] ; then
 				# --encoding=LIST writes to stderr
 				encodings=`${first} --encoding=LIST 2>&1|grep -v 'Supported encodings'|sed 's#[,)]##g'|sed 's#(or ##g'`
-			cur=${cur#*=}
+			cur=${cur#*[=:]}
 				if [[ ${COMP_CWORD} -eq 2 || ${COMP_CWORD} -eq 3 && "_${cur}" != "_" ]] ; then
 					encodings="${encodings} LIST"
 					# make sure LIST will be the first option:
@@ -411,11 +418,11 @@ _john()
 			fi
 			return 0
 			;;
-		-?(-)po?(t)=*)
-			if  echo "${valopts}" | grep "^--encoding=" > /dev/null ; then
+		-?(-)po?(t)+(=|:)*)
+			if  [[ "${valopts}" == *--pot=* ]] ; then
 				# if --pot= is used, john always looks for the file $PWD
 				# (tested with system-wide and local build of john)
-				cur=${cur#*=}
+				cur=${cur#*[=:]}
 				#redirect stderr just in case __expand_tilde_by_ref
 				#doesn't exist everywhere
 				#(I'm a bit worried because of the __ at the begin.
@@ -425,68 +432,65 @@ _john()
 			fi
 			return 0
 			;;
-		-?(-)co?(n|nf|nfi|nfig)=*)
-			if  echo "${valopts}" | grep "^--encoding=" > /dev/null ; then
+		-?(-)co?(n|nf|nfi|nfig)+(=|:)*)
+			if [[ "${valopts}" == *--config=* ]] ; then
 				# if --config= is used, john always looks for files in $PWD
 				# (tested for system-wide and local builds)
-				cur=${cur#*=}
+				cur=${cur#*[=:]}
 				__expand_tilde_by_ref cur 2>/dev/null
 				_filedir '@...nf|ini)'
 			fi
 			return 0
 			;;
-		-?(-)sav?(e|e-|e-m|e-me|e-mem|e-memo|e-memor|e-memory)=*)
-			cur=${cur#*=}
+		-?(-)sav?(e|e-|e-m|e-me|e-mem|e-memo|e-memor|e-memory)+(=|:)*)
+			cur=${cur#*[=:]}
 			COMPREPLY=( $(compgen -W "1 2 3" -- ${cur}) )
 			return 0
 			;;
-		-?(-)reg?(e|en|en-|en-l|en-lo|en-los|en-lost|en-lost-|en-lost-s|en-lost-sa|en-lost-sal|en-lost-salt|en-lost-salts)=*)
-			if echo "${valopts}" | grep "^--regen-lost-salts=" > /dev/null ; then
-				cur=${cur#*=}
+		-?(-)reg?(e|en|en-|en-l|en-lo|en-los|en-lost|en-lost-|en-lost-s|en-lost-sa|en-lost-sal|en-lost-salt|en-lost-salts)+(=|:)*)
+			if [[ "${valopts}" == *--regen-lost-salts=* ]] ; then
+				cur=${cur#*[=:]}
 				COMPREPLY=( $(compgen -W "1 2 3 4 5" -- ${cur}) )
 			fi
 			return 0
 			;;
-		--subformat=l*)
-			if echo "${options}" | grep "^--subformat=" > /dev/null ; then
-				cur=${cur#*=}
+		-?(-)su?(b|bf|bfo|bfor|bform|bforma|bformat)+(=|:)l*)
+			if [[ "${options}" == *--subformat=* ]] ; then
+				cur=${cur#*[=:]}
 				COMPREPLY=( $(compgen -W "list" -- ${cur}) )
 			fi
 			return 0
 			;;
-		--subformat=*)
-			if echo "${valopts}" | grep "^--subformat=" > /dev/null ; then
-				cur=${cur#*=}
+		-?(-)su?(b|bf|bfo|bfor|bform|bforma|bformat)+(=|:)*)
+			if [[ "${options}" == *--subformat=* ]] ; then
+				cur=${cur#*[=:]}
 				COMPREPLY=( $(compgen -W "LIST" -- ${cur}) )
 			fi
 			return 0
 			;;
-		-?(-)pla?(t|tf|tfo|tfor|tform)=+(L|l)*|-?(-)dev?(i|ic|ice)=+(L|l)*)
+		-?(-)pla?(t|tf|tfo|tfor|tform)+(=|:)+(L|l)*|-?(-)dev?(i|ic|ice)+(=|:)+(L|l)*)
 			# CUDA doesn't allow --device=LIST
 			# workaround: check if --platform= is allowed
-			if echo "${valopts}" | grep "^--platform=$" > /dev/null ; then
-				cur=${cur#*=}
+			if [[ "${valopts}" == *--platform=* ]] ; then
+				cur=${cur#*[=:]}
 				COMPREPLY=( $(compgen -W "LIST list" -- ${cur}) )
 			fi
 			return 0
 			;;
-		--platform=|--device=)
+		-?(-)platform+(=|:)|-?(-)device+(=|:))
 			# --device=LIST isn't supported for CUDA, but for CUDA
 			# --platform= is not a valid option
-			if echo "${valopts}" | grep "^--platform=$" > /dev/null ; then
+			if [[ "${valopts}" == *--platform=* ]] ; then
 				# Calling john --platform=LIST just to find possible completions
 				# will take too long
-				cur=${cur#*=}
+				cur=${cur#*[=:]}
 				COMPREPLY=( $(compgen -W "LIST N" -- ${cur}) )
 			fi
 			return 0
 			;;
-		--platform=*|--device=*)
-			return 0
-			;;
-		-?(-)l?(i|is|ist)=*)
-			if echo "${hidden}" | grep "^--list=" > /dev/null ; then
-				cur=${cur#*=}
+		-?(-)l?(i|is|ist)+(=|:)*)
+			if [[ "${hidden}" == *--list=* ]] ; then
+				cur=${cur#*[=:]}
 				# the --list=? output changed, that's why a more complex regex is used
 				# to cover all cases
 				list=`${first} --list=? 2>/dev/null|sed 's#\(,\)\?\( or\)\?[ ]*[<].*$##; s#,##g'`
@@ -498,7 +502,7 @@ _john()
 			fi
 			return 0
 			;;
-		-*=)
+		-*+(=|:))
 			return 0;
 			;;
 		-*)

Powered by blists - more mailing lists

Your e-mail address:

Powered by Openwall GNU/*/Linux - Powered by OpenVZ