forked from epics_driver_modules/require
Merged with require version for Linux.
Should work now on all operating systems.
This commit is contained in:
@@ -1,32 +1,180 @@
|
||||
#include <vxWorks.h>
|
||||
#include <symLib.h>
|
||||
#include <sysSymTbl.h>
|
||||
#include <sysLib.h>
|
||||
#include <symLib.h>
|
||||
#include <loadLib.h>
|
||||
#include <shellLib.h>
|
||||
#include <usrLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <stat.h>
|
||||
/*
|
||||
* ld - load code dynamically
|
||||
*
|
||||
* $Author: zimoch $
|
||||
* $ID$
|
||||
* $Date: 2011/07/21 14:57:25 $
|
||||
*
|
||||
* DISCLAIMER: Use at your own risc and so on. No warranty, no refund.
|
||||
*/
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <ioLib.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <require.h>
|
||||
|
||||
#include <epicsVersion.h>
|
||||
#ifdef BASE_VERSION
|
||||
#define EPICS_3_13
|
||||
int dbLoadDatabase(char *filename, char *path, char *substitutions);
|
||||
extern volatile int interruptAccept;
|
||||
#else
|
||||
#define EPICS_3_14
|
||||
#include <iocsh.h>
|
||||
extern int iocshCmd (const char *cmd);
|
||||
#include <dbAccess.h>
|
||||
extern int iocshCmd (const char *cmd);
|
||||
#include <epicsExit.h>
|
||||
#include <epicsExport.h>
|
||||
#endif
|
||||
|
||||
static int validate(char* version, char* loaded)
|
||||
#include "require.h"
|
||||
|
||||
int requireDebug=0;
|
||||
|
||||
#define DIRSEP "/"
|
||||
#define PATHSEP ":"
|
||||
#define PREFIX
|
||||
#define INFIX
|
||||
|
||||
#if defined (__vxworks)
|
||||
|
||||
#include <symLib.h>
|
||||
#include <sysSymTbl.h>
|
||||
#include <sysLib.h>
|
||||
#include <symLib.h>
|
||||
#include <loadLib.h>
|
||||
#include <shellLib.h>
|
||||
#include <usrLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <ioLib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define HMODULE MODULE_ID
|
||||
#undef INFIX
|
||||
#define INFIX "Lib"
|
||||
#define EXT ".munch"
|
||||
|
||||
#elif defined (UNIX)
|
||||
|
||||
#include <dlfcn.h>
|
||||
#define HMODULE void *
|
||||
|
||||
#ifdef CYGWIN32
|
||||
|
||||
#define EXT ".dll"
|
||||
|
||||
#else
|
||||
|
||||
#undef PREFIX
|
||||
#define PREFIX "lib"
|
||||
#define EXT ".so"
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined (_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
#undef DIRSEP
|
||||
#define DIRSEP "\\"
|
||||
#undef PATHSEP
|
||||
#define PATHSEP ";"
|
||||
#define EXT ".dll"
|
||||
|
||||
#else
|
||||
|
||||
#error unknwn OS
|
||||
|
||||
#endif
|
||||
|
||||
/* loadlib (library)
|
||||
Find a loadable library by name and load it.
|
||||
*/
|
||||
|
||||
static HMODULE loadlib(const char* libname)
|
||||
{
|
||||
HMODULE libhandle = NULL;
|
||||
|
||||
if (!libname)
|
||||
{
|
||||
fprintf (stderr, "missing library name\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined (UNIX)
|
||||
if (!(libhandle = dlopen(libname, RTLD_NOW|RTLD_GLOBAL)))
|
||||
{
|
||||
fprintf (stderr, "Loading %s library failed: %s\n",
|
||||
libname, dlerror());
|
||||
}
|
||||
#elif defined (_WIN32)
|
||||
if (!(libhandle = LoadLibrary(libname)))
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0, NULL );
|
||||
fprintf (stderr, "Loading %s library failed: %s\n",
|
||||
libname, lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
#elif defined (__vxworks)
|
||||
{
|
||||
int fd, loaderror;
|
||||
fd = open(libname, O_RDONLY, 0);
|
||||
loaderror = errno;
|
||||
if (fd >= 0)
|
||||
{
|
||||
errno = 0;
|
||||
libhandle = loadModule(fd, LOAD_GLOBAL_SYMBOLS);
|
||||
if (errno == S_symLib_SYMBOL_NOT_FOUND)
|
||||
{
|
||||
libhandle = NULL;
|
||||
}
|
||||
loaderror = errno;
|
||||
close (fd);
|
||||
}
|
||||
if (libhandle == NULL)
|
||||
{
|
||||
fprintf(stderr, "Loading %s library failed: %s\n",
|
||||
libname, strerror(loaderror));
|
||||
}
|
||||
}
|
||||
#else
|
||||
fprintf (stderr, "cannot load libraries on this OS.\n");
|
||||
#endif
|
||||
return libhandle;
|
||||
}
|
||||
|
||||
typedef struct moduleitem
|
||||
{
|
||||
struct moduleitem* next;
|
||||
char name[100];
|
||||
char version[20];
|
||||
} moduleitem;
|
||||
|
||||
moduleitem* loadedModules = NULL;
|
||||
|
||||
const char* getLibVersion(const char* libname)
|
||||
{
|
||||
moduleitem* m;
|
||||
|
||||
for (m = loadedModules; m; m=m->next)
|
||||
{
|
||||
if (strncmp(m->name, libname, sizeof(m->name)) == 0)
|
||||
{
|
||||
return m->version;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int validate(const char* version, const char* loaded)
|
||||
{
|
||||
int lmajor, lminor, lpatch, lmatches;
|
||||
int major, minor, patch, matches;
|
||||
@@ -34,14 +182,14 @@ static int validate(char* version, char* loaded)
|
||||
if (!version || !*version || strcmp(loaded, version) == 0)
|
||||
{
|
||||
/* no version requested or exact match */
|
||||
return OK;
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(loaded, "test") == 0)
|
||||
{
|
||||
/* test version already loaded */
|
||||
printf("Warning: version is test where %s was requested\n",
|
||||
version);
|
||||
return OK;
|
||||
return 0;
|
||||
}
|
||||
/* non-numerical versions must match exactly
|
||||
numerical versions must have exact match in major version and
|
||||
@@ -56,44 +204,109 @@ static int validate(char* version, char* loaded)
|
||||
|| (matches >= 2 && minor > lminor)
|
||||
|| (matches > 2 && minor == lminor && patch > lpatch))
|
||||
{
|
||||
return ERROR;
|
||||
return -1;
|
||||
}
|
||||
return OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int require(char* lib, char* vers)
|
||||
/* require (module)
|
||||
Look if module is already loaded.
|
||||
If module is already loaded check for version mismatch.
|
||||
If module is not yet loaded load the library with ld,
|
||||
load <module>.dbd with dbLoadDatabase (if file exists)
|
||||
and call <module>_registerRecordDeviceDriver function.
|
||||
|
||||
If require is called from the iocsh before iocInit and fails,
|
||||
it calls epicsExit to abort the application.
|
||||
*/
|
||||
|
||||
#ifdef __vxworks
|
||||
/* wrapper to abort statup script */
|
||||
static int require_priv(const char* module, const char* ver);
|
||||
|
||||
int require(const char* module, const char* ver)
|
||||
{
|
||||
char** path;
|
||||
char* loaded;
|
||||
SYM_TYPE type;
|
||||
struct stat filestat;
|
||||
char version[20];
|
||||
int fd;
|
||||
MODULE_ID libhandle = NULL;
|
||||
|
||||
if (symFindByName(sysSymTbl, "LIB", (char**)&path, &type) != OK)
|
||||
if (require_priv(module, ver) != 0 && !interruptAccept)
|
||||
{
|
||||
static char* here = ".";
|
||||
path = &here;
|
||||
/* require failed in startup script before iocInit */
|
||||
fprintf(stderr, "Aborting startup script\n");
|
||||
shellScriptAbort();
|
||||
return -1;
|
||||
}
|
||||
if (!lib)
|
||||
return 0;
|
||||
}
|
||||
#define require require_priv
|
||||
static
|
||||
#endif
|
||||
|
||||
int require(const char* module, const char* vers)
|
||||
{
|
||||
char* driverpath = ".";
|
||||
char version[20];
|
||||
const char* loaded;
|
||||
moduleitem* m;
|
||||
struct stat filestat;
|
||||
HMODULE libhandle;
|
||||
char* p;
|
||||
char *end; /* end of string */
|
||||
const char sep[1] = PATHSEP;
|
||||
#ifdef __vxworks
|
||||
SYM_TYPE type;
|
||||
#endif
|
||||
|
||||
if (requireDebug)
|
||||
printf("require: checking module %s version %s\n",
|
||||
module, vers);
|
||||
driverpath = getenv("EPICS_DRIVER_PATH");
|
||||
if (requireDebug)
|
||||
printf("require: searchpath=%s\n",
|
||||
driverpath);
|
||||
if (!module)
|
||||
{
|
||||
printf("Usage: require \"<libname>\" [, \"<version>\"]\n");
|
||||
printf("Loads <libname>Lib[-<version>] and dbd/<libname>[-<version>].dbd\n");
|
||||
printf("Directory is LIB = %s\n", *path);
|
||||
return ERROR;
|
||||
printf("Usage: require \"<module>\" [, \"<version>\"]\n");
|
||||
printf("Loads " PREFIX "<module>" INFIX "[-<version>]" EXT " and dbd/<libname>[-<version>].dbd\n");
|
||||
#ifdef EPICS_3_14
|
||||
printf("And calls <module>_registerRecordDeviceDriver\n");
|
||||
#endif
|
||||
printf("Search path is %s\n", driverpath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero(version, sizeof(version));
|
||||
if (vers) strncpy(version, vers, sizeof(version));
|
||||
|
||||
loaded = getLibVersion(lib);
|
||||
if (!loaded)
|
||||
loaded = getLibVersion(module);
|
||||
if (requireDebug)
|
||||
printf("require: loaded version of %s is %s\n",
|
||||
module, loaded);
|
||||
if (loaded)
|
||||
{
|
||||
/* Library already loaded. Check Version. */
|
||||
if (validate(version, loaded) != 0)
|
||||
{
|
||||
printf("Conflict between requested %s version %s\n"
|
||||
"and already loaded version %s.\n",
|
||||
module, version, loaded);
|
||||
return -1;
|
||||
}
|
||||
/* Loaded version is ok */
|
||||
printf ("%s %s already loaded\n", module, loaded);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
char libname[256];
|
||||
char dbdname[256];
|
||||
char depname[256];
|
||||
char libdir[256];
|
||||
char fulllibname[256];
|
||||
char fulldbdname[256];
|
||||
char fulldepname[256];
|
||||
char symbolname[256];
|
||||
|
||||
/* user may give a minimal version (e.g. "1.2.4+")
|
||||
load highest matching version (here "1.2") and check later
|
||||
*/
|
||||
if (version[strlen(version)-1] == '+')
|
||||
{
|
||||
char* p = strrchr(version, '.');
|
||||
@@ -101,202 +314,243 @@ int require(char* lib, char* vers)
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
/* try to find module in local /bin directory first, then in path
|
||||
prefer *Lib.munch file over *Lib file
|
||||
check for dependencies in *.dep file
|
||||
load *.dbd file if it exists
|
||||
*/
|
||||
|
||||
/* first try local library */
|
||||
if (version && *version)
|
||||
/* make filenames with or without version string */
|
||||
|
||||
if (version[0])
|
||||
{
|
||||
sprintf(libname, "bin/%sLib-%s.munch", lib, version);
|
||||
sprintf(depname, "bin/%s-%s.dep", lib, version);
|
||||
sprintf(dbdname, "dbd/%s-%s.dbd", lib, version);
|
||||
sprintf(libname, PREFIX "%s" INFIX "-%s" EXT, module, version);
|
||||
sprintf(depname, "%s-%s.dep", module, version);
|
||||
sprintf(dbdname, "%s-%s.dbd", module, version);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(libname, "bin/%sLib.munch", lib);
|
||||
sprintf(depname, "bin/%s.dep", lib);
|
||||
sprintf(dbdname, "dbd/%s.dbd", lib);
|
||||
sprintf(libname, PREFIX "%s" INFIX EXT, module);
|
||||
sprintf(depname, "%s.dep", module);
|
||||
sprintf(dbdname, "%s.dbd", module);
|
||||
}
|
||||
if (stat(libname, &filestat) == ERROR)
|
||||
if (requireDebug)
|
||||
{
|
||||
/* no munched local lib */
|
||||
libname[strlen(libname)-6]=0; /* skip ".munch" */
|
||||
printf("require: libname is %s\n", libname);
|
||||
printf("require: depname is %s\n", depname);
|
||||
printf("require: dbdname is %s\n", dbdname);
|
||||
}
|
||||
if (stat(libname, &filestat) == ERROR)
|
||||
{
|
||||
/* no local lib at all */
|
||||
libname[strlen(libname)-6]=0; /* skip ".munch" */
|
||||
if (version && *version)
|
||||
|
||||
/* search for library in driverpath */
|
||||
for (p = driverpath; p != NULL; p = end)
|
||||
{
|
||||
end = strchr(p, sep[0]);
|
||||
if (end)
|
||||
{
|
||||
sprintf(libname, "%s/%sLib-%s.munch", *path, lib, version);
|
||||
sprintf(depname, "%s/%s-%s.dep", *path, lib, version);
|
||||
sprintf(dbdname, "%s/dbd/%s-%s.dbd", *path, lib, version);
|
||||
sprintf (libdir, "%.*s", end-p, p);
|
||||
end++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(libname, "%s/%sLib.munch", *path, lib);
|
||||
sprintf(depname, "%s/%s.dep", *path, lib);
|
||||
sprintf(dbdname, "%s/dbd/%s.dbd", *path, lib);
|
||||
}
|
||||
if (stat(libname, &filestat) == ERROR)
|
||||
{
|
||||
/* no munched lib */
|
||||
libname[strlen(libname)-6]=0; /* skip ".munch" */
|
||||
}
|
||||
if (stat(libname, &filestat) == ERROR &&
|
||||
/* allow alias without library */
|
||||
stat(depname, &filestat) == ERROR)
|
||||
{
|
||||
/* still no library found */
|
||||
printf("Library %s not found\n", libname);
|
||||
printf("Aborting startup stript.\n");
|
||||
shellScriptAbort();
|
||||
return ERROR;
|
||||
sprintf (libdir, "%s", p);
|
||||
}
|
||||
/* ignore empty driverpath elements */
|
||||
if (libdir[0] == 0) continue;
|
||||
|
||||
sprintf (fulllibname, "%s" DIRSEP "%s", libdir, libname);
|
||||
sprintf (fulldepname, "%s" DIRSEP "%s", libdir, depname);
|
||||
if (requireDebug)
|
||||
printf("require: looking for %s\n", fulllibname);
|
||||
if (stat(fulllibname, &filestat) == 0) break;
|
||||
#ifdef __vxworks
|
||||
/* now without the .munch */
|
||||
fulllibname[strlen(fulllibname)-6] = 0;
|
||||
if (requireDebug)
|
||||
printf("require: looking for %s\n", fulllibname);
|
||||
if (stat(fulllibname, &filestat) == 0) break;
|
||||
#endif
|
||||
/* allow dependency without library for aliasing */
|
||||
if (requireDebug)
|
||||
printf("require: looking for %s\n", fulldepname);
|
||||
if (stat(fulldepname, &filestat) == 0) break;
|
||||
}
|
||||
if (requireDebug)
|
||||
printf("require: found in %s\n", p);
|
||||
if (!p)
|
||||
{
|
||||
fprintf(stderr, "Library %s not found in EPICS_DRIVER_PATH=%s\n",
|
||||
libname, driverpath);
|
||||
return -1;
|
||||
}
|
||||
errno = 0;
|
||||
|
||||
/* check dependencies */
|
||||
if (stat(depname, &filestat) != ERROR)
|
||||
/* parse dependency file if exists */
|
||||
if (stat(fulldepname, &filestat) == 0)
|
||||
{
|
||||
FILE* depfile;
|
||||
char buffer[40];
|
||||
char *l; /* required library */
|
||||
char *v; /* required version */
|
||||
char *e; /* end */
|
||||
char *rmodule; /* required module */
|
||||
char *rversion; /* required version */
|
||||
|
||||
depfile = fopen(depname, "r");
|
||||
if (requireDebug)
|
||||
printf("require: parsing dependency file %s\n", fulldepname);
|
||||
depfile = fopen(fulldepname, "r");
|
||||
while (fgets(buffer, sizeof(buffer), depfile))
|
||||
{
|
||||
l = buffer;
|
||||
while (isspace((int)*l)) l++;
|
||||
if (*l == 0 || *l == '#') continue;
|
||||
v = l;
|
||||
while (*v && !isspace((int)*v)) v++;
|
||||
*v++ = 0;
|
||||
while (isspace((int)*v)) v++;
|
||||
e = v;
|
||||
while (*e && !isspace((int)*e)) e++;
|
||||
*e++ = '+';
|
||||
*e = 0;
|
||||
printf ("%s depends on %s %s\n", lib, l, v);
|
||||
if (require(l, v) != OK)
|
||||
rmodule = buffer;
|
||||
/* ignore leading spaces */
|
||||
while (isspace((int)*rmodule)) rmodule++;
|
||||
/* ignore empty lines and comment lines */
|
||||
if (*rmodule == 0 || *rmodule == '#') continue;
|
||||
/* rmodule at start of module name */
|
||||
rversion = rmodule;
|
||||
/* find end of module name */
|
||||
while (*rversion && !isspace((int)*rversion)) rversion++;
|
||||
/* terminate module name */
|
||||
*rversion++ = 0;
|
||||
/* ignore spaces */
|
||||
while (isspace((int)*rversion)) rversion++;
|
||||
/* rversion at start of version */
|
||||
end = rversion;
|
||||
/* find end of version */
|
||||
while (*end && !isspace((int)*end)) end++;
|
||||
/* append + to version to allow newer compaible versions */
|
||||
*end++ = '+';
|
||||
/* terminate version */
|
||||
*end = 0;
|
||||
printf("%s depends on %s %s\n", module, rmodule, rversion);
|
||||
if (require(rmodule, rversion) != 0)
|
||||
{
|
||||
fclose(depfile);
|
||||
return ERROR;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
fclose(depfile);
|
||||
}
|
||||
|
||||
if (stat(libname, &filestat) == ERROR)
|
||||
if (stat(fulllibname, &filestat) != 0)
|
||||
{
|
||||
/* no library, dep file was an alias */
|
||||
if (requireDebug)
|
||||
printf("require: no library to load\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* load library */
|
||||
printf("Loading %s\n", libname);
|
||||
fd = open(libname, O_RDONLY, 0);
|
||||
if (fd >= 0)
|
||||
if (requireDebug)
|
||||
printf("require: loading library %s\n", fulllibname);
|
||||
if (!(libhandle = loadlib(fulllibname)))
|
||||
{
|
||||
errno = 0;
|
||||
libhandle = loadModule(fd, LOAD_GLOBAL_SYMBOLS);
|
||||
close (fd);
|
||||
if (requireDebug)
|
||||
printf("require: loading failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (libhandle == NULL || errno == S_symLib_SYMBOL_NOT_FOUND)
|
||||
|
||||
/* now check if we got what we wanted (with original version number) */
|
||||
sprintf (symbolname, "_%sLibRelease", module);
|
||||
#if defined (UNIX)
|
||||
loaded = (char*) dlsym(libhandle, symbolname);
|
||||
#elif defined (_WIN32)
|
||||
loaded = (char*) GetProcAddress(libhandle, symbolname);
|
||||
#elif defined (__vxworks)
|
||||
loaded = NULL;
|
||||
symFindByName(sysSymTbl, symbolname, (char**)&loaded, &type);
|
||||
#endif
|
||||
if (loaded)
|
||||
{
|
||||
printf("Loading %s library failed: %s\n", lib, strerror(errno));
|
||||
printf("Aborting startup stript.\n");
|
||||
shellScriptAbort();
|
||||
return ERROR;
|
||||
printf("Loading %s (version %s)\n", fulllibname, loaded);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Loading %s (no version)\n", fulllibname);
|
||||
loaded = "(no version)";
|
||||
}
|
||||
loaded = getLibVersion(lib);
|
||||
|
||||
/* load dbd file */
|
||||
if (stat(dbdname, &filestat) != ERROR && filestat.st_size > 0)
|
||||
if (validate(vers, loaded) != 0)
|
||||
{
|
||||
/* If file exists and is not empty */
|
||||
printf("Loading %s\n", dbdname);
|
||||
if (dbLoadDatabase(dbdname, NULL, NULL) != OK)
|
||||
fprintf(stderr, "Requested %s version %s not available, found only %s.\n",
|
||||
module, vers, loaded);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* look for dbd in . ./dbd ../dbd ../../dbd (relative to lib dir) */
|
||||
p = PATHSEP DIRSEP "dbd"
|
||||
PATHSEP DIRSEP ".." DIRSEP "dbd"
|
||||
PATHSEP DIRSEP ".." DIRSEP ".." DIRSEP "dbd";
|
||||
while (p)
|
||||
{
|
||||
end = strchr(p, sep[0]);
|
||||
if (end)
|
||||
{
|
||||
taskDelay(sysClkRateGet());
|
||||
printf ("Aborting startup stript.\n");
|
||||
shellScriptAbort();
|
||||
return ERROR;
|
||||
sprintf(fulldbdname, "%s%.*s" DIRSEP "%s",
|
||||
libdir, end-p, p, dbdname);
|
||||
end++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(fulldbdname, "%s%s" DIRSEP "%s",
|
||||
libdir, p, dbdname);
|
||||
}
|
||||
if (requireDebug)
|
||||
printf("require: Looking for %s\n", fulldbdname);
|
||||
if (stat(fulldbdname, &filestat) == 0) break;
|
||||
p=end;
|
||||
}
|
||||
|
||||
/* if dbd file exists and is not empty load it */
|
||||
if (p && filestat.st_size > 0)
|
||||
{
|
||||
printf("Loading %s\n", fulldbdname);
|
||||
if (dbLoadDatabase(fulldbdname, NULL, NULL) != 0)
|
||||
{
|
||||
fprintf (stderr, "require: can't load %s\n", fulldbdname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no dbd file, but that might be OK */
|
||||
printf("no dbd file %s\n", dbdname);
|
||||
}
|
||||
|
||||
/* register module */
|
||||
m = (moduleitem*) calloc(sizeof (moduleitem),1);
|
||||
if (!m)
|
||||
{
|
||||
printf ("require: out of memory\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy (m->name, module, sizeof(m->name));
|
||||
strncpy (m->version, loaded, sizeof(m->version));
|
||||
m->next = loadedModules;
|
||||
loadedModules = m;
|
||||
}
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
/* call register function for R3.14 */
|
||||
{
|
||||
char initfunc[256];
|
||||
|
||||
sprintf (initfunc, "%s_registerRecordDeviceDriver", lib);
|
||||
printf("calling %s\n", initfunc);
|
||||
iocshCmd (initfunc);
|
||||
}
|
||||
/* call register function for R3.14 */
|
||||
/* call register function */
|
||||
sprintf (symbolname, "%s_registerRecordDeviceDriver", module);
|
||||
printf ("Calling %s function\n", symbolname);
|
||||
#ifdef __vxworks
|
||||
{
|
||||
FUNCPTR f;
|
||||
if (symFindByName(sysSymTbl, symbolname, (char**)&f, &type) == 0)
|
||||
f(pdbbase);
|
||||
else
|
||||
fprintf (stderr, "require: can't find %s function\n", symbolname);
|
||||
}
|
||||
#else
|
||||
iocshCmd(symbolname);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
if (validate(vers, loaded) == ERROR)
|
||||
{
|
||||
printf("Requested %s version %s not available, found only %s.\n"
|
||||
"Aborting startup stript.\n",
|
||||
lib, vers, loaded);
|
||||
shellScriptAbort();
|
||||
return ERROR;
|
||||
}
|
||||
if (loaded) printf("%s version is %s\n", lib, loaded);
|
||||
return OK;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
int libversionShow(const char* pattern)
|
||||
{
|
||||
moduleitem* m;
|
||||
|
||||
for (m = loadedModules; m; m=m->next)
|
||||
{
|
||||
/* Library already loaded. Check Version. */
|
||||
if (validate(version, loaded) == ERROR)
|
||||
{
|
||||
printf("Conflict between requested %s version %s\n"
|
||||
"and already loaded version %s.\n"
|
||||
"Aborting startup stript.\n",
|
||||
lib, version, loaded);
|
||||
shellScriptAbort();
|
||||
return ERROR;
|
||||
}
|
||||
/* Loaded version is ok */
|
||||
printf("%sLib-%s already loaded\n", lib, loaded);
|
||||
return OK;
|
||||
if (pattern && !strstr(m->name, pattern)) return 0;
|
||||
printf("%15s %s\n", m->name, m->version);
|
||||
}
|
||||
}
|
||||
|
||||
char* getLibVersion(char* lib)
|
||||
{
|
||||
char symbol[256];
|
||||
char* loaded;
|
||||
SYM_TYPE type;
|
||||
|
||||
sprintf(symbol, "_%sLibRelease", lib);
|
||||
if (symFindByName(sysSymTbl, symbol, &loaded, &type) != OK) return NULL;
|
||||
return loaded;
|
||||
}
|
||||
|
||||
static BOOL printIfLibversion(char* name, int val,
|
||||
SYM_TYPE type, int arg, UINT16 group)
|
||||
{
|
||||
int l;
|
||||
char* pattern = (char*) arg;
|
||||
|
||||
l = strlen(name);
|
||||
if (l > 10 && strcmp(name+l-10, "LibRelease") == 0)
|
||||
{
|
||||
if (pattern && !strstr(name, pattern)) return TRUE;
|
||||
printf("%15.*s %s\n", l-11, name+1, (char*)val);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int libversionShow(char* pattern)
|
||||
{
|
||||
symEach(sysSymTbl, (FUNCPTR)printIfLibversion, (int)pattern);
|
||||
return OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef EPICS_3_14
|
||||
@@ -306,24 +560,36 @@ static const iocshArg * const requireArgs[2] = { &requireArg0, &requireArg1 };
|
||||
static const iocshFuncDef requireDef = { "require", 2, requireArgs };
|
||||
static void requireFunc (const iocshArgBuf *args)
|
||||
{
|
||||
if (require (args[0].sval, args[1].sval) != 0
|
||||
&& !interruptAccept)
|
||||
{
|
||||
/* require failed in startup script before iocInit */
|
||||
fprintf (stderr, "Aborting startup script\n");
|
||||
epicsExit (1);
|
||||
}
|
||||
require(args[0].sval, args[1].sval);
|
||||
}
|
||||
|
||||
static const iocshArg libversionShowArg0 = { "pattern", iocshArgString };
|
||||
static const iocshArg * const libversionArgs[1] = { &libversionShowArg0 };
|
||||
static const iocshFuncDef libversionShowDef = { "libversionShow", 1, libversionArgs };
|
||||
static void libversionShowFunc (const iocshArgBuf *args)
|
||||
{
|
||||
libversionShow(args[0].sval);
|
||||
}
|
||||
|
||||
static const iocshArg ldArg0 = { "library", iocshArgString };
|
||||
static const iocshArg * const ldArgs[1] = { &ldArg0 };
|
||||
static const iocshFuncDef ldDef = { "ld", 1, ldArgs };
|
||||
static void ldFunc (const iocshArgBuf *args)
|
||||
{
|
||||
loadlib(args[0].sval);
|
||||
}
|
||||
|
||||
static void requireRegister(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
iocshRegister (&ldDef, ldFunc);
|
||||
iocshRegister (&libversionShowDef, libversionShowFunc);
|
||||
iocshRegister (&requireDef, requireFunc);
|
||||
firstTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
epicsExportRegistrar(requireRegister);
|
||||
|
||||
epicsExportAddress(int, requireDebug);
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef require_h
|
||||
#define require_h
|
||||
|
||||
int require(char* lib, char* version);
|
||||
char* getLibVersion(char* lib);
|
||||
int libversionShow(char* pattern);
|
||||
int require(const char* libname, const char* version);
|
||||
const char* getLibVersion(const char* libname);
|
||||
int libversionShow(const char* pattern);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user