diff --git a/CHANGELOG.md b/CHANGELOG.md
index 12ddf28ba5f38833a7e702420acdb2df373241be..d1abc7a824a73bf426ad2ac534d9167df597d266 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,11 +13,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 * Fixed an issue where .template and .substitutions files with the same name would build incorrectly
 * Fixed an issue where filenames with spaces in them that had been modified
 in the wrapper would cause all of the module `make` commands to fail.
+* Removed a number of memory leaks found by valgrind
 
 ### Other changes
 
 * Replaced `tclx` script to expand .dbd files with a python script
 * Removed `hdrs` target. Note that this has been entirely replaced by the automatic db expansion.
+* Removed ability to pass `args` to require (which have not been used within e3)
+* Removed `require module,ifexists` option
+* Stop require from looking in legacy locations for various files
 
 ## [5.0.0]
 
diff --git a/require-ess/src/require.c b/require-ess/src/require.c
index 5b09b5289957a968b2f5ea3ca5267988db366432..933e061ff5c445e82e048978b5b3524e66f46879 100644
--- a/require-ess/src/require.c
+++ b/require-ess/src/require.c
@@ -15,6 +15,9 @@
 
 #include <ctype.h>
 #include <dbAccess.h>
+#include <epicsExit.h>
+#include <epicsExport.h>
+#include <epicsStdio.h>
 #include <epicsVersion.h>
 #include <errno.h>
 #include <initHooks.h>
@@ -25,12 +28,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
-/* This prototype is missing in older EPICS versions */
-DBCORE_API int epicsStdCall iocshCmd(const char *cmd);
-#include <epicsExit.h>
-#include <epicsExport.h>
-#include <epicsStdio.h>
-#include <osiFileName.h>
 
 #include "version.h"
 
@@ -101,6 +98,9 @@ int requireDebug;
 #error OS_CLASS not defined: Try to compile with USR_CFLAGS += -DOS_CLASS='"${OS_CLASS}"'
 #endif  // OS_CLASS
 
+#define debug(...) \
+  if (requireDebug) printf(__VA_ARGS__)
+
 const char osClass[] = OS_CLASS;
 
 /* loadlib (library)
@@ -118,7 +118,11 @@ void set_require_env() {
   sprintf(epicsRelease, "%s.%s.%s", epics_version_major, epics_version_middle,
           epics_version_minor);
   targetArch = getenv("EPICS_HOST_ARCH");
-  return;
+
+  putenvprintf("T_A=%s", targetArch);
+  putenvprintf("EPICS_HOST_ARCH=%s", targetArch);
+  putenvprintf("EPICS_RELEASE=%s", epicsRelease);
+  putenvprintf("OS_CLASS=%s", osClass);
 }
 
 static HMODULE loadlib(const char *libname) {
@@ -147,8 +151,8 @@ static unsigned long maxModuleNameLength = 0;
 
 int putenvprintf(const char *format, ...) {
   va_list ap;
-  char *var;
-  char *val;
+  char *var = NULL;
+  char *val = NULL;
   int status = 0;
 
   if (!format) return -1;
@@ -159,7 +163,7 @@ int putenvprintf(const char *format, ...) {
   }
   va_end(ap);
 
-  if (requireDebug) printf("require: putenv(\"%s\")\n", var);
+  debug("require: putenv(\"%s\")\n", var);
 
   val = strchr(var, '=');
   if (!val) {
@@ -177,7 +181,7 @@ int putenvprintf(const char *format, ...) {
 }
 
 void pathAdd(const char *varname, const char *dirname) {
-  char *old_path;
+  char *old_path = NULL;
 
   if (!varname || !dirname) {
     fprintf(stderr, "usage: pathAdd \"ENVIRONMENT_VARIABLE\",\"directory\"\n");
@@ -194,7 +198,7 @@ void pathAdd(const char *varname, const char *dirname) {
     putenvprintf("%s=." OSI_PATH_LIST_SEPARATOR "%s", varname, dirname);
   } else {
     size_t len = strlen(dirname);
-    char *p;
+    char *p = NULL;
 
     /* skip over "." at the beginning */
     if (old_path[0] == '.' && old_path[1] == OSI_PATH_LIST_SEPARATOR[0])
