summaryrefslogtreecommitdiffstats
path: root/include/pils
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--include/pils/Makefile.am25
-rw-r--r--include/pils/generic.h118
-rw-r--r--include/pils/interface.h159
-rw-r--r--include/pils/plugin.h.in736
4 files changed, 1038 insertions, 0 deletions
diff --git a/include/pils/Makefile.am b/include/pils/Makefile.am
new file mode 100644
index 0000000..4b6c6a0
--- /dev/null
+++ b/include/pils/Makefile.am
@@ -0,0 +1,25 @@
+#
+# linux-ha: Linux-HA heartbeat code
+#
+# Copyright (C) 2001 Michael Moerz
+# This instance created by Horms
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+MAINTAINERCLEANFILES = Makefile.in
+
+idir=$(includedir)/pils
+
+i_HEADERS = generic.h interface.h plugin.h
diff --git a/include/pils/generic.h b/include/pils/generic.h
new file mode 100644
index 0000000..83bf3e3
--- /dev/null
+++ b/include/pils/generic.h
@@ -0,0 +1,118 @@
+#ifndef PILS_GENERIC_H
+#define PILS_GENERIC_H
+/*
+ * Copyright (C) 2000 Alan Robertson <alanr@unix.sh>
+ * This software licensed under the GNU LGPL.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * Generic interface (implementation) manager
+ *
+ * This manager will manage any number of types of interfaces.
+ *
+ * This means that when any implementations of our client interfaces register
+ * or unregister, it is us that makes their interfaces show up in the outside
+ * world.
+ *
+ * And, of course, we have to do this in a very generic way, since we have
+ * no idea about the client programs or interface types, or anything else.
+ *
+ * We do that by getting a parameter passed to us which tell us the names
+ * of the interface types we want to manage, and the address of a GHashTable
+ * for each type that we put the implementation in when they register
+ * themselves.
+ *
+ * So, each type of interface that we manage gets its own private
+ * GHashTable of the implementations of that type that are currently
+ * registered.
+ *
+ * For example, if we manage communication modules, their exported
+ * interfaces will be registered in a hash table. If we manage
+ * authentication modules, they'll have their (separate) hash table that
+ * their exported interfaces are registered in.
+ *
+ */
+#include <pils/interface.h>
+
+/*
+ * Header defintions for using the generic interface/implementation
+ * manager plugin.
+ */
+
+/*
+ * Notification types for the callback function.
+ */
+typedef enum {
+ PIL_REGISTER, /* Someone has registered an implementation */
+ PIL_UNREGISTER /* Someone has unregistered an implementation */
+}GenericPILCallbackType;
+
+/* A user callback for the generic interface manager */
+typedef int (*GenericPILCallback)
+( GenericPILCallbackType type /* Event type */
+, PILPluginUniv* univ /* pointer to plugin universe */
+, const char * iftype /* Interface type */
+, const char * ifname /* Implementation (interface) name */
+, void * userptr /* Whatever you want it to be ;-) */
+);
+
+/*
+ * Structures to declare the set of interface types we're managing.
+ */
+typedef struct {
+ const char * iftype; /* What type of interface is this? */
+ GHashTable** ifmap; /* Table with implementation info */
+ void* importfuns; /* Functions for interface to import */
+ GenericPILCallback callback; /* Function2call when events occur */
+ void* userptr; /* Passed to Callback function */
+}PILGenericIfMgmtRqst;
+/*
+ * What does this look like in practice?
+ *
+ * GHashTable* authmodules = NULL;
+ * GHashTable* commmodules = NULL;
+ * PILGenericIfMgmtRqst RegisterRequests[] =
+ * {
+ * {"auth", &authmodules, &authimports, NULL, NULL},
+ * {"comm", &commmodules, &commimports, NULL, NULL},
+ * {NULL, NULL, NULL, NULL, NULL}
+ // NULL entry must be here
+ * };
+ *
+ * PILPlugin* PluginUniverse;
+ *
+ * PluginUniverse = NewPILPlugin("/usr/lib/whatever/plugins");
+ *
+ * PILLoadPlugin(PluginUniverse, "InterfaceMgr", "generic", &RegisterRequests);
+ * // N. B.: Passing RegisterRequests as an argument is essential
+ *
+ * Then, when you load an auth module, its exported interface gets added
+ * to "authmodules". When you unload an auth module, it gets removed
+ * from authmodules.
+ *
+ * Then, when you load a comm module, its exported interfaces gets added
+ * to "commodules". When you unload a comm module, its exported
+ * interfaces get removed from "commodules"
+ *
+ * If there are simple changes that would be useful for this generic
+ * plugin manager, then "patches are being accepted" :-)
+ *
+ * On the other hand, If you don't like the way this plugin manager works
+ * in a broader way, you're free to write your own - it's just another
+ * plugin ;-)
+ */
+#endif
diff --git a/include/pils/interface.h b/include/pils/interface.h
new file mode 100644
index 0000000..5a5114e
--- /dev/null
+++ b/include/pils/interface.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2000 Alan Robertson <alanr@unix.sh>
+ * This software licensed under the GNU LGPL.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef PILS_INTERFACE_H
+# define PILS_INTERFACE_H
+# ifndef PILS_PLUGIN_H
+# include <pils/plugin.h>
+# endif
+
+/*****************************************************************************
+ *
+ * The most basic interface type is the "IFManager" interface.
+ * Each interface manager registers and deals with interfaces of a given type.
+ *
+ * Such an interface must be loaded before any plugins of it's type can
+ * be loaded.
+ *
+ * In order to register any plugin of type "foo", we must load a interface of
+ * type "Interface" named "foo". This interface then manages the
+ * registration of all interfaces of type foo.
+ *
+ * To bootstrap, we load a interface of type "Interface" named "Interface"
+ * during the initialization of the plugin system.
+ *
+ * IFManagers will be autoloaded if certain conditions are met...
+ *
+ * If a IFManager is to be autoloaded, there must be one interface manager
+ * per file, and the file must be named according to the type of the
+ * interface it implements, and loaded in the directory named PI_IFMANAGER
+ * ("Interface").
+ *
+ */
+
+
+/*
+ * I'm unsure exactly which of the following structures
+ * are needed to write a interface, or a interface manager.
+ * We'll get that figured out and scope the defintions accordingly...
+ */
+
+/*
+ * PILInterface (AKA struct PILInterface_s) holds the information
+ * we use to track a single interface manager.
+ */
+
+
+struct PILInterface_s {
+ unsigned long MagicNum;
+ PILInterfaceType* interfacetype; /* Parent pointer */
+ char * interfacename; /* malloced interface name */
+ PILInterface* ifmanager; /* plugin managing us */
+ void* exports; /* Exported Functions */
+ /* for this interface */
+ PILInterfaceFun if_close; /* Interface close operation*/
+ void* ud_interface; /* per-interface user data */
+ int refcnt; /* Ref count for plugin */
+ PILPlugin* loadingpi; /* Plugin that loaded us */
+};
+/*
+ * PILInterfaceType (AKA struct PILInterfaceType_s) holds the info
+ * we use to track the set of all interfaces of a single kind.
+ */
+struct PILInterfaceType_s {
+ unsigned long MagicNum;
+ char* typename; /* Our interface type name */
+ GHashTable* interfaces; /* The set of interfaces
+ * of our type. The
+ * "values" are all
+ * PILInterface * objects
+ */
+ void* ud_if_type; /* per-interface-type user
+ data*/
+ PILInterfaceUniv* universe; /* Pointer to parent (up) */
+ PILInterface* ifmgr_ref; /* Pointer to our interface
+ manager */
+};
+
+/*
+ * PILInterfaceUniv (AKA struct PILInterfaceUniv_s) holds the information
+ * for all interfaces of all types. From our point of view this is
+ * our universe ;-)
+ */
+
+struct PILInterfaceUniv_s{
+ unsigned long MagicNum;
+ GHashTable* iftypes; /*
+ * Set of Interface Types
+ * The values are all
+ * PILInterfaceType objects
+ */
+ struct PILPluginUniv_s* piuniv; /* parallel universe of
+ * plugins
+ */
+};
+
+#ifdef ENABLE_PLUGIN_MANAGER_PRIVATE
+/*
+ * From here to the end is specific to interface managers.
+ * This data is only needed by interface managers, and the interface
+ * management system itself.
+ *
+ */
+typedef struct PILInterfaceOps_s PILInterfaceOps;
+
+
+/* Interfaces imported by a IFManager interface */
+struct PILInterfaceImports_s {
+
+ /* Return current reference count */
+ int (*RefCount)(PILInterface * eifinfo);
+
+ /* Incr/Decr reference count */
+ int (*ModRefCount)(PILInterface*eifinfo, int plusminus);
+
+ /* Unregister us as a interface */
+ void (*ForceUnRegister)(PILInterface *eifinfo);
+
+ /* For each client */
+ void (*ForEachClientDel)(PILInterface* manangerif
+ , gboolean(*f)(PILInterface* clientif, void * other)
+ , void* other);
+
+};
+
+/* Interfaces exported by an InterfaceManager interface */
+struct PILInterfaceOps_s{
+/*
+ * These are the interfaces exported by an InterfaceManager to the
+ * interface management infrastructure. These are not imported
+ * by interfaces - only the interface management infrastructure.
+ */
+
+ /* RegisterInterface - register this interface */
+ PIL_rc (*RegisterInterface)(PILInterface* newif
+ , void** imports);
+
+ PIL_rc (*UnRegisterInterface)(PILInterface*ifinfo); /* Unregister IF*/
+ /* And destroy PILInterface object */
+};
+
+#endif /* ENABLE_PLUGIN_MANAGER_PRIVATE */
+#endif /* PILS_INTERFACE_H */
diff --git a/include/pils/plugin.h.in b/include/pils/plugin.h.in
new file mode 100644
index 0000000..cb67d91
--- /dev/null
+++ b/include/pils/plugin.h.in
@@ -0,0 +1,736 @@
+/*
+ * Copyright (C) 2000 Alan Robertson <alanr@unix.sh>
+ * This software licensed under the GNU LGPL.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef PILS_PLUGIN_H
+# define PILS_PLUGIN_H
+# include <ltdl.h>
+# include <glue_config.h>
+
+/* Glib headers generate warnings - so we make them go away */
+
+#define time FOOtime
+#define index FOOindex
+#include <glib.h>
+#undef index
+#undef time
+
+/*****************************************************************************
+ * PILS - Universal Plugin and Interface loading system
+ *****************************************************************************
+ *
+ * An Overview of PILS...
+ *
+ * PILS is fairly general and reasonably interesting plugin loading system.
+ * We manage both plugins and their interfaces
+ *
+ * This plugin / interface management system is quite general, and should be
+ * directly usable by basically any project on any platform on which it runs
+ * - which should be many, since everything is build with automake
+ * and libtool.
+ *
+ * Some terminology...
+ *
+ * There are two basic kinds of objects we deal with here:
+ *
+ * Plugins: dynamically loaded chunks of code which implement one or more
+ * interfaces. The system treats all plugins as the same.
+ * In UNIX, these are dynamically loaded ".so" files.
+ *
+ * Interface: A set of functions which implement a particular capability
+ * (or interface)
+ * Generally interfaces are registered as part of a plugin.
+ * The system treats all interfaces of the same type the same.
+ * It is common to have exactly one interface inside of each plugin.
+ * In this case, the interface name should match the plugin name.
+ *
+ * Each interface implementation exports certain functions for its clients
+ * to use. We refer to these those "Ops". Every interface of the same type
+ * "imports" the same interfaces from its interface manager,
+ * and exports the same "Ops".
+ *
+ * Each interface implementation is provided certain interfaces which it
+ * imports when it from its interface manager when it is registered.
+ * We refer to these as "Imports". Every interface of a given type
+ * imports the same interfaces.
+ *
+ * The story with plugins is a little different...
+ *
+ * Every plugin exports a certain set of interfaces, regardless of what type
+ * of interfaces is implemented by it. These are described in the
+ * PILPluginOps structure.
+ *
+ * Every plugin imports a certain set of interfaces, regardless of what type
+ * of interfaces it may implement. These are described by the
+ * PILPluginImports structure.
+ *
+ * In the function parameters below, the following notation will
+ * sometimes appear:
+ *
+ * (OP) == Output Parameter - a parameter which is modified by the
+ * function being called
+ *
+ *
+ *****************************************************************************
+ *
+ * The basic structures we maintain about plugins are as follows:
+ *
+ * PILPlugin The data which represents a plugin.
+ * PILPluginType The data common to all plugins of a given type
+ * PILPluginUniv The set of all plugin types in the Universe
+ * (well... at least *this* universe)
+ *
+ * The basic structures we maintain about interfaces are as follows:
+ * PILInterface The data which represents a interface
+ * PILInterfaceType The data which is common to all
+ * interfaces of a given type
+ * PILPluginUniv The set of all interface types in the Universe
+ * (well... at least *this* universe)
+ *
+ * Regarding "Universe"s. It is our intent that a given program can deal
+ * with plugins in more than one universe. This might occur if you have two
+ * independent libraries each of which uses the plugin loading environment
+ * to manage their own independent interface components. There should be
+ * no restriction in creating a program which uses both of these libraries.
+ * At least that's what we hope ;-)
+ *
+ *
+ ***************************************************************************
+ * SOME MORE DETAILS ABOUT PLUGINS...
+ ***************************************************************************
+ *
+ * Going back to more detailed data structures about plugins...
+ *
+ * PILPluginImports The set of standard functions all plugins
+ * import.
+ * This includes:
+ * register_plugin()
+ * unregister_plugin()
+ * register_interface()
+ * unregister_interface()
+ * load_plugin()
+ * log() Preferred logging function
+ *
+ * PILPluginOps The set of standard operations all plugins
+ * export.
+ * This includes:
+ * pluginversion()
+ * pluginname()
+ * getdebuglevel()
+ * setdebuglevel()
+ * close() Prepare for unloading...
+ *
+ * Although we treat plugins pretty much the same, they are still
+ * categorized into "types" - one type per directory. These types
+ * generally correspond to interface types.
+ *
+ * One can only cause a plugin to be loaded - not a interface. But it is
+ * common to assume that loading a plugin named foo of type bar will
+ * cause a interface named foo of type bar to be registered. If one
+ * wants to implement automatic plugin loading in a given interface type,
+ * this assumption is necessary.
+ *
+ * The general way this works is...
+ *
+ * - A request is made to load a particular plugin of a particular type.
+ *
+ * - The plugin is loaded from the appropriate directory for plugins
+ * of that type.
+ *
+ * - The ml_plugin_init() function is called once when the plugin is
+ * loaded.
+ *
+ * The ml_plugin_init() function is passed a vector of functions which
+ * point to functions it can call to register itself, etc.
+ * (it's of type PILPluginImports)
+ *
+ * The ml_plugin_init function then uses this set of imported functions
+ * to register itself and its interfaces.
+ *
+ * The mechanism of registering a interface is largely the same for
+ * every interface. However, the semantics of registering a interfaces
+ * is determined by the interface manager for the particular type of
+ * interface being discussed.
+ *
+ ***************************************************************************
+ * SOME MORE DETAILS ABOUT PLUGINS...
+ ***************************************************************************
+ *
+ * There is only one built in type of interface. That's the Interface
+ * manager interface.
+ * The interface manager for the interface of type "InterfaceMgr",
+ * named "InterfaceMgr" inserts itself into the system in order
+ * to bootstrap things...
+ *
+ * When an attempt is made to register a interface of an unknown type,
+ * then the appropriate Interface manager is loaded automatically.
+ *
+ * The name of an interface manager determines the type of
+ * interface it manages.
+ *
+ * It handles requests for interfaces whose type is the same
+ * as its interface name. If the interface manager's interface name
+ * is foo, then it is the interface manager for all interfaces whose
+ * type is foo.
+ *
+ * Types associated with interfaces of type Interface
+ *
+ * PILInterfaceOps The set of interfaces that every interface
+ * manager exports
+ * PILInterfaceImports The set of interfaces which are supplied to
+ * (imported by) every interface of type
+ * Interface. (that is, every interface
+ * manager).
+ *
+ *****************************************************************************
+ *
+ * Each plugin has only one entry point which is exported directly, regardless
+ * of what kind of interface(s) it may implement...
+ *
+ * This entrypoint is named ml_plugin_init() {more or less - see below}
+ *
+ * The ml_plugin_init() function is called once when the plugin is loaded.
+ *
+ *
+ * All other function pointers are registered (exported) through parameters
+ * passed to ml_plugin_init()
+ *
+ * It is the purpose of the Ml_plugin_init() to register the plugin,
+ * and all the interfaces which this plugin implements. A pointer to
+ * the registration function is in the parameters which are passed
+ * to ml_plugin_init().
+ *
+ *****************************************************************************
+ *
+ * THINGS IN THIS DESIGN WHICH ARE PROBABLY BROKEN...
+ *
+ * It may also be the case that the plugin loading environment needs
+ * to be able to have some kind of user_data passed to it which it can
+ * also pass along to any interface ...
+ *
+ * Maybe this should be handled by a sort of global user_data registration
+ * structure, so globals can be passed to interfaces when they're registered.
+ *
+ * A sort of "user_data" registry. One for each interface type and one
+ * for each interface... Or maybe it could be even more flexible...
+ *
+ * This is all so that these nice pristene, beautiful concepts can come out
+ * and work well in the real world where interfaces need to interact with
+ * some kind of global system view, and with each other...
+ *
+ * Probably need some better way of managing interface versions, etc.
+ *
+ ****************************************************************************
+ */
+
+/*
+ * If you want to use this funky export stuff, then you need to #define
+ * PIL_PLUGINTYPE and PIL_PLUGIN *before* including this file.
+ *
+ * The way to use this stuff is to declare your primary entry point this way:
+ *
+ * This example is for an plugin of type "auth" named "sha1"
+ *
+ * #define PIL_PLUGINTYPE auth
+ * #define PIL_PLUGIN sha1
+ * #include <upmls/PILPlugin.h>
+ *
+ * static const char* Ourpluginversion (void);
+ * static const char* Ourpluginname (void);
+ * static int Ourgetdebuglevel(void);
+ * static void Oursetdebuglevel(int);
+ * static void Ourclose (PILPlugin*);
+ *
+ * static struct PILPluginOps our_exported_plugin_operations =
+ * { Ourpluginversion,
+ * , Ourpluginname
+ * , Ourgetdebuglevel
+ * , Oursetdebuglevel
+ * , Ourclose
+ * };
+ *
+ * static const PILPluginImports* PluginOps;
+ * static PILPlugin* OurPlugin;
+ *
+ * // Our plugin initialization and registration function
+ * // It gets called when the plugin gets loaded.
+ * PIL_rc
+ * PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports)
+ * {
+ * PluginOps = imports;
+ * OurPlugin = us;
+ *
+ * // Register ourself as a plugin * /
+ * imports->register_plugin(us, &our_exported_plugin_operations);
+ *
+ * // Register our interfaces
+ * imports->register_interface(us, "interfacetype", "interfacename"
+ * // Be sure and define "OurExports" and OurImports
+ * // above...
+ * , &OurExports
+ * , &OurImports);
+ * // Repeat for all interfaces in this plugin...
+ *
+ * }
+ *
+ * Except for the PIL_PLUGINTYPE and the PIL_PLUGIN definitions, and changing
+ * the names of various static variables and functions, every single plugin is
+ * set up pretty much the same way
+ *
+ */
+
+/*
+ * No doubt there is a fancy preprocessor trick for avoiding these
+ * duplications but I don't have time to figure it out. Patches are
+ * being accepted...
+ */
+#define mlINIT_FUNC _pil_plugin_init
+#define mlINIT_FUNC_STR "_pil_plugin_init"
+#define PIL_INSERT _LTX_
+#define PIL_INSERT_STR "_LTX_"
+
+/*
+ * snprintf-style format string for initialization entry point name:
+ * arguments are: (plugintype, pluginname)
+ */
+#define PIL_FUNC_FMT "%s" PIL_INSERT_STR "%s" mlINIT_FUNC_STR
+
+#ifdef __STDC__
+# define EXPORTHELPER1(plugintype, insert, pluginname, function) \
+ plugintype##insert##pluginname##function
+#else
+# define EXPORTHELPER1(plugintype, insert, pluginname, function) \
+ plugintype/**/insert/**/pluginname/**/function
+#endif
+
+#define EXPORTHELPER2(a, b, c, d) EXPORTHELPER1(a, b, c, d)
+#define PIL_PLUGIN_INIT \
+ EXPORTHELPER2(PIL_PLUGINTYPE,PIL_INSERT,PIL_PLUGIN,mlINIT_FUNC)
+
+/*
+ * Plugin loading return codes. OK will always be zero.
+ *
+ * There are many ways to fail, but only one kind of success ;-)
+ */
+
+typedef enum {
+ PIL_OK=0, /* Success */
+ PIL_INVAL=1, /* Invalid Parameters */
+ PIL_BADTYPE=2, /* Bad plugin/interface type */
+ PIL_EXIST=3, /* Duplicate Plugin/Interface name */
+ PIL_OOPS=4, /* Internal Error */
+ PIL_NOPLUGIN=5 /* No such plugin or Interface */
+}PIL_rc; /* Return code from Plugin fns*/
+
+const char * PIL_strerror(PIL_rc rc);
+
+typedef struct PILPluginImports_s PILPluginImports;
+typedef struct PILPluginOps_s PILPluginOps;
+typedef struct PILPlugin_s PILPlugin;
+typedef struct PILPluginUniv_s PILPluginUniv;
+typedef struct PILPluginType_s PILPluginType;
+
+typedef struct PILInterface_s PILInterface;
+typedef struct PILInterfaceImports_s PILInterfaceImports;
+typedef struct PILInterfaceUniv_s PILInterfaceUniv;
+typedef struct PILInterfaceType_s PILInterfaceType;
+
+typedef PIL_rc(*PILInterfaceFun)(PILInterface*, void* ud_interface);
+
+#define PIL_MAGIC_PLUGIN 0xFEEDBEEFUL
+#define PIL_MAGIC_PLUGINTYPE 0xFEEDCEEFUL
+#define PIL_MAGIC_PLUGINUNIV 0xFEEDDEEFUL
+#define PIL_MAGIC_INTERFACE 0xFEEDEEEFUL
+#define PIL_MAGIC_INTERFACETYPE 0xFEEDFEEFUL
+#define PIL_MAGIC_INTERFACEUNIV 0xFEED0EEFUL
+
+#define IS_PILPLUGIN(s) ((s)->MagicNum == PIL_MAGIC_PLUGIN)
+#define IS_PILPLUGINTYPE(s) ((s)->MagicNum == PIL_MAGIC_PLUGINTYPE)
+#define IS_PILPLUGINUNIV(s) ((s)->MagicNum == PIL_MAGIC_PLUGINUNIV)
+#define IS_PILINTERFACE(s) ((s)->MagicNum == PIL_MAGIC_INTERFACE)
+#define IS_PILINTERFACETYPE(s) ((s)->MagicNum == PIL_MAGIC_INTERFACETYPE)
+#define IS_PILINTERFACEUNIV(s) ((s)->MagicNum == PIL_MAGIC_INTERFACEUNIV)
+
+/* The type of a Plugin Initialization Function */
+typedef PIL_rc (*PILPluginInitFun) (PILPlugin*us
+, PILPluginImports* imports
+, void* plugin_user_data);
+
+/*
+ * struct PILPluginOps_s (typedef PILPluginOps) defines the set of functions
+ * exported by all plugins...
+ */
+struct PILPluginOps_s {
+ const char* (*pluginversion) (void);
+ int (*getdebuglevel) (void);
+ void (*setdebuglevel) (int);
+ const char* (*license) (void);
+ const char* (*licenseurl) (void);
+ void (*close) (PILPlugin*);
+};
+
+/*
+ * Logging levels for the "standard" log interface.
+ */
+
+typedef enum {
+ PIL_FATAL= 1, /* BOOM! Causes program to stop */
+ PIL_CRIT = 2, /* Critical -- serious error */
+ PIL_WARN = 3, /* Warning */
+ PIL_INFO = 4, /* Informative message */
+ PIL_DEBUG= 5 /* Debug message */
+}PILLogLevel;
+typedef void (*PILLogFun)(PILLogLevel priority, const char * fmt, ...)
+ G_GNUC_PRINTF(2,3);
+
+/*
+ * The size glib2 type du jour?
+ * (once, this used to be size_t, so this change could break
+ * distributions with older glib2 versions; if so, just add an
+ * #ifelse below)
+ */
+#if GLIB_MINOR_VERSION <= 14
+ typedef gulong glib_size_t;
+#else
+ typedef gsize glib_size_t;
+#endif
+
+/*
+ * struct PILPluginImports_s (typedef PILPluginImports) defines
+ * the functions and capabilities that every plugin imports when it is loaded.
+ */
+
+
+struct PILPluginImports_s {
+ PIL_rc (*register_plugin)(PILPlugin* piinfo
+ , const PILPluginOps* commonops);
+ PIL_rc (*unregister_plugin)(PILPlugin* piinfo);
+/*
+ * A little explanation of the close_func parameter to register_interface
+ * is in order.
+ *
+ * It is an exported operation function, just like the Ops structure.
+ * However, the Ops vector is exported to applications that
+ * are using the interface. Unlike the Ops structure, close_func is
+ * exported only to the interface system, since applications shouldn't
+ * call it directly, but should manage the reference counts for the
+ * interfaces instead.
+ * The generic interface system doesn't have any idea how to call
+ * any functions in the operations vector. So, it's a separate
+ * parameter for two good reasons.
+ */
+ PIL_rc (*register_interface)(PILPlugin* piinfo
+ , const char * interfacetype /* Type of interface */
+ , const char * interfacename /* Name of interface */
+ , void* Ops /* Info (functions) exported
+ by this interface */
+ /* Function to call to shut down this interface */
+ , PILInterfaceFun close_func
+
+ , PILInterface** interfaceid /* Interface id (OP) */
+ , void** Imports
+ , void* ud_interface); /* interface user data */
+
+ PIL_rc (*unregister_interface)(PILInterface* interfaceid);
+ PIL_rc (*load_plugin)(PILPluginUniv* universe
+ , const char * plugintype, const char * pluginname
+ , void* plugin_private);
+
+ void (*log) (PILLogLevel priority, const char * fmt, ...)
+ G_GNUC_PRINTF(2,3);
+ gpointer (*alloc)(glib_size_t size);
+ gpointer (*mrealloc)(gpointer space, glib_size_t size);
+ void (*mfree)(gpointer space);
+ char* (*mstrdup)(const char *s);
+};
+
+/*
+ * Function for logging with the given logging function
+ * The reason why it's here is so we can get printf arg checking
+ * You can't get that when you call a function pointer directly.
+ */
+void PILCallLog(PILLogFun logfun, PILLogLevel priority, const char * fmt, ...)
+ G_GNUC_PRINTF(3,4);
+
+/*
+ * EXPORTED INTERFACES...
+ */
+
+/* Create a new plugin universe - start the plugin loading system up */
+PILPluginUniv* NewPILPluginUniv(const char * baseplugindirectory);
+
+/* Change memory allocation functions right after creating universe */
+void PilPluginUnivSetMemalloc(PILPluginUniv*
+, gpointer (*alloc)(glib_size_t size)
+, gpointer (*mrealloc)(gpointer, glib_size_t size)
+, void (*mfree)(void* space)
+, char* (*mstrdup)(const char *s));
+
+
+void PilPluginUnivSetLog(PILPluginUniv*
+, void (*log) (PILLogLevel priority, const char * fmt, ...)
+ G_GNUC_PRINTF(2,3));
+
+
+/* Delete a plugin universe - shut the plugin loading system down */
+/* Best if used carefully ;-) */
+void DelPILPluginUniv(PILPluginUniv*);
+
+/* Set the debug level for the plugin system itself */
+void PILpisysSetDebugLevel (int level);
+
+/* Return a list of plugins of the given type */
+char ** PILListPlugins(PILPluginUniv* u, const char *plugintype
+, int* plugincount /*can be NULL*/);
+
+/* Free the plugin list returned by PILFreeListPlugins */
+void PILFreePluginList(char ** pluginlist);
+
+/* Load the requested plugin */
+PIL_rc PILLoadPlugin(PILPluginUniv* piuniv
+, const char * plugintype
+, const char * pluginname
+, void * pi_private);
+
+/* Return PIL_OK if the given plugin exists */
+PIL_rc PILPluginExists(PILPluginUniv* piuniv
+, const char * plugintype
+, const char * pluginname);
+
+/* Either or both of pitype and piname may be NULL */
+void PILSetDebugLevel(PILPluginUniv*u, const char * pitype
+, const char * piname
+, int level);
+
+/* Neither pitype nor piname may be NULL */
+int PILGetDebugLevel(PILPluginUniv* u, const char * pitype
+, const char * piname);
+
+PIL_rc PILIncrIFRefCount(PILPluginUniv* piuniv
+, const char * interfacetype
+, const char * interfacename
+, int plusminus);
+
+int PILGetIFRefCount(PILPluginUniv* piuniv
+, const char * interfacetype
+, const char * interfacename);
+
+void PILLogMemStats(void);
+/* The plugin/interface type of a interface manager */
+
+#define PI_IFMANAGER "InterfaceMgr"
+#define PI_IFMANAGER_TYPE InterfaceMgr
+
+/*
+ * These functions are standard exported functions for all plugins.
+ */
+
+#define PIL_PLUGIN_BOILERPLATE_PROTOTYPES_GENERIC(PluginVersion, DebugName) \
+/* \
+ * Prototypes for boilerplate functions \
+ */ \
+static const char* Ourpluginversion(void); \
+static int GetOurDebugLevel(void); \
+static void SetOurDebugLevel(int); \
+static const char * ReturnOurLicense(void); \
+static const char * ReturnOurLicenseURL(void);
+
+#define PIL_PLUGIN_BOILERPLATE_FUNCS(PluginVersion, DebugName) \
+/* \
+ * Definitions of boilerplate functions \
+ */ \
+static const char* \
+Ourpluginversion(void) \
+{ return PluginVersion; } \
+ \
+static int DebugName = 0; \
+ \
+static int \
+GetOurDebugLevel(void) \
+{ return DebugName; } \
+ \
+static void \
+SetOurDebugLevel(int level) \
+{ DebugName = level; } \
+ \
+static const char * \
+ReturnOurLicense(void) \
+{ return PIL_PLUGINLICENSE; } \
+ \
+static const char * \
+ReturnOurLicenseURL(void) \
+{ return PIL_PLUGINLICENSEURL; }
+
+#define PIL_PLUGIN_BOILERPLATE(PluginVersion, DebugName, CloseName) \
+PIL_PLUGIN_BOILERPLATE_PROTOTYPES_GENERIC(PluginVersion, DebugName) \
+static void CloseName(PILPlugin*); \
+/* \
+ * Initialize Plugin Exports structure \
+ */ \
+static PILPluginOps OurPIExports = \
+{ Ourpluginversion \
+, GetOurDebugLevel \
+, SetOurDebugLevel \
+, ReturnOurLicense \
+, ReturnOurLicenseURL \
+, CloseName \
+}; \
+PIL_PLUGIN_BOILERPLATE_FUNCS(PluginVersion, DebugName)
+
+#define PIL_PLUGIN_BOILERPLATE2(PluginVersion, DebugName) \
+PIL_PLUGIN_BOILERPLATE_PROTOTYPES_GENERIC(PluginVersion, DebugName) \
+/* \
+ * Initialize Plugin Exports structure \
+ */ \
+static PILPluginOps OurPIExports = \
+{ Ourpluginversion \
+, GetOurDebugLevel \
+, SetOurDebugLevel \
+, ReturnOurLicense \
+, ReturnOurLicenseURL \
+, NULL \
+}; \
+PIL_PLUGIN_BOILERPLATE_FUNCS(PluginVersion, DebugName)
+
+
+/* A few sample licenses and URLs. We can easily add to this */
+
+#define LICENSE_GPL "gpl"
+#define URL_GPL "http://www.fsf.org/licenses/gpl.html"
+
+#define LICENSE_LGPL "lgpl"
+#define URL_LGPL "http://www.fsf.org/licenses/lgpl.html"
+
+#define LICENSE_X11 "x11"
+#define URL_X11 "http://www.x.org/terms.htm"
+
+#define LICENSE_PUBDOM "publicdomain"
+#define URL_PUBDOM "file:///dev/null"
+
+#define LICENSE_MODBSD "modbsd"
+#define URL_MODBSD "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5"
+
+#define LICENSE_OLDBSD "origbsd"
+#define URL_OLDBSD "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#6"
+
+#define LICENSE_EXPAT "expat"
+#define URL_EXPAT "http://www.jclark.com/xml/copying.txt"
+
+#define LICENSE_ZLIB "zlib"
+#define URL_ZLIB "http://www.gzip.org/zlib/zlib_license.html"
+
+#define LICENSE_APACHE_10 "apache1_0"
+#define URL_APACHE_10 "http://www.apache.org/LICENSE-1.0"
+
+#define LICENSE_APACHE_11 "apache1_1"
+#define URL_APACHE_11 "http://www.apache.org/LICENSE-1.1"
+
+#define LICENSE_MPL "mpl"
+#define URL_MPL "http://www.mozilla.org/MPL/MPL-1.1.html"
+
+#define LICENSE_PROP "proprietary"
+#define URL_PROP ""
+
+#define LICENSE_IBMPL "ibmpl"
+#define URL_IBMPL "http://oss.software.ibm.com/developerworks/opensource/license10.html"
+
+#ifdef ENABLE_PIL_DEFS_PRIVATE
+/* Perhaps these should be moved to a different header file */
+
+/*
+ * PILPluginType is the "class" for the basic plugin loading mechanism.
+ *
+ * To enable loading of plugins from a particular plugin type
+ * one calls NewPILPluginType with the plugin type name, the plugin
+ * base directory, and the set of functions to be imported to the plugin.
+ *
+ *
+ * The general idea of these structures is as follows:
+ *
+ * The PILPluginUniv object contains information about all plugins of
+ * all types.
+ *
+ * The PILPluginType object contains information about all the plugins of a
+ * specific type.
+ *
+ * Note: for plugins which implement a single interface, the plugin type name
+ * should be the same as the interface type name.
+ *
+ * For other plugins that implement more than one interface, one of
+ * the interface names should normally match the plugin name.
+ */
+
+
+/*
+ * struct PILPlugin_s (typedef PILPlugin) is the structure which
+ * represents/defines a plugin, and is used to identify which plugin is
+ * being referred to in various function calls.
+ *
+ * NOTE: It may be the case that this definition should be moved to
+ * another header file - since no one ought to be messing with them anyway ;-)
+ *
+ * I'm not sure that we're putting the right stuff in here, either...
+ */
+
+struct PILPlugin_s {
+ unsigned long MagicNum;
+ char* plugin_name;
+ PILPluginType* plugintype; /* Parent structure */
+ int refcnt; /* Reference count for this plugin */
+ lt_dlhandle dlhandle; /* Reference to D.L. object */
+ PILPluginInitFun dlinitfun; /* Initialization function */
+ const PILPluginOps* pluginops; /* Exported plugin operations */
+
+ void* ud_plugin; /* Plugin-Private data */
+ /* Other stuff goes here ... (?) */
+};
+
+/*
+ * PILPluginType Information about all plugins of a given type.
+ * (i.e., in a given directory)
+ * (AKA struct PILPluginType_s)
+ */
+
+struct PILPluginType_s {
+ unsigned long MagicNum;
+ char * plugintype;
+ PILPluginUniv* piuniv; /* The universe to which we belong */
+ GHashTable* Plugins;
+ /* Key is plugin type, value is PILPlugin */
+
+ char** (*listplugins)(PILPluginType*, int* listlen);
+};
+
+/*
+ * PILPluginUniv (aka struct PILPluginUniv_s) is the structure which
+ * represents the universe of all PILPluginType objects.
+ * There is one PILPluginType object for each Plugin type.
+ */
+
+struct PILPluginUniv_s {
+ unsigned long MagicNum;
+ char ** rootdirlist;
+ /* key is plugin type, data is PILPluginType* */
+ GHashTable* PluginTypes;
+ struct PILInterfaceUniv_s*ifuniv; /* Universe of interfaces */
+ PILPluginImports* imports;
+};
+
+# endif /* ENABLE_PIL_DEFS_PRIVATE */
+#endif /*PILS_PLUGIN_H */