[Bash-completion-devel] [PATCH] New improved cryptsetup completion
Bruno Ricci
bruno.ricci at epfl.ch
Wed Feb 5 15:09:15 UTC 2014
I have been working on the cryptsetup completion. The one currently in
the tree is missing some option (ex tcryptOpen, tcryptDump, etc), has
some obsolete options (for example luksDelKey is now obselete as of
cryptsetup 1.6.2). Moreover the current completion is in general not
clever enough. For example --use-random and --use-urandom are mutually
exclusive and so if --use-random is on the command line, --use-urandom
should not be suggested. As a downside, the completion is now approx 40k
in size.
Features of the new completion.
-- all command in the man page (except create)
(as of cryptsetup 1.6.2) are now completed with
the appropriate options. Ex. luksKillSlot <tab> <tab>
does only show the options and parameter
which are valid with this command.
-- mutually exclusive command are implemented
Ex. --use-urandom | --use-random, --hash | --cipher
for the benchmark command
-- the majority of options only make sense specified once
(exception are --key-file with tcrypt* and some few other)
so options already specified on the command line are not
suggested again (except for the few exceptions).
-- the file is now documented
-- I believe it complies with the style guideline
(in particular the 79 char limit and the "tab-are-4-space")
The patch and the whole file are attached. What do you think about it ?
In particular how do we deal with users who have
an older version of cryptsetup which might not have all the commands
in this completion (in particular tcrypt* which was introduced in 1.6.0)
Comments, suggestions and criticism are welcome.
Bruno Ricci
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cryptsetup.patch
Type: text/x-diff
Size: 42900 bytes
Desc: not available
URL: <http://lists.alioth.debian.org/pipermail/bash-completion-devel/attachments/20140205/683aa031/attachment-0001.patch>
-------------- next part --------------
# bash completion for cryptsetup -*- shell-script -*-
# based on the man page of cryptsetup dated May 2012 (version 1.6.2)
_cryptsetup_name()
{
COMPREPLY=( $( compgen -X control -W '$( command ls /dev/mapper )' \
-- "$cur" ) )
}
_cryptsetup_device()
{
cur=${cur:=/dev/}
_filedir
}
_cryptsetup_option_once()
{
local cword words
_get_comp_words_by_ref words cword
for ((i=0; i<cword; i++));do
if [[ "${words[i]}" == $1 ]];then
return 1
fi
done
}
_cryptsetup()
{
local cur prev words cword split
_init_completion -s || return
case $prev in
--key-file|--master-key-file|--header-backup-file|-d)
_filedir
return 0
;;
esac
$split && return
local arg
_get_first_arg
_get_comp_words_by_ref cur prev words cword
if [[ -z $arg ]]; then
if [[ "$cur" == -* ]]; then
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) )
[[ $COMPREPLY == *= ]] && compopt -o nospace
else
COMPREPLY=( $( compgen -W 'open luksOpen loopaesOpen tcryptOpen
close remove plainClose luksClose loopaesClose tcryptClose
status resize luksFormat luksSuspend luksResume luksAddKey
luksRemoveKey luksChangeKey luksKillSlot luksUUID isLuks
luksDump luksHeaderBackup luksHeaderRestore tcryptDump
repair benchmark' -- "$cur" ) )
fi
else
local args
_count_args
#thoses options are valid with all commands
local global_options="--verbose --debug --batch-mode --version
--usage --help"
case $arg in
#BASIC COMMANDS
open)
case $args in
2)
_cryptsetup_device
;;
3)
#mapping name
return 0
;;
*)
#valid options are : --type <plain|luks|loopaes|tcrypt>
case $prev in
--type)
COMPREPLY=( $( compgen -W "plain luks loopaes
tcrypt" -- "$cur" ) )
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--type"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
#remove, plainClose, luksClose,
#loopaesClose, tcryptClose are synonyms of close
#and behave exactly the same
close|remove|plainClose|luksClose|loopaesClose|tcryptClose)
case $args in
2)
_cryptsetup_name
;;
*)
#valid options are : (none specific to close)
case $prev in
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
status)
case $args in
2)
_cryptsetup_name
;;
*)
#valid options are : (none specific to status)
case $prev in
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
resize)
case $args in
2)
_cryptsetup_name
;;
*)
#valid options are : --size <sectors>
case $prev in
--size)
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--size"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
#LUKS EXTENSION commands, same order as in the man page
luksFormat)
case $args in
2)
_cryptsetup_device
;;
*)
#valid options are --hash <hash>, --cipher <cipher>,
#--verify-passphrase, --key-size <size>,
#--key-slot <slot number>, --key-file <file>,
#--keyfile-offset <offset>, --keyfile-size <size>,
#--use-random | --use-urandom, --uuid <uuid>,
#--master-key-file <file>, --iter-time <ms>,
#--header <file>, --force-password
case $prev in
--key-file|--master-key-file|--header)
_filedir
;;
--hash|--cipher|--key-size|--key-slot|\
--keyfile-offset|--keyfile-size|\
--uuid|--iter-time)
#thoses options takes parameters which are
#hard to guess with bash-completion
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--hash --cipher
--verify-passphrase --key-size --key-slot
--key-file --keyfile-offset --keyfile-size
--uuid --master-key-file
--iter-time --header --force-password"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
#--use-random and --use-urandom
#are mutually exclusive
if _cryptsetup_option_once --use-random && \
_cryptsetup_option_once --use-urandom ;then
valid_options="$valid_options --use-random
--use-urandom"
fi
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
luksOpen)
case $args in
2)
_cryptsetup_device
;;
3)
#cryptsetup device name. Impossible to guess.
return 0
;;
*)
#valid options are --key-file <file>,
#--keyfile-offset <offset>, --keyfile-size <size>,
#--readonly, --test-passphrase, --allow-discards,
#--header <file>, --key-slot <slot>,
#--master-key-file <file>
case $prev in
--key-file|--master-key-file|--header)
_filedir
;;
--keyfile-offset|--keyfile-size|--key-slot)
#thoses options takes parameters which are
#hard to guess with bash-completion
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--key-file --keyfile-offset
--keyfile-size --readonly --test-passphrase
--allow-discards --header --key-slot
--master-key-file"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
luksSuspend)
case $args in
2)
_cryptsetup_name
;;
*)
#valid options are --header <file>
case $prev in
--header)
_filedir
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--header"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
luksResume)
case $args in
2)
_cryptsetup_name
;;
*)
#valid options are --key-file <file>,
#--keyfile-size <size>, --header <file>
case $prev in
--header|--key-file)
_filedir
;;
--keyfile-size)
#thoses options takes parameters which are
#hard to guess with bash-completion
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--key-file --keyfile-size
--header"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
luksAddKey)
case $args in
2)
_cryptsetup_device
;;
*)
#valid options are --key-file <file>,
#--keyfile-offset <offset>, --keyfile-size <size>,
#--new-keyfile-offset <offset>,
#--new-keyfile-size <size>, --key-slot <slot>,
#--master-key-file <file>, --iter-time <time_ms>,
#--force-password
case $prev in
--key-file|--master-key-file)
_filedir
;;
--keyfile-offset|--keyfile-size|\
--new-keyfile-offset|--new-keyfile-size|\
--key-slot|--iter-time)
#thoses options takes parameters which are
#hard to guess with bash-completion
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--key-file --keyfile-offset
--keyfile-size --new-keyfile-offset
--new-keyfile-size --key-slot --master-key-file
--iter-time --force-password"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
luksRemoveKey)
case $args in
2)
_cryptsetup_device
;;
*)
#valid options are --key-file <file>,
#--keyfile-offset <offset>, --keyfile-size <size>
case $prev in
--key-file)
_filedir
;;
--keyfile-offset|--keyfile-size)
#thoses options takes parameters which are
#hard to guess with bash-completion
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--key-file --keyfile-offset
--keyfile-size"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
luksChangeKey)
case $args in
2)
_cryptsetup_device
;;
*)
#valid options are --key-file <file>,
#--keyfile-offset <offset>, --keyfile-size <size>,
#--new-keyfile-offset <offset>,
#--new-keyfile-size <size>, --key-slot <slot>,
#--force-password
case $prev in
--key-file)
_filedir
;;
--keyfile-offset|--keyfile-size|\
--new-keyfile-offset|--new-keyfile-size|\
--key-slot)
#thoses options takes parameters which
#are hard to guess with bash-completion
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--key-file --keyfile-offset
--keyfile-size --new-keyfile-offset
--new-keyfile-size --key-slot --force-password"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
luksKillSlot)
case $args in
2)
_cryptsetup_device
;;
3)
#key slot number
return 0
;;
*)
#valid options are --key-file <file>,
#--keyfile-offset <offset>, --keyfile-size <size>
case $prev in
--key-file)
_filedir
;;
--keyfile-offset|--keyfile-size)
#thoses options takes parameters which are
#hard to guess with bash-completion
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--key-file --keyfile-offset
--keyfile-size"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
luksUUID)
case $args in
2)
_cryptsetup_device
;;
*)
#valid options are --uuid <uuid>
case $prev in
--uuid)
#thoses options takes parameters which are
#hard to guess with bash-completion
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--uuid"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
isLuks)
case $args in
2)
_cryptsetup_device
;;
*)
#valid options are -v
case $prev in
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
luksDump)
case $args in
2)
_cryptsetup_device
;;
*)
#valid options are --dump-master-key,
#--key-file <file>, --keyfile-offset <offset>,
#--keyfile-size <size>
case $prev in
--key-file)
_filedir
;;
--keyfile-offset|--keyfile-size)
#thoses options takes parameters which are
#hard to guess with bash-completion
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--dump-master-key --key-file
--keyfile-offset --keyfile-size"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
luksHeaderBackup|luksHeaderRestore)
case $args in
2)
_cryptsetup_device
;;
*)
#valid options are --header-backup-file <file>
case $prev in
--header-backup-file)
_filedir
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--header-backup-file"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
#Loop-AES EXTENSION commands, same order as in the man page
loopaesOpen)
case $args in
2)
_cryptsetup_device
;;
3)
#name, impossible to guess
return 0;
;;
*)
#valid options are --key-file <file>,
#--keyfile-size <size>, --offset <offset>,
#--skip <iv_offset>, --hash <hash_name>, --readonly,
#--allow-discards
case $prev in
--key-file)
_filedir
;;
--keyfile-size|--offset|--skip|--hash)
#thoses options takes parameters which are
#hard to guess with bash-completion
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--key-file --keyfile-size
--offset --skip --hash
--readonly --allow-discards"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
#TCRYPT EXTENSION commands, same order as in the man page
tcryptOpen)
case $args in
2)
_cryptsetup_device
;;
3)
#name, impossible to guess
return 0;
;;
*)
#valid options are --key-file <file>, --tcrypt-hidden,
#--tcrypt-system, --readonly, --test-passphrase
#note: --key-file <file> can be repeated
case $prev in
--key-file)
_filedir
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--tcrypt-hidden --tcrypt-system
--readonly --test-passphrase"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
#--key-file <file> can be repeated
valid_options="$valid_options --key-file"
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
tcryptDump)
case $args in
2)
_cryptsetup_device
;;
*)
#valid options are --dump-master-key,
#--key-file <file>, --tcrypt-hidden, --tcrypt-system,
#note: --key-file <file> can be repeated
case $prev in
--key-file)
_filedir
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options="--dump-master-key
--tcrypt-hidden --tcrypt-system"
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
#--key-file <file> can be repeated
valid_options="$valid_options --key-file"
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
#MISC commands, same order as in the man page
repair)
case $args in
2)
_cryptsetup_device
;;
*)
#valid options are : (none specific to repair)
case $prev in
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
#--key-file <file> can be repeated
valid_options="$valid_options --key-file"
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
benchmark)
case $args in
*)
#valid options are --cipher <cipher>, --hash <hash>,
#--key-size <size>
#note: --cipher --hash are mutually exclusive
# --key-size is only valid with --cipher
case $prev in
--cipher|--hash|--key-size)
return 0
;;
*)
#the previous argument was either an option
#without an argument or
#the argument of an option
#
#generate the list of valid options
local valid_options
local options
options="$options $global_options"
for option in $options;do
if _cryptsetup_option_once "$option";then
valid_options="$valid_options $option"
fi
done
if _cryptsetup_option_once --cipher && \
_cryptsetup_option_once --key-size && \
_cryptsetup_option_once --hash ;then
valid_options="$valid_options --hash"
fi
if _cryptsetup_option_once --hash && \
_cryptsetup_option_once --key-size ;then
valid_options="$valid_options --key-size"
fi
if _cryptsetup_option_once --hash && \
_cryptsetup_option_once --cipher ;then
valid_options="$valid_options --cipher"
fi
COMPREPLY=( $( compgen -W "$valid_options" \
-- "$cur" ) )
;;
esac
;;
esac
;;
esac
fi
return 0
} &&
complete -F _cryptsetup cryptsetup
# ex: ts=4 sw=4 et filetype=sh
More information about the Bash-completion-devel
mailing list