--- /dev/null
+/* CobraMUSH Module System based upon cross-platform libldl */
+#ifndef _MODULES_H_
+#define _MODULES_H_
+
+struct module_entry_t {
+ char *name; /* Name of module */
+ char *info; /* Short Description */
+ float version; /* Version of Module */
+ int (*load)(struct module_entry_t *); /* Load Function */
+ int (*unload)(struct module_entry_t *); /* Unload function */
+ void *handle;
+ struct module_entry_t *next;
+};
+
+struct module_entry_t *module_entry_add(char *name);
+int module_entry_del(struct module_entry_t *entry);
+int modules_init(void);
+int module_open(char *path, char *name);
+int module_close(struct module_entry_t *m);
+int modules_shutdown(void);
+
+
+/* Iterate through Module List */
+#define MODULE_ITER(m) for(m = module_list ; m != NULL ; m = m->next)
+/* Check and Free */
+#define MODULE_CAF(mem,check) if(mem != NULL) \
+ mush_free(mem, check);
+/* Retrieve Module Function */
+#define MODULE_FUNC(h, m, func, ...) \
+ if((h = lt_dlsym(m, func))) { \
+ h(__VAR_ARGS__) \
+ }
+
+#define MODULE_FUNCRET(m, func) lt_dlsym(m, func);
+
+
+#endif /* _MODULES_H_ */
# Libs
LIBS=$(CLIBS) $(RLIBS) $(ILIBS)
+CC=libtool
CFLAGS=$(CCFLAGS) $(RDEFS) $(IDEFS)
extmail.c filecopy.c flaglocal.c flags.c funcrypt.c function.c \
fundb.c fundiv.c funlist.c funlocal.c funmath.c funmisc.c funstr.c funtime.c \
funufun.c game.c help.c htab.c ident.c local.c lock.c log.c look.c \
- malias.c match.c memcheck.c move.c mushlua.c mushlua_wrap.c mycrypt.c mymalloc.c mysocket.c \
+ malias.c match.c memcheck.c move.c modules.c mushlua.c mushlua_wrap.c mycrypt.c mymalloc.c mysocket.c \
myssl.c notify.c parse.c pcre.c player.c plyrlist.c \
predicat.c privtab.c prog.o ptab.c rob.c rplog.c services.c set.c shs.c \
sig.c speech.c sql.c strdup.c strtree.c strutil.c tables.c timer.c unparse.c \
../hdrs/function.h ../hdrs/game.h ../hdrs/getpgsiz.h ../hdrs/help.h \
../hdrs/htab.h ../hdrs/htab.h ../hdrs/ident.h ../hdrs/lock.h \
../hdrs/log.h ../hdrs/log.h ../hdrs/malias.h ../hdrs/match.h \
- ../hdrs/mushdb.h ../hdrs/mushlua.h ../hdrs/mushtype.h \
+ ../hdrs/modules.h ../hdrs/mushdb.h ../hdrs/mushlua.h ../hdrs/mushtype.h \
../hdrs/mymalloc.h ../hdrs/mysocket.h ../hdrs/myssl.h \
../hdrs/parse.h ../hdrs/pcre.h ../hdrs/privtab.h ../hdrs/ptab.h \
../hdrs/strtree.h ../hdrs/version.h ../options.h ../hdrs/division.h ../hdrs/cron.h
extmail.o filecopy.o flaglocal.o flags.o funcrypt.o function.o \
fundb.o funlist.o fundiv.o funlocal.o funmath.o funmisc.o funstr.o funtime.o \
funufun.o game.o help.o htab.o ident.o local.o lock.o log.o look.o \
- malias.o match.o memcheck.o move.o mushlua.o mushlua_wrap.o mycrypt.o mymalloc.o \
+ malias.o match.o memcheck.o move.o modules.o mushlua.o mushlua_wrap.o mycrypt.o mymalloc.o \
mysocket.o myssl.o notify.o parse.o pcre.o player.o plyrlist.o predicat.o privtab.o \
prog.o ptab.o rob.o rplog.o services.o set.o shs.o sig.o speech.o sql.o strdup.o \
strtree.o strutil.o tables.o timer.o unparse.o utils.o version.o warnings.o \
netmud: $(O_FILES)
@echo "Making netmud."
-mv -f netmud netmud~
- $(CC) $(LDFLAGS) $(CCFLAGS) -o netmud $(O_FILES) $(LIBS)
+ $(LIBTOOL) --mode=link $(CC) -export-dynamic $(LDFLAGS) $(CCFLAGS) -o netmud $(O_FILES) $(LIBS)
console: $(CONSOLE_O_FILES)
@echo "Making console."
-mv -f console console~
- $(CC) $(LDFLAGS) $(CCFLAGS) -o console $(CONSOLE_O_FILES) $(LIBS)
+ $(LIBTOOL) --mode=link $(CC) -export-dynamic $(LDFLAGS) $(CCFLAGS) -o netmud $(O_FILES) $(LIBS)
+
# By default, db.c initially allocates enough space for 5000 objects, then
# grows the space if needed. To change this value, include
--- /dev/null
+/* CobraMUSH Module/Plugin System - File created 3/31/11
+ *
+ * Our Approach shall be one using the libtool library, mostly for the fact
+ * that is a cross-platform designed library.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <ltdl.h>
+
+#include "conf.h"
+#include "externs.h"
+#include "command.h"
+#include "switches.h"
+#include "mushtype.h"
+#include "log.h"
+#include "modules.h"
+
+struct module_entry_t *module_list = NULL;
+
+/* Ads a module entry and returns */
+struct module_entry_t *module_entry_add(char *name) {
+ struct module_entry_t *entry;
+
+ entry = (struct module_entry_t *) mush_malloc(sizeof(struct module_entry_t), "MODULE_ENTRY");
+
+ if(!entry) {
+ return NULL; /* Should really panic here.. */
+ }
+
+ entry->name = mush_strdup(name, "MODULE_ENTRY.NAME");
+ entry->info = NULL;
+ entry->load = NULL;
+ entry->unload = NULL;
+ entry->next = module_list;
+ module_list = entry;
+
+ return entry;
+}
+
+/* removes a module entry from the list */
+int module_entry_del(struct module_entry_t *entry) {
+ struct module_entry_t *m, *e = NULL;
+
+ if(module_list == entry)
+ e = module_list;
+ else MODULE_ITER(m)
+ if(m->next != NULL && m->next == entry) {
+ e = m;
+ m->next = m->next->next;
+ break;
+ }
+
+ if(e == NULL)
+ return 0;
+
+ MODULE_CAF(e->name, "MODULE_ENTRY.NAME");
+ MODULE_CAF(e->info, "MODULE_ENTRY.INFO");
+ MODULE_CAF(e, "MODULE_ENTRY");
+
+ return 1;
+}
+
+/* Initialize Module Interface */
+int modules_init() {
+ return lt_dlinit(); /* Initialize libltdl. 0 is good */
+}
+
+/* Load Module name */
+int module_open(char *path, char *name) {
+ char file[BUFFER_LEN];
+ int (*module_loader)(struct module_entry_t *);
+ struct module_entry_t *module;
+ void *handle;
+
+ memset(file, '\0', BUFFER_LEN);
+ snprintf(file, BUFFER_LEN, "%s/%s", path, name);
+
+ handle = lt_dlopen(file);
+
+ if(!handle) {
+ do_rawlog(LT_ERR, "Error Loading Module: %s | %s ", file, lt_dlerror());
+ return 0;
+ }
+
+ /* Some OSes may need symbols to be prefixed with _.. Will need to look into autoconfig code for this */
+ module_loader = MODULE_FUNCRET(handle, "module_load");
+
+ if(!module_loader) {
+ do_rawlog(LT_ERR, "Error Loading Module: Could not call module_load | %s", file);
+ return 0;
+ }
+
+ /* Add the module to the linked list */
+ module = module_entry_add(name);
+ if(module == NULL) {
+ return 0;
+ }
+ module->handle = handle;
+ module->load = module_loader;
+ module->unload = MODULE_FUNCRET(handle, "module_unload");
+
+ /* Grab info and version from module & put it in */
+ /* Success.. Call the module */
+ return module_loader(module);
+}
+
+/* Unload one Module */
+int module_close(struct module_entry_t *m) {
+ int ret;
+
+ ret = m->unload(m); /* first run requierd unload code */
+
+ if(!ret)
+ return 0;
+
+ /* next unload the modules for real */
+ ret = lt_dlclose(m->handle);
+
+ if(ret != 0) {
+ do_rawlog(LT_ERR, "Could not unload module: %s/%d | %s", __FILE__, __LINE__, lt_dlerror());
+ return 0;
+ }
+
+ if(!module_entry_del(m)) {
+ do_rawlog(LT_ERR, "Could not unload module: %s/%d ", __FILE__, __LINE__);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Unload all modules */
+int modules_shutdown() {
+ struct module_entry_t *m;
+
+ MODULE_ITER(m)
+ m->unload(m);
+
+ return lt_dlexit(); /* 0 is good */
+}
+
+/* MUSH Module Interface Portion... Much of this section will probably actually move to a module itself and become a resident module */
+
+ /* command will be restricted to Director player in nature from the command file */
+COMMAND(cmd_module) {
+ struct module_entry_t *m;
+ char tbuf1[BUFFER_LEN];
+ int ret;
+
+ if(SW_ISSET(sw, SWITCH_LOAD)) {
+ if(!arg_left) {
+ notify(player, "Requires at least one argument.");
+ return;
+ }
+ /* Load a Module By name in arg_left */
+ (void) getcwd(tbuf1, BUFFER_LEN);
+ ret = module_open(tbuf1, arg_left);
+ if(ret)
+ notify(player, "module successfully loaded.");
+ else
+ notify(player, "module could not load.");
+
+ } else if(module_list == NULL) {
+ notify_format(player, "Search-path: %s", lt_dlgetsearchpath());
+ notify(player, "No modules loaded.");
+ return;
+ } else if(SW_ISSET(sw, SWITCH_UNLOAD)) {
+ /* This is after the no modules loaded one.. because you have to modules loaded in order to unload something */
+ if(!arg_left) {
+ notify(player, "Reqiures at least one argument.");
+ return;
+ }
+ MODULE_ITER(m)
+ if(!strcasecmp(arg_left, m->name)) {
+ if(module_close(m))
+ notify(player, "unloaded module");
+ else
+ notify(player, "could not unload module");
+ return;
+ }
+ } else {
+ /* No Switches.. Just view modules loaded */
+ MODULE_ITER(m) {
+ notify_format(player, "Module-Name: %s", m->name);
+ }
+ }
+}
+
+