From 27e6b58dacdb56651d7098fd55c1c0f2151f3cb9 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch <dirk.zimoch@psi.ch> Date: Tue, 6 Sep 2016 14:18:21 +0200 Subject: [PATCH] allow to search scripts in all loaded modules --- require.c | 89 +++++++++++++++++++++++++++++++++-------------------- require.h | 1 + runScript.c | 38 ++++++++++++++++++++++- 3 files changed, 93 insertions(+), 35 deletions(-) diff --git a/require.c b/require.c index ef8ca9e3..ba50d483 100644 --- a/require.c +++ b/require.c @@ -372,67 +372,71 @@ int putenvprintf(const char* format, ...) return status; } -static int setupDbPath(const char* module, const char* dbdir) +static void insertDirIntoPath(const char* varname, const char* dirname) { char* old_path; - char* p; - size_t len; - - char* absdir = realpath(dbdir, NULL); /* so we can change directory later safely */ - if (absdir == NULL) - { - if (requireDebug) - printf("require: cannot resolve %s\n", dbdir); - return -1; - } - len = strlen(absdir); - - if (requireDebug) - printf("require: found template directory %s\n", absdir); - - /* set up db search path environment variables - <module>_TEMPLATES template path of <module> - <module>_DB template path of <module> - TEMPLATES template path of the current module (overwritten) - EPICS_DB_INCLUDE_PATH template path of all loaded modules (last in front after ".") - */ - putenvprintf("%s_DB=%s", module, absdir); - putenvprintf("%s_TEMPLATES=%s", module, absdir); - putenvprintf("TEMPLATES=%s", absdir); - - /* add directory to front of EPICS_DB_INCLUDE_PATH */ - old_path = getenv("EPICS_DB_INCLUDE_PATH"); + /* add directory to front */ + old_path = getenv(varname); if (old_path == NULL) - putenvprintf("EPICS_DB_INCLUDE_PATH=." OSI_PATH_LIST_SEPARATOR "%s", absdir); + putenvprintf("%s=." OSI_PATH_LIST_SEPARATOR "%s", varname, dirname); else { + size_t len = strlen(dirname); + char* p; + /* skip over "." at the beginning */ if (old_path[0] == '.' && old_path[1] == OSI_PATH_LIST_SEPARATOR[0]) old_path += 2; /* If directory is already in path, move it to front */ p = old_path; - while ((p = strstr(p, absdir)) != NULL) + while ((p = strstr(p, dirname)) != NULL) { if ((p == old_path || *(p-1) == OSI_PATH_LIST_SEPARATOR[0]) && (p[len] == 0 || p[len] == OSI_PATH_LIST_SEPARATOR[0])) { if (p == old_path) break; /* already at front, nothing to do */ memmove(old_path+len+1, old_path, p-old_path-1); - strcpy(old_path, absdir); + strcpy(old_path, dirname); old_path[len] = OSI_PATH_LIST_SEPARATOR[0]; if (requireDebug) - printf("require: modified EPICS_DB_INCLUDE_PATH=%s\n", old_path); + printf("require: modified %s=%s\n", varname, old_path); break; } p += len; } if (p == NULL) /* add new directory to the front (after "." )*/ - putenvprintf("EPICS_DB_INCLUDE_PATH=." OSI_PATH_LIST_SEPARATOR "%s" OSI_PATH_LIST_SEPARATOR "%s", - absdir, old_path); + putenvprintf("%s=." OSI_PATH_LIST_SEPARATOR "%s" OSI_PATH_LIST_SEPARATOR "%s", + varname, dirname, old_path); } +} + +static int setupDbPath(const char* module, const char* dbdir) +{ + char* absdir = realpath(dbdir, NULL); /* so we can change directory later safely */ + if (absdir == NULL) + { + if (requireDebug) + printf("require: cannot resolve %s\n", dbdir); + return -1; + } + + if (requireDebug) + printf("require: found template directory %s\n", absdir); + + /* set up db search path environment variables + <module>_TEMPLATES template path of <module> + <module>_DB template path of <module> + TEMPLATES template path of the current module (overwritten) + EPICS_DB_INCLUDE_PATH template path of all loaded modules (last in front after ".") + */ + + putenvprintf("%s_DB=%s", module, absdir); + putenvprintf("%s_TEMPLATES=%s", module, absdir); + putenvprintf("TEMPLATES=%s", absdir); + insertDirIntoPath("EPICS_DB_INCLUDE_PATH", absdir); free(absdir); return 0; } @@ -739,6 +743,21 @@ static void registerExternalModules() } #endif +size_t foreachLoadedLib(size_t (*func)(const char* name, const char* version, const char* path, void* arg), void* arg) +{ + moduleitem* m; + int result; + + for (m = loadedModules; m; m=m->next) + { + const char* name = m->content; + const char* version = name + strlen(name)+1; + const char* path = version + strlen(version)+1; + result = func(name, version, path, arg); + if (result) return result; + } + return 0; +} const char* getLibVersion(const char* libname) { @@ -1533,6 +1552,8 @@ loadlib: status = 0; + insertDirIntoPath("SCRIPT_PATH", filename); + if (requireDebug) printf("require: looking for template directory\n"); /* filename = "<dirname>/[dirlen]<module>/<version>/R<epicsRelease>/[releasediroffs]..." */ diff --git a/require.h b/require.h index 4d618879..5e33736b 100644 --- a/require.h +++ b/require.h @@ -10,6 +10,7 @@ extern "C" { #endif int require(const char* libname, const char* version, const char* args); +size_t foreachLoadedLib(size_t (*func)(const char* name, const char* version, const char* path, void* arg), void* arg); const char* getLibVersion(const char* libname); const char* getLibLocation(const char* libname); int libversionShow(const char* outfile); diff --git a/runScript.c b/runScript.c index de9b70c4..1ac8b270 100644 --- a/runScript.c +++ b/runScript.c @@ -10,6 +10,7 @@ #include <epicsVersion.h> #ifdef vxWorks +#include "asprintf.h" #include <sysSymTbl.h> #ifdef _WRS_VXWORKS_MAJOR /* vxWorks 6+ */ @@ -22,10 +23,15 @@ #include <symLib.h> #endif +#define IS_ABS_PATH(filename) (filename[0] == '/') /* may be different for other OS */ + #ifdef BASE_VERSION #define EPICS_3_13 extern char** ppGlobalEnviron; +#define OSI_PATH_SEPARATOR "/" +#define OSI_PATH_LIST_SEPARATOR ":" #else +#include <osiFileName.h> #include <iocsh.h> epicsShareFunc int epicsShareAPI iocshCmd(const char *cmd); #include <epicsExport.h> @@ -210,7 +216,37 @@ int runScript(const char* filename, const char* args) free(pairs); } - if ((file = fopen(filename, "r")) == NULL) { perror(filename); return errno; } + if (IS_ABS_PATH(filename)) + { + file = fopen(filename, "r"); + } + else + { + const char* dirname; + const char* end; + char* fullname; + const char* path = getenv("SCRIPT_PATH"); + int dirlen; + + for (dirname = path; dirname != NULL; dirname = end) + { + end = strchr(dirname, OSI_PATH_LIST_SEPARATOR[0]); + if (end && end[1] == OSI_PATH_SEPARATOR[0] && end[2] == OSI_PATH_SEPARATOR[0]) /* "http://..." and friends */ + end = strchr(end+2, OSI_PATH_LIST_SEPARATOR[0]); + if (end) dirlen = (int)(end++ - dirname); + else dirlen = (int)strlen(dirname); + if (dirlen == 0) continue; /* ignore empty path elements */ + asprintf(&fullname, "%.*s" OSI_PATH_SEPARATOR "%s", + dirlen, dirname, filename); + if (runScriptDebug) + printf("runScript: trying %s\n", fullname); + file = fopen(fullname, "r"); + if (!file && errno != ENOENT) perror(fullname); + free(fullname); + if (file) break; + } + } + if (file == NULL) { perror(filename); return errno; } /* line by line after expanding macros with arguments or environment */ while (fgets(line_raw, line_raw_size, file)) -- GitLab