--- /dev/null
+#include "squid.h"
+
+/* The original code has this constant ./configure-able.
+ * The "#else" branches use raw dlopen interface and have not been tested.
+ * We can remove that code if we are going to rely on libtool's ltdl in
+ * all environments. */
+#define XSTD_USE_LIBLTDL 1
+
+#if XSTD_USE_LIBLTDL
+ #include "libLtdl/ltdl.h" /* generated file */
+#else
+ #include <dlfcn.h>
+#endif
+
+#include "TextException.h"
+#include "LoadableModule.h"
+
+// Note: We must use preprocessor instead of C ifs because if dlopen()
+// is seen by the static linker, the linker will complain.
+
+LoadableModule::LoadableModule(const String &aName): theName(aName), theHandle(0) {
+# if XSTD_USE_LIBLTDL
+ // Initialise preloaded symbol lookup table.
+ LTDL_SET_PRELOADED_SYMBOLS();
+ if (lt_dlinit() != 0)
+ throw TexcHere("internal error: cannot initialize libtool module loader");
+# endif
+}
+
+LoadableModule::~LoadableModule() {
+ if (loaded())
+ unload();
+# if XSTD_USE_LIBLTDL
+ assert(lt_dlexit() == 0); // XXX: replace with a warning
+# endif
+}
+
+bool LoadableModule::loaded() const {
+ return theHandle != 0;
+}
+
+void LoadableModule::load(int mode) {
+ if (loaded())
+ throw TexcHere("internal error: reusing LoadableModule object");
+
+ theHandle = openModule(mode);
+
+ if (!loaded())
+ throw TexcHere(errorMsg());
+}
+
+void LoadableModule::unload() {
+ if (!loaded())
+ throw TexcHere("internal error: unloading not loaded module");
+
+ if (!closeModule())
+ throw TexcHere(errorMsg());
+
+ theHandle = 0;
+}
+
+void *LoadableModule::openModule(int mode) {
+# if XSTD_USE_LIBLTDL
+ return lt_dlopen(theName.buf());
+# else
+ return dlopen(theName.c_str(),
+ mode == lmNow ? RTLD_NOW : RTLD_LAZY);
+# endif
+}
+
+bool LoadableModule::closeModule() {
+# if XSTD_USE_LIBLTDL
+ // we cast to avoid including ltdl.h in LoadableModule.h
+ return lt_dlclose(static_cast<lt_dlhandle>(theHandle)) == 0;
+# else
+ return dlclose(theHandle) == 0;
+# endif
+}
+
+const char *LoadableModule::errorMsg() {
+# if XSTD_USE_LIBLTDL
+ return lt_dlerror();
+# else
+ return dlerror();
+# endif
+}
--- /dev/null
+#ifndef SQUID_LOADABLE_MODULE_H
+#define SQUID_LOADABLE_MODULE_H
+
+#include "SquidString.h"
+
+// wrapper for dlopen(3), libltdl, and friends
+class LoadableModule {
+public:
+ enum LoadMode { lmNow, lmLazy };
+
+public:
+ LoadableModule(const String &aName);
+ ~LoadableModule(); // unloads if loaded
+
+ bool loaded() const;
+ const String &name() const { return theName; }
+ const String &error() const { return theError; }
+
+ void load(int mode = lmNow); // throws Texc
+ void unload(); // throws Texc
+
+protected:
+ String theName;
+ String theError;
+ void *theHandle;
+
+private:
+ void *openModule(int mode);
+ bool closeModule();
+ const char *errorMsg();
+};
+
+#endif
--- /dev/null
+#include "squid.h"
+#include "wordlist.h"
+#include "LoadableModule.h"
+#include "LoadableModules.h"
+
+static void
+LoadModule(const char *fname)
+{
+ debugs(1, 1, "loading Squid module from '" << fname << "'");
+
+ LoadableModule *m = new LoadableModule(fname);
+ m->load();
+ debugs(1, 2, "loaded Squid module from '" << fname << "'");
+
+ //TODO: TheModules.push_back(m);
+}
+
+void
+LoadableModulesConfigure(const wordlist *names)
+{
+ int count = 0;
+ for (const wordlist *i = names; i; i = i->next, ++count)
+ LoadModule(i->key);
+ debugs(1, 1, "loaded " << count << " Squid modules");
+}
--- /dev/null
+#ifndef SQUID_LOADABLE_MODULES_H
+#define SQUID_LOADABLE_MODULES_H
+
+// TODO: add reporting for cachemgr
+// TODO: add reconfiguration support
+
+class wordlist;
+extern void LoadableModulesConfigure(const wordlist *names);
+
+#endif /* SQUID_LOADABLE_MODULES_H */
SNMP_SOURCE =
endif
+LOADABLE_MODULES_SOURCES = \
+ LoadableModule.h \
+ LoadableModule.cc \
+ LoadableModules.h \
+ LoadableModules.cc
+
TESTS=$(check_PROGRAMS)
check_PROGRAMS=
noinst_LTLIBRARIES = libsquid.la libauth.la
INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)/lib/libTrie/include
+INCLUDES += -I$(top_builddir)/lib
INCLUDES += @SQUID_CPPUNIT_INC@
EXTRA_PROGRAMS = \
$(UNLINKDSOURCE) \
$(SSL_ALL_SOURCE) \
$(WIN32_ALL_SOURCE) \
+ $(LOADABLE_MODULES_SOURCES) \
DiskIO/DiskThreads/aiops.cc \
DiskIO/DiskThreads/aiops_win32.cc
${ADAPTATION_LIBS}
if USE_LOADABLE_MODULES
+squid_SOURCES += $(LOADABLE_MODULES_SOURCES)
squid_LDADD += \
@LIBLTDL@
squid_LDFLAGS = \
icap_access class_1 allow all
DOC_END
+COMMENT_START
+ eCAP OPTIONS
+ -----------------------------------------------------------------------------
+COMMENT_END
+
+NAME: loadable_modules
+TYPE: wordlist
+IFDEF: USE_LOADABLE_MODULES
+LOC: Config.loadable_module_names
+DEFAULT: none
+DOC_START
+ Instructs Squid to load the specified dynamic module(s) or activate
+ preloaded module(s).
+Example:
+loadable_modules @DEFAULT_PREFIX@/lib/MinimalAdapter.so
+DOC_END
+
COMMENT_START
DNS OPTIONS
-----------------------------------------------------------------------------
#include "MemPool.h"
#include "ICMPSquid.h"
+#if USE_LOADABLE_MODULES
+#include "LoadableModules.h"
+#endif
+
#if ICAP_CLIENT
#include "ICAP/ICAPConfig.h"
#endif
memCheckInit();
+#if USE_LOADABLE_MODULES
+ LoadableModulesConfigure(Config.loadable_module_names);
+#endif
+
#if ICAP_CLIENT
TheICAPConfig.finalize(); // must be after we load modules
#endif
#endif
char *accept_filter;
+
+#if USE_LOADABLE_MODULES
+ wordlist *loadable_module_names;
+#endif
};
SQUIDCEXTERN SquidConfig Config;