diff --git a/Makefile b/Makefile
index 1fbb6d4dc3038ae71932a3f7a9f0958a9e8df696..f908443a830d9c3c28e35e356ad05a0cb7db6c4a 100644
--- a/Makefile
+++ b/Makefile
@@ -107,7 +107,7 @@ install: uninstall
 	$(QUIET) sudo install -m 644  $(TOP)/$(E3_ENV_NAME)/setE3Env.bash  $(REQUIRE_BIN)/	
 #
 ## Uninstall "Require" Module in order not to use it
-uninstall:
+uninstall: conf
 	$(QUIET) sudo -E bash -c 'make $(M_OPTIONS) uninstall'
 
 
@@ -115,8 +115,13 @@ uninstall:
 build: conf
 	$(QUIET) make $(M_OPTIONS)
 
+
+## clean, build, and install again.
+rebuild: clean build install
+
+
 ## Clean the EPICS Module
-clean:
+clean: conf
 	$(QUIET) make $(M_OPTIONS) clean
 
 
@@ -171,4 +176,4 @@ conf:
 
 
 
-.PHONY: help default init $(EPICS_MODULE_NAME) $(E3_ENV_NAME) env conf install uninstall build clean 
+.PHONY: help default init $(EPICS_MODULE_NAME) $(E3_ENV_NAME) env conf install uninstall build clean rebuild 
diff --git a/ess-env.conf b/ess-env.conf
index 647abe213cbcfad24770952d15cd27fefc978884..c18f6283569dd7af9dee4c488dd7f2e32a61c462 100644
--- a/ess-env.conf
+++ b/ess-env.conf
@@ -4,4 +4,4 @@ EPICS_LOCATION=/e3/bases
 EPICS_MODULES=/e3/modules
 
 REQUIRE=require
-IOCSH_HASH_VERSION=a17ef3d
+IOCSH_HASH_VERSION=ebc0c0b
diff --git a/iocsh.bash b/iocsh.bash
index 12472e00ed87aa441198110e6300afcef94de954..6cbc9437b7dc90236ee28628f603932fc23496dc 100755
--- a/iocsh.bash
+++ b/iocsh.bash
@@ -58,6 +58,7 @@ trap "softIoc_end ${IOC_STARTUP}" EXIT HUP INT TERM
 {
     printIocEnv;
     loadRequire;
+
     loadFiles "$@";
     if [ "$init" != NO ]; then
 	printf "iocInit\n"
@@ -67,6 +68,7 @@ trap "softIoc_end ${IOC_STARTUP}" EXIT HUP INT TERM
     printf "epicsEnvSet IOCSH_PS1 \"$IOCSH_PS1\"\n";
     printf "epicsEnvShow T_A\n";
     printf "epicsEnvShow EPICS_HOST_ARCH\n";
+    printf "var requireDebug 1\n";
     
 }  > ${IOC_STARTUP}
 
diff --git a/require.Makefile b/require.Makefile
index 24b51232a6d9466d3b00d84c05eb0e78af8ce78f..ebc22851c918016bac9427fe5b0bc4893ab81f6f 100644
--- a/require.Makefile
+++ b/require.Makefile
@@ -21,13 +21,11 @@ SOURCES_T2 += strdup.c
 SOURCES_vxWorks   += asprintf.c
 HEADERS += strdup.h asprintf.h
 HEADERS += require.h
+HEADERS += require_env.h
 
 # We need to find the Linux link.h before the EPICS link.h
 USR_INCLUDES_Linux=-idirafter $(EPICS_BASE)/include 
 
-# Pass T_A to the code
-# Should use '
-USR_CFLAGS += -DT_A='"$(T_A)"'
 
 # This should really go into some global WIN32 config file
 USR_CFLAGS_WIN32 += /D_WIN32_WINNT=0x501