@@ -209,8 +213,7 @@ void pathAdd(const char *varname, const char *dirname) {
         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);
+        debug("require: modified %s=%s\n", varname, old_path);
         break;
       }
       p += len;
@@ -223,11 +226,11 @@ void pathAdd(const char *varname, const char *dirname) {
 }
 
 char *realpathSeparator(const char *location) {
-  size_t ll;
+  size_t ll = 0;
   char *buffer = malloc(PATH_MAX + strlen(OSI_PATH_SEPARATOR));
   buffer = realpath(location, buffer);
   if (!buffer) {
-    if (requireDebug) printf("require: realpath(%s) failed\n", location);
+    debug("require: realpath(%s) failed\n", location);
     return NULL;
   }
   ll = strlen(buffer);
@@ -244,11 +247,11 @@ static int setupDbPath(const char *module, const char *dbdir) {
   char *absdir =
       realpathSeparator(dbdir); /* so we can change directory later safely */
   if (absdir == NULL) {
-    if (requireDebug) printf("require: cannot resolve %s\n", dbdir);
+    debug("require: cannot resolve %s\n", dbdir);
     return -1;
   }
 
-  if (requireDebug) printf("require: found template directory %s\n", absdir);
+  debug("require: found template directory %s\n", absdir);
 
   /* set up db search path environment variables
     <module>_DB             template path of <module>
@@ -269,7 +272,7 @@ static int setupDbPath(const char *module, const char *dbdir) {
 
 static int getRecordHandle(const char *namepart, short type, long minsize,
                            DBADDR *paddr) {
-  char recordname[PVNAME_STRINGSZ] = "";
+  char recordname[PVNAME_STRINGSZ] = {0};
   long dummy = 0L;
   long offset = 0L;
 
@@ -319,13 +322,13 @@ must wait until initHooks is loaded before we can register the hook.
 static void fillModuleListRecord(initHookState state) {
   /* MODULES record exists and has allocated memory */
   if (state == initHookAfterFinishDevSup) {
-    DBADDR modules, versions, modver;
-    int have_modules, have_versions, have_modver;
-    moduleitem *m;
+    DBADDR modules = {0}, versions = {0}, modver = {0};
+    int have_modules = 0, have_versions = 0, have_modver = 0;
+    moduleitem *m = NULL;
     int i = 0;
     long c = 0;
 
-    if (requireDebug) printf("require: fillModuleListRecord\n");
+    debug("require: fillModuleListRecord\n");
 
     have_modules =
         (getRecordHandle(":Modules", DBF_STRING, moduleCount, &modules) == 0);
@@ -339,23 +342,20 @@ static void fillModuleListRecord(initHookState state) {
     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);
+        debug("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);
+        debug("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);
+        debug("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);
       }
@@ -368,24 +368,16 @@ static void fillModuleListRecord(initHookState state) {
 
 void registerModule(const char *module, const char *version,
                     const char *location) {
-  moduleitem *m, **pm;
+  moduleitem *m = NULL, **pm = NULL;
   size_t lm = strlen(module) + 1;
   size_t lv = (version ? strlen(version) : 0) + 1;
   size_t ll = 1;
   char *absLocation = NULL;
   char *absLocationRequire = NULL;
   char *argstring = NULL;
-  const char *mylocation;
-  static int firstTime = 1;
-
-  if (requireDebug)
-    printf("require: registerModule(%s,%s,%s)\n", module, version, location);
+  const char *mylocation = NULL;
 
-  if (firstTime) {
-    initHookRegister(fillModuleListRecord);
-    if (requireDebug) printf("require: initHookRegister\n");
-    firstTime = 0;
-  }
+  debug("require: registerModule(%s,%s,%s)\n", module, version, location);
 
   if (!version) version = "";
 
@@ -433,11 +425,11 @@ void registerModule(const char *module, const char *version,
     return;
   /*
      Require DB has the following four PVs:
-     - $(REQUIRE_IOC):$(MODULE)_VER
-     - $(REQUIRE_IOC):MOD_VER
-     - $(REQUIRE_IOC):VERSIONS
-     - $(REQUIRE_IOC):MODULES
-     We reserved 30 chars for :$(MODULE)_VER, so MODULE has the maximum 24
+     - $(REQUIRE_IOC):$(MODULE)Version
+     - $(REQUIRE_IOC):ModuleVersions
+     - $(REQUIRE_IOC):Versions
+     - $(REQUIRE_IOC):Modules
+     We reserved 30 chars for :$(MODULE)Version, so MODULE has the maximum 24
      chars. And we've reserved for 30 chars for $(REQUIRE_IOC). So, the whole PV
      and record name in moduleversion.template has 59 + 1.
    */
@@ -461,13 +453,13 @@ 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;
+  void *handle = NULL;
   char *location = NULL;
-  char *p;
-  char *version;
-  char *symname;
+  char *p = NULL;
+  char *version = NULL;
+  char *symname = NULL;
   /* get space for library path + "LibRelease" */
-  char name[PATH_MAX + 11];
+  char name[PATH_MAX + 11] = {0};
 
   (void)data; /* unused */
   if (size < sizeof(struct dl_phdr_info))
@@ -517,24 +509,8 @@ static void registerExternalModules() {
 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;
+  moduleitem *m = NULL;
 
   for (m = loadedModules; m; m = m->next) {
     if (strcmp(m->content, libname) == 0) {
@@ -545,8 +521,8 @@ const char *getLibVersion(const char *libname) {
 }
 
 const char *getLibLocation(const char *libname) {
-  moduleitem *m;
-  char *v;
+  moduleitem *m = NULL;
+  char *v = NULL;
 
   for (m = loadedModules; m; m = m->next) {
     if (strcmp(m->content, libname) == 0) {
@@ -558,7 +534,7 @@ const char *getLibLocation(const char *libname) {
 }
 
 int isModuleLoaded(const char *libname) {
-  moduleitem *m;
+  moduleitem *m = NULL;
 
   for (m = loadedModules; m; m = m->next) {
     if (strcmp(m->content, libname) == 0) return TRUE;
@@ -567,8 +543,8 @@ int isModuleLoaded(const char *libname) {
 }
 
 int libversionShow(const char *outfile) {
-  moduleitem *m;
-  size_t lm, lv;
+  moduleitem *m = NULL;
+  size_t lm = 0, lv = 0;
 
   FILE *out = epicsGetStdout();
 
@@ -597,9 +573,6 @@ int libversionShow(const char *outfile) {
 #define MATCH 1
 #define HIGHER 3
 
-#define debug(...) \
-  if (requireDebug) printf(__VA_ARGS__)
-
 static int compareDigit(int found, int requested, const char *name) {
   debug("require: compareDigit: found %d, requested %d for digit %s\n", found,
         requested, name);
@@ -616,7 +589,7 @@ static int compareDigit(int found, int requested, const char *name) {
 }
 
 static int compareNumericVersion(semver_t *sv_found, semver_t *sv_request) {
-  int match;
+  int match = 0;
 
   match = compareDigit(sv_found->major, sv_request->major, "major");
   if (match != MATCH) {
@@ -634,8 +607,8 @@ static int compareNumericVersion(semver_t *sv_found, semver_t *sv_request) {
  */
 static int compareVersions(const char *found, const char *request,
                            int already_matched) {
-  semver_t *sv_found, *sv_request;
-  int match;
+  semver_t *sv_found = NULL, *sv_request = NULL;
+  int match = 0;
 
   debug("require: compareVersions(found=%s, request=%s)\n", found,
         request ? request : "");
@@ -723,32 +696,15 @@ 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();
+static int require_priv(const char *module, const char *version);
 
-    putenvprintf("T_A=%s", targetArch);
-    putenvprintf("EPICS_HOST_ARCH=%s", targetArch);
-    putenvprintf("EPICS_RELEASE=%s", epicsRelease);
-    putenvprintf("OS_CLASS=%s", osClass);
-  }
+int require(const char *module, const char *version) {
+  int status = 0;
 
   if (module == NULL) {
-    printf(
-        "Usage: require \"<module>\" [, \"<version>\" | \"ifexists\"] [, "
-        "\"<args>\"]\n");
+    printf("Usage: require \"<module>\" [, \"<version>\" ]\n");
     printf("Loads " PREFIX "<module>" INFIX EXT " and <libname>.dbd\n");
     printf("And calls <module>_registerRecordDeviceDriver\n");
-    printf("If available, runs startup script snippet (only before iocInit)\n");
     return -1;
   }
 
@@ -757,42 +713,14 @@ int require(const char *module, const char *version, const char *args) {
     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");
+    debug("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);
+  status = require_priv(module, version);
 
   if (status == 0) return 0;
   if (status != -1) perror("require");
@@ -805,58 +733,62 @@ int require(const char *module, const char *version, const char *args) {
 }
 
 static off_t fileSize(const char *filename) {
-  struct stat filestat;
+  struct stat filestat = {0};
   if (stat(filename, &filestat) != 0) {
-    if (requireDebug) printf("require: %s does not exist\n", filename);
+    debug("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);
+      debug("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);
+      debug("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);
+      debug("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);
+      debug("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);
+      debug("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);
+      debug("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);
+      debug("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)
+#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))
 
 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);
+  FILE *depfile = NULL;
+  char buffer[40] = {0};
+  char *end = NULL;      /* end of string */
+  char *rmodule = NULL;  /* required module */
+  char *rversion = NULL; /* required version */
+
+  debug("require: parsing dependency file %s\n", depfilename);
   depfile = fopen(depfilename, "r");
   while (fgets(buffer, sizeof(buffer) - 1, depfile)) {
     rmodule = buffer;
@@ -882,7 +814,7 @@ static int handleDependencies(const char *module, char *depfilename) {
       *end = 0;
     }
     printf("Module %s depends on %s %s\n", module, rmodule, rversion);
-    if (require(rmodule, rversion, NULL) != 0) {
+    if (require(rmodule, rversion) != 0) {
       fclose(depfile);
       return -1;
     }
@@ -891,68 +823,257 @@ static int handleDependencies(const char *module, char *depfilename) {
   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;
-  int returnvalue = 0;
-  const char *loaded = NULL;
+/*
+ * Fetches the correct module version based on the requested version by
+ * searching through EPICS_DRIVER_PATH until it finds a matching version.
+ *
+ * Sets <filename> to be the path the the underlying module.
+ */
+static int fetch_module_version(char *filename, size_t max_file_len,
+                                const char *module, const char *version) {
+  const char *dirname = NULL;
+  const char *driverpath = NULL;
+  const char *end = 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[PATH_MAX];
 
   int someVersionFound = 0;
   int someArchFound = 0;
 
-  static char *globalTemplates = NULL;
+  driverpath = getenv("EPICS_DRIVER_PATH");
+  if (driverpath == NULL) driverpath = ".";
+  debug("require: searchpath=%s\n", driverpath);
+
+  for (dirname = driverpath; dirname != NULL; dirname = end) {
+    /* get one directory from driverpath */
+    int dirlen = 0;
+    int modulediroffs = 0;
+    DIR_HANDLE dir = NULL;
+    DIR_ENTRY direntry = NULL;
+
+    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 */
+
+    debug("require: trying %.*s\n", dirlen, dirname);
+
+    snprintf(filename, max_file_len,
+             "%.*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) {
+      debug("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. */
+        debug("require: checking version %s against required %s\n",
+              currentFilename, version ? version : "");
+
+        switch (compareVersions(currentFilename, version, FALSE)) {
+          case MATCH: /* all given numbers match. */
+          {
+            someArchFound = 1;
+
+            debug("require: %s %s may match %s\n", module, currentFilename,
+                  version ? 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 */
+
+            /* Step 1 : library file location */
+            /* filename = "<dirname>/[dirlen]<module>/[modulediroffs]" */
+            if (!TRY_FILE(modulediroffs,
+                          "%s" OSI_PATH_SEPARATOR LIBDIR
+                          "%s" OSI_PATH_SEPARATOR,
+                          currentFilename, targetArch)) {
+              /* filename =
+               * "<dirname>/[dirlen]<module>/[modulediroffs]<version>/lib/<targetArch>/"
+               */
+              debug("require: %s %s has no support for %s %s\n", module,
+                    currentFilename, epicsRelease, targetArch);
+              continue;
+            }
 
-  if (requireDebug)
-    printf("require: module=\"%s\" version=\"%s\" args=\"%s\"\n", module,
-           version, args);
+            /* Is it higher than the one we found before? */
+            if (found)
+              debug(
+                  "require: %s %s support for %s %s found, compare against "
+                  "previously found %s\n",
+                  module, currentFilename, epicsRelease, targetArch, found);
+            if (!found ||
+                compareVersions(currentFilename, found, TRUE) == HIGHER) {
+              debug("require: %s %s looks promising\n", module,
+                    currentFilename);
+              break;
+            }
+            debug("require: version %s is lower than %s \n", currentFilename,
+                  found);
+            continue;
+          }
+          default: {
+            debug("require: %s %s does not match %s\n", module, currentFilename,
+                  version);
+            continue;
+          }
+        }
+        /* we have found something */
+        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 */
+      }
+      END_DIR_LOOP
+    }
+    /* filename = "<dirname>/[dirlen]..." */
+    if (!found)
+      debug("require: no matching version in %.*s\n", dirlen, filename);
+  }
 
-#if defined __GNUC__ && __GNUC__ < 3
-#define TRY_FILE(offs, args...)                                \
-  (snprintf(filename + offs, sizeof(filename) - offs, args) && \
-   fileExists(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 : "");
+    if (founddir) free(founddir);
+    return -1;
+  }
 
-#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))
+  /* founddir = "<dirname>/[dirlen]<module>/<version>" */
+  printf("Module %s version %s found in %s" OSI_PATH_SEPARATOR "\n", module,
+         found, founddir);
 
-#define TRY_NONEMPTY_FILE(offs, ...)                                  \
-  (snprintf(filename + offs, sizeof(filename) - offs, __VA_ARGS__) && \
-   fileNotEmpty(filename))
-#endif
+  snprintf(filename, max_file_len, "%s" OSI_PATH_SEPARATOR, founddir);
+  free(founddir);
+  return 0;
+}
 
-  driverpath = getenv("EPICS_DRIVER_PATH");
+/*
+ * Loads the shared library if available.
+ *
+ * Returns the actual version string for the module, and NULL if there is a
+ * mismatch.
+ */
+static const char *compare_module_version(char *filename, const char *module,
+                                          const char *version, int libdiroffs) {
+  HMODULE libhandle = NULL;
+  char *symbolname = NULL;
+  const char *found = NULL;
+  /* filename =
+     "<dirname>/[dirlen]<module>/<version>/[releasediroffs]/lib/<targetArch>/[libdiroffs]/PREFIX<module>INFIX(EXT)?"
+   */
+  if (!(TRY_FILE(libdiroffs, PREFIX "%s" INFIX EXT, module))) {
+    printf("Module %s has no library\n", module);
+    found = version;
+  } else {
+    printf("Loading library %s\n", filename);
+    if ((libhandle = loadlib(filename)) == NULL) {
+      return NULL;
+    }
+
+    /* now check what version we really got (with compiled-in version number)
+     */
+    if (asprintf(&symbolname, "_%sLibRelease", module) < 0) {
+      return NULL;
+    }
+
+    found = (const char *)getAddress(libhandle, symbolname);
+    free(symbolname);
+    printf("Loaded %s version %s\n", module, found);
+
+    /* check what we got */
+    debug("require: compare requested version %s with loaded version %s\n",
+          version, found);
+    if (compareVersions(found, version, FALSE) == MISMATCH) {
+      fprintf(stderr, "Requested %s version %s not available, found only %s.\n",
+              module, version, found);
+      return NULL;
+    }
+  }
+  return found;
+}
+
+/*
+ * Loads the module .dbd file and runs registerRecordDeviceDriver.
+ */
+static int load_module_data(char *filename, const char *module,
+                            const char *version, int releasediroffs) {
+  int returnvalue = NULL;
+  char *symbolname = NULL;
+
+  /* load dbd file */
+  if (TRY_NONEMPTY_FILE(releasediroffs, "dbd" OSI_PATH_SEPARATOR "%s.dbd",
+                        module)) {
+    printf("Loading dbd file %s\n", filename);
+    if (dbLoadDatabase(filename, NULL, NULL) != 0) {
+      fprintf(stderr, "Error loading %s\n", filename);
+      return -1;
+    }
+
+    /* when dbd is loaded call register function */
+    if (asprintf(&symbolname, "%s_registerRecordDeviceDriver", module) < 0) {
+      return -1;
+    }
+
+    printf("Calling function %s\n", symbolname);
+    returnvalue = iocshCmd(symbolname);
+    free(symbolname);
+    if (returnvalue) return -1;
+  } else {
+    /* no dbd file, but that might be OK */
+    printf("%s has no dbd file\n", module);
+  }
+  return 0;
+}
+
+static int require_priv(const char *module, const char *version) {
+  int returnvalue = 0;
+  const char *loaded = NULL;
+  const char *found = NULL;
+  const char *dirname = NULL;
+
+  int dirlen = 0;
+  int releasediroffs = 0;
+  int libdiroffs = 0;
+  char filename[PATH_MAX] = {0};
+
+  static char *globalTemplates = NULL;
   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 = "";
-  }
+  debug("require: module=\"%s\" version=\"%s\"\n", module, version);
 
   /* check already loaded verion */
   loaded = getLibVersion(module);
@@ -971,295 +1092,67 @@ static int require_priv(
     }
     dirname = getLibLocation(module);
     if (dirname[0] == 0) return 0;
-    if (requireDebug) printf("require: library found in %s\n", dirname);
+    debug("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 = 0;
-      int modulediroffs = 0;
-      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 ? version : "");
-
-          switch ((status = compareVersions(currentFilename, version, FALSE))) {
-            case MATCH: /* all given numbers match. */
-            {
-              someArchFound = 1;
-
-              if (requireDebug)
-                printf("require: %s %s may match %s\n", module, currentFilename,
-                       version ? 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 */
-
-              /* Step 1 : library file location */
-              /* filename = "<dirname>/[dirlen]<module>/[modulediroffs]" */
-              if (!TRY_FILE(modulediroffs,
-                            "%s" OSI_PATH_SEPARATOR LIBDIR
-                            "%s" OSI_PATH_SEPARATOR,
-                            currentFilename, targetArch)) {
-                /* filename =
-                 * "<dirname>/[dirlen]<module>/[modulediroffs]<version>/lib/<targetArch>/"
-                 */
-                if (requireDebug)
-                  printf("require: %s %s has no support for %s %s\n", module,
-                         currentFilename, epicsRelease, targetArch);
-                continue;
-              }
-
-              /* 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, TRUE) == 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 */
-          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 */
-        }
-        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;
-          }
+    debug("require: no %s version loaded yet\n", module);
 
-          /* 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"
-               */
-          ) {
-            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 : "");
-      if (founddir) free(founddir);
-      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);
+    /* Step 1: Search for module in driverpath */
+    returnvalue =
+        fetch_module_version(filename, sizeof(filename), module, version);
+    if (returnvalue) goto require_priv_end;
 
-    /* Step 2 : Looking for  Dep file */
-    if (requireDebug) printf("require: looking for dependency file\n");
+    /* Step 2 : Looking for .dep file */
+    debug("require: looking for dependency file\n");
 
-    if (!TRY_FILE(0,
-                  "%s" OSI_PATH_SEPARATOR "%n" LIBDIR "%s" OSI_PATH_SEPARATOR
-                  "%n%s.dep",
-                  founddir, &releasediroffs, targetArch, &libdiroffs, module)) {
+    dirlen = strlen(filename);
+    if (!TRY_FILE(dirlen,
+                  OSI_PATH_SEPARATOR "%n" LIBDIR "%s" OSI_PATH_SEPARATOR
+                                     "%n%s.dep",
+                  &releasediroffs, targetArch, &libdiroffs, module)) {
       /* filename =
-         "<dirname>/[dirlen]<module>/<version>/R<epicsRelease>/[releasediroffs]/lib/<targetArch>/[libdiroffs]/module.dep"
+         "<dirname>/[dirlen]<module>/<version>/[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))) {
-      /* 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"
+       * "<dirname>/[dirlen]<module>/<version>/[releasediroffs]/lib/<targetArch>/[libdiroffs]/module.dep"
        */
-      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, FALSE) == MISMATCH) {
-        fprintf(stderr,
-                "Requested %s version %s not available, found only %s.\n",
-                module, version, found);
+      if (handleDependencies(module, filename) == -1) {
         returnvalue = -1;
-        goto require_priv_error;
+        goto require_priv_end;
       }
+    }
+    releasediroffs += dirlen;
+    libdiroffs += dirlen;
 
-      /* 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);
-          returnvalue = -1;
-          goto require_priv_error;
-        }
-
-        /* when dbd is loaded call register function */
-        if (asprintf(&symbolname, "%s_registerRecordDeviceDriver", module) < 0)
-          return errno;
+    /* Step 3: Ensure that we have loaded the correct version */
+    debug("require: Check that the loaded and requested versions match");
+    found = compare_module_version(filename, module, version, libdiroffs);
+    if (!found) {
+      returnvalue = -1;
+      goto require_priv_end;
+    }
 
-        printf("Calling function %s\n", symbolname);
-        iocshCmd(symbolname);
-        free(symbolname);
-      } else {
-        /* no dbd file, but that might be OK */
-        printf("%s has no dbd file\n", module);
-      }
+    /* Step 4: Load module data */
+    debug("require: Load module data\n");
+    returnvalue = load_module_data(filename, module, version, releasediroffs);
+    if (returnvalue) {
+      goto require_priv_end;
     }
+
     /* register module with path */
     filename[releasediroffs] = 0;
     registerModule(module, found, filename);
   }
 
-  status = 0;
-
-  if (requireDebug) printf("require: looking for template directory\n");
+  debug("require: looking for template directory\n");
   /* filename =
-   * "<dirname>/[dirlen]<module>/<version>/R<epicsRelease>/[releasediroffs]..."
+   * "<dirname>/[dirlen]<module>/<version>/[releasediroffs]..."
    */
-  if (!((TRY_FILE(releasediroffs, TEMPLATEDIR) ||
-         TRY_FILE(releasediroffs, ".." OSI_PATH_SEPARATOR TEMPLATEDIR)) &&
+  if (!(TRY_FILE(releasediroffs, TEMPLATEDIR) &&
         setupDbPath(module, filename) == 0)) {
     /* if no template directory found, restore TEMPLATES to initial value */
     char *t;
@@ -1268,30 +1161,19 @@ static int require_priv(
       putenvprintf("TEMPLATES=%s", globalTemplates);
   }
 
-  if (founddir) free(founddir);
-
-  /* no need to execute startup script twice if not with new arguments */
-  if (loaded && args == NULL) {
-    return 0;
-  }
-
-  return status;
-
-require_priv_error:
-  if (founddir) free(founddir);
+require_priv_end:
   return returnvalue;
 }
 
 static const iocshFuncDef requireDef = {
-    "require", 3,
+    "require", 2,
     (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);
+  require(args[0].sval, args[1].sval);
 }
 
 static const iocshFuncDef libversionShowDef = {
@@ -1331,6 +1213,9 @@ static void requireRegister(void) {
     iocshRegister(&ldDef, ldFunc);
     iocshRegister(&pathAddDef, pathAddFunc);
     registerExternalModules();
+
+    set_require_env();
+    initHookRegister(fillModuleListRecord);
   }
 }
 
diff --git a/require-ess/src/require.h b/require-ess/src/require.h
index f9ba5060f7852d74077d162d0c6c034b67ccd5c6..443c98f52b88bf543b6108c73b9bedce4dc3342d 100644
--- a/require-ess/src/require.h
+++ b/require-ess/src/require.h
@@ -13,10 +13,7 @@ extern "C" {
 #define __attribute__(dummy)
 #endif  // __GNUC__
 
-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);
+int require(const char *libname, const char *version);
 const char *getLibVersion(const char *libname);
 const char *getLibLocation(const char *libname);
 int libversionShow(const char *outfile);