diff --git a/require.c b/require.c index 2cfd20c4bad28f35585eee90d418296ad84f514f..1e4d1978fde3e6ee875e536f5be8baed4659f6da 100644 --- a/require.c +++ b/require.c @@ -153,6 +153,9 @@ int requireDebug=0; #endif #include <windows.h> + #include <Psapi.h> + #pragma comment(lib, "kernel32.lib") + #pragma comment(lib, "psapi.lib") #include "asprintf.h" #define snprintf _snprintf #define setenv(name,value,overwrite) _putenv_s(name,value) @@ -438,7 +441,7 @@ void registerModule(const char* module, const char* version, const char* locatio size_t lm = strlen(module) + 1; size_t lv = (version ? strlen(version) : 0) + 1; size_t ll = 1; - char* abslocation; + char* abslocation = NULL; if (requireDebug) printf("require: registerModule(%s,%s,%s)\n", module, version, location); @@ -492,12 +495,10 @@ static BOOL findLibRelease ( if (lm <= 10) /* strlen("LibRelease") */ return TRUE; lm -= 10; if (strcmp(name+lm, "LibRelease") != 0) return TRUE; - module = strdup(name+1); - module[lm-1]=0; + module = strdup(name+1); /* remove '_' */ + module[lm-1]=0; /* remove "libRelase" */ if (getLibVersion(module) == NULL) - { registerModule(module, (char*)val, NULL); - } free(module); return TRUE; } @@ -518,41 +519,32 @@ static int findLibRelease ( void *data /* user-supplied arg */ ) { void *handle; - char* name; char* location = NULL; char* p; char* version; char* symname; + char name[NAME_MAX + 11]; /* get space for library path + "LibRelease" */ /* find a symbol with a name like "_<module>LibRelease" where <module> is from the library name "<location>/lib<module>.so" */ if (info->dlpi_name == NULL || info->dlpi_name[0] == 0) return 0; /* no library name */ - name = malloc(strlen(info->dlpi_name)+11); /* get a modifiable copy + space for "LibRelease" */ - if (name == NULL) - { - perror("require"); - return 0; - } - strcpy(name, info->dlpi_name); + strcpy(name, info->dlpi_name); /* get a modifiable copy of the library name */ handle = dlopen(info->dlpi_name, RTLD_LAZY); /* re-open already loaded library */ p = strrchr(name, '/'); /* find file name part in "<location>/lib<module>.so" */ - if (p) {location = name; *++p=0;} /* terminate "<location>/" */ - else p=name; - symname = p+2; /* replace "lib" with "_" */ - symname[0] = '_'; - p = strchr(symname, '.'); /* replace ".so" with "LibRelease" */ - if (p == NULL) p = symname + strlen(symname); - strcpy(p, "LibRelease"); + if (p) {location = name; *++p=0;} else p=name; /* terminate "<location>/" (if exists) */ + *(symname = p+2) = '_'; /* replace "lib" with "_" */ + p = strchr(symname, '.'); /* find ".so" extension */ + if (p == NULL) p = symname + strlen(symname); /* no file extension ? */ + strcpy(p, "LibRelease"); /* append "LibRelease" to module name */ version = dlsym(handle, symname); /* find symbol "_<module>LibRelease" */ if (version) { - *p=0; symname++; /* build module name "<module>" */ - if ((p = strstr(name, OSI_PATH_SEPARATOR LIBDIR)) != NULL) - p[1]=0; /* cut "<location>" before libdir */ - registerModule(symname, version, location); + *p=0; symname++; /* get "<module>" from "_<module>LibRelease" */ + if ((p = strstr(name, "/" LIBDIR)) != NULL) p[1]=0; /* cut "<location>" before LIBDIR */ + if (getLibVersion(symname) == NULL) + registerModule(symname, version, location); } dlclose(handle); - free(name); return 0; } @@ -566,7 +558,42 @@ static void registerExternalModules() static void registerExternalModules() { - fprintf (stderr, "How to find symbols on Windows?\n"); + HMODULE hMods[100]; + HANDLE hProcess = GetCurrentProcess(); + DWORD cbNeeded; + char* location = NULL; + char* p; + char* version; + char* symname; + unsigned int i; + char name [MAX_PATH+11]; /* get space for library path + "LibRelease" */ + + /* iterate over all loaded libraries */ + if (!EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) return; + for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) + { + /* Get the full path to the module's file. */ + if (!GetModuleFileName(hMods[i], name, MAX_PATH)) continue; /* no library name */ + name[sizeof(name)-1] = 0; /* WinXP may not terminate the string */ + p = strrchr(name, '\\'); /* find file name part in "<location>/<module>.dll" */ + if (p) { location = name; } else p=name; /* find end of "<location>\\" (if exists) */ + symname = p; + p = strchr(symname, '.'); /* find ".dll" */ + if (p == NULL) p = symname + strlen(symname); /* no file extension ? */ + memmove(symname+2, symname, p - symname); /* make room for 0 and '_' */ + *symname++ = 0; /* terminate "<location>/" */ + *symname = '_'; /* prefix module name with '_' */ + strcpy((p+=2), "LibRelease"); /* append "LibRelease" to module name */ + + version = (char*)GetProcAddress(hMods[i], symname); /* find symbol "_<module>LibRelease" */ + if (version) + { + *p=0; symname++; /* get "<module>" from "_<module>LibRelease" */ + if ((p = strstr(name, "\\" LIBDIR)) != NULL) p[1]=0; /* cut "<location>" before LIBDIR */ + if (getLibVersion(symname) == NULL) + registerModule(symname, version, location); + } + } } @@ -814,12 +841,10 @@ int require(const char* module, const char* version, const char* args) #ifndef EPICS_3_13 printf("And calls <module>_registerRecordDeviceDriver\n"); #endif - printf("If available, runs startup script snippet or loads substitution file or templates with args\n"); + printf("If available, runs startup script snippet (only before iocInit)\n"); return -1; } - if (version && version[0] == 0) version = NULL; - /* either order for version and args, either may be empty or NULL */ if (version && strchr(version, '=')) { @@ -830,6 +855,15 @@ int require(const char* module, const char* version, const char* args) printf("require: swap version and args\n"); } + if (version && version[0] == 0) version = NULL; + + if (version && strcmp(version, "none") == 0) + { + if (requireDebug) + printf("require: skip version=none\n"); + return 0; + } + if (version) { /* needed for old style only: */ @@ -1023,6 +1057,11 @@ static int require_priv(const char* module, const char* version, const char* arg (snprintf(filename + offs, sizeof(filename) - offs, __VA_ARGS__) && fileNotEmpty(filename)) #endif +#if defined (_WIN32) + /* enable %n in printf */ + _set_printf_count_output(1); +#endif + driverpath = getenv("EPICS_DRIVER_PATH"); if (!globalTemplates) { @@ -1312,7 +1351,8 @@ loadlib: if (TRY_NONEMPTY_FILE(releasediroffs, "dbd" OSI_PATH_SEPARATOR "%s%s.dbd", module, versionstr) || TRY_NONEMPTY_FILE(releasediroffs, "%s%s.dbd", module, versionstr) || TRY_NONEMPTY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "dbd" OSI_PATH_SEPARATOR "%s%s.dbd", module, versionstr) || - TRY_NONEMPTY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "%s%s.dbd", module, versionstr)) + TRY_NONEMPTY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "%s%s.dbd", module, versionstr) || + TRY_NONEMPTY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR ".." OSI_PATH_SEPARATOR "dbd" OSI_PATH_SEPARATOR "%s.dbd", module)) /* org EPICSbase */ { printf("Loading dbd file %s\n", filename); if (dbLoadDatabase(filename, NULL, NULL) != 0)