#!/bin/bash help () { { echo "usage: iocsh [options] [files]" echo "Start an EPICS iocsh and load files" echo "Recognized filetypes: *.db *.dbt *.template *.subs *.subst *.dbd *.so" echo echo "Possible options:" echo " -3.xx.yy: Set EPICS base version." echo " -32: Force 32 bit version (on 64 bit systems)." echo " -? or -h or --help: Show this page and exit." echo " -v or --version: Show version and exit." echo " -c: The next string is executed as a command by the EPICS shell." echo " -s: The next string is a sequencer program (and arguments), run with 'seq'." echo " This forces an 'iocInit' before running the program." echo " -r: The next string is a module (and version), loaded via 'require'." echo " -n: The next string is the IOC name (used for prompt)." echo " Default: dirname if parent dir is \"ioc\" otherwise hostname." echo echo "Supported filetypes:" echo "*.db, *.dbt and *.template are loaded via 'dbLoadRecords'." echo " After the filename, you can specify substitutions like MACRO=value." echo "*.subs and *.subst are loaded via 'dbLoadTemplate'." echo "*.dbd is loaded via 'dbLoadDatabase'." echo "*.so is loaded via 'ld' or 'dlload' (3.14.12 or higer)." echo "If an argument is @file, more arguments are read from that file." echo "All other files are executed as startup scripts by the EPICS shell." } >&2 exit } version () { { echo "iocsh by Dirk Zimoch" } >&2 exit } case $1 in ( -h | "-?" | -help | --help ) help ;; ( -v | -ver | --ver | -version | --version ) version ;; ( -3.* ) unset EPICS_BASE BASE=${1#-} shift ;; esac # realpath and readlink are not available on all systems, let's try what works... rp() { ( realpath $1 || readlink -f $1 || readlink $1 || (cd -P $1 && echo $PWD) || (x=$(\ls -ld $1) && echo ${x##* }) || echo $1 ) 2>/dev/null } # if EPICS_HOST_ARCH is not set guess it if [ -z "$EPICS_HOST_ARCH" ] then echo "EPICS_HOST_ARCH is not set" EPICS_HOST_ARCH=$(basename $(dirname $(rp $(which caRepeater)))) if [ -n "$EPICS_HOST_ARCH" ] then echo "Guessing EPICS_HOST_ARCH=$EPICS_HOST_ARCH" else exit 1 fi fi # check if user requested 32 bit version on a 64 bit system case $1 in ( -32 ) EPICS_HOST_ARCH=${EPICS_HOST_ARCH%_64} shift ;; esac # Either EPICS or EPICS_BASE should be set to the install directory if [ -z "$EPICS_BASE" ] then if [ -z "$EPICS" ] then # look for some standard install directories for EPICS in /usr/local/epics /opt/epics /epics do if [ -d $EPICS ] then break 2 fi echo "Cannot find any EPICS installation directory." >&2 echo "Try setting EPICS_BASE environment variable to full path" >&2 exit 1 done fi # find highest (requested) EPICS version that supports our architecture (or its 32 bit version) EPICS_BASE=$(\ls -1vrd $EPICS/base*$BASE*/bin/{${EPICS_HOST_ARCH},${EPICS_HOST_ARCH%_64}} 2>/dev/null | head -n1) if [ -z $EPICS_BASE ] then echo Cannot find any $BASE EPICS version for $EPICS_HOST_ARCH. >&2 exit 1 fi # maybe we need to change from 64 bit to 32 bit if [ $EPICS_HOST_ARCH != ${EPICS_BASE#*/bin/} ] then EPICS_HOST_ARCH=${EPICS_BASE#*/bin/} echo "No 64 bit version in ${EPICS_BASE%bin*}. Switch to 32 bit version $EPICS_HOST_ARCH" fi EPICS_BASE=$(rp ${EPICS_BASE%bin*}) fi if [ ! -d $EPICS_BASE ] then echo "Cannot find EPICS_BASE directory." >&2 echo "Try setting EPICS_BASE environment variable to full path" >&2 exit 1 fi # Check revision if [ -r $EPICS_BASE/configure/CONFIG_BASE_VERSION ] then BASE=$(awk -F '[ \t]*=[ \t]*' ' /^[ \t]*EPICS_VERSION[ \t]*=/ {v=$2} /^[ \t]*EPICS_REVISION[ \t]*=/ {r=$2} /^[ \t]*EPICS_MODIFICATION[ \t]*=/ {m=$2} END {print v"."r"."m}' < $EPICS_BASE/configure/CONFIG_BASE_VERSION) else BASE=$(basename $(rp $EPICS_BASE)) BASE=${BASE#*base-} fi if [ "${BASE#3.14.}" = "$BASE" -a "${BASE#3.15.}" = "$BASE" ] then echo "Cannot find any EPICS 3.14 or 3.15 version" >&2 echo "Try setting EPICS_BASE environment variable to full path" >&2 exit 1 fi export BASE BASEMINOR=${BASE#3.} BASEPATCH=${BASEMINOR#*.} BASEMINOR=${BASEMINOR%.*} # IOC name derives from hostname # (trailing possible '\r' under cygwin) IOC=$(hostname|tr -d '\r') # trailing possible domain name IOC=${IOC%%.*} # or get IOC name from start directory following PSI convention if [ $(basename $(dirname $PWD)) = "ioc" ] then IOC=$(basename $PWD) fi export IOC # Check for 64 bit versions, default to 32 bit if [ ! -d $EPICS_BASE/lib/${EPICS_HOST_ARCH} -a -d $EPICS_BASE/lib/${EPICS_HOST_ARCH%_64} ] then echo "No 64 bit EPICS installation found. Defaulting to 32 bit" EPICS_HOST_ARCH=${EPICS_HOST_ARCH%_64} fi # setup search path for require ODIR=O.${BASE}_$EPICS_HOST_ARCH EPICS_DRIVER_PATH=.:bin:snl:../snl:$ODIR:src/$ODIR:snl/$ODIR:../snl/$ODIR:${EPICS_DRIVER_PATH#:} #Special PSI: find installation base for libs from working directory D=$(rp $PWD) I=${D%/iocBoot/*} if [ $I != $D ] then INSTBASE=$I export INSTBASE fi EPICS_DRIVER_PATH=${EPICS_DRIVER_PATH%:}:${EPICS_MODULES:=/ioc/modules}:${INSTBASE:=/work}/iocBoot/R$BASE/$EPICS_HOST_ARCH # convert for win32-x86 arch if [ ${EPICS_HOST_ARCH#win32-} != $EPICS_HOST_ARCH ] then EPICS_DRIVER_PATH=$(cygpath -wp $EPICS_DRIVER_PATH) DBD=$(cygpath -wp $DBD) fi if [ ${EPICS_HOST_ARCH#cygwin-} != $EPICS_HOST_ARCH ] then DBD=$(cygpath -wp $DBD) fi export EPICS_DRIVER_PATH subst () { subst="" while [ "$#" -gt 1 ] do case $2 in ( *=* ) subst="$subst,$2"; shift ;; ( * ) break ;; esac done echo ${subst#,} } loadFiles () { while [ "$#" -gt 0 ] do file=$1 case $file in ( -h | "-?" | -help | --help ) help ;; ( -v | -ver | --ver | -version | --version ) version ;; ( @* ) loadFiles $(cat ${file#@}) ;; ( *.db | *.template) subst="" while [ "$#" -gt 1 ] do case $2 in ( *=* ) subst="$subst,$2"; shift ;; ( * ) break ;; esac done echo "dbLoadRecords \"$file\",\"${subst#,}\"" ;; ( *.subs | *.subst ) echo "dbLoadTemplate \"$file\"" ;; ( *.dbd ) # some dbd files must be loaded before main to take effect echo "dbLoadDatabase \"$file\",\"$DBD\"" ;; ( *.so ) if [ $BASEMINOR -ge 15 -o $BASEPATCH -ge 12 ] then echo "dlload \"$file\"" else echo "ld \"$file\"" fi ;; ( -c ) shift case $1 in ( seq* ) if [ "$init" != NO ] then echo "iocInit" init=NO fi ;; ( iocInit ) init=NO ;; esac echo $1 ;; ( -s ) shift if [ "$init" != NO ] then echo "iocInit" init=NO fi echo "seq $1" ;; ( -r ) shift echo "require $1" ;; ( -n ) shift IOC="$1" ;; ( -3.* ) echo "Version $file must be first argument" >&2 exit 1 ;; ( -32 ) echo "-32 option must come before all others (except -3.xx.yy)" >&2 exit 1 ;; ( -* ) { echo "unknown option $1" echo "try: $(basename $0) --help" } >&2 exit 1 ;; ( * ) echo "< \"$file\"" if grep -q iocInit $file; then init=NO; fi ;; esac shift done } startup=/tmp/iocsh.startup.$$ trap "stty sane; echo; rm -f $startup" EXIT TERM KILL { echo "# date=\"$(date)\"" echo "# user=\"${USER:-$(whoami)}\"" for var in PWD BASE EPICS_HOST_ARCH SHELLBOX EPICS_CA_ADDR_LIST EPICS_DRIVER_PATH do echo "# $var=\"${!var}\"" done if [ $BASEMINOR -ge 15 -o $BASEPATCH -ge 12 ] then EXE=$EPICS_BASE/bin/$EPICS_HOST_ARCH/softIoc ARGS="-D $EPICS_BASE/dbd/softIoc.dbd" # load "require" command LIBPREFIX=lib LIBPOSTFIX=.so if [ -d $EPICS_MODULES/${REQUIRE:=require} ] then # new module pool model REQUIRE_LIB=$EPICS_MODULES/$REQUIRE/${REQUIRE_VERSION:=$(cd $EPICS_MODULES/$REQUIRE; ls -1rvd *.*.* | head -n 1)}/R$BASE/lib/$EPICS_HOST_ARCH/$LIBPREFIX$REQUIRE$LIBPOSTFIX REQUIRE_DBD=$EPICS_MODULES/$REQUIRE/$REQUIRE_VERSION/R$BASE/dbd/$REQUIRE.dbd else # old driver pool model REQUIRE=misc${REQUIRE_VERSION:+-}$REQUIRE_VERSION REQUIRE_LIB=$INSTBASE/iocBoot/R$BASE/$EPICS_HOST_ARCH/$LIBPREFIX$REQUIRE$LIBPOSTFIX REQUIRE_DBD=$INSTBASE/iocBoot/R$BASE/dbd/$REQUIRE.dbd fi if [ ! -f "$REQUIRE_LIB" ] then echo "Library $REQUIRE_LIB not found." >&2 echo "Command 'require' is not available." >&2 else echo "dlload $REQUIRE_LIB" echo "dbLoadDatabase $REQUIRE_DBD" echo "${REQUIRE%-*}_registerRecordDeviceDriver" fi else # get rid of the compiled-in rpath because at PSI that is a link pointing to current EPICS version. LOADER=/lib/ld-linux.so.2 LOADERARGS="--library-path $EPICS_BASE/lib/$EPICS_HOST_ARCH --inhibit-rpath ''" APP=ioc EXE=$EPICS_EXTENSIONS/bin/$EPICS_HOST_ARCH/$APP DBD=$EPICS_EXTENSIONS/dbd echo "dbLoadDatabase \"$APP.dbd\",\"$DBD\"" echo "${APP}_registerRecordDeviceDriver(pdbbase)" fi echo "require misc $MISC_VERSION" loadFiles "$@" if [ "$init" != NO ] then echo "iocInit" fi if [ "$SHELLBOX" ] then PATH=$PATH:/home/ioc/bin export BCAST_ADDR=$(/sbin/ifconfig | awk -F '[ :]+' '/Bcast/ {print $6; exit}') echo "! rm -f /tmp/${IOC}.dbl" echo 'dbl "","RTYP DESC" > /tmp/${IOC}.dbl' echo "! dbl2odb.sh ${IOC} \"$BCAST_ADDR\" \"$EPICS_CA_SERVER_PORT\"" echo "! rm -f /tmp/${IOC}.libs" echo "libversionShow > /tmp/${IOC}.libs" echo "! upload_libinfo.py -i ${IOC} -l /tmp/${IOC}.libs" fi echo 'epicsEnvSet IOCSH_PS1,"${IOC}> "' } > $startup # convert startup script file name for win32-x86 if [ ${EPICS_HOST_ARCH#win32-} != $EPICS_HOST_ARCH ] then startup=`cygpath -w $startup` fi if [ ${EPICS_HOST_ARCH#win32-} != $EPICS_HOST_ARCH -o ${EPICS_HOST_ARCH#cygwin-} != $EPICS_HOST_ARCH ] then PATH=$INSTBASE/iocBoot/R$BASE/$EPICS_HOST_ARCH:$EPIC_BASE/bin/$EPICS_HOST_ARCH:$EPICS_BASE/../seq/bin/$EPICS_HOST_ARCH:$PATH fi echo $EXE $ARGS $startup ulimit -c unlimited eval "$LOADER $LOADERARGS $EXE" $ARGS "$startup" 2>&1