WFDB SWIG Toolbox for MATLAB 1.0.0
(19,775 bytes)
#!/bin/bash
#
# headless wfdb-swig-matlab installer for *nix systems
#
#
#
#
BASE_URL=""
MATLAB=""
TEMP_JAR_DIR=""
WSM_TEMP_DIR=~/.wfdb-swig-matlab-tmp
WSM_FINAL_DIR=~/.wfdb-swig-matlab
WSM_VERSION=0.0.1
#
#
#
CURL=$(which curl 2>/dev/null || echo)
JAR=$(which jar 2>/dev/null || echo)
UUIDGEN=$(which uuidgen 2>/dev/null || echo)
WGET=$(which wget 2>/dev/null || echo)
#
#
#
INSTALL_GLOBALLY=""
JAR_NAME=""
PRINT_HELP=""
SOURCE_PATH=$(pwd)
SU_METHOD=sudo
#
#
#
detailed_usage_msg()
{
echo "Try \`$0 -h' to see detailed usage." 1>&2
}
#
# $1 is the location of a matlab binary (may be a symlink)
#
# if OK, return 0, and return the result into stdout;
# on error, return 1, and return the error string into stdout
#
find_default_matlab_path()
{
matlab_bin="$1"
if [ -z "$matlab_bin" ]
then
echo "*** Error: No default MATLAB found." 1>&2
return 1
fi
matlab=$("$matlab_bin" -e | sed -n 's/^MATLAB=\(.*\)$/\1/p')
if [ -z "$matlab" ]
then
echo "*** Error: No MATLAB env. var. for default MATLAB." 1>&2
return 1
fi
echo "$matlab"
return 0
}
#
# $1 is the url,
# $2 is the location to put the file
#
http_get()
{
if [ ! -z "$WGET" ]
then
wget -O "$2" "$1"
elif [ ! -z "$CURL" ]
then
curl -o "$2" "$1"
else
echo "*** Error: neither wget nor curl available; can't get $1." 1>&2
return 1
fi
}
#
# $1 is the OS name
# $2 is the arch name
#
is_valid_kernel_and_arch()
{
if [ "$#" -ne "2" ]
then
echo "*** Error: is_valid_kernel_and_arch() used incorrectly;"
echo " expected 2 args., but passed $#."
echo " Exiting."
exit 1
fi
case "$1" in
"Linux" )
case "$2" in
"i386" )
return 0
;;
"amd64" )
return 0
;;
* )
echo "*** Error: Unsupported architecture for operating system $1: $2" 1>&2
return 1
;;
esac
;;
"Darwin" )
case "$2" in
"ppc" )
return 0
;;
* )
echo "*** Error: Unsupported architecture for operating system $1: $2" 1>&2
return 1
;;
esac
;;
* )
echo "*** Error: Unsupported OS: $1" 1>&2
return 1
;;
esac
}
#
# $1 is the kernel name as printed by uname
# the result is what i've been calling it elsewhere
#
kernel_to_os()
{
case "$1" in
"Linux" )
echo "linux"
return 0
;;
"Darwin" )
echo "macosx"
return 0
;;
* )
echo "*** Error: Unknown kernel name: $1" 1>&2
return 1
esac
}
#
#
#
make_uuid()
{
if [ ! -z "$UUIDGEN" ]
then
"$UUIDGEN"
else
echo "00000000-0000-0000-0000-000000000000"
fi
}
#
#
#
on_err_exit()
{
echo "Exiting."
exit 1
}
#
# FIXME: should use an associative array for the USED_? vars.
#
parse_args()
{
local USED_J=""
local USED_M=""
local USED_P=""
local USED_S=""
while [ "$#" -ne "0" ]
do
case "$1" in
# FIXME: re-launch as root, or at least warn about not being root
"-g" )
INSTALL_GLOBALLY=1
;;
"-h" )
PRINT_HELP=true
;;
"-j" )
shift
if [ ! -z "$USED_J" ]
then
echo "*** Error: -j used more than once." 1>&2
detailed_usage_msg
return 1
elif [ -z "$1" ]
then
echo "*** Error: -j used without a JAR_NAME." 1>&2
detailed_usage_msg
return 1
else
JAR_NAME="$1"
USED_J=1
fi
;;
"-m" )
shift
if [ ! -z "$USED_M" ]
then
echo "*** Error: -m used more than once." 1>&2
detailed_usage_msg
return 1
elif [ -z "$1" ]
then
echo "*** Error: -m used without a MATLAB_PATH." 1>&2
detailed_usage_msg
return 1
else
MATLAB="$1"
USED_M=1
fi
;;
"-p" )
shift
if [ ! -z "$USED_P" ]
then
echo "*** Error: -p used more than once." 1>&2
detailed_usage_msg
return 1
elif [ -z "$1" ]
then
echo "*** Error: -p used without a PATH." 1>&2
detailed_usage_msg
return 1
else
SOURCE_PATH="$1"
USED_P=1
fi
;;
"-s" )
shift
if [ ! -z "$USED_S" ]
then
echo "*** Error: -s used more than once." 1>&2
detailed_usage_msg
return 1
elif [ -z "$1" ]
then
echo "*** Error: -s used without a METHOD." 1>&2
detailed_usage_msg
return 1
else
if [ "$1" != "sudo" ] && [ "$1" != "su" ]
then
echo "*** Error: -s used with invalid method." 1>&2
detailed_usage_msg
return 1
else
SU_METHOD="$1"
USED_S=1
fi
fi
;;
* )
echo "*** Error: invalid argument: $1" 1>&2
detailed_usage_msg
return 1
;;
esac
shift
done
}
#
#
#
print_help()
{
echo "Usage: $0 [OPTION] ..."
echo "Install WFDB Tools for MATLAB."
echo
echo "All arguments are optional:"
echo " -g install globally, i.e. in one location"
echo " accessible to all users; must be run"
echo " as superuser (default: no)"
echo " -h print this usage information"
echo " -j JAR_NAME use a jar program called JAR_NAME;"
echo " on some systems, it is called \"gjar\" or"
echo " \"fastjar\" (default: \"jar\")"
echo " -m MATLAB_PATH use the Matlab installation in MATLAB_PATH"
echo " (default: first executable matlab in your \$PATH)"
echo " -p PATH install from the source path PATH,"
echo " which is either a directory in the"
echo " local file system or a URL starting"
echo " with \"http://\" (default: current working dir.)"
echo " -s METHOD if superuser access is necessary, use"
echo " su if METHOD is \"su\" and sudo if \"sudo\""
echo " (default: \"sudo\")"
return 0
}
#
# $1 should be the prompt to display;
# $2 should be a string of characters that don't need
# to be escaped in a regular expression
#
# returns result into $RESULT
#
# FIXMEFIXME: have DEFAULTS!!!
# FIXME: change this to use stdout
#
read_char_prompt()
{
if [ "$#" -ne "2" ]
then
echo "*** Error: read_char_prompt() used incorrectly;"
echo " expected 2 args., but passed $#."
echo " Exiting."
exit 1
fi
prompt="$1"
chars_allowed="$2"
while [ true ]
do
echo -n "$prompt [$chars_allowed] "
read v
v=$(echo "$v" | sed -n "/^[$chars_allowed]\$/p")
if [ ! -z "$v" ]
then
RESULT="$v"
return 0
fi
done
}
#
# $1 should be the prompt to display;
# $2 should be the default choice
#
# returns result into $RESULT
# does not allow empty string to be returned
#
# FIXME: change this to use stdout
#
read_string_prompt()
{
if [ "$#" -ne "2" ]
then
echo "*** Error: read_string_prompt() used incorrectly;"
echo " expected 2 args., but passed $#."
echo " Exiting."
exit 1
fi
prompt="$1"
default="$2"
while [ true ]
do
echo -n "$prompt [default: $default] "
read v
if [ -z "$v" ]
then
v="$default"
fi
if [ ! -z "$v" ]
then
RESULT="$v"
return 0
fi
done
}
#
#
#
run_su()
{
case "$SU_METHOD" in
"su" )
su -c "$*"
return "$?"
;;
"sudo" )
sudo $*
return "$?"
;;
esac
}
#
# if any individual command fails, exit
#
trap on_err_exit ERR
#
#
#
parse_args $*
if [ ! -z "$PRINT_HELP" ]
then
print_help
exit 0
fi
#
# prompt for final dir. if installing globally
#
if [ ! -z "$INSTALL_GLOBALLY" ]
then
if [ $(id -u) -ne "0" ]
then
echo "*** You've chosen global installation; please restart $0 as superuser."
exit 1
fi
read_string_prompt "Where would you like to put the wfdb-swig-matlab directory?" \
"/usr/local/wfdb-swig-matlab"
WSM_FINAL_DIR=$RESULT
echo "OK, I'll install to $WSM_FINAL_DIR."
fi
#
#
#
if [ ! -z "$JAR_NAME" ]
then
JAR=$(which "$JAR_NAME" 2>/dev/null || echo)
fi
if [ -z "$JAR" ]
then
echo "*** Error: No jar program found. Please put it in your path,"
echo " or use -j to specify an alternate name (e.g. gjar or fastjar.)"
exit 1
fi
#
# find matlab
#
if [ -z "$MATLAB" ]
then
echo
echo "Looking for MATLAB ..."
MATLABBIN=$(which matlab 2>/dev/null || echo)
MATLAB=$(find_default_matlab_path "$MATLABBIN")
echo "Found MATLAB in $MATLAB"
else
MATLABBIN="$MATLAB/bin/matlab"
if [ ! -e "$MATLABBIN" ]
then
echo "*** Error: I expected a Matlab executable at $MATLABBIN, but it wasn't there." 1>&2
exit 1
fi
fi
# FIXME: is this strictly necessary?
for pf in classpath.txt librarypath.txt
do
if [ ! -e "$MATLAB/toolbox/local/$pf" ]
then
echo "*** Error: I expected $MATLAB/toolbox/local/$pf to exist, but it doesn't." 1>&2
exit 1
fi
done
#
# get matlab version and jvm arch.
# FIXME: this is ever so slightly brittle; i preferred keeping the
# version and arch. on separate lines, but matlab is not
# consistent about it what it prints before/after my fprintf()
#
echo "Asking MATLAB for version and JVM arch. information ..."
VERSION_AND_ARCH=$("$MATLABBIN" -nodesktop -nodisplay -nosplash \
-r "nl=['\\','n'];fprintf(1,['%s vvvvv %s',nl], \
version, \
char(java.lang.System.getProperty('os.arch')));exit;"\
| grep ".* vvvvv .*")
OLDIFS="$IFS"
IFS=''
MATLAB_VERSION=$(echo "$VERSION_AND_ARCH" | sed -n -e 's/\(.*\) vvvvv \(.*\)/\1/p')
ARCH=$(echo "$VERSION_AND_ARCH" | sed -n -e 's/\(.*\) vvvvv \(.*\)/\2/p')
IFS="$OLDIFS"
echo "This is MATLAB version $MATLAB_VERSION, with JVM arch. $ARCH"
#
#
#
KERNEL=$(uname -s)
is_valid_kernel_and_arch "$KERNEL" "$ARCH"
OS=$(kernel_to_os "$KERNEL")
#
# decide on a temp. dir.
#
while [ -e "$WSM_TEMP_DIR" ]
do
echo
# FIXME: break this up into separate lines
read_char_prompt \
"I want to use $WSM_TEMP_DIR but it already exists; can I remove it?" \
"yn"
if [ "$RESULT" = "y" ]
then
{ rm -rf "$WSM_TEMP_DIR"; } || \
{ echo "Unable to remove $WSM_TEMP_DIR -- exiting."; exit 1; }
else
# "$RESULT" = "n"
read_string_prompt \
"OK, what should I use as a temp. directory?" \
""
WSM_TEMP_DIR="$RESULT"
fi
done
mkdir "$WSM_TEMP_DIR"
#
# verify that the given path contains the right files
#
if [[ "$SOURCE_PATH" == "http://"* ]]
then
BASE_URL="$SOURCE_PATH"
TEMP_JAR_DIR="$WSM_TEMP_DIR/tmp"
SOURCE_PATH="$TEMP_JAR_DIR"
mkdir "$SOURCE_PATH"
http_get "$BASE_URL/wfdb-swig.jar" "$SOURCE_PATH/wfdb-swig.jar"
http_get "$BASE_URL/wsm-matlab-code.jar" "$SOURCE_PATH/wsm-matlab-code.jar"
http_get "$BASE_URL/wfdb-swig-matlab-$OS.jar" \
"$SOURCE_PATH/wfdb-swig-matlab-$OS.jar"
http_get "$BASE_URL/wfdb-nativelibs-$OS-$ARCH.jar" \
"$SOURCE_PATH/wfdb-nativelibs-$OS-$ARCH.jar"
fi
#
# check that all the files are there
#
FILES_MISSING=""
for f in wfdb-swig.jar wsm-matlab-code.jar \
"wfdb-swig-matlab-$OS.jar" "wfdb-nativelibs-$OS-$ARCH.jar"
do
if [ ! -e "$SOURCE_PATH/$f" ]
then
echo "*** Error: $SOURCE_PATH/$f should exist, but it doesn't." 1>&2
# if [[ "$SOURCE_PATH" != "http://"* ]]
# then
# echo " (Did you not run make first?)" 1>&2
# fi
FILES_MISSING=1
fi
done
if [ ! -z "$FILES_MISSING" ]
then
if [[ "$SOURCE_PATH" == "http://"* ]]
then
exit 1
else
echo
read_char_prompt "Should I try running make in ${SOURCE_PATH}?" "yn"
if [ "$RESULT" = "n" ]
then
echo "OK, giving up."
exit 1
fi
(pushd $(pwd) >/dev/null && \
cd "$SOURCE_PATH" && \
make && \
popd >/dev/null)
# FIXME: a bit of redundancy here, with the above check
for f in wfdb-swig.jar wsm-matlab-code.jar \
"wfdb-swig-matlab-$OS.jar" "wfdb-nativelibs-$OS-$ARCH.jar"
do
if [ ! -e "$SOURCE_PATH/$f" ]
then
echo "*** Error: $SOURCE_PATH/$f still doesn't exist;" 1>&2
echo " something has gone very wrong." 1>&2
exit 1
fi
done
fi
fi
#
# copy the files into ~/.wfdb-swig-matlab
#
echo
echo "OK, copying files into temp. dir. ${WSM_TEMP_DIR} ..."
mkdir "$WSM_TEMP_DIR/$WSM_VERSION"
mkdir "$WSM_TEMP_DIR/$WSM_VERSION/util"
mkdir "$WSM_TEMP_DIR/$WSM_VERSION/lib-$ARCH"
# unjar
(pushd $(pwd) >/dev/null && \
cd "$WSM_TEMP_DIR/$WSM_VERSION/" && \
"$JAR" xvf "$SOURCE_PATH/wfdb-swig.jar" wfdb.jar && \
"$JAR" xvf "$SOURCE_PATH/wfdb-swig-matlab-$OS.jar" wsm-classes.jar && \
"$JAR" xvf "$SOURCE_PATH/wsm-matlab-code.jar" && \
cd "lib-$ARCH" && \
"$JAR" xvf "$SOURCE_PATH/wfdb-nativelibs-$OS-$ARCH.jar" && \
popd >/dev/null)
# remove the extraneous stuff that got unjarred
rm "$WSM_TEMP_DIR/$WSM_VERSION/matlab-files.txt"
rm -r "$WSM_TEMP_DIR/$WSM_VERSION/META-INF"
for f in "$WSM_TEMP_DIR/$WSM_VERSION/lib-$ARCH/"*
do
if [[ "$f" != *"-$ARCH" ]]
then
rm -r "$f"
fi
done
# rename the shared libs.
for lf in "$WSM_TEMP_DIR/$WSM_VERSION/lib-$ARCH/"*"-$ARCH"
do
mv "$lf" "$WSM_TEMP_DIR/$WSM_VERSION/lib-$ARCH/$(basename $lf -$ARCH)"
done
# check that these jars exist
if [ ! -e "$WSM_TEMP_DIR/$WSM_VERSION/wfdb.jar" ]
then
echo "*** Error: $SOURCE_PATH/wfdb-swig.jar does not appear to contain wfdb.jar" 1>&2
exit 1
fi
if [ ! -e "$WSM_TEMP_DIR/$WSM_VERSION/wsm-classes.jar" ]
then
echo "*** Error: $SOURCE_PATH/wfdb-swig-matlab-$OS.jar does not appear to contain wsm-classes.jar" 1>&2
exit 1
fi
# FIXME: should probably check that the other files are there, too
#
# if we downloaded from the web site, remove the temp. dir.
#
if [ ! -z "$TEMP_JAR_DIR" ]
then
rm -r "$TEMP_JAR_DIR"
fi
#
# update classpath.txt and librarypath.txt, into temp. files
# FIXME: why doesn't [[:graph:]]+ work???
#
SED_PROG='1{h;$p;d;};x;G;/^# DO NOT EDIT: WSM v\. [[:graph:]][[:graph:]]* [[:graph:]][[:graph:]]* \(.*\)\n\1$/!{P;$!d;g;p;};$!{n;h;${g;p;};d;}'
sed -n -e "$SED_PROG" "$MATLAB/toolbox/local/classpath.txt" \
> "$WSM_TEMP_DIR/classpath.txt"
sed -n -e "$SED_PROG" "$MATLAB/toolbox/local/librarypath.txt" \
> "$WSM_TEMP_DIR/librarypath.txt"
WSM_CODE_DIR="$WSM_FINAL_DIR/$WSM_VERSION"
WSM_LIB_DIR="$WSM_CODE_DIR/lib-$ARCH"
NEW_UUID=$(make_uuid)
WSM_COMMENT_PREFIX="# DO NOT EDIT: WSM v. $WSM_VERSION $NEW_UUID"
echo "$WSM_COMMENT_PREFIX $WSM_LIB_DIR" >> "$WSM_TEMP_DIR/librarypath.txt"
echo "$WSM_LIB_DIR" >> "$WSM_TEMP_DIR/librarypath.txt"
echo "$WSM_COMMENT_PREFIX $WSM_CODE_DIR/wfdb.jar" >> "$WSM_TEMP_DIR/classpath.txt"
echo "$WSM_CODE_DIR/wfdb.jar" >> "$WSM_TEMP_DIR/classpath.txt"
echo "$WSM_COMMENT_PREFIX $WSM_CODE_DIR/wsm-classes.jar" \
>> "$WSM_TEMP_DIR/classpath.txt"
echo "$WSM_CODE_DIR/wsm-classes.jar" >> "$WSM_TEMP_DIR/classpath.txt"
#
# write config file
#
WSM_CONF_FILE="$WSM_TEMP_DIR/$WSM_VERSION.conf"
touch "$WSM_CONF_FILE"
echo "$NEW_UUID" >> "$WSM_CONF_FILE"
echo "$MATLAB_VERSION" >> "$WSM_CONF_FILE"
echo "$MATLAB" >> "$WSM_CONF_FILE"
#
# create backups of classpath.txt and librarypath.txt
#
echo
echo "Just so you know, I'm going to put backups of classpath.txt and"
echo "librarypath.txt into $WSM_FINAL_DIR, before I change them."
cp "$MATLAB/toolbox/local/classpath.txt" "$WSM_TEMP_DIR/classpath.txt.backup"
cp "$MATLAB/toolbox/local/librarypath.txt" "$WSM_TEMP_DIR/librarypath.txt.backup"
#
# move temp. dir. to final dir.
#
if [ -e "$WSM_FINAL_DIR" ]
then
echo
read_char_prompt "$WSM_FINAL_DIR already exists; can I replace it? \
(If not, installation will abort.)" \
"yn"
if [ "$RESULT" = "n" ]
then
echo "OK, I'm aborting. If you want, you can finish manually:"
echo "copy $WSM_TEMP_DIR/classpath.txt into $MATLAB/toolbox/local/ and"
echo "copy $WSM_TEMP_DIR/librarypath.txt into $MATLAB/toolbox/local/ and then"
echo "move $WSM_TEMP_DIR to $WSM_FINAL_DIR."
echo "Everything should work after that!"
exit 1
fi
rm -rf "$WSM_FINAL_DIR"
fi
echo
echo "OK, moving $WSM_TEMP_DIR to $WSM_FINAL_DIR ..."
if [ ! -e "$(dirname "$WSM_FINAL_DIR")" ]
then
mkdir -p "$(dirname "$WSM_FINAL_DIR")"
fi
mv "$WSM_TEMP_DIR" "$WSM_FINAL_DIR"
#
# move temp. classpath.txt and librarypath.txt into $MATLAB/toolbox/local
# FIXME: why can't i figure out how to run run_su on multiple commands??
#
echo
echo "OK, now I have to copy classpath.txt and librarypath.txt"
echo " into $MATLAB/toolbox/local/."
if [ -z "$INSTALL_GLOBALLY" ]
then
echo " You may be prompted for a password (maybe more than once.)"
fi
for pf in classpath.txt librarypath.txt
do
{ cp "$WSM_FINAL_DIR/$pf" \
"$MATLAB/toolbox/local/$pf" 2>/dev/null; } || \
{ [ -z "$INSTALL_GLOBALLY" ] && \
{ run_su cp "$WSM_FINAL_DIR/$pf" \
"$MATLAB/toolbox/local/$pf"; }; }
rm -f "$WSM_FINAL_DIR/$pf"
done
#
# FIXME: need to escape the paths!
# FIXMEFIXME: use the userpath!
#
echo
echo "OK, updating MATLAB path ..."
if [ -z "$INSTALL_GLOBALLY" ]
then
"$MATLABBIN" -nodesktop -nodisplay -nosplash \
-r "addpath('$WSM_FINAL_DIR/$WSM_VERSION'); \
addpath('$WSM_FINAL_DIR/$WSM_VERSION/util'); \
mkdir('$HOME','matlab'); \
path2rc('$HOME/matlab/pathdef.m'); \
exit;" >/dev/null
else
"$MATLABBIN" -nodesktop -nodisplay -nosplash \
-r "addpath('$WSM_FINAL_DIR/$WSM_VERSION'); \
addpath('$WSM_FINAL_DIR/$WSM_VERSION/util'); \
path2rc; \
exit;" >/dev/null
fi
#
#
#
echo
echo "All done! Enjoy!"
echo