diff --git a/require.c b/require.c
new file mode 100644
index 0000000000000000000000000000000000000000..cb3d360640c5a4063139ceab73bad7478fc5578d
--- /dev/null
+++ b/require.c
@@ -0,0 +1,1703 @@
+/*
+* ld - load code dynamically
+*
+* $Author: zimoch $
+* $ID$
+* $Date: 2015/06/29 09:47:30 $
+*
+* DISCLAIMER: Use at your own risc and so on. No warranty, no refund.
+*/
+
+#ifdef __unix
+/* for vasprintf and dl_iterate_phdr */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#endif
+
+/* for 64 bit (NFS) file systems */
+#define _FILE_OFFSET_BITS 64
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <recSup.h>
+#include <initHooks.h>
+#include <osiFileName.h>
+#include <epicsVersion.h>
+
+
+#ifdef BASE_VERSION
+#define EPICS_3_13
+
+#define epicsGetStdout() stdout
+extern int dbLoadDatabase(const char *filename, const char *path, const char *substitutions);
+int dbLoadRecords(const char *filename, const char *substitutions)
+{
+    /* This implementation uses EPICS_DB_INCLUDE_PATH */
+    return dbLoadDatabase(filename, NULL, substitutions);
+}
+extern volatile int interruptAccept;
+
+#else /* 3.14+ */
+
+#include <iocsh.h>
+#include <dbAccess.h>
+/* This prototype is missing in older EPICS versions */
+epicsShareFunc int epicsShareAPI iocshCmd(const char *cmd);
+#include <epicsExit.h>
+#include <epicsStdio.h>
+#include <osiFileName.h>
+#include <epicsExport.h>
+
+#endif
+
+#include "require.h"
+#include "require_env.h"
+
+int requireDebug;
+
+#if defined(vxWorks)
+    #ifndef OS_CLASS
+        #define OS_CLASS "vxWorks"
+    #endif
+
+    #include <symLib.h>
+    #include <sysSymTbl.h>
+    #include <loadLib.h>
+    #include <shellLib.h>
+    #include <ioLib.h>
+    #include <envLib.h>
+    #include <epicsAssert.h>
+    #include "strdup.h"
+    #include "asprintf.h"
+
+    #define HMODULE MODULE_ID
+    #define PREFIX
+    #define INFIX "Lib"
+    #define EXT ".munch"
+
+    #define getAddress(module, name) __extension__ \
+        ({SYM_TYPE t; char* a = NULL; symFindByName(sysSymTbl, (name), &a, &t); a;})
+
+    /* vxWorks has no snprintf() */
+    #define snprintf(s, maxchars, f, args...) __extension__ \
+        ({int printed=sprintf(s, f, ## args); assert(printed < maxchars); printed;})
+
+    /* vxWorks has no realpath() -- at least make directory absolute */
+    static char* realpath(const char* path, char* buf)
+    {
+        size_t len = 0;
+        if (!buf) buf = malloc(MAX_FILENAME_LENGTH);
+        if (!buf) return NULL;
+        if (path[0] != OSI_PATH_SEPARATOR[0])
+        {
+            getcwd(buf, MAX_FILENAME_LENGTH);
+            len = strlen(buf);
+            if (len && buf[len-1] != OSI_PATH_SEPARATOR[0])
+                buf[len++] = OSI_PATH_SEPARATOR[0];
+        }
+        strcpy(buf+len, path);
+        return buf;
+    }
+
+#elif defined(__unix)
+
+    #ifndef OS_CLASS
+        #ifdef __linux
+            #define OS_CLASS "Linux"
+        #endif
+
+        #ifdef SOLARIS
+            #define OS_CLASS "solaris"
+        #endif
+        
+        #ifdef __rtems__
+            #define OS_CLASS "RTEMS"
+        #endif
+        
+        #ifdef CYGWIN32
+            #define OS_CLASS "cygwin32"
+        #endif
+
+        #ifdef freebsd
+            #define OS_CLASS "freebsd"
+        #endif
+
+        #ifdef darwin
+            #define OS_CLASS "Darwin"
+        #endif
+
+        #ifdef _AIX32
+            #define OS_CLASS "AIX"
+        #endif
+    #endif
+
+    #include <dlfcn.h>
+    #define HMODULE void *
+
+    #define getAddress(module, name) dlsym(module, name)
+
+    #ifdef CYGWIN32
+        #define PREFIX
+        #define INFIX
+        #define EXT ".dll"
+    #else
+        #define PREFIX "lib"
+        #define INFIX
+        #define EXT ".so"
+    #endif
+
+#elif defined (_WIN32)
+
+    #ifndef OS_CLASS
+        #define OS_CLASS "WIN32"
+    #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)
+    #define NAME_MAX MAX_PATH
+
+    #define PREFIX
+    #define INFIX
+    #define EXT ".dll"
+
+    #define getAddress(module, name) GetProcAddress(module, name)
+    
+    static char* realpath(const char* path, char* buffer)
+    {
+        int len = MAX_PATH;
+        if (buffer == NULL)
+        {
+            len = GetFullPathName(path, 0, NULL, NULL);
+            if (len == 0) return NULL;
+            buffer = malloc(len);
+            if (buffer == NULL) return NULL;
+        }
+        GetFullPathName(path, len, buffer, NULL);
+        return buffer;
+    }
+    
+#else
+
+    #warning unknown OS
+    #define PREFIX
+    #define INFIX
+    #define EXT
+    #define getAddress(module, name) NULL
+
+#endif
+
+/* for readdir: Windows or Posix */
+#if defined(_WIN32)
+    #define DIR_HANDLE HANDLE
+    #define DIR_ENTRY WIN32_FIND_DATA
+    #define IF_OPEN_DIR(f) if(snprintf(f+modulediroffs, sizeof(f)-modulediroffs, "\\*.*"), (dir=FindFirstFile(filename, &direntry)) != INVALID_HANDLE_VALUE || (FindClose(dir), 0))
+    #define START_DIR_LOOP do
+    #define END_DIR_LOOP while(FindNextFile(dir,&direntry)); FindClose(dir);
+    #define SKIP_NON_DIR(e) if (!(e.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || (e.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) continue;
+    #define FILENAME(e) e.cFileName
+
+#else
+    #include <dirent.h>
+    #define DIR_HANDLE DIR*
+    #define IF_OPEN_DIR(f) if ((dir = opendir(f)))
+    #define DIR_ENTRY struct dirent*
+    #define START_DIR_LOOP while ((errno = 0, direntry = readdir(dir)) != NULL)
+    #define END_DIR_LOOP if (!direntry && errno) fprintf(stderr, "error reading directory %s: %s\n", filename, strerror(errno)); if (dir) closedir(dir);
+    #ifdef _DIRENT_HAVE_D_TYPE
+    #define SKIP_NON_DIR(e) if (e->d_type != DT_DIR && e->d_type != DT_UNKNOWN) continue;
+    #else
+    #define SKIP_NON_DIR(e)
+    #endif
+    #define FILENAME(e) e->d_name
+
+#endif
+
+
+
+#define LIBDIR "lib" OSI_PATH_SEPARATOR
+#define TEMPLATEDIR "db"
+
+
+
+#ifndef OS_CLASS
+#error OS_CLASS not defined: Try to compile with USR_CFLAGS += -DOS_CLASS='"${OS_CLASS}"'
+#endif
+
+const char osClass[] = OS_CLASS;
+
+/* loadlib (library)
+Find a loadable library by name and load it.
+*/
+
+void set_require_env()
+{
+  char* epics_version_major  = getenv("EPICS_VERSION_MAJOR");
+  char* epics_version_middle = getenv("EPICS_VERSION_MIDDLE");
+  char* epics_version_minor  = getenv("EPICS_VERSION_MINOR");
+
+  sprintf(epicsRelease, "%s.%s.%s", epics_version_major, epics_version_middle, epics_version_minor);
+  sprintf(epicsBasetype, "%s.%s", epics_version_major, epics_version_middle);
+  targetArch = getenv("EPICS_HOST_ARCH");
+  return;
+}
+
+static HMODULE loadlib(const char* libname)
+{
+    HMODULE libhandle = NULL;
+
+    if (libname == NULL)
+    {
+        fprintf (stderr, "missing library name\n");
+        return NULL;
+    }
+
+#if defined (__unix)
+    if ((libhandle = dlopen(libname, RTLD_NOW|RTLD_GLOBAL)) == NULL)
+    {
+        fprintf (stderr, "Loading %s library failed: %s\n",
+            libname, dlerror());
+    }
+#elif defined (_WIN32)
+    if ((libhandle = LoadLibrary(libname)) == NULL)
+    {
+        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);
+#ifndef _WRS_VXWORKS_MAJOR
+/* vxWorks 5 */
+            if (errno == S_symLib_SYMBOL_NOT_FOUND)
+            {
+                libhandle = NULL;
+            }
+#endif
+            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 content[0];
+} moduleitem;
+
+static moduleitem* loadedModules = NULL;
+static unsigned long moduleCount = 0;
+static unsigned long moduleListBufferSize = 1;
+static unsigned long maxModuleNameLength = 0;
+
+int putenvprintf(const char* format, ...)
+{
+    va_list ap;
+    char *var;
+    char *val;
+    int status = 0;
+
+    if (!format) return -1;
+    va_start(ap, format);
+    if (vasprintf(&var, format, ap) < 0)
+    {
+        perror("require putenvprintf");
+        return errno;
+    }
+    va_end(ap);
+
+    if (requireDebug)
+        printf("require: putenv(\"%s\")\n", var);
+
+    val = strchr(var, '=');
+    if (!val) 
+    {
+        fprintf(stderr, "putenvprintf: string contains no =: %s\n", var);
+        status = -1;
+    }
+    else
+    {
+#ifdef vxWorks
+        if (putenv(var) != 0) /* vxWorks putenv() makes a copy */
+        {
+            perror("require putenvprintf: putenv failed");
+            status = errno;
+        }
+#else
+        *val++ = 0;
+        if (setenv(var, val, 1) != 0)
+        {
+            perror("require putenvprintf: setenv failed");
+            status = errno;
+        }
+#endif
+    }
+    free(var);
+    return status;
+}
+
+void pathAdd(const char* varname, const char* dirname)
+{
+    char* old_path;           
+
+    if (!varname || !dirname) {
+        fprintf(stderr, "usage: pathAdd \"ENVIRONMENT_VARIABLE\",\"directory\"\n");
+        fprintf(stderr, "       Adds or moves the directory to the front of the ENVIRONMENT_VARIABLE\n");
+        fprintf(stderr, "       but after a leading \".\".\n");
+        return;
+    }
+
+    /* add directory to front */
+    old_path = getenv(varname);
+    if (old_path == NULL)
+        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, 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, dirname);
+                old_path[len] = OSI_PATH_LIST_SEPARATOR[0];
+                if (requireDebug)
+                    printf("require: modified %s=%s\n", varname, old_path);
+                break;
+            }
+            p += len;
+        }
+        if (p == NULL)
+            /* add new directory to the front (after "." )*/
+            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);
+    pathAdd("EPICS_DB_INCLUDE_PATH", absdir);
+    free(absdir);
+    return 0;
+}
+
+static int getRecordHandle(const char* namepart, short type, long minsize, DBADDR* paddr)
+{
+    char recordname[PVNAME_STRINGSZ];
+    long dummy, offset;
+
+    sprintf(recordname, "%.*s%s", (int)(PVNAME_STRINGSZ-strlen(namepart)-1), getenv("IOC"), namepart);
+    if (dbNameToAddr(recordname, paddr) != 0)
+    {
+        fprintf(stderr, "require: record %s not found\n",
+            recordname);
+        return -1;
+    }
+    if (paddr->field_type != type)
+    {
+        fprintf(stderr, "require: record %s has wrong type %s instead of %s\n",
+            recordname, pamapdbfType[paddr->field_type].strvalue, pamapdbfType[type].strvalue);
+        return -1;
+    }
+    if (paddr->no_elements < minsize)
+    {
+        fprintf(stderr, "require: record %s has not enough elements: %lu instead of %lu\n",
+            recordname, paddr->no_elements, minsize);
+        return -1;
+    }
+    if (paddr->pfield == NULL)
+    {
+        fprintf(stderr, "require: record %s has not yet allocated memory\n",
+            recordname);
+        return -1;
+    }
+    /* update array information */
+    dbGetRset(paddr)->get_array_info(paddr, &dummy, &offset);
+    return 0;
+}
+
+/*
+We can fill the records only after they have been initialized, at initHookAfterFinishDevSup.
+But use double indirection here because in 3.13 we must
+wait until initHooks is loaded before we can register the hook.
+*/
+
+static void fillModuleListRecord(initHookState state)
+{
+    if (state == initHookAfterFinishDevSup) /* MODULES record exists and has allocated memory */
+    {
+        DBADDR modules, versions, modver;
+        int have_modules, have_versions, have_modver;
+        moduleitem *m;
+        int i = 0;
+        long c = 0;
+        
+        if (requireDebug)
+            printf("require: fillModuleListRecord\n");
+
+        have_modules  = (getRecordHandle(":MODULES",  DBF_STRING, moduleCount, &modules) == 0);
+        have_versions = (getRecordHandle(":VERSIONS", DBF_STRING, moduleCount, &versions) == 0);
+        
+        moduleListBufferSize += moduleCount * maxModuleNameLength;
+        have_modver   = (getRecordHandle(":MOD_VER",  DBF_CHAR, moduleListBufferSize, &modver) == 0);
+
+        for (m = loadedModules, i = 0; m; m=m->next, i++)
+        {
+            size_t lm = strlen(m->content)+1;
+            if (have_modules)
+            {
+                if (requireDebug)
+                    printf("require: %s[%d] = \"%.*s\"\n",
+                    modules.precord->name, i, 
+                    MAX_STRING_SIZE-1, m->content);
+                sprintf((char*)(modules.pfield) + i * MAX_STRING_SIZE, "%.*s",
+                    MAX_STRING_SIZE-1, m->content);
+            }
+            if (have_versions)
+            {
+                if (requireDebug)
+                    printf("require: %s[%d] = \"%.*s\"\n",
+                    versions.precord->name, i, 
+                    MAX_STRING_SIZE-1, m->content+lm);
+                sprintf((char*)(versions.pfield) + i * MAX_STRING_SIZE, "%.*s",
+                    MAX_STRING_SIZE-1, m->content+lm);
+            }
+            if (have_modver)
+            {
+                if (requireDebug)
+                    printf("require: %s+=\"%-*s%s\"\n",
+                        modver.precord->name,
+                        (int)maxModuleNameLength, m->content, m->content+lm);
+                c += sprintf((char*)(modver.pfield) + c, "%-*s%s\n",
+                        (int)maxModuleNameLength, m->content, m->content+lm);
+            }
+        }
+        if (have_modules) dbGetRset(&modules)->put_array_info(&modules, i);
+        if (have_versions) dbGetRset(&versions)->put_array_info(&versions, i);
+        if (have_modver) dbGetRset(&modver)->put_array_info(&modver, c+1);
+    }
+}
+
+void registerModule(const char* module, const char* version, const char* location)
+{
+    moduleitem *m, **pm;
+    size_t lm = strlen(module) + 1;
+    size_t lv = (version ? strlen(version) : 0) + 1;
+    size_t ll = 1;
+    char* abslocation = NULL;
+    char* argstring = NULL;
+    int addSlash=0;
+    const char *mylocation;
+    static int firstTime = 1;
+    
+    if (requireDebug)
+        printf("require: registerModule(%s,%s,%s)\n", module, version, location);
+        
+    if (firstTime)
+    {
+#ifdef EPICS_3_13
+        int (*initHookRegister)() = NULL;
+        SYM_TYPE type;
+        symFindByName(sysSymTbl, "initHookRegister", (char**)&initHookRegister, &type);
+        if (initHookRegister)
+#endif
+        {
+            initHookRegister(fillModuleListRecord);
+            if (requireDebug)
+                printf("require: initHookRegister\n");
+        }
+        firstTime = 0;
+    }
+    
+    if (!version) version="";
+        
+    if (location)
+    {
+        abslocation = realpath(location, NULL);
+        if (!abslocation) abslocation = (char*)location;
+        ll = strlen(abslocation) + 1;
+        /* linux realpath removes trailing slash */
+        if (abslocation[ll-1-strlen(OSI_PATH_SEPARATOR)] != OSI_PATH_SEPARATOR[0])
+        {
+            addSlash = strlen(OSI_PATH_SEPARATOR);
+        }
+    }
+    m = (moduleitem*) malloc(sizeof(moduleitem) + lm + lv + ll + addSlash);
+    if (m == NULL)
+    {
+        fprintf(stderr, "require: out of memory\n");
+        return;
+    }
+    m->next = NULL;
+    strcpy (m->content, module);
+    strcpy (m->content+lm, version);
+    strcpy (m->content+lm+lv, abslocation ? abslocation : "");
+    if (addSlash) strcpy (m->content+lm+lv+ll-1, OSI_PATH_SEPARATOR);
+    if (abslocation != location) free(abslocation);
+    for (pm = &loadedModules; *pm != NULL; pm = &(*pm)->next);
+    *pm = m;
+    if (lm > maxModuleNameLength) maxModuleNameLength = lm;
+    moduleListBufferSize += lv;
+    moduleCount++;
+
+    putenvprintf("MODULE=%s", module);
+    putenvprintf("%s_VERSION=%s", module, version);
+    if (location)
+    {
+        putenvprintf("%s_DIR=%s", module, m->content+lm+lv);
+        pathAdd("SCRIPT_PATH", m->content+lm+lv);
+    }
+    
+    /* only do registration register stuff at init */
+    if (interruptAccept) return;
+    
+    /* create a record with the version string */
+    mylocation = getenv("require_DIR");
+    if (mylocation == NULL) return;
+    if (asprintf(&abslocation, "%s" OSI_PATH_SEPARATOR "db" OSI_PATH_SEPARATOR "moduleversion.template", mylocation) < 0) return;
+    if (asprintf(&argstring, "IOC=%.30s, MODULE=%.24s, VERSION=%.39s, MODULE_COUNT=%lu, BUFFER_SIZE=%lu",
+        getenv("IOC"), module, version, moduleCount,
+        moduleListBufferSize+maxModuleNameLength*moduleCount) < 0) return;
+    printf("Loading module info records for %s\n", module);
+    dbLoadRecords(abslocation, argstring);
+    free(argstring);
+    free(abslocation);
+}
+
+#if defined (vxWorks)
+static BOOL findLibRelease (
+    char      *name,  /* symbol name       */
+    int       val,    /* value of symbol   */
+    SYM_TYPE  type,   /* symbol type       */
+    int       arg,    /* user-supplied arg */
+    UINT16    group   /* group number      */
+) {
+    /* find symbols with a name like "_<module>LibRelease" */
+    char* module;
+    size_t lm;
+
+    if (name[0] != '_') return TRUE;
+    lm = strlen(name);
+    if (lm <= 10) /* strlen("LibRelease") */ return TRUE;
+    lm -= 10;
+    if (strcmp(name+lm, "LibRelease") != 0) return TRUE;
+    module = strdup(name+1);                  /* remove '_' */
+    module[lm-1]=0;                           /* remove "libRelase" */
+    if (getLibVersion(module) == NULL)
+        registerModule(module, (char*)val, NULL);
+    free(module);
+    return TRUE;
+}
+
+void registerExternalModules()
+{
+    /* iterate over all symbols */
+    symEach(sysSymTbl, (FUNCPTR)findLibRelease, 0);
+}
+
+#elif defined (__linux)
+/* This is the Linux link.h, not the EPICS link.h ! */
+#include <link.h>
+
+static int findLibRelease (
+    struct dl_phdr_info *info, /* shared library info */
+    size_t size,               /* size of info structure */
+    void *data                 /* user-supplied arg */
+) {
+    void *handle;
+    char* location = NULL;
+    char* p;
+    char* version;
+    char* symname;
+    char name[NAME_MAX + 11];                               /* get space for library path + "LibRelease" */
+    
+    (void)data;                                             /* unused */
+    if (size < sizeof(struct dl_phdr_info)) return 0;       /* wrong version of struct dl_phdr_info */
+    /* 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 */
+    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;} 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++;                                    /* 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);
+    return 0;
+}
+
+static void registerExternalModules()
+{
+    /* iterate over all loaded libraries */
+    dl_iterate_phdr(findLibRelease, NULL);
+}
+
+#elif defined (_WIN32)
+
+static void registerExternalModules()
+{
+    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);
+        }
+    }
+}
+
+
+#else
+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)
+{
+    moduleitem* m;
+
+    for (m = loadedModules; m; m=m->next)
+    {
+        if (strcmp(m->content, libname) == 0)
+        {
+            return m->content+strlen(m->content)+1;
+        }
+    }
+    return NULL;
+}
+
+const char* getLibLocation(const char* libname)
+{
+    moduleitem* m;
+    char *v;
+
+    for (m = loadedModules; m; m=m->next)
+    {
+        if (strcmp(m->content, libname) == 0)
+        {
+            v = m->content+strlen(m->content)+1;
+            return v+strlen(v)+1;
+        }
+    }
+    return NULL;
+}
+
+int libversionShow(const char* outfile)
+{
+    moduleitem* m;
+    size_t lm, lv;
+    
+    FILE* out = epicsGetStdout();
+
+    if (outfile)
+    {
+        out = fopen(outfile, "w");
+        if (out == NULL)
+        {
+            fprintf(stderr, "can't open %s: %s\n",
+                outfile, strerror(errno));
+            return -1;
+        }
+    }
+    for (m = loadedModules; m; m=m->next)
+    {
+        lm = strlen(m->content)+1;
+        lv = strlen(m->content+lm)+1;
+        fprintf(out, "%-*s%-20s %s\n",
+            (int)maxModuleNameLength, m->content,
+            m->content+lm, m->content+lm+lv);
+    }
+    if (fflush(out) < 0 && outfile)
+    {
+        fprintf(stderr, "can't write to %s: %s\n",
+            outfile, strerror(errno));
+        return -1;
+    }
+    if (outfile)
+        fclose(out);
+    return 0;
+}
+
+#define MISMATCH -1
+#define EXACT 0
+#define MATCH 1
+#define TESTVERS 2
+#define HIGHER 3
+
+static int compareVersions(const char* found, const char* request)
+{
+    int found_major, found_minor=0, found_patch=0, found_parts = 0;
+    int req_major, req_minor, req_patch, req_parts;
+    const char* found_extra;
+    const char* req_extra;
+    int n;
+    
+    if (requireDebug)
+        printf("require: compareVersions(found=%s, request=%s)\n", found, request);
+        
+    if (found == NULL || found[0] == 0)                /* no version found: any requested? */
+    {
+        if (request == NULL || request[0] == 0)
+        {
+            if (requireDebug)
+                printf("require: compareVersions: EXACT both empty\n");
+            return EXACT;
+        }
+        else
+        {
+            if (requireDebug)
+                printf("require: compareVersions: MISMATCH version requested, empty version found\n");
+            return MISMATCH;
+        }
+    }
+    n = 0;
+    found_parts = sscanf(found, "%d%n.%d%n.%d%n", &found_major, &n, &found_minor, &n, &found_patch, &n);
+    found_extra = found + n;
+    if (request == NULL || request[0] == 0)            /* no particular version request: match anything */
+    {
+        if (found_parts == 0 || found_extra[0] != 0)
+        {
+            if (requireDebug)
+                printf("require: compareVersions: TESTVERS nothing requested, test version found\n");
+            return TESTVERS;
+        }
+        else
+        {
+            if (requireDebug)
+                printf("require: compareVersions: MATCH no version requested, numeric version found\n");
+            return MATCH;
+        }
+    }
+
+    if (strcmp(found, request) == 0)
+    {
+        if (requireDebug)
+            printf("require: compareVersions: MATCH exactly\n");
+        return EXACT;
+    }
+
+    /* Numerical version compare. Format is major.minor.patch
+       Numerical requests must have exact match in major and
+       backward-compatible number in minor and patch
+    */
+    n = 0;
+    req_parts = sscanf(request, "%d%n.%d%n.%d%n", &req_major, &n, &req_minor, &n, &req_patch, &n);
+    req_extra = request + n;
+    if (req_parts == 0 || (req_extra[0] != 0 && strcmp(req_extra, "+") != 0))
+    {
+        if (requireDebug)
+            printf("require: compareVersions: MISMATCH test version requested, different version found\n");
+        return MISMATCH;
+    }
+    if (found_parts == 0 || (found_extra[0] != 0 && strcmp(found_extra, "+") != 0))
+    {
+        if (requireDebug)
+            printf("require: compareVersions: TESTVERS numeric requested, test version found");
+        if (req_extra[0] == '+')
+            return TESTVERS;
+        else
+            return MISMATCH;
+    }
+    if (found_major < req_major)
+    {
+        if (requireDebug)
+            printf("require: compareVersions: MISMATCH too low major number\n");
+        return MISMATCH;
+    }
+    if (found_major > req_major)
+    {
+        if (requireDebug)
+            printf("require: compareVersions: HIGHER major number\n");
+        return HIGHER;
+    }
+    if (req_parts == 1)
+    {
+        if (requireDebug)
+            printf("require: compareVersions: MATCH only major number requested\n");
+        return MATCH;
+    }
+    if (found_minor < req_minor)
+    {
+        if (requireDebug)
+            printf("require: compareVersions: MISMATCH minor number too low\n");
+        return MISMATCH;
+    }
+    if (found_minor > req_minor)                        /* minor larger than required */
+    {
+        if (req_extra[0] == '+')
+        {
+            if (requireDebug)
+                printf("require: compareVersions: MATCH minor number higher than requested with +\n");
+            return MATCH;
+        }
+        else
+        {
+            if (requireDebug)
+                printf("require: compareVersions: HIGHER minor number\n");
+            return HIGHER;
+        }
+    }
+    if (req_parts == 2)
+    {
+        if (requireDebug)
+            printf("require: compareVersions: MATCH only major.minor number requested\n");
+        return MATCH;
+    }
+    if (found_patch < req_patch)
+    {
+        if (requireDebug)
+            printf("require: compareVersions: MISMATCH patch level too low\n");
+        return MISMATCH;
+    }
+    if (found_patch == req_patch)
+    {
+        if (requireDebug)
+            printf("require: compareVersions: MATCH patch level matches exactly requested\n");
+        return MATCH;
+    }
+    if (req_extra[0] == '+')
+    {
+        if (requireDebug)
+            printf("require: compareVersions: MATCH patch level higher than requested with +\n");
+        return MATCH;
+    }
+    if (requireDebug)
+        printf("require: compareVersions: HIGHER patch level\n");
+    return HIGHER; 
+}
+
+/* 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.
+*/
+
+/* wrapper to abort statup script */
+static int require_priv(const char* module, const char* version, const char* args, const char* versionstr);
+
+int require(const char* module, const char* version, const char* args)
+{
+    int status;
+    char* versionstr;
+    static int firstTime = 1;
+
+
+    if (firstTime)
+    {
+        firstTime = 0;
+	
+	set_require_env();
+	
+	putenvprintf("T_A=%s",             targetArch);
+	putenvprintf("EPICS_HOST_ARCH=%s", targetArch);
+        putenvprintf("EPICS_RELEASE=%s",   epicsRelease);
+        putenvprintf("EPICS_BASETYPE=%s",  epicsBasetype);
+        putenvprintf("OS_CLASS=%s",        osClass);
+    
+    }
+
+    if (module == NULL)
+    {
+        printf("Usage: require \"<module>\" [, \"<version>\" | \"ifexists\"] [, \"<args>\"]\n");
+        printf("Loads " PREFIX "<module>" INFIX EXT " and <libname>.dbd\n");
+#ifndef EPICS_3_13
+        printf("And calls <module>_registerRecordDeviceDriver\n");
+#endif
+        printf("If available, runs startup script snippet (only before iocInit)\n");
+        return -1;
+    }
+    
+    /* either order for version and args, either may be empty or NULL */
+    if (version && strchr(version, '='))
+    {
+        const char *v = version;
+        version = args;
+        args = v;
+        if (requireDebug)
+            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: */
+        if (asprintf(&versionstr, "-%s", version) < 0) return errno;
+        if (isdigit((unsigned char)version[0]) && version[strlen(version)-1] == '+')
+        {
+            /*
+                user may give a minimal version (e.g. "1.2.4+")
+                load highest matching version (here "1.2") and check later
+            */
+            char* p = strrchr(versionstr, '.');
+            if (p == NULL) p = versionstr;
+            *p = 0;
+        }
+    }
+    else
+        versionstr = "";
+    if (requireDebug)
+        printf("require: versionstr = \"%s\"\n", versionstr);
+
+    status = require_priv(module, version, args, versionstr);
+
+    if (version) free(versionstr);
+
+    if (status == 0) return 0;
+    if (status != -1) perror("require");
+    if (interruptAccept) return status;
+
+    /* require failed in startup script before iocInit */
+    fprintf(stderr, "Aborting startup script\n");
+    #ifdef vxWorks
+    shellScriptAbort();
+    #else
+    epicsExit(1);
+    #endif
+    return status;
+}
+
+static off_t fileSize(const char* filename)
+{
+    struct stat filestat;
+    if (stat(
+#ifdef vxWorks
+        (char*) /* vxWorks has buggy stat prototype */
+#endif
+        filename, &filestat) != 0)
+    {
+        if (requireDebug)
+            printf("require: %s does not exist\n", filename);
+        return -1;
+    }
+    switch (filestat.st_mode & S_IFMT)
+    {
+        case S_IFREG:
+            if (requireDebug)
+                printf("require: file %s exists, size %lld bytes\n",
+                    filename, (unsigned long long)filestat.st_size);
+            return filestat.st_size;
+        case S_IFDIR:
+            if (requireDebug)
+                printf("require: directory %s exists\n",
+                    filename);
+            return 0;
+        #ifdef S_IFBLK
+        case S_IFBLK:
+            if (requireDebug)
+                printf("require: %s is a block device\n",
+                    filename);
+            return -1;
+        #endif
+        #ifdef S_IFCHR
+        case S_IFCHR:
+            if (requireDebug)
+                printf("require: %s is a character device\n",
+                    filename);
+            return -1;
+        #endif
+        #ifdef S_IFIFO
+        case S_IFIFO:
+            if (requireDebug)
+                printf("require: %s is a FIFO/pipe\n",
+                    filename);
+            return -1;
+        #endif
+        #ifdef S_IFSOCK
+        case S_IFSOCK:
+            if (requireDebug)
+                printf("require: %s is a socket\n",
+                    filename);
+            return -1;
+        #endif
+        default:
+            if (requireDebug)
+                printf("require: %s is an unknown type of special file\n",
+                    filename);
+            return -1;
+    }
+}
+#define fileExists(filename) (fileSize(filename)>=0)
+#define fileNotEmpty(filename) (fileSize(filename)>0)
+
+static int handleDependencies(const char* module, char* depfilename)
+{
+    FILE* depfile;
+    char buffer[40];
+    char *end; /* end of string */
+    char *rmodule; /* required module */
+    char *rversion; /* required version */
+
+    if (requireDebug)
+        printf("require: parsing dependency file %s\n", depfilename);
+    depfile = fopen(depfilename, "r");
+    while (fgets(buffer, sizeof(buffer)-1, depfile))
+    {
+        rmodule = buffer;
+        /* ignore leading spaces */
+        while (isspace((unsigned char)*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((unsigned char)*rversion)) rversion++;
+        /* terminate module name */
+        *rversion++ = 0;
+        /* ignore spaces */
+        while (isspace((unsigned char)*rversion)) rversion++;
+        /* rversion at start of version */
+        
+        if (*rversion)
+        {
+            end = rversion;
+            /* find end of version */
+            while (*end && !isspace((unsigned char)*end)) end++;
+
+            /* add + to numerial versions if not yet there */
+            if (*(end-1) != '+' && strspn(rversion, "0123456789.") == (size_t)(end-rversion)) *end++ = '+';
+
+            /* terminate version */
+            *end = 0;
+        }
+        printf("Module %s depends on %s %s\n", module, rmodule, rversion);
+        if (require(rmodule, rversion, NULL) != 0)
+        {
+            fclose(depfile);
+            return -1;
+        }
+    }
+    fclose(depfile);
+    return 0;
+}
+
+static int require_priv(const char* module, const char* version, const char* args,
+    const char* versionstr  /* "-<version>" or "" (for old style only */ )
+{
+    int status;
+    const char* loaded = NULL;
+    const char* found = NULL;
+    HMODULE libhandle;
+    int ifexists = 0;
+    const char* driverpath;
+    const char* dirname;
+    const char *end;
+
+    int releasediroffs;
+    int libdiroffs;
+    int extoffs;
+    char* founddir = NULL;
+    char* symbolname;
+    char filename[NAME_MAX];
+    
+    int someVersionFound = 0;
+    int someArchFound = 0;
+    
+    static char* globalTemplates = NULL;
+
+    if (requireDebug)
+        printf("require: module=\"%s\" version=\"%s\" args=\"%s\"\n", module, version, args);
+
+#if defined __GNUC__ && __GNUC__ < 3
+    #define TRY_FILE(offs, args...) \
+        (snprintf(filename + offs, sizeof(filename) - offs, args) && fileExists(filename))
+
+    #define TRY_NONEMPTY_FILE(offs, args...) \
+        (snprintf(filename + offs, sizeof(filename) - offs, args) && fileNotEmpty(filename))
+#else
+    #define TRY_FILE(offs, ...) \
+        (snprintf(filename + offs, sizeof(filename) - offs, __VA_ARGS__) && fileExists(filename))
+
+    #define TRY_NONEMPTY_FILE(offs, ...) \
+        (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)
+    {
+        char *t = getenv("TEMPLATES");
+        if (t) globalTemplates = strdup(t);
+    }
+    
+    if (driverpath == NULL) driverpath = ".";
+    if (requireDebug)
+        printf("require: searchpath=%s\n", driverpath);
+
+    if (version && strcmp(version,"ifexists") == 0)
+    {
+        ifexists = 1;
+        version = NULL;
+        versionstr = "";
+    }
+
+    /* check already loaded verion */
+    loaded = getLibVersion(module);
+    if (loaded)
+    {
+        /* Library already loaded. Check Version. */
+        switch (compareVersions(loaded, version))
+        {
+            case TESTVERS:
+                if (version)
+                    printf("Warning: Module %s test version %s already loaded where %s was requested\n",
+                        module, loaded, version);
+            case EXACT:
+            case MATCH:
+                printf ("Module %s version %s already loaded\n", module, loaded);
+                break;
+            default:
+                printf("Conflict between requested %s version %s and already loaded version %s.\n",
+                    module, version, loaded);
+                return -1;
+        }
+        dirname = getLibLocation(module);
+        if (dirname[0] == 0) return 0;
+        if (requireDebug)
+            printf("require: library found in %s\n", dirname);
+        snprintf(filename, sizeof(filename), "%s%n", dirname, &releasediroffs);
+        putenvprintf("MODULE=%s", module);
+        pathAdd("SCRIPT_PATH", dirname);
+    }
+    else
+    {
+        if (requireDebug)
+            printf("require: no %s version loaded yet\n", module);
+
+        /* Search for module in driverpath */
+        for (dirname = driverpath; dirname != NULL; dirname = end)
+        {
+            /* get one directory from driverpath */
+            int dirlen;
+            int modulediroffs;
+            DIR_HANDLE dir;
+            DIR_ENTRY direntry;
+
+            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 driverpath elements */
+
+            if (requireDebug)
+                printf("require: trying %.*s\n", dirlen, dirname);
+
+            snprintf(filename, sizeof(filename), "%.*s" OSI_PATH_SEPARATOR "%s" OSI_PATH_SEPARATOR "%n", 
+                dirlen, dirname, module, &modulediroffs);
+            dirlen++;
+            /* filename = "<dirname>/[dirlen]<module>/[modulediroffs]" */
+
+            /* Does the module directory exist? */
+            IF_OPEN_DIR(filename)
+            {
+                if (requireDebug)
+                    printf("require: found directory %s\n", filename);
+                    
+                /* Now look for versions. */
+                START_DIR_LOOP
+                {
+                    char* currentFilename = FILENAME(direntry);
+                    
+                    SKIP_NON_DIR(direntry)
+                    if (currentFilename[0] == '.') continue;  /* ignore hidden directories */
+
+                    someVersionFound = 1;
+
+                    /* Look for highest matching version. */
+                    if (requireDebug)
+                        printf("require: checking version %s against required %s\n",
+                                currentFilename, version);
+
+                    switch ((status = compareVersions(currentFilename, version)))
+                    {
+                        case EXACT: /* exact match found */
+                        case MATCH: /* all given numbers match. */
+                        {
+                            someArchFound = 1;
+
+                            if (requireDebug)
+                                printf("require: %s %s may match %s\n",
+                                    module, currentFilename, version);
+
+                            /* Check if it has our EPICS version and architecture. */
+                            /* Even if it has no library, at least it has a dep file in the lib dir */
+
+                            /* filename = "<dirname>/[dirlen]<module>/[modulediroffs]" */
+                            if (!TRY_FILE(modulediroffs, "%s" OSI_PATH_SEPARATOR "R%s" OSI_PATH_SEPARATOR LIBDIR "%s" OSI_PATH_SEPARATOR,
+                                currentFilename, epicsRelease, targetArch))
+                            /* filename = "<dirname>/[dirlen]<module>/[modulediroffs]<version>/R<epicsRelease>/lib/<targetArch>/" */
+                            {
+                                if (requireDebug)
+                                    printf("require: %s %s has no support for %s %s\n",
+                                        module, currentFilename, epicsRelease, targetArch);
+                                continue;
+                            }
+
+                            if (status == EXACT)
+                            {
+                                if (requireDebug)
+                                    printf("require: %s %s matches %s exactly\n",
+                                        module, currentFilename, version);
+                                /* We are done. */
+                                end = NULL;
+                                break;
+                            }
+
+                            /* Is it higher than the one we found before? */
+                            if (found && requireDebug)
+                                printf("require: %s %s support for %s %s found, compare against previously found %s\n",
+                                    module, currentFilename, epicsRelease, targetArch, found);
+                            if (!found || compareVersions(currentFilename, found) == HIGHER)
+                            {
+                                if (requireDebug)
+                                    printf("require: %s %s looks promising\n", module, currentFilename);
+                                break;
+                            }
+                            if (requireDebug)
+                                printf("require: version %s is lower than %s \n", currentFilename, found);
+                            continue;
+                        }
+                        default:
+                        {
+                            if (requireDebug)
+                                printf("require: %s %s does not match %s\n",
+                                    module, currentFilename, version);
+                            continue;
+                        }
+                    }
+                    /* we have found something (EXACT or MATCH) */
+                    free(founddir);
+                    /* filename = "<dirname>/[dirlen]<module>/[modulediroffs]..." */
+                    if (asprintf(&founddir, "%.*s%s", modulediroffs, filename, currentFilename) < 0)
+                        return errno;
+                    /* founddir = "<dirname>/[dirlen]<module>/[modulediroffs]<version>" */
+                    found = founddir + modulediroffs; /* version part in the path */
+                    if (status == EXACT) break;
+                }
+                END_DIR_LOOP
+            }
+            else
+            {
+                /* filename = "<dirname>/[dirlen]<module>/" */
+                if (requireDebug)
+                    printf("require: no %s directory\n", filename);
+
+                /* try local/old style module only if no new style candidate has been found */
+                if (!found)
+                {
+                    /* look for dep file */
+                    releasediroffs = libdiroffs = dirlen;
+                    if (TRY_FILE(dirlen, "%s%s.dep", module, versionstr))
+                    /* filename = "<dirname>/[dirlen][releasediroffs][libdiroffs]<module>(-<version>)?.dep" */
+                    {
+                        if (requireDebug)
+                            printf("require: found old style %s\n", filename);
+                        printf ("Module %s%s found in %.*s\n", module,
+                            versionstr, dirlen, filename);
+                        goto checkdep;
+                    }
+
+                    /* look for library file */
+                    if (TRY_FILE(dirlen, PREFIX "%s" INFIX "%s%n" EXT, module, versionstr, &extoffs)
+                    /* filename = "<dirname>/[dirlen][releasediroffs][libdiroffs]PREFIX<module>INFIX(-<version>)?[extoffs]EXT" */
+                    #ifdef vxWorks
+                        /* try without extension */
+                        || (filename[dirlen + extoffs] = 0, fileExists(filename))
+                    #endif
+                        )
+                    {
+                        if (requireDebug)
+                            printf("require: found old style %s\n", filename);
+                        printf ("Module %s%s found in %.*s\n", module,
+                            versionstr, dirlen, filename);
+                        goto loadlib;
+                    }
+                }
+            }
+            /* filename = "<dirname>/[dirlen]..." */
+            if (!found && requireDebug)
+                printf("require: no matching version in %.*s\n", dirlen, filename);
+        }
+
+        if (!found)
+        {
+            if (someArchFound)
+                fprintf(stderr, "Module %s%s%s not available for %s\n(but maybe for other EPICS versions or architectures)\n",
+                    module, version ? " version " : "", version ? version : "", targetArch);
+            else
+            if (someVersionFound)
+                fprintf(stderr, "Module %s%s%s not available (but other versions are available)\n",
+                    module, version ? " version " : "", version ? version : "");
+            else
+                fprintf(stderr, "Module %s%s%s not available\n",
+                    module, version ? " version " : "", version ? version : "");
+            return ifexists ? 0 : -1;
+        }
+
+        versionstr = "";
+
+        /* founddir = "<dirname>/[dirlen]<module>/<version>" */
+        printf ("Module %s version %s found in %s" OSI_PATH_SEPARATOR "\n", module, found, founddir);
+
+        if (requireDebug)
+            printf("require: looking for dependency file\n");
+
+        if (!TRY_FILE(0, "%s" OSI_PATH_SEPARATOR "R%s" OSI_PATH_SEPARATOR "%n" LIBDIR "%s" OSI_PATH_SEPARATOR "%n%s.dep",
+            founddir, epicsRelease, &releasediroffs, targetArch, &libdiroffs, module))
+        /* filename = "<dirname>/[dirlen]<module>/<version>/R<epicsRelease>/[releasediroffs]/lib/<targetArch>/[libdiroffs]/module.dep" */
+        {
+            fprintf(stderr, "Dependency file %s not found\n", filename);
+        }
+        else
+        {
+checkdep:
+            /* filename = "<dirname>/[dirlen]<module>/<version>/R<epicsRelease>/[releasediroffs]/lib/<targetArch>/[libdiroffs]/module.dep" */
+            /* or (old)   "<dirname>/[dirlen]][releasediroffs][libdiroffs]<module>(-<version>)?.dep" */
+            if (handleDependencies(module, filename) == -1)
+                return -1;
+        }
+
+        if (requireDebug)
+            printf("require: looking for library file\n");
+
+        if (!(TRY_FILE(libdiroffs, PREFIX "%s" INFIX "%s%n" EXT, module, versionstr, &extoffs)
+        #ifdef vxWorks
+            /* try without extension */
+            || (filename[libdiroffs + extoffs] = 0, fileExists(filename))
+        #endif
+            ))
+        /* filename = "<dirname>/[dirlen]<module>/<version>/R<epicsRelease>/[releasediroffs]/lib/<targetArch>/[libdiroffs]/PREFIX<module>INFIX[extoffs](EXT)?" */
+        /* or  (old)  "<dirname>/[dirlen][releasediroffs][libdiroffs]PREFIX<module>INFIX(-<version>)?[extoffs](EXT)?" */
+        {
+            printf("Module %s has no library\n", module);
+        }
+        else
+        {
+loadlib:
+            /* filename = "<dirname>/[dirlen]<module>/<version>/R<epicsRelease>/[releasediroffs]/lib/<targetArch>/[libdiroffs]/PREFIX<module>INFIX[extoffs]EXT" */
+            /* or  (old)  "<dirname>/[dirlen][releasediroffs][libdiroffs]PREFIX<module>INFIX(-<version>)?[extoffs]EXT" */
+            printf("Loading library %s\n", filename);
+            if ((libhandle = loadlib(filename)) == NULL)
+                return -1;
+
+            /* now check what version we really got (with compiled-in version number) */
+            if (asprintf (&symbolname, "_%sLibRelease", module) < 0)
+                return errno;
+
+            found = (const char*) getAddress(libhandle, symbolname);
+            free(symbolname);
+            printf("Loaded %s version %s\n", module, found);
+
+            /* check what we got */
+            if (requireDebug)
+                printf("require: compare requested version %s with loaded version %s\n", version, found);
+            if (compareVersions(found, version) == MISMATCH)
+            {
+                fprintf(stderr, "Requested %s version %s not available, found only %s.\n",
+                    module, version, found);
+                return -1;
+            }
+
+            /* load dbd file */
+            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 ".." 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)
+                {
+                    fprintf (stderr, "Error loading %s\n", filename);
+                    return -1;
+                }
+
+                #ifndef EPICS_3_13
+                /* when dbd is loaded call register function */
+                if (asprintf(&symbolname, "%s_registerRecordDeviceDriver", module) < 0)
+                    return errno;
+
+                printf ("Calling function %s\n", symbolname);
+                #ifdef vxWorks
+                {
+                    FUNCPTR f = (FUNCPTR) getAddress(NULL, symbolname);
+                    if (f)
+                        f(pdbbase);
+                    else
+                        fprintf (stderr, "require: can't find %s function\n", symbolname);
+                }        
+                #else /* !vxWorks */
+                iocshCmd(symbolname);
+                #endif /* !vxWorks */
+                free(symbolname);
+                #endif /* !EPICS_3_13 */
+            }
+            else
+            {
+                /* no dbd file, but that might be OK */
+                printf("%s has no dbd file\n", module);
+            }
+        }
+        /* register module with path */
+        filename[releasediroffs] = 0;
+        registerModule(module, found, filename);
+    }
+
+    status = 0;       
+
+    if (requireDebug)
+        printf("require: looking for template directory\n");
+    /* filename = "<dirname>/[dirlen]<module>/<version>/R<epicsRelease>/[releasediroffs]..." */
+    if (!((TRY_FILE(releasediroffs, TEMPLATEDIR) ||
+        TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR TEMPLATEDIR)) && setupDbPath(module, filename) == 0))
+    {
+        /* if no template directory found, restore TEMPLATES to initial value */
+        char *t;
+        t = getenv("TEMPLATES");
+        if (globalTemplates && (!t || strcmp(globalTemplates, t) != 0))
+            putenvprintf("TEMPLATES=%s", globalTemplates);
+    }
+
+    if (loaded && args == NULL) return 0; /* no need to execute startup script twice if not with new arguments */
+
+    /* load startup script */
+    if (requireDebug)
+        printf("require: looking for startup script\n");
+    /* filename = "<dirname>/[dirlen]<module>/<version>/R<epicsRelease>/[releasediroffs]db" */
+    if (TRY_FILE(releasediroffs, "%s-%s.cmd", targetArch, epicsRelease) ||
+        TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "%s-%s.cmd", targetArch, epicsRelease) ||
+        TRY_FILE(releasediroffs, "%s-%s.cmd", targetArch, epicsBasetype) ||
+        TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "%s-%s.cmd", targetArch, epicsBasetype) ||
+        TRY_FILE(releasediroffs, "%s-%s.cmd", osClass, epicsRelease) ||
+        TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "%s-%s.cmd", osClass, epicsRelease) ||
+        TRY_FILE(releasediroffs, "%s-%s.cmd", osClass, epicsBasetype) ||
+        TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "%s-%s.cmd", osClass, epicsBasetype) ||
+        TRY_FILE(releasediroffs, "startup-%s.cmd", epicsRelease) ||
+        TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "startup-%s.cmd", epicsRelease) ||
+        TRY_FILE(releasediroffs, "startup-%s.cmd", epicsBasetype) ||
+        TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "startup-%s.cmd", epicsBasetype) ||
+        TRY_FILE(releasediroffs, "%s.cmd", targetArch) ||
+        TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "%s.cmd", targetArch) ||
+        TRY_FILE(releasediroffs, "%s.cmd", osClass) ||
+        TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "%s.cmd", osClass) ||
+        TRY_FILE(releasediroffs, "startup.cmd") ||
+        TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR "startup.cmd")
+        )
+    {
+        if (args)
+            printf("Executing %s with \"%s\"\n", filename, args);
+        else if (interruptAccept)
+        {
+            printf("Not executing %s after iocInit\n", filename);
+            return 0;
+        }
+        else
+            printf("Executing %s\n", filename);
+        if (runScript(filename, args) != 0)
+            fprintf (stderr, "Error executing %s\n", filename);
+        else
+            printf("Done with %s\n", filename);
+    }
+    return status;
+}
+
+#ifndef EPICS_3_13
+static const iocshFuncDef requireDef = {
+    "require", 3, (const iocshArg *[]) {
+        &(iocshArg) { "module", iocshArgString },
+        &(iocshArg) { "[version]", iocshArgString },
+        &(iocshArg) { "[substitutions]", iocshArgString },
+}};
+    
+static void requireFunc (const iocshArgBuf *args)
+{
+    require(args[0].sval, args[1].sval, args[2].sval);
+}
+
+static const iocshFuncDef libversionShowDef = {
+    "libversionShow", 1, (const iocshArg *[]) {
+        &(iocshArg) { "outputfile", iocshArgString },
+}};
+
+static void libversionShowFunc (const iocshArgBuf *args)
+{
+    libversionShow(args[0].sval);
+}
+
+static const iocshFuncDef ldDef = {
+    "ld", 1, (const iocshArg *[]) {
+        &(iocshArg) { "library", iocshArgString },
+}};
+
+static void ldFunc (const iocshArgBuf *args)
+{
+    loadlib(args[0].sval);
+}
+
+static const iocshFuncDef pathAddDef = {
+    "pathAdd", 2, (const iocshArg *[]) {
+        &(iocshArg) { "ENV_VARIABLE", iocshArgString },
+        &(iocshArg) { "directory", iocshArgString },
+}};
+
+static void pathAddFunc (const iocshArgBuf *args)
+{
+    pathAdd(args[0].sval, args[1].sval);
+}
+
+static void requireRegister(void)
+{
+    static int firstTime = 1;
+    if (firstTime) {
+        firstTime = 0;
+        iocshRegister (&requireDef, requireFunc);
+        iocshRegister (&libversionShowDef, libversionShowFunc);
+        iocshRegister (&ldDef, ldFunc);
+        iocshRegister (&pathAddDef, pathAddFunc);
+        registerExternalModules();
+    }
+}
+
+epicsExportRegistrar(requireRegister);
+epicsExportAddress(int, requireDebug);
+#endif