merged disctools and exec into this directory.

Added iocsh wrapper with flexible EPICS version handling
This commit is contained in:
zimoch
2011-11-28 14:18:37 +00:00
parent 8281a7c778
commit 8674e81a42
7 changed files with 755 additions and 6 deletions
+3
View File
@@ -7,4 +7,7 @@ SOURCES += require.c
SOURCES += listRecords.c
SOURCES += updateMenuConvert.c
SOURCES += addScan.c
SOURCES += disctools.c
SOURCES += exec.c
SOURCES_vxWorks += bootNotify.c
+22 -6
View File
@@ -8,14 +8,30 @@ require "<lib>" [,"<version>"]
load a library and its dbd file
updateMenuConvert
shell function
add all breakpoint tables found on this ioc to menu convert
startup script function
add all loaded breakpoint tables found on this ioc to menu convert
to be called before iocInit
addScan rate
startup script function
create a new scan rate (seconds) and add it to menuScan
to be called before iocInit
bootNotify
startup script function
call a script on the boot pc and tell it a lot of boot infos
iocCheck / iocCheckInit
subroutine record function
set record to 0 if any task dies
reset record to 1 when 1 is written to A
dir / ls / ll / mkdir / rmdir / rm / mv / umask / chmod
shell functions
make disc functions available in iocsh
not needed on vxWorks
exec / !
execute an externel command from iocsh
shell function
not available on vxWorks
listRecords filename fields
shell function
wrapper for dbl to get same syntax in 3.13 and 3.14
+366
View File
@@ -0,0 +1,366 @@
/*
* disctools - dir etc.
*
* $Author: zimoch $
* $ID$
* $Date: 2011/11/28 14:18:37 $
*
* DISCLAIMER: Use at your own risc and so on. No warranty, no refund.
*/
#include <iocsh.h>
#include <stdio.h>
#ifdef UNIX
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include <malloc.h>
#include <pwd.h>
#include <grp.h>
#endif
#include <epicsExport.h>
#ifdef UNIX
/* dir, ll, ls */
static const iocshArg dirArg0 = { "directrory", iocshArgString };
static const iocshArg * const dirArgs[1] = { &dirArg0 };
static const iocshFuncDef dirDef = { "dir", 1, dirArgs };
static const iocshFuncDef llDef = { "ll", 1, dirArgs };
static const iocshFuncDef lsDef = { "ls", 1, dirArgs };
static int nohidden(const struct dirent *entry)
{
return entry->d_name[0] != '.';
}
static void llFunc(const iocshArgBuf *args)
{
char* dirname = ".";
struct dirent** namelist;
struct stat filestat;
char type;
char filename[256];
char target[256];
struct group* group;
struct passwd* user;
struct tm time;
char timestr[20];
int n, i, len;
if (args[0].sval) dirname = args[0].sval;
n = scandir(dirname, &namelist, nohidden, alphasort);
if (n < 0)
{
perror(dirname);
return;
}
for (i = 0; i < n; i++)
{
sprintf(filename, "%s/%s", dirname, namelist[i]->d_name);
if (lstat(filename, &filestat))
{
perror(namelist[i]->d_name);
continue;
}
if (S_ISREG(filestat.st_mode)) type='-';
else if (S_ISDIR(filestat.st_mode)) type='d';
else if (S_ISCHR(filestat.st_mode)) type='c';
else if (S_ISBLK(filestat.st_mode)) type='b';
else if (S_ISFIFO(filestat.st_mode)) type='p';
else if (S_ISLNK(filestat.st_mode)) type='l';
else if (S_ISSOCK(filestat.st_mode)) type='s';
else type='?';
localtime_r(&filestat.st_mtime, &time);
strftime(timestr, 20, "%b %e %Y %H:%M", &time);
printf("%c%c%c%c%c%c%c%c%c%c %4d",
type,
filestat.st_mode & S_IRUSR ? 'r' : '-',
filestat.st_mode & S_IWUSR ? 'w' : '-',
filestat.st_mode & S_ISUID ? 's' :
filestat.st_mode & S_IXUSR ? 'x' : '-',
filestat.st_mode & S_IRGRP ? 'r' : '-',
filestat.st_mode & S_IWGRP ? 'w' : '-',
filestat.st_mode & S_ISGID ? 's' :
filestat.st_mode & S_IXGRP ? 'x' : '-',
filestat.st_mode & S_IROTH ? 'r' : '-',
filestat.st_mode & S_IWOTH ? 'w' : '-',
filestat.st_mode & S_ISVTX ? 't' :
filestat.st_mode & S_IXOTH ? 'x' : '-',
filestat.st_nlink);
user=getpwuid(filestat.st_uid);
if (user) printf(" %-8s", user->pw_name);
else printf(" %-8d", filestat.st_uid);
group=getgrgid(filestat.st_gid);
if (group) printf(" %-8s", group->gr_name);
else printf(" %-8d", filestat.st_gid);
printf (" %8ld %s %s",
filestat.st_size, timestr,
namelist[i]->d_name);
if (S_ISLNK(filestat.st_mode))
{
len = readlink(filename, target, 255);
if (len == -1) perror(filename);
else
{
target[len] = 0;
printf(" -> %s\n", target);
}
}
else
{
printf("\n");
}
free(namelist[i]);
}
free(namelist);
}
static void lsFunc(const iocshArgBuf *args)
{
char* dirname = ".";
struct dirent** namelist;
int n, i, cols, rows, r, c, len, maxlen=0;
if (args[0].sval) dirname = args[0].sval;
n = scandir(dirname, &namelist, nohidden, alphasort);
if (n < 0)
{
perror(dirname);
return;
}
for (i = 0; i < n; i++)
{
len = strlen(namelist[i]->d_name);
if (len > maxlen) maxlen = len;
}
cols=80/(maxlen+=2);
rows=(n-1)/cols+1;
for (r = 0; r < rows; r++)
{
for (c = 0; c < cols; c++)
{
i = r + c*rows;
if (i >= n) continue;
printf("%-*s",
maxlen, namelist[i]->d_name);
free(namelist[i]);
}
printf("\n");
}
free(namelist);
}
/* mkdir */
static const iocshArg mkdirArg0 = { "directrory", iocshArgString };
static const iocshArg * const mkdirArgs[1] = { &mkdirArg0 };
static const iocshFuncDef mkdirDef = { "mkdir", 1, mkdirArgs };
static void mkdirFunc(const iocshArgBuf *args)
{
char* dirname;
dirname = args[0].sval;
if (!dirname)
{
fprintf(stderr, "missing directory name\n");
return;
}
if (mkdir(dirname, 0777))
{
perror(dirname);
}
}
/* rmdir */
static const iocshArg rmdirArg0 = { "directrory", iocshArgString };
static const iocshArg * const rmdirArgs[1] = { &rmdirArg0 };
static const iocshFuncDef rmdirDef = { "rmdir", 1, rmdirArgs };
static void rmdirFunc(const iocshArgBuf *args)
{
char* dirname;
dirname = args[0].sval;
if (!dirname)
{
fprintf(stderr, "missing directory name\n");
return;
}
if (rmdir(dirname))
{
perror(dirname);
}
}
/* rm */
static const iocshArg rmArg0 = { "file", iocshArgString };
static const iocshArg * const rmArgs[1] = { &rmArg0 };
static const iocshFuncDef rmDef = { "rm", 1, rmArgs };
static void rmFunc(const iocshArgBuf *args)
{
char* filename;
filename = args[0].sval;
if (!filename)
{
fprintf(stderr, "missing file name\n");
return;
}
if (unlink(filename))
{
perror(filename);
}
}
/* mv */
static const iocshArg mvArg0 = { "oldname", iocshArgString };
static const iocshArg mvArg1 = { "newname", iocshArgString };
static const iocshArg * const mvArgs[2] = { &mvArg0, &mvArg1 };
static const iocshFuncDef mvDef = { "mv", 2, mvArgs };
static void mvFunc(const iocshArgBuf *args)
{
char* oldname;
char* newname;
struct stat filestat;
char filename[256];
oldname = args[0].sval;
newname = args[1].sval;
if (!oldname || !newname)
{
fprintf(stderr, "need 2 file names\n");
return;
}
if (!stat(newname, &filestat) && S_ISDIR(filestat.st_mode))
{
sprintf(filename, "%s/%s", newname, oldname);
newname = filename;
}
if (rename(oldname, newname))
{
perror("mv");
}
}
/* cp, copy */
static const iocshArg cpArg0 = { "source", iocshArgString };
static const iocshArg cpArg1 = { "target", iocshArgString };
static const iocshArg * const cpArgs[2] = { &cpArg0, &cpArg1 };
static const iocshFuncDef cpDef = { "cp", 2, cpArgs };
static const iocshFuncDef copyDef = { "copy", 2, cpArgs };
static void cpFunc(const iocshArgBuf *args)
{
char buffer [256];
char* sourcename;
char* targetname;
FILE* sourcefile;
FILE* targetfile;
size_t len;
sourcename = args[0].sval;
targetname = args[1].sval;
if (sourcename == NULL || sourcename[0] == '\0')
sourcefile = stdin;
else if (!(sourcefile = fopen(sourcename,"r")))
{
perror(sourcename);
return;
}
if (targetname == NULL || targetname[0] == '\0')
targetfile = stdout;
else if (!(targetfile = fopen(targetname,"w")))
{
perror(targetname);
return;
}
while (!feof(sourcefile))
{
len = fread(buffer, 1, 256, sourcefile);
if (ferror(sourcefile))
{
perror(sourcename);
break;
}
fwrite(buffer, 1, len, targetfile);
if (ferror(targetfile))
{
perror(targetname);
break;
}
}
if (sourcefile != stdin)
fclose(sourcefile);
if (targetfile != stdout)
fclose(targetfile);
else
fflush(stdout);
}
/* umask */
static const iocshArg umaskArg0 = { "mask", iocshArgString };
static const iocshArg * const umaskArgs[1] = { &umaskArg0 };
static const iocshFuncDef umaskDef = { "umask", 1, umaskArgs };
static void umaskFunc(const iocshArgBuf *args)
{
mode_t mask;
if (args[0].sval == NULL)
{
mask = umask(0);
umask(mask);
printf("%03o\n", (int)mask);
return;
}
if (sscanf(args[0].sval, "%o", &mask) == 1)
{
umask(mask);
return;
}
fprintf(stderr, "mode %s not recognized\n", args[0].sval);
}
/* chmod */
static const iocshArg chmodArg0 = { "mode", iocshArgInt };
static const iocshArg chmodArg1 = { "file", iocshArgString };
static const iocshArg * const chmodArgs[2] = { &chmodArg0, &chmodArg1 };
static const iocshFuncDef chmodDef = { "chmod", 2, chmodArgs };
static void chmodFunc(const iocshArgBuf *args)
{
mode_t mode = args[0].ival;
char* path = args[1].sval;
if (chmod(path, mode) != 0)
{
perror(path);
}
}
#endif
static void
disctoolsRegister(void)
{
static int firstTime = 1;
if (firstTime) {
#ifdef UNIX
iocshRegister(&dirDef, llFunc);
iocshRegister(&llDef, llFunc);
iocshRegister(&lsDef, lsFunc);
iocshRegister(&mkdirDef, mkdirFunc);
iocshRegister(&rmdirDef, rmdirFunc);
iocshRegister(&rmDef, rmFunc);
iocshRegister(&mvDef, mvFunc);
iocshRegister(&cpDef, cpFunc);
iocshRegister(&copyDef, cpFunc);
iocshRegister(&umaskDef, umaskFunc);
iocshRegister(&chmodDef, chmodFunc);
#endif
firstTime = 0;
}
}
epicsExportRegistrar(disctoolsRegister);
+1
View File
@@ -0,0 +1 @@
registrar(disctoolsRegister)
+105
View File
@@ -0,0 +1,105 @@
/*
* exec - execute shell commands.
*
* $Author: zimoch $
* $ID$
* $Date: 2011/11/28 14:18:37 $
*
* DISCLAIMER: Use at your own risc and so on. No warranty, no refund.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <iocsh.h>
#include <stdio.h>
#ifdef UNIX
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <time.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#endif
#include <epicsExport.h>
#ifdef UNIX
static const iocshArg execArg0 = { "command", iocshArgString };
static const iocshArg execArg1 = { "arguments", iocshArgArgv };
static const iocshArg * const execArgs[2] = { &execArg0, &execArg1 };
static const iocshFuncDef execDef = { "exec", 2, execArgs };
static const iocshFuncDef exclDef = { "!", 2, execArgs }; /* alias */
static void execFunc (const iocshArgBuf *args)
{
int i;
int status;
char commandline [256];
char *p = commandline;
if (args[0].sval == NULL)
{
fprintf(stderr, "missing command\n");
return;
}
p += sprintf(p, "\"%s\"", args[0].sval);
for (i = 1; i < args[1].aval.ac; i++)
{
p += sprintf(p, " \"%s\"", args[1].aval.av[i]);
}
status = system(commandline);
if (WIFSIGNALED(status))
{
#ifdef __USE_GNU
fprintf (stderr, "%s killed by signal %d: %s\n",
args[0].sval, WTERMSIG(status), strsignal(WTERMSIG(status)));
#else
fprintf (stderr, "%s killed by signal %d: statuscode %d\n",
args[0].sval, WTERMSIG(status), WTERMSIG(status));
#endif
}
if (WEXITSTATUS(status))
{
fprintf (stderr, "exit status is %d\n", WEXITSTATUS(status));
}
}
/* sleep */
static const iocshArg sleepArg0 = { "seconds", iocshArgDouble };
static const iocshArg * const sleepArgs[1] = { &sleepArg0 };
static const iocshFuncDef sleepDef = { "sleep", 1, sleepArgs };
static void sleepFunc (const iocshArgBuf *args)
{
struct timespec sleeptime;
sleeptime.tv_sec = (long) args[0].dval;
sleeptime.tv_nsec = (long) ((args[0].dval - (long) args[0].dval) * 1000000000);
while (nanosleep (&sleeptime, &sleeptime) == -1)
{
if (errno != EINTR)
{
perror("sleep");
break;
}
}
}
#endif
static void
execRegister(void)
{
static int firstTime = 1;
if (firstTime) {
#ifdef UNIX
iocshRegister (&execDef, execFunc);
iocshRegister (&exclDef, execFunc);
iocshRegister (&sleepDef, sleepFunc);
#endif
firstTime = 0;
}
}
epicsExportRegistrar(execRegister);
+1
View File
@@ -0,0 +1 @@
registrar(execRegister)
Executable
+257
View File
@@ -0,0 +1,257 @@
#!/bin/bash
SOURCE='$Source: /cvs/G/DRV/misc/iocsh,v $'
REVISION='$Revision: 1.1 $'
DATE='$Date: 2011/11/28 14:18:37 $'
rp() {
( realpath $1 || readlink -f $1 || readlink $1 || echo $1 ) 2>/dev/null
}
# Either EPICS or EPICS_BASE should be set to the install directory
if [ -z "$EPICS_BASE" ]
then
if [ -z "$EPICS" ]
then
for EPICS in /epics /opt/epics /usr/local/epics
do
if [ -d $EPICS ]
then
break 2
fi
echo "Cannot find EPICS installation directory." >&2
exit 1
done
fi
EPICS_BASE=$EPICS/base-3.14.12
if [ ! -d $EPICS_BASE ]
then
EPICS_BASE=$(rp $EPICS/base)
fi
fi
if [ ! -d $EPICS_BASE ]
then
echo "Cannot find EPICS base directory." >&2
exit 1
fi
# Check revision
if [ -r $EPICS_BASE/configure/CONFIG_BASE_VERSION ]
then
BASE=$(awk -F '[[:space:]]*=[[:space:]]*' '
/^EPICS_VERSION[[:space:]]*=[[:space:]]*/ {v=$2}
/^EPICS_REVISION[[:space:]]*=[[:space:]]*/ {r=$2}
/^EPICS_MODIFICATION[[:space:]]*=[[:space:]]*/ {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" ]
then
echo "Do not find an EPICS 3.14 version" >&2
exit 1
fi
export BASE
# 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
# 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
if [ -z "$INSTBASE" ]
then
INSTBASE=/work
fi
EPICS_DRIVER_PATH=${EPICS_DRIVER_PATH%:}:$INSTBASE/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
loadFiles () {
while [ "$#" -gt 0 ]
do
file=$1
case $file in
( @* )
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 )
echo "ld \"$file\""
;;
( -c )
shift
echo $1
;;
( -r )
shift
echo "require $1"
;;
( -n )
shift
IOC="$1"
;;
( -h | "-?" | -help | --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 " -? 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 iocsh."
echo " -r: The next string is a module, 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
echo "*.subs and *.subst are loaded via dbLoadTemplate"
echo
echo "*.dbd is loaded via dbLoadDatabase"
echo
echo "*.so is loaded via ld"
echo
echo "If a file is @filename, more arguments are read from filename."
echo
echo "All other files are executed as startup scripts by the EPICS iocsh."
} >&2
exit
;;
( -v | -ver | --ver | -version | --version )
{
echo "iocsh by Dirk Zimoch"
echo $SOURCE
echo $REVISION
echo $DATE
} >&2
exit
;;
( -* )
{
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 "rm -f $startup" EXIT TERM KILL
{
echo "#date=$(date)"
echo "#user=${USER:-$(whoami)}"
echo "#PWD=$PWD"
echo "#EPICS_CA_ADDR_LIST=$EPICS_CA_ADDR_LIST"
echo "#EPICS_DRIVER_PATH=$EPICS_DRIVER_PATH"
if [ ${BASE#3.14.} -ge 12 ]
then
EXE=$EPICS_BASE/bin/$EPICS_HOST_ARCH/softIoc
ARGS="-D $EPICS_BASE/dbd/softIoc.dbd"
# load "require" command
REQUIRE=misc
LIBPREFIX=lib
LIBPOSTFIX=.so
echo "dlload $INSTBASE/iocBoot/R$BASE/$EPICS_HOST_ARCH/${LIBPREFIX}${REQUIRE}${LIBPOSTFIX}"
echo "dbLoadDatabase $INSTBASE/iocBoot/R$BASE/dbd/${REQUIRE}.dbd"
echo "${REQUIRE%-*}_registerRecordDeviceDriver"
# STDLIBS="exec disctools"
else
APP=ioc
EXE=$EPICS_EXTENSIONS/bin/$EPICS_HOST_ARCH/$APP
DBD=$EPICS_EXTENSIONS/dbd
echo "dbLoadDatabase \"$APP.dbd\",\"$DBD\""
echo "${APP}_registerRecordDeviceDriver(pdbbase)"
fi
for i in $STDLIBS; do echo "require $i"; done
loadFiles "$@"
if [ "$init" != NO ]
then
echo "iocInit"
fi
if [ "$SHELLBOX" ]
then
PATH=$PATH:/home/ioc/bin
echo 'dbl "","RTYP DESC" > /home/ioc/${SHELLBOX}.dbl'
echo "! dbl2odb.sh ${SHELLBOX} $(/sbin/ifconfig eth0 | awk -F '[ :]+' '/Bcast/ {print $6}') $EPICS_CA_SERVER_PORT"
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
eval "$EXE" $ARGS "$startup" 2>&1
echo