Commit e407d275 by devttys0

Added bash auto-completion

parent b11b6654
......@@ -2,6 +2,7 @@
import sys
import os.path
import binwalk
import binwalk.cmdopts
from binwalk.compat import *
from threading import Thread
from getopt import GetoptError, gnu_getopt as GetOpt
......@@ -57,92 +58,6 @@ See http://binwalk.org/wiki/usage for more.
""" % (name, name, name, name, name, name, name, name))
sys.exit(0)
def usage(fd):
fd.write("\n")
fd.write("Binwalk v%s\n" % binwalk.Config.VERSION)
fd.write("Craig Heffner, http://www.devttys0.com\n")
fd.write("\n")
fd.write("Usage: %s [OPTIONS] [FILE1] [FILE2] [FILE3] ...\n" % os.path.basename(sys.argv[0]))
fd.write("\n")
fd.write("Signature Analysis:\n")
fd.write("\t-B, --binwalk Perform a file signature scan (default)\n")
fd.write("\t-R, --raw-bytes=<string> Search for a custom signature\n")
fd.write("\t-A, --opcodes Scan for executable code signatures\n")
fd.write("\t-C, --cast Cast file contents as various data types\n")
fd.write("\t-m, --magic=<file> Specify an alternate magic file to use\n")
fd.write("\t-x, --exclude=<filter> Exclude matches that have <filter> in their description\n")
fd.write("\t-y, --include=<filter> Only search for matches that have <filter> in their description\n")
fd.write("\t-I, --show-invalid Show results marked as invalid\n")
fd.write("\t-T, --ignore-time-skew Do not show results that have timestamps more than 1 year in the future\n")
fd.write("\t-k, --keep-going Show all matching results at a given offset, not just the first one\n")
fd.write("\t-b, --dumb Disable smart signature keywords\n")
fd.write("\n")
fd.write("Strings Analysis:\n")
fd.write("\t-S, --strings Scan for ASCII strings (may be combined with -B, -R, -A, or -E)\n")
fd.write("\t-s, --strlen=<n> Set the minimum string length to search for (default: 3)\n")
fd.write("\n")
fd.write("Entropy Analysis:\n")
fd.write("\t-E, --entropy Plot file entropy (may be combined with -B, -R, -A, or -S)\n")
fd.write("\t-H, --heuristic Identify unknown compression/encryption based on entropy heuristics (implies -E)\n")
fd.write("\t-K, --block=<int> Set the block size for entropy analysis (default: %d)\n" % binwalk.entropy.FileEntropy.DEFAULT_BLOCK_SIZE)
fd.write("\t-a, --gzip Use gzip compression ratios to measure entropy\n")
fd.write("\t-N, --no-plot Do not generate an entropy plot graph\n")
fd.write("\t-F, --marker=<offset:name> Add a marker to the entropy plot graph\n")
fd.write("\t-Q, --no-legend Omit the legend from the entropy plot graph\n")
fd.write("\t-J, --save-plot Save plot as an SVG (implied if multiple files are specified)\n")
fd.write("\n")
fd.write("Binary Diffing:\n")
fd.write("\t-W, --diff Hexdump / diff the specified files\n")
fd.write("\t-K, --block=<int> Number of bytes to display per line (default: %d)\n" % binwalk.hexdiff.HexDiff.DEFAULT_BLOCK_SIZE)
fd.write("\t-G, --green Only show hex dump lines that contain bytes which were the same in all files\n")
fd.write("\t-i, --red Only show hex dump lines that contain bytes which were different in all files\n")
fd.write("\t-U, --blue Only show hex dump lines that contain bytes which were different in some files\n")
fd.write("\t-w, --terse Diff all files, but only display a hex dump of the first file\n")
fd.write("\n")
fd.write("Extraction Options:\n")
fd.write("\t-D, --dd=<type:ext[:cmd]> Extract <type> signatures, give the files an extension of <ext>, and execute <cmd>\n")
fd.write("\t-e, --extract=[file] Automatically extract known file types; load rules from file, if specified\n")
fd.write("\t-M, --matryoshka=[n] Recursively scan extracted files, up to n levels deep (8 levels of recursion is the default)\n")
fd.write("\t-j, --max-size=<int> Limit extracted file sizes (default: no limit)\n")
fd.write("\t-r, --rm Cleanup extracted files and zero-size files\n")
fd.write("\t-d, --honor-footers Only extract files up to their corresponding footer signatures\n")
fd.write("\t-z, --carve Carve data from files, but don't execute extraction utilities (implies -d)\n")
fd.write("\n")
fd.write("Plugin Options:\n")
fd.write("\t-X, --disable-plugin=<name> Disable a plugin by name\n")
fd.write("\t-Y, --enable-plugin=<name> Enable a plugin by name\n")
fd.write("\t-p, --disable-plugins Do not load any binwalk plugins\n")
fd.write("\t-L, --list-plugins List all user and system plugins by name\n")
fd.write("\n")
fd.write("General Options:\n")
fd.write("\t-o, --offset=<int> Start scan at this file offset\n")
fd.write("\t-l, --length=<int> Number of bytes to scan\n")
fd.write("\t-g, --grep=<text> Grep results for the specified text\n")
fd.write("\t-f, --file=<file> Log results to file\n")
fd.write("\t-c, --csv Log results to file in csv format\n")
fd.write("\t-O, --skip-unopened Ignore file open errors and process only the files that can be opened\n")
fd.write("\t-t, --term Format output to fit the terminal window\n")
fd.write("\t-q, --quiet Supress output to stdout\n")
fd.write("\t-v, --verbose Be verbose (specify twice for very verbose)\n")
fd.write("\t-u, --update Update magic signature files\n")
fd.write("\t-?, --examples Show example usage\n")
fd.write("\t-h, --help Show help output\n")
fd.write("\n")
if fd == sys.stderr:
sys.exit(1)
else:
sys.exit(0)
def main():
# The Binwalk class instance must be global so that the display_status thread can access it.
global bwalk
......@@ -198,77 +113,19 @@ def main():
config = binwalk.Config()
short_options = "AaBbCcdEeGHhIiJkLMNnOPpQqrSTtUuvWwz?D:F:f:g:j:K:o:l:m:R:s:X:x:Y:y:"
long_options = [
"rm",
"help",
"green",
"red",
"blue",
"examples",
"quiet",
"csv",
"verbose",
"opcodes",
"cast",
"update",
"binwalk",
"keep-going",
"show-invalid",
"ignore-time-skew",
"honor-footers",
"profile",
"delay", # delay is depreciated, but kept for backwards compatability
"skip-unopened",
"term",
"tim",
"terse",
"diff",
"dumb",
"entropy",
"heuristic",
"math",
"gzip",
"save-plot",
"no-plot",
"no-legend",
"strings",
"carve",
"matryoshka=",
"list-plugins",
"disable-plugins",
"disable-plugin=",
"enable-plugin=",
"max-size=",
"marker=",
"strlen=",
"file=",
"block=",
"offset=",
"length=",
"exclude=",
"include=",
"search=",
"extract=",
"dd=",
"grep=",
"magic=",
"raw-bytes=",
]
# Require at least one argument (the target file)
if len(sys.argv) < MIN_ARGC:
usage(sys.stderr)
binwalk.cmdopts.usage(sys.stderr)
try:
opts, args = GetOpt(sys.argv[1:], short_options, long_options)
opts, args = GetOpt(sys.argv[1:], binwalk.cmdopts.short_options, binwalk.cmdopts.long_options)
except GetoptError as e:
sys.stderr.write("%s\n" % str(e))
usage(sys.stderr)
binwalk.cmdopts.usage(sys.stderr)
for opt, arg in opts:
if opt in ("-h", "--help"):
usage(sys.stdout)
binwalk.cmdopts.usage(sys.stdout)
elif opt in ("-?", "--examples"):
examples()
elif opt in ("-d", "--delay", "--honor-footers"):
......@@ -418,7 +275,7 @@ def main():
# The --profile option is handled prior to calling main()
elif opt not in ('-P', '--profile'):
usage(sys.stderr)
binwalk.cmdopts.usage(sys.stderr)
# Keep track of the options and arguments.
# This is used later to determine which argv entries are file names.
......@@ -461,7 +318,7 @@ def main():
if not verbose:
verbose = 1
elif len(target_files) == 0:
usage(sys.stderr)
binwalk.cmdopts.usage(sys.stderr)
# Instantiate the Binwalk class
bwalk = binwalk.Binwalk(magic_files=magic_files,
......
# Bash auto-completion file for binwalk
_binwalk()
{
local cur prev opts long_opts short_opts file_opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
# Long and short options are dynamically generated by setup.py
long_opts="%%LONG_OPTS%%"
short_opts="%%SHORT_OPTS%%"
file_opts="--file --extract --magic"
opts="${long_opts} ${short_opts}"
# If this is a long option, then tab complete a list of matching long options
if [[ ${cur} == --* ]]
then
COMPREPLY=( $(compgen -W "${long_opts}" -- ${cur}) )
# Else, if this is any other option, tab complete it from then entire list of valid options
elif [[ ${cur} == -* ]]
then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
# Finally, if this is not an option at all, tab complete a list of files
else
COMPREPLY=( $(compgen -f ${cur}) )
fi
# If there is only one matching option, and if it is a long option, then don't put a space after the equals sign.
if [ "$(echo "$COMPREPLY" | wc -w)" == "1" ] && [ "$(echo "$COMPREPLY" | grep -e '=$')" != "" ]
then
compopt -o nospace;
# Else, if there are no matching options, check to see if the previous option is a long option that takes a file path argument
elif [ "$COMPREPLY" == "" ]
then
for file_opt in ${file_opts}
do
if [ "${prev}" == "${file_opt}" ]
then
# If the previous option does take a file path argument, tab complete a list of files
COMPREPLY=( $(compgen -f "") )
break
fi
done
fi
return 0
}
complete -F _binwalk binwalk
# Contains all the command line options and usage output for the binwlak script.
# Placed here so that other scripts can programmatically access the command line options list (e.g., for auto-completion generation).
import os
import sys
import binwalk.config
short_options = "AaBbCcdEeGHhIiJkLMNnOPpQqrSTtUuvWwz?D:F:f:g:j:K:o:l:m:R:s:X:x:Y:y:"
long_options = [
"rm",
"help",
"green",
"red",
"blue",
"examples",
"quiet",
"csv",
"verbose",
"opcodes",
"cast",
"update",
"binwalk",
"keep-going",
"show-invalid",
"ignore-time-skew",
"honor-footers",
"profile",
"delay", # delay is depreciated, but kept for backwards compatability
"skip-unopened",
"term",
"tim",
"terse",
"diff",
"dumb",
"entropy",
"heuristic",
"math",
"gzip",
"save-plot",
"no-plot",
"no-legend",
"strings",
"carve",
"matryoshka=",
"list-plugins",
"disable-plugins",
"disable-plugin=",
"enable-plugin=",
"max-size=",
"marker=",
"strlen=",
"file=",
"block=",
"offset=",
"length=",
"exclude=",
"include=",
"search=",
"extract=",
"dd=",
"grep=",
"magic=",
"raw-bytes=",
]
def usage(fd):
fd.write("\n")
fd.write("Binwalk v%s\n" % binwalk.config.Config.VERSION)
fd.write("Craig Heffner, http://www.devttys0.com\n")
fd.write("\n")
fd.write("Usage: %s [OPTIONS] [FILE1] [FILE2] [FILE3] ...\n" % os.path.basename(sys.argv[0]))
fd.write("\n")
fd.write("Signature Analysis:\n")
fd.write("\t-B, --binwalk Perform a file signature scan (default)\n")
fd.write("\t-R, --raw-bytes=<string> Search for a custom signature\n")
fd.write("\t-A, --opcodes Scan for executable code signatures\n")
fd.write("\t-C, --cast Cast file contents as various data types\n")
fd.write("\t-m, --magic=<file> Specify an alternate magic file to use\n")
fd.write("\t-x, --exclude=<filter> Exclude matches that have <filter> in their description\n")
fd.write("\t-y, --include=<filter> Only search for matches that have <filter> in their description\n")
fd.write("\t-I, --show-invalid Show results marked as invalid\n")
fd.write("\t-T, --ignore-time-skew Do not show results that have timestamps more than 1 year in the future\n")
fd.write("\t-k, --keep-going Show all matching results at a given offset, not just the first one\n")
fd.write("\t-b, --dumb Disable smart signature keywords\n")
fd.write("\n")
fd.write("Strings Analysis:\n")
fd.write("\t-S, --strings Scan for ASCII strings (may be combined with -B, -R, -A, or -E)\n")
fd.write("\t-s, --strlen=<n> Set the minimum string length to search for (default: 3)\n")
fd.write("\n")
fd.write("Entropy Analysis:\n")
fd.write("\t-E, --entropy Plot file entropy (may be combined with -B, -R, -A, or -S)\n")
fd.write("\t-H, --heuristic Identify unknown compression/encryption based on entropy heuristics (implies -E)\n")
fd.write("\t-K, --block=<int> Set the block size for entropy analysis (default: %d)\n" % binwalk.entropy.FileEntropy.DEFAULT_BLOCK_SIZE)
fd.write("\t-a, --gzip Use gzip compression ratios to measure entropy\n")
fd.write("\t-N, --no-plot Do not generate an entropy plot graph\n")
fd.write("\t-F, --marker=<offset:name> Add a marker to the entropy plot graph\n")
fd.write("\t-Q, --no-legend Omit the legend from the entropy plot graph\n")
fd.write("\t-J, --save-plot Save plot as an SVG (implied if multiple files are specified)\n")
fd.write("\n")
fd.write("Binary Diffing:\n")
fd.write("\t-W, --diff Hexdump / diff the specified files\n")
fd.write("\t-K, --block=<int> Number of bytes to display per line (default: %d)\n" % binwalk.hexdiff.HexDiff.DEFAULT_BLOCK_SIZE)
fd.write("\t-G, --green Only show hex dump lines that contain bytes which were the same in all files\n")
fd.write("\t-i, --red Only show hex dump lines that contain bytes which were different in all files\n")
fd.write("\t-U, --blue Only show hex dump lines that contain bytes which were different in some files\n")
fd.write("\t-w, --terse Diff all files, but only display a hex dump of the first file\n")
fd.write("\n")
fd.write("Extraction Options:\n")
fd.write("\t-D, --dd=<type:ext[:cmd]> Extract <type> signatures, give the files an extension of <ext>, and execute <cmd>\n")
fd.write("\t-e, --extract=[file] Automatically extract known file types; load rules from file, if specified\n")
fd.write("\t-M, --matryoshka=[n] Recursively scan extracted files, up to n levels deep (8 levels of recursion is the default)\n")
fd.write("\t-j, --max-size=<int> Limit extracted file sizes (default: no limit)\n")
fd.write("\t-r, --rm Cleanup extracted files and zero-size files\n")
fd.write("\t-d, --honor-footers Only extract files up to their corresponding footer signatures\n")
fd.write("\t-z, --carve Carve data from files, but don't execute extraction utilities (implies -d)\n")
fd.write("\n")
fd.write("Plugin Options:\n")
fd.write("\t-X, --disable-plugin=<name> Disable a plugin by name\n")
fd.write("\t-Y, --enable-plugin=<name> Enable a plugin by name\n")
fd.write("\t-p, --disable-plugins Do not load any binwalk plugins\n")
fd.write("\t-L, --list-plugins List all user and system plugins by name\n")
fd.write("\n")
fd.write("General Options:\n")
fd.write("\t-o, --offset=<int> Start scan at this file offset\n")
fd.write("\t-l, --length=<int> Number of bytes to scan\n")
fd.write("\t-g, --grep=<text> Grep results for the specified text\n")
fd.write("\t-f, --file=<file> Log results to file\n")
fd.write("\t-c, --csv Log results to file in csv format\n")
fd.write("\t-O, --skip-unopened Ignore file open errors and process only the files that can be opened\n")
fd.write("\t-t, --term Format output to fit the terminal window\n")
fd.write("\t-q, --quiet Supress output to stdout\n")
fd.write("\t-v, --verbose Be verbose (specify twice for very verbose)\n")
fd.write("\t-u, --update Update magic signature files\n")
fd.write("\t-?, --examples Show example usage\n")
fd.write("\t-h, --help Show help output\n")
fd.write("\n")
if fd == sys.stderr:
sys.exit(1)
else:
sys.exit(0)
......@@ -133,3 +133,47 @@ setup( name = "binwalk",
scripts = ["bin/binwalk"],
)
# If the bash auto-completion directory exists, generate an auto-completion file
bash_completion_dir = os.path.join('/', 'etc', 'bash_completion.d')
if os.path.exists(bash_completion_dir):
import binwalk.cmdopts
print("Installing bash auto-completion file")
long_opts_key = '%%LONG_OPTS%%'
short_opts_key = '%%SHORT_OPTS%%'
file_opts_key = '%%FILE_OPTS%%'
file_name_in = 'binwalk.completion'
file_name_out = os.path.join(bash_completion_dir, 'binwalk')
long_opts = []
short_opts = []
file_opts = ['--file=', '--extract=', '--magic=']
for opt in binwalk.cmdopts.short_options:
if opt != ':':
short_opts.append('-' + opt)
for opt in binwalk.cmdopts.long_options:
long_opts.append('--' + opt)
try:
with open(file_name_in) as fd_in:
with open(file_name_out, 'w') as fd_out:
for line in fd_in.readlines():
if long_opts_key in line:
line = line.replace(long_opts_key, ' '.join(long_opts))
elif short_opts_key in line:
line = line.replace(short_opts_key, ' '.join(short_opts))
elif file_opts_key in line:
line = line.replace(file_opts_key, ' '.join(file_opts))
fd_out.write(line)
except Exception as e:
print("WARNING: Failed to install auto-completion file: %s" % e)
try:
os.unlink(file_name_out)
except:
pass
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment