mirror of
https://github.com/Llewellynvdm/Tomb.git
synced 2024-11-19 19:15:14 +00:00
Merge pull request #18 from boyska/only_optparsing
New CLI option parsing supports contextual options following commands. ZSH functions are used to parse options. Further testing will follow.
This commit is contained in:
commit
21be9e204e
267
src/tomb
267
src/tomb
@ -24,20 +24,28 @@ VERSION=1.1
|
|||||||
DATE=May/2011
|
DATE=May/2011
|
||||||
TOMBEXEC=$0
|
TOMBEXEC=$0
|
||||||
TOMBOPENEXEC="tomb-open"
|
TOMBOPENEXEC="tomb-open"
|
||||||
|
typeset -a OLDARGS
|
||||||
|
for arg in ${argv}; do OLDARGS+=($arg); done
|
||||||
STEGHIDE=1
|
STEGHIDE=1
|
||||||
MOUNTOPTS="rw,noatime,nodev"
|
MOUNTOPTS="rw,noatime,nodev"
|
||||||
|
|
||||||
|
#declare global variables
|
||||||
|
QUIET=0
|
||||||
|
DEBUG=0
|
||||||
|
typeset -A global_opts
|
||||||
|
typeset -A opts
|
||||||
|
|
||||||
# PATH=/usr/bin:/usr/sbin:/bin:/sbin
|
# PATH=/usr/bin:/usr/sbin:/bin:/sbin
|
||||||
|
|
||||||
autoload colors; colors
|
autoload colors; colors
|
||||||
|
|
||||||
# standard output message routines
|
# standard output message routines
|
||||||
# it's always useful to wrap them, in case we change behaviour later
|
# it's always useful to wrap them, in case we change behaviour later
|
||||||
notice() { if ! [ $QUIET ]; then print "$fg_bold[green][*]$fg_no_bold[white] $1" >&2; fi }
|
notice() { if [[ $QUIET == 0 ]]; then print "$fg_bold[green][*]$fg_no_bold[white] $1" >&2; fi }
|
||||||
error() { if ! [ $QUIET ]; then print "$fg[red][!]$fg[white] $1" >&2; fi }
|
error() { if [[ $QUIET == 0 ]]; then print "$fg[red][!]$fg[white] $1" >&2; fi }
|
||||||
func() { if [ $DEBUG ]; then print "$fg[blue][D]$fg[white] $1" >&2; fi }
|
func() { if [[ $DEBUG == 1 ]]; then print "$fg[blue][D]$fg[white] $1" >&2; fi }
|
||||||
act() {
|
act() {
|
||||||
if ! [ $QUIET ]; then
|
if [[ $QUIET == 0 ]]; then
|
||||||
if [ "$1" = "-n" ]; then
|
if [ "$1" = "-n" ]; then
|
||||||
print -n "$fg_bold[white] . $fg_no_bold[white] $2" >&2;
|
print -n "$fg_bold[white] . $fg_no_bold[white] $2" >&2;
|
||||||
else
|
else
|
||||||
@ -156,7 +164,7 @@ exec_as_user() {
|
|||||||
# escalate privileges
|
# escalate privileges
|
||||||
check_priv() {
|
check_priv() {
|
||||||
if [ $UID != 0 ]; then
|
if [ $UID != 0 ]; then
|
||||||
func "Using sudo for root execution of 'tomb ${(f)ARGS}'"
|
func "Using sudo for root execution of 'tomb ${(f)OLDARGS}'"
|
||||||
# check if sudo has a timestamp active
|
# check if sudo has a timestamp active
|
||||||
sudok=false
|
sudok=false
|
||||||
sudo -n ${TOMBEXEC} 2> /dev/null
|
sudo -n ${TOMBEXEC} 2> /dev/null
|
||||||
@ -165,12 +173,12 @@ check_priv() {
|
|||||||
OPTION ttyname=$TTY
|
OPTION ttyname=$TTY
|
||||||
OPTION lc-ctype=$LANG
|
OPTION lc-ctype=$LANG
|
||||||
SETTITLE Super user privileges required
|
SETTITLE Super user privileges required
|
||||||
SETDESC Sudo execution of Tomb ${ARGS[@]}
|
SETDESC Sudo execution of Tomb ${OLDARGS[@]}
|
||||||
SETPROMPT Insert your USER password:
|
SETPROMPT Insert your USER password:
|
||||||
GETPIN
|
GETPIN
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
sudo "${TOMBEXEC}" ${(s: :)ARGS}
|
sudo "${TOMBEXEC}" "${(@)OLDARGS}"
|
||||||
exit $?
|
exit $?
|
||||||
fi # are we root already
|
fi # are we root already
|
||||||
return 0
|
return 0
|
||||||
@ -312,8 +320,8 @@ EOF
|
|||||||
|
|
||||||
create_tomb() {
|
create_tomb() {
|
||||||
if ! [ ${CMD2} ]; then
|
if ! [ ${CMD2} ]; then
|
||||||
error "no tomb name specified for creation"
|
error "no tomb name specified for creation"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tombfile=`basename ${CMD2}`
|
tombfile=`basename ${CMD2}`
|
||||||
@ -321,6 +329,7 @@ create_tomb() {
|
|||||||
# make sure the file has a .tomb extension
|
# make sure the file has a .tomb extension
|
||||||
tombname=${tombfile%%\.*}
|
tombname=${tombfile%%\.*}
|
||||||
tombfile=${tombname}.tomb
|
tombfile=${tombname}.tomb
|
||||||
|
tombsize=$opts[-s]
|
||||||
|
|
||||||
if [ -e ${tombdir}/${tombfile} ]; then
|
if [ -e ${tombdir}/${tombfile} ]; then
|
||||||
error "tomb exists already. I'm not digging here:"
|
error "tomb exists already. I'm not digging here:"
|
||||||
@ -336,17 +345,11 @@ create_tomb() {
|
|||||||
|
|
||||||
notice "Creating a new tomb in ${tombdir}/${tombfile}"
|
notice "Creating a new tomb in ${tombdir}/${tombfile}"
|
||||||
|
|
||||||
if [ -z $SIZE ]; then
|
if [ -z $tombsize ]; then
|
||||||
if [ $CMD3 ]; then
|
act "No size specified, summoning the Tomb Undertaker to guide us in the creation."
|
||||||
tombsize=${CMD3}
|
"$TOMBOPENEXEC" &
|
||||||
else
|
wait $!
|
||||||
act "No size specified, summoning the Tomb Undertaker to guide us in the creation."
|
return 0
|
||||||
"$TOMBOPENEXEC" &
|
|
||||||
wait $!
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
tombsize=${SIZE}
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tombsize_4k=`expr $tombsize \* 1024 / 4`
|
tombsize_4k=`expr $tombsize \* 1024 / 4`
|
||||||
@ -480,38 +483,45 @@ create_tomb() {
|
|||||||
mount_tomb() {
|
mount_tomb() {
|
||||||
notice "Commanded to open tomb $CMD2"
|
notice "Commanded to open tomb $CMD2"
|
||||||
get_arg_tomb $CMD2
|
get_arg_tomb $CMD2
|
||||||
|
local tombkey
|
||||||
|
if option_is_set -k ; then
|
||||||
|
tombkey=`option_value -k`
|
||||||
|
else
|
||||||
|
tombkey="${PARAM[1]}.key"
|
||||||
|
fi
|
||||||
|
echo the key used is $tombkey
|
||||||
if [ $? != 0 ]; then
|
if [ $? != 0 ]; then
|
||||||
error "operation aborted."
|
error "operation aborted."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! [ $CMD3 ]; then
|
if ! [ $CMD3 ]; then
|
||||||
tombmount=/media/${tombfile}
|
tombmount=/media/${tombfile}
|
||||||
act "mountpoint not specified, using default: $tombmount"
|
act "mountpoint not specified, using default: $tombmount"
|
||||||
elif ! [ -x $CMD3 ]; then
|
elif ! [ -x $CMD3 ]; then
|
||||||
error "mountpoint $CMD3 doesn't exist, operation aborted."
|
error "mountpoint $CMD3 doesn't exist, operation aborted."
|
||||||
if [ -n "$usbkey_mount" ]; then
|
if [ -n "$usbkey_mount" ]; then
|
||||||
umount $usbkey_mount
|
umount $usbkey_mount
|
||||||
rmdir $usbkey_mount
|
rmdir $usbkey_mount
|
||||||
unset usbkey_mount
|
unset usbkey_mount
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
else
|
else
|
||||||
tombmount=$CMD3
|
tombmount=$CMD3
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# check if its already open
|
# check if its already open
|
||||||
mount -l | grep "${tombname}.tomb.*\[$tombname\]$" 2>&1 > /dev/null
|
mount -l | grep "${tombname}.tomb.*\[$tombname\]$" 2>&1 > /dev/null
|
||||||
if [ $? = 0 ]; then
|
if [ $? = 0 ]; then
|
||||||
error "$tombname is already mounted on $tombmount"
|
error "$tombname is already mounted on $tombmount"
|
||||||
act "tomb list - show all tombs currently open"
|
act "tomb list - show all tombs currently open"
|
||||||
if [ -n "$usbkey_mount" ]; then
|
if [ -n "$usbkey_mount" ]; then
|
||||||
umount $usbkey_mount
|
umount $usbkey_mount
|
||||||
rmdir $usbkey_mount
|
rmdir $usbkey_mount
|
||||||
unset usbkey_mount
|
unset usbkey_mount
|
||||||
fi
|
fi
|
||||||
error "operation aborted."
|
error "operation aborted."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
notice "mounting $tombfile on mountpoint $tombmount"
|
notice "mounting $tombfile on mountpoint $tombmount"
|
||||||
@ -522,18 +532,18 @@ mount_tomb() {
|
|||||||
|
|
||||||
nstloop=`losetup -f`
|
nstloop=`losetup -f`
|
||||||
if [ $? = 255 ]; then
|
if [ $? = 255 ]; then
|
||||||
error "too many tomb opened. Please close any of them to open another tomb"
|
error "too many tomb opened. Please close any of them to open another tomb"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
losetup -f ${tombdir}/${tombfile}
|
losetup -f ${tombdir}/${tombfile}
|
||||||
|
|
||||||
act "check for a valid LUKS encrypted device"
|
act "check for a valid LUKS encrypted device"
|
||||||
cryptsetup isLuks ${nstloop}
|
cryptsetup isLuks ${nstloop}
|
||||||
if [ $? != 0 ]; then
|
if [ $? != 0 ]; then
|
||||||
# is it a LUKS encrypted nest? see cryptsetup(1)
|
# is it a LUKS encrypted nest? see cryptsetup(1)
|
||||||
error "$tombfile is not a valid Luks encrypted storage file"
|
error "$tombfile is not a valid Luks encrypted storage file"
|
||||||
$norm || rmdir $tombmount 2>/dev/null
|
$norm || rmdir $tombmount 2>/dev/null
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# save date of mount in minutes since 1970
|
# save date of mount in minutes since 1970
|
||||||
@ -562,10 +572,10 @@ mount_tomb() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
if ! [ -r /dev/mapper/${mapper} ]; then
|
if ! [ -r /dev/mapper/${mapper} ]; then
|
||||||
error "failure mounting the encrypted file"
|
error "failure mounting the encrypted file"
|
||||||
losetup -d ${nstloop}
|
losetup -d ${nstloop}
|
||||||
$norm || rmdir ${tombmount} 2>/dev/null
|
$norm || rmdir ${tombmount} 2>/dev/null
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
act "encrypted storage filesystem check"
|
act "encrypted storage filesystem check"
|
||||||
@ -582,8 +592,8 @@ mount_tomb() {
|
|||||||
|
|
||||||
notice "encrypted storage $tombfile succesfully mounted on $tombmount"
|
notice "encrypted storage $tombfile succesfully mounted on $tombmount"
|
||||||
if ! [ $NOBIND ]; then
|
if ! [ $NOBIND ]; then
|
||||||
exec_safe_bind_hooks ${tombmount}
|
exec_safe_bind_hooks ${tombmount}
|
||||||
exec_safe_post_hooks ${tombmount} open
|
exec_safe_post_hooks ${tombmount} open
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -689,6 +699,9 @@ print "-----END PGP MESSAGE-----"
|
|||||||
}
|
}
|
||||||
|
|
||||||
exec_safe_bind_hooks() {
|
exec_safe_bind_hooks() {
|
||||||
|
if [[ -n ${(k)opts[-o]} ]]; then
|
||||||
|
MOUNTOPTS=${opts[-o]}
|
||||||
|
fi
|
||||||
local MOUNTPOINT="${1}"
|
local MOUNTPOINT="${1}"
|
||||||
local ME=${SUDO_USER:-$(whoami)}
|
local ME=${SUDO_USER:-$(whoami)}
|
||||||
local HOME=$(grep $ME /etc/passwd | sed "s/^${ME}:.*:.*:.*:.*:\([\/a-z]*\):.*$/\1/" 2>/dev/null)
|
local HOME=$(grep $ME /etc/passwd | sed "s/^${ME}:.*:.*:.*:.*:\([\/a-z]*\):.*$/\1/" 2>/dev/null)
|
||||||
@ -1061,53 +1074,121 @@ EOF
|
|||||||
act "Tomb is now installed."
|
act "Tomb is now installed."
|
||||||
}
|
}
|
||||||
|
|
||||||
main () {
|
option_is_set() {
|
||||||
echo $@ | grep '\-D' 2>&1 > /dev/null
|
#First argument, the option (something like "-s")
|
||||||
# ?????
|
#Second (optional) argument: if it's "out", command will print it out 'set'/'unset'
|
||||||
if [ $? = 0 ]; then
|
# This is useful for if conditions
|
||||||
|
#Return 0 if is set, 1 otherwise
|
||||||
|
[[ -n ${(k)opts[$1]} ]];
|
||||||
|
r=$?
|
||||||
|
if [[ $2 == out ]]; then
|
||||||
|
if [[ $r == 0 ]]; then
|
||||||
|
echo 'set'
|
||||||
|
else
|
||||||
|
echo 'unset'
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
option_value() {
|
||||||
|
#First argument, the option (something like "-s")
|
||||||
|
echo ${opts[$1]}
|
||||||
|
}
|
||||||
|
|
||||||
ARGS=$@[@]
|
main() {
|
||||||
|
local -A subcommands_opts
|
||||||
OPTS=`getopt -o hvqDs:k:no: -n 'tomb' -- "$@"`
|
### Options configuration
|
||||||
while true; do
|
#Hi, dear developer! Are you trying to add a new subcommand, or to add some options?
|
||||||
case "$1" in
|
#Well, keep in mind that:
|
||||||
-h)
|
# 1. An option CAN'T have differente meanings/behaviour in different subcommands.
|
||||||
usage
|
# For example, "-s" means "size" and accept an argument. If you are tempted to add
|
||||||
exit 0 ;;
|
# an option "-s" (that means, for example "silent", and doesn't accept an argument)
|
||||||
-v)
|
# DON'T DO IT!
|
||||||
notice "Tomb - simple commandline tool for encrypted storage"
|
# There are two reasons for that:
|
||||||
act "version $VERSION ($DATE) by Jaromil @ dyne.org"
|
# I. usability; user expect that "-s" is "size
|
||||||
# print out the GPL license in this file
|
# II. Option parsing WILL EXPLODE if you do this kind of bad things
|
||||||
act ""
|
# (it will say "option defined more than once, and he's right)
|
||||||
cat ${TOMBEXEC} | awk 'BEGIN { license=0 } /^# This source/ { license=1 } { if(license==1) print " " $0 }
|
main_opts=(q -quiet=q D -debug=D h -help=h v -verbose=v)
|
||||||
/MA 02139, USA.$/ { license=0 }'
|
subcommands_opts[open]="n -nohook=n k: -key=k o: -mount-options=o"
|
||||||
act ""
|
subcommands_opts[mount]=${subcommands_opts[open]}
|
||||||
exit 0 ;;
|
subcommands_opts[create]="s: -size=s"
|
||||||
-q) QUIET=1; shift 1 ;;
|
subcommands_opts[close]=""
|
||||||
-D)
|
subcommands_opts[help]=""
|
||||||
print "[D] Tomb invoked with args \"${(f)@}\" "
|
subcommands_opts[slam]=""
|
||||||
print "[D] running on `date`"
|
subcommands_opts[list]=""
|
||||||
DEBUG=1; shift 1 ;;
|
subcommands_opts[help]=""
|
||||||
-s) SIZE=$2; shift 2 ;;
|
subcommands_opts[bury]=""
|
||||||
-k) KEY=$2; shift 2 ;;
|
subcommands_opts[exhume]=""
|
||||||
-n) NOBIND=1; shift 1 ;;
|
subcommands_opts[decompose]=""
|
||||||
-o) MOUNTOPTS=$2; shift 2;;
|
subcommands_opts[recompose]=""
|
||||||
--) shift; break ;;
|
subcommands_opts[install]=""
|
||||||
*) CMD=$1;
|
subcommands_opts[askpass]=""
|
||||||
FILE=$2; MOUNT=$3; # compat with old args
|
subcommands_opts[mktemp]=""
|
||||||
CMD2=${2}; CMD3=${3}; break ;;
|
### Detect subcommand
|
||||||
esac
|
local -aU every_opts #every_opts behave like a set; that is, an array with unique elements
|
||||||
|
for optspec in $subcommands_opts$main_opts; do
|
||||||
|
for opt in ${=optspec}; do
|
||||||
|
every_opts+=${opt}
|
||||||
|
done
|
||||||
done
|
done
|
||||||
|
local -a oldstar
|
||||||
if ! [ $CMD ]; then
|
oldstar=($argv)
|
||||||
error "first argument missing, use -h for help"
|
zparseopts -M -E -D -Adiscardme ${every_opts}
|
||||||
exit 0
|
unset discardme
|
||||||
|
subcommand=$1
|
||||||
|
if [[ -z ${(k)subcommands_opts[$subcommand]} ]]; then #there's no such subcommand
|
||||||
|
error "Subcommand '$subcommand' doesn't exist"
|
||||||
|
exit 127
|
||||||
fi
|
fi
|
||||||
|
argv=(${oldstar})
|
||||||
|
unset oldstar
|
||||||
|
|
||||||
|
### Parsing global + command-specific options
|
||||||
|
# zsh magic: ${=string} will split to multiple arguments when spaces occur
|
||||||
|
set -A cmd_opts ${main_opts} ${=subcommands_opts[$subcommand]}
|
||||||
|
if [[ -n $cmd_opts ]]; then #if there is no option, we don't need parsing
|
||||||
|
zparseopts -M -E -D -Aopts ${cmd_opts}
|
||||||
|
if [[ $? != 0 ]]; then
|
||||||
|
error "Some error occurred during option processing. See \"tomb help\" for more info"
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
#build PARAM (array of arguments) and check if there are unrecognized options
|
||||||
|
ok=0
|
||||||
|
PARAM=()
|
||||||
|
for arg in $*; do
|
||||||
|
if [[ $arg == '--' || $arg == '-' ]]; then
|
||||||
|
ok=1
|
||||||
|
continue #it shouldnt be appended to PARAM
|
||||||
|
elif [[ $arg[1] == '-' ]]; then
|
||||||
|
if [[ $ok == 0 ]]; then
|
||||||
|
error "unrecognized option $arg"
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
PARAM+=$arg
|
||||||
|
done
|
||||||
|
#first parameter actually is the subcommand: delete it and shift
|
||||||
|
PARAM[1]=()
|
||||||
|
shift
|
||||||
|
### End parsing command-specific options
|
||||||
|
|
||||||
|
### Set global options (useless, but for code retro-compatibility)
|
||||||
|
for opt in ${(k)global_opts}; do
|
||||||
|
if [[ $opt == '-q' ]]; then
|
||||||
|
QUIET=1
|
||||||
|
elif [[ $opt == '-D' ]]; then
|
||||||
|
DEBUG=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
CMD=$subcommand
|
||||||
|
CMD2=$PARAM[1]
|
||||||
|
CMD3=$PARAM[2]
|
||||||
|
|
||||||
func "Tomb command: $CMD $CMD2 $CMD3"
|
func "Tomb command: $CMD $CMD2 $CMD3"
|
||||||
|
|
||||||
case "$CMD" in
|
case "$subcommand" in
|
||||||
create) check_priv ; create_tomb ;;
|
create) check_priv ; create_tomb ;;
|
||||||
mount) check_priv ; mount_tomb ;;
|
mount) check_priv ; mount_tomb ;;
|
||||||
open) check_priv ; mount_tomb ;;
|
open) check_priv ; mount_tomb ;;
|
||||||
|
@ -211,7 +211,7 @@ if [ $1 ]; then # is it a file?
|
|||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
|
|
||||||
"${TOMBEXEC}" -k ${tombkey} mount ${tombdir}/${tombfile}
|
"${TOMBEXEC}" mount -k ${tombkey} ${tombdir}/${tombfile}
|
||||||
success=$?
|
success=$?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ if [ "$1" != "wizard" ]; then
|
|||||||
if [ -z $DISPLAY ]; then
|
if [ -z $DISPLAY ]; then
|
||||||
error "tomb-open is a wrapper for the command 'tomb'"
|
error "tomb-open is a wrapper for the command 'tomb'"
|
||||||
error "[!] type 'tomb-open wizard' if you want to be guided"
|
error "[!] type 'tomb-open wizard' if you want to be guided"
|
||||||
"${TOMBEXEC}" -h
|
"${TOMBEXEC}" help
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -338,7 +338,7 @@ cat <<EOF
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
tombfile=${tombname}.tomb
|
tombfile=${tombname}.tomb
|
||||||
"${TOMBEXEC}" -s $tombsize create ${tombfile}
|
"${TOMBEXEC}" create -s $tombsize ${tombfile}
|
||||||
|
|
||||||
if [ $? != 0 ]; then
|
if [ $? != 0 ]; then
|
||||||
error "An error occurred creating tomb, operation aborted."
|
error "An error occurred creating tomb, operation aborted."
|
||||||
@ -368,7 +368,7 @@ if [ $? = 0 ]; then
|
|||||||
notice "${tombname}.key succesfully saved on your USB"
|
notice "${tombname}.key succesfully saved on your USB"
|
||||||
act "now we'll proceed opening your brand new tomb"
|
act "now we'll proceed opening your brand new tomb"
|
||||||
|
|
||||||
"${TOMBEXEC}" -k ${tombfile}.key open ${tombfile}
|
"${TOMBEXEC}" open -k ${tombfile}.key ${tombfile}
|
||||||
if [ $? = 0 ]; then
|
if [ $? = 0 ]; then
|
||||||
launch_status ${tombname}
|
launch_status ${tombname}
|
||||||
fi
|
fi
|
||||||
@ -392,7 +392,7 @@ cat <<EOF
|
|||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
"${TOMBEXEC}" -k ${tombname}.tomb.key open ${tombfile}
|
"${TOMBEXEC}" open -k ${tombname}.tomb.key ${tombfile}
|
||||||
if [ $? = 0 ]; then
|
if [ $? = 0 ]; then
|
||||||
launch_status ${tombname}
|
launch_status ${tombname}
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user