[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Mon, 21 May 2012 10:24:51 +0200
From: Frank Dittrich <frank_dittrich@...mail.com>
To: john-users@...ts.openwall.com
Subject: bash completion for john and unique
Hi all,
I created a bash completion script for John the Ripper which supports
bash completion for john (official releases and jumbo versions) and
unique (here, bash completion only makes sense for the jumbo version,
and is limited to listing possible options mentioned in the usage output).
The attached file john.bash_completion contains some fixes for
--wordlist= completion and --restore=/--status= completion, compared to
the version in magnum's current git repository on github.
Once included in the jumbo version, this file will probably be located
in the src directory.
I'd like to get some feedback from you so that I can change the
completion logic or fix bugs before the next jumbo version is released.
To just test bash completion for john, you can download the attached
file somewhere and source it like this, if you are in the directory
where you downloaded the file:
. john.bash_completion
(It is a dot, followed by a space, followed by the file name.)
If you want to use the bash completion for john permanently, not just in
the current session, you should add this line to your ~/.bashrc file:
. /full_path_name/john.bash_completion
If you want to enable bash completion for john permanently for all users
with bash as their shell, you have to copy this file into the
/etc/bash_completion.d/ directory (admin privilege is needed).
For those of you who didn't know this already:
Bash completion means: the shell (bash) suggests possible command
completions or automatically completes the command, as far as this is
possible, when you press the [tab] key on the command line.
Pressing [tab] once adds those characters which are common between all
possible completions. Pressing [tab] twice will list all possible
completions.
In the following examples, I'll use the $ sign as a marker for the
command prompt. Imagine that the cursor is located at the end of the
command, without any trailing spaces between command and cursor.
(If the cursor is separated from the words on the command line, then the
default bash completion logic applies, which means bash suggests
existing file and directory names.)
A first, simple example:
$ ./john -wo
Pressing [tab], will automatically change the command line to
$ ./john --wordlist=
Wile john allows to specify options with just one leading dash, I use
the form mention in john's usage output for completion.
That's why - will be replaced by --.
Since there is only one john option name starting with --wo, it gets
completed to --wordlist. Since this option requires a value, bash
completion adds the =.
Actually, there is only one option starting with --w, so even
$ ./john -w
would get expanded to
$ ./john --wordlist=
Pressing [tab] on the command line
$ ./john --wordlist=
will change nothing (unless all the names of files and directories in
the current directory start with the same character).
Pressing [tab] once more will list all the file (and directory) names in
the current directory as possible completions.
Pressing [tab] twice on the command line
$ ./john --wordlist=p
will just list file names starting with p as possible completions:
$ ./john --wordlist=p
pass_gen.pl password.lst pdf2john pwsafe2john
Pressing [tab] once on
$ ./john --wordlist=passw
will change the command line to
$ ./john --wordlist=password.lst
(A space is added at the end of the command, so that you can just type
the next word...)
Pressing [tab] twice on the command line
$ ./john --pot=will list files with the .pot extension and directories
as possible completions:
$ ./john --pot=
fdtest/ fdtestpot.pot john.pot
In some cases, completion options based on usage information is suggested:
$ john --test
--test --test=SECONDS
(provided that the john version in question already supports an optional
value for the --time option)
or
$ ./john --markov
--markov --markov=LEVEL[:START[:END[:LENGTH]]]
(jumbo version only)
I implemented completion for every option known the john version you are
trying to execute.
If you find bugs or if you have suggestions for possible improvements,
please mention what you tried, what you expected, and what you got instead.
Please also include the output of these commands:
$ uname -a
$ bash --version
$ ./john | head -n 1
or
$ john | head -n 1
(depending on how you start john)
Also, if completion for john options doesn't work at all, please test
whether completion for other commands works.
E.g., cd into the src directory, and try completion for
$ make lin
Now to the questions I hope get some feedback:
1.
$ ./john --make-charset=
all.chr alpha.chr fdtest/
alnum.chr digits.chr lanman.chr
As you see, the completion logic lists directories and .chr files.
Should the completion logic just list directories (or nothing at all),
to avoid accidentally overwriting an existing .chr file?
2.
$ john -i
gets completed to
$ john --incremental
(There is no trailing space added, because the --incremental option has
optional values.)
$ john --incremental
--incremental --incremental=Alnum --incremental=Digits
--incremental=All --incremental=Alpha --incremental=LanMan
(output for a non-jumbo john version 1.7.8)
$ ./john --incremental
--incremental --incremental=alpha --incremental=lanman
--incremental=all --incremental=digits
--incremental=alnum --incremental=digits8
(output for the current git version, will be similar for next jumbo)
The above is the currently implemented default completion logic for john.
Mixed case incremental mode names indicate a hard coded list of
incremental modes.
Lower case incremental mode names indicate a list derived from
analyzing the config file (in this case, john.conf).
So, the user will have to type the space character (to use the default
incremental mode) or the '=' character, to get completion for possible
incremental modes when pressing [tab]:
$ john --incremental=
All Alnum Alpha Digits LanMan
or
$ ./john --incremental=
all alnum alpha digits digits8 lanman
An alternative completion logic would replace "--incremental" with
"--incremental=" when pressing [tab], even though --incremental without
a '=' and without an incremental mode name would also be valid.
$ ./john --incremental
would then get completed to
$ ./john --incremental=
when pressing [tab].
For jumbo versions, the --rules and --single options are similar to
--incremental, because they also allow to specify an optional value.
(The official, non-jumbo version doesn't allow --rules=... or --single=...)
Because I am not sure what john users might prefer, I implemented both
versions of the completion logic.
The default logic is the one which doesn't add the trailing '=' when
pressing tab.
$ ./john --rules
--rules --rules=single
--rules=nt --rules=wordlist
To try the alternative logic, use
$ export __john_completion=2
This will add the trailing '=' when pressing [tab] here:
$ ./john --incremental
(jumbo and official version)
and here:
$ ./john --rules
$ ./john --single
(jumbo version only)
If you want to switch back to the default logic, just use
$ export __john_completion=1
When including the line
export __john_completion=2
into your ~/.bashrc, please note that the logic might change until the
next jumbo version is released.
Please let me know what questions / suggestions you have.
Should I add a doc/README.bash-completion file?
Frank
# bash completion for john and unique commands (John the Ripper)
#
# This software is Copyright © 2012 Frank Dittrich
# and hereby released to the general public under the following terms:
# Redistribution and use in source and binary forms, with or without
# modification, are permitted.
#
# Minor improvements suggested by Aleksey Cherepanov have been
# incorporated.
#
#
# This file needs to be copied into the /etc/bash_completion.d/.
# To make the new completion rules work, you need to logout and login,
# or source /etc/bash_completion instead.
#
# Alternatively, just add a line
# . <path_to_john's_source_directory>/john.bash_completion
# to your ~/.bashrc and logout/login.
#
# To use the same completion rules not just for john, but for
# differently named binaries (say john-omp, john-sse2i, john-avx,
# john-cuda, john-gpu, ...),
# just use this command to get the current completion rule settings:
# complete -p john
#
# If the output is
# complete -F _john john
# you can use this command to activate the same completion rules
# for john-omp:
# complete -F _john john-omp
#
# To use these completion rules permanently, you might add
# complete -F _john john-omp
# to your ~/.bashrc file.
#
#
# The code is still ugly, many things can probably be done more efficiently.
# Currently, grep 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.
#
# john can either be globally installed (e.g. in /usr/bin/john),
# or it can be installed locally somewhere in a user's home directory.
# It can be an official version, or a community encanced (jumbo) version,
# with a variety of patches.
#
# FIXME: is using __expand_tilde_by_ref OK?
#
# FIXME: for some reason completion for --option= only works
# if the cursor is at the end of the command,
# i.e. [[ ${COMP_POINT} -eq ${#COMP_LINE} ]]
# not if some words follow the one to be completed...
# If ${cur#*=} is not empty, completion works even in the middle
# of the command line
# This is annoying if I want to complete --rules= in
# ./john --rules= --config=test.conf
#
# FIXME: should completion for --make-charset really list existing .chr files?
#
# TODO:
# --wordlist=~user/filename or --wordlist=~/dir/file doesn't work,
# 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?
# 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 &&
_john()
{
local first cur options valopts compreplya compreplyb encodings formats subformats list hidden dir cmd i ver ver1 ver2 ver3 prev
COMPREPLY=()
_get_comp_words_by_ref -n = cur
# We need to make sure we run the correct program, not some other program
# called john which is located somewhere in $PATH
first="${COMP_WORDS[0]}"
# Most options are listed at the begin of the line, but the line with the --pipe option
# does have trailing spaces, and --stdin is mentioned after --wordlist=FILE.
#
# All options (the '=' will be emoved for options with an optional value)
options=""
# FIXME: How do I suppress the error message if someone tries to be clever: cd run; ./john --[tab] ???
options="`${first} 2>/dev/null|sed -n '{ s#^ *\(--[a-z-]*=\?\(LIST\)\?\).*$#\1# }; /^--/ p'` --stdin"
if [[ "_${options}" == "_ --stdin" ]] ; then
_filedir_xspec 2> /dev/null
return 0
fi
# Just those options that can be used together with a value, even if that value is optional:
valopts=`${first} 2>/dev/null|grep '^ *--[a-z\[-]*='|grep -v '^ *--subformat='|sed 's#^ *\([a-z=-]*\).*$#\1#'`
# This is used to decide whether or not the completion should add a trailing space.
# (That means, for a jumbo build, --rules doesn't get a trailing space, but for the john version
# distributed by fedora16, --rules does get a trailing space during completion.
# The same applies for --show and single)
# now add the "hidden options" (not mentioned in the usage output, but in doc/OPTIONS and
# with --list=hidden-options
# Currently, all hidden options do have mandatory values (--option=value), this makes
# addition of these easier
hidden=""
hidden=`${first} --list=hidden-options 2>/dev/null|sed 's#^\(--[a-z-]*=\?\).*$#\1#'`
case "${cur}" in
--format=dynamic*)
if echo "${options}" | grep "^--subformat" > /dev/null ; then
subformats=`${first} --subformat=LIST|sed 's#^\(User\)\?Format = \(dynamic_[0-9]*\).*$#\2#'`
cur=${cur#*=}
COMPREPLY=( $(compgen -W "${subformats}" -- ${cur}) )
fi
return 0
;;
--format=dy|--format=dyn|--format=dyna|--format=dynam|--format=dynami)
if echo "${options}" | grep "^--subformat" > /dev/null ; then
cur=${cur#*=}
COMPREPLY=( $(compgen -W "dynamic" -- ${cur}) )
compopt -o nospace
fi
return 0
;;
--format=*)
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
;;
--restore|--status)
if [[ "_${__john_completion}" == "_2" ]] ; then
COMPREPLY=( $(compgen -W "${cur}=" -- ${cur}) )
compopt -o nospace
else
prev="${cur}"
cur=""
_filedir "rec"
for (( i=0; i < ${#COMPREPLY[@... i++)); do
COMPREPLY[$i]="${prev}=${COMPREPLY[$i]%*.rec}"
done
COMPREPLY[${#COMPREPLY[@...="${prev}"
fi
return 0
;;
--restore=*|--status=*)
# 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#*=}
# 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)
__expand_tilde_by_ref cur 2>/dev/null
_filedir "rec"
for (( i=0; i < ${#COMPREPLY[@... i++)); do
# Do I have to add the trailing / for directories? Apparently not!
COMPREPLY[$i]="${COMPREPLY[$i]%*.rec}"
done
return 0
;;
--wordlist=*)
cur=${cur#*=}
__expand_tilde_by_ref cur 2>/dev/null
_filedir
return 0
;;
--rules|--single)
if echo "${valopts}" | grep "^${cur}$" > /dev/null ; then
if [[ "_${__john_completion}" == "_2" ]] ; then
COMPREPLY=( $(compgen -W "${cur}=" -- ${cur}) )
compopt -o nospace
else
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 [[ $? -ne 0 ]] ; then
list="single wordlist NT"
fi
list=`echo "${list}"|sed 's# #\n#g'|sed "s#^\(.\)#${cur}=\1#"`
list="${list} ${cur}"
COMPREPLY=( $(compgen -W "${list}" -- ${cur}) )
fi
else
COMPREPLY=( $(compgen -W "${cur}" -- ${cur}) )
fi
return 0
;;
--rules=*|--single=*)
if echo "${valopts}" | grep "^${cur%=*}$" > /dev/null ; 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=${cur#*=}
COMPREPLY=( $(compgen -W "${list}" -- ${cur}) )
else
cur=${cur#*=}
COMPREPLY=( $(compgen -W "NT single wordlist" -- ${cur}) )
fi
fi
return 0
;;
--external=*)
cmd=`echo ${COMP_LINE}|sed "s# ${cur}# --list=externals #"`
list=`${cmd} 2>/dev/null`
if [[ $? -ne 0 ]] ; then
list=`${first} --list=externals 2>/dev/null`
fi
if [[ $? -ne 0 ]] ; then
list="Filter_Alpha Filter_Digits Filter_Alnum Filter_LanMan LanMan Double Parallel Strip Keyboard"
ver=`${first} 2>/dev/null|sed -n '/^John the Ripper password cracker, ver/ s#^John the Ripper password cracker, ver[a-z :]*\([0-9.]*\).*$#\1#p'`
ver1=`echo $ver|sed 's#^\([0-9]*\).*$#\1#'`
ver2=`echo $ver|sed 's#^[0-9]*.\([0-9]*\).*$#\1#'`
ver3=`echo $ver|sed 's#^[0-9]*.[0-9]*.\([0-9]*\).*$#\1#'`
if [[ "_${ver3}" == "_" ]] ; then
ver3=0
fi
if [[ $ver1 -eq 1 && $ver2 -eq 7 ]] ; then
if [[ $ver3 -ge 3 ]] ; then
list="${list} DumbForce KnownForce"
fi
if [[ $ver3 -ge 7 ]] ; then
list="${list} DateTime Repeats Subsets AtLeast1-Simple AtLeast1-Generic Policy"
fi
if [[ $ver3 -ge 8 ]] ; then
list="${list} AppendLuhn"
fi
if [[ $ver3 -ge 9 ]] ; then
list="${list} AutoAbort AutoStatus"
fi
else
if [[ $ver1 -gt 1 || $ver1 -eq 1 && ver2 -gt 7 ]] ; then
list="${list} DumbForce KnownForce DateTime Repeats Subsets AtLeast1-Simple AtLeast1-Generic Policy AppendLuhn AutoAbort AutoStatus"
fi
fi
fi
cur=${cur#*=}
COMPREPLY=( $(compgen -W "${list}" -- ${cur}) )
return 0
;;
--incremental)
if [[ "_${__john_completion}" == "_2" ]] ; then
COMPREPLY=( $(compgen -W "${cur}=" -- ${cur}) )
compopt -o nospace
else
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 [[ $? -ne 0 ]] ; then
list="All Alpha Digits Alnum LanMan"
fi
list=`echo "${list}"|sed 's# #\n#g'|sed "s#^\(.\)#${cur}=\1#"`
list="${list} ${cur}"
COMPREPLY=( $(compgen -W "${list}" -- ${cur}) )
fi
return 0
;;
--incremental=*)
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=${cur#*=}
COMPREPLY=( $(compgen -W "${list}" -- ${cur}) )
else
cur=${cur#*=}
COMPREPLY=( $(compgen -W "All Alpha Digits Alnum LanMan" -- ${cur}) )
fi
return 0
;;
--make-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.
#May be this function isn't part of an "official" API.)
__expand_tilde_by_ref cur 2>/dev/null
# FIXME: should I just use directories for completion, not files,
# FIXME: to make overwriting existing files harder?
_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
COMPREPLY=( $(compgen -W "--markov --markov=LEVEL[:START[:END[:LENGTH]]]" -- ${cur}) )
fi
return 0
;;
--test)
if echo "${valopts}" | grep "^${cur}$" > /dev/null ; then
COMPREPLY=( $(compgen -W "--test --test=SECONDS" -- ${cur}) )
else
COMPREPLY=( $(compgen -W "${cur}" -- ${cur}) )
fi
return 0
;;
--show)
if echo "${valopts}" | grep "^--show$" > /dev/null ; then
COMPREPLY=( $(compgen -W "--show --show=LEFT" -- ${cur}) )
else
COMPREPLY=( $(compgen -W "--show" -- ${cur}) )
fi
return 0
;;
--show=l*)
if echo "${valopts}" | grep "^--show$" > /dev/null ; then
cur=${cur#*=}
COMPREPLY=( $(compgen -W "left" -- ${cur}) )
fi
return 0
;;
--show=*)
if echo "${valopts}" | grep "^--show$" > /dev/null ; 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=-*)
return 0
;;
--users=*)
cur=${cur#*=}
COMPREPLY=( $(compgen -W "LOGIN,... UID,... -LOGIN,... -UID,..." -- ${cur}) )
return 0
;;
--groups=*)
cur=${cur#*=}
COMPREPLY=( $(compgen -W "GID,... -GID,..." -- ${cur}) )
return 0
;;
--shells=*)
cur=${cur#*=}
COMPREPLY=( $(compgen -W "SHELL,... -SHELL,..." -- ${cur}) )
return 0
;;
--salts=*)
cur=${cur#*=}
COMPREPLY=( $(compgen -W "COUNT -COUNT" -- ${cur}) )
return 0
;;
--encoding=*)
if echo "${options}" | grep "^--encoding=" > /dev/null ; 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#*=}
if [[ ${COMP_CWORD} -eq 2 || ${COMP_CWORD} -eq 3 && "_${cur}" != "_" ]] ; then
encodings="${encodings} LIST"
# make sure LIST will be the first option:
LC_ALL=C
fi
COMPREPLY=( $(compgen -W "${encodings}" -- ${cur}) )
fi
return 0
;;
--pot=*)
# if --pot= is used, john always looks for the file $PWD
# (tested with system-wide and local build of john)
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.
#May be this function isn't part of an "official" API.)
#
__expand_tilde_by_ref cur 2>/dev/null
_filedir "pot"
return 0
;;
--config=*)
# if --config= is used, john always looks for files in $PWD
# (tested for system-wide and local builds)
cur=${cur#*=}
__expand_tilde_by_ref cur 2>/dev/null
_filedir '@...nf|ini)'
return 0
;;
--save-memory=*)
cur=${cur#*=}
COMPREPLY=( $(compgen -W "1 2 3" -- ${cur}) )
return 0
;;
--regen-lost-salts=*)
if echo "${options}" | grep "^--regen-lost-salts=" > /dev/null ; 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#*=}
COMPREPLY=( $(compgen -W "list" -- ${cur}) )
fi
return 0
;;
--subformat=*)
if echo "${options}" | grep "^--subformat=" > /dev/null ; then
cur=${cur#*=}
COMPREPLY=( $(compgen -W "LIST" -- ${cur}) )
fi
return 0
;;
--session=*|--mem-file-size=*|--field-separator-char=*|--fix-state-delay=*|--max-run-time=*|--mkpc=*)
return 0
;;
--list=*)
if echo "${hidden}" | grep "^--list=" > /dev/null ; 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'`
if [[ $? -eq 0 ]] ; then
# add "?" to the list of possible completions, but don't add any
# section names like "Options"...
COMPREPLY=( $(compgen -W "${list} ?" -- ${cur}) )
fi
fi
return 0
;;
-*)
compreplya=`compgen -W "${options} ${hidden}" -- ${cur}`
if [[ "_${compreplya}_" == "__" ]] ; then
cur="-${cur}"
compreplya=`compgen -W "${options} ${hidden}" -- ${cur}`
fi
compreplyb=`compgen -W "${valopts} ${hidden}" -- ${cur}`
COMPREPLY=( $(compgen -W "${options} ${hidden}" -- ${cur}) )
if [[ "_${compreplya}" == "_${compreplyb}" ]] ; then
compopt -o nospace
fi
return 0
;;
*)
_filedir
return 0
;;
esac
} &&
complete -F _john john
# unique
## have grep && have sed &&
_unique()
{
local first filename cur usage options valopts compreplya compreplyb
COMPREPLY=()
_get_comp_words_by_ref -n = cur
# we need to make sure we run the correct program, not some other program
# called unique which is located somewhere in $PATH
first="${COMP_WORDS[0]}"
filename=`echo "${first}"|sed 's#^.*/\(.*\)$#\1#'`
usage=`${first}|grep '^Usage:'|sed 's#^Usage:\? \?[^ ]*unique *##'`
case "_${cur}" in
_|_${first})
if [[ "_${usage}" != "_OUTPUT-FILE" ]] ; then
COMPREPLY=( $(compgen -W "${usage}" -- "") )
fi
return 0
;;
_-cut=*|_-mem=*)
return 0
;;
_-inp=*|_-ex_file=*|_-ex_file_only=*)
cur=${cur#*=}
__expand_tilde_by_ref cur 2>/dev/null
_filedir
return 0
;;
_-*)
if [[ "_${usage}_" != "_OUTPUT-FILE_" ]] ; then
options=`echo ${usage}|sed 's# #\n#g'|grep '^\[.*\]$'|sed 's#^.\(.*\).$#\1#'|sed 's#=.*$#=#'`
valopts=`echo "${options}"|grep '='`
compreplya=`compgen -W "${options}" -- ${cur}`
compreplyb=`compgen -W "${valopts}" -- ${cur}`
if [[ "_${compreplya}" == "_${compreplyb}" ]] ; then
COMPREPLY=( $(compgen -W "${valopts}" -- "${cur}") )
compopt -o nospace
else
COMPREPLY=( $(compgen -W "${options}" -- "${cur}") )
fi
fi
return 0
;;
_*)
return 0
;;
esac
} &&
complete -F _unique unique
Powered by blists - more mailing lists
Powered by Openwall GNU/*/Linux -
Powered by OpenVZ