+1998-09-17 Nathan Bryant <bryant@cs.usm.maine.edu>
+ * Makefile.in: add SERV_MODULES and PROXY_TARGETS to `cleaner'
+ * dynloader.[ch], serv_{chat,test}.[ch], sysdep.c: cleaned
+ up the dynamic loader interface as follows:
+ - all the symbol table stuff is gone.
+ - modules are loaded once at server startup and never unloaded.
+ - Added a new function CtdlRegisterProtoHook() to handle the stuff
+ that was being done with the symbol tables.
+ - Dynamic_Module_Init() now returns a pointer to a static struct
+ DLModule_Info; this structure itself has been modified to use char*
+ fields instead of fixed char arrays.
+
Wed Sep 16 22:25:13 EDT 1998 Art Cancro <ajc@uncnsrd.mt-kisco.ny.us>
* Implemented separate structs, lists, and functions for each type
of server-side hook available.
find . -name \*.[o] -print -exec rm -f {} \;
cleaner: clean
- rm -f $(CLIENT_TARGETS) $(SERVER_TARGETS) $(UTIL_TARGETS)
+ rm -f $(CLIENT_TARGETS) $(SERVER_TARGETS) $(UTIL_TARGETS) \
+ $(SERV_MODULES) $(PROXY_TARGETS)
realclean: cleaner
rm -f Makefile sysdep.h
#include <strings.h>
#include <syslog.h>
#include <pthread.h>
+#include <limits.h>
#include "dynloader.h"
#include "citadel.h"
#include "server.h"
#include "sysdep_decls.h"
-symtab *global_symtab;
-
struct CleanupFunctionHook *CleanupHookTable = NULL;
struct NewRoomFunctionHook *NewRoomHookTable = NULL;
struct SessionFunctionHook *SessionHookTable = NULL;
struct LoginFunctionHook *LoginHookTable = NULL;
-int DLoader_Exec_Cmd(char *cmdbuf)
+struct ProtoFunctionHook
{
- symtab *t_sym;
- void *fcn_handle;
- char *dl_error;
- void (*cmd_ptr)(void *);
-
- for (t_sym = global_symtab; ((t_sym) && (strncmp(t_sym->server_cmd, cmdbuf, strlen(t_sym->server_cmd))) ); t_sym=t_sym->next)
- ;
-
- if (t_sym)
- {
- if (!(fcn_handle = dlopen(t_sym->module_path, RTLD_NOW)))
- {
- dl_error = dlerror();
- syslog(LOG_NOTICE, "WARNING: module %s failed to load", t_sym->module_path);
- return(0);
- }
-
- cmd_ptr = dlsym(fcn_handle, t_sym->fcn_name);
- if ((dl_error = dlerror()) != NULL)
- {
- syslog(LOG_NOTICE, "dlsym error: %s - %s", dl_error, t_sym->module_path);
- return(0);
- }
- (*cmd_ptr)(&cmdbuf[5]);
- dlclose(fcn_handle);
- if ((dl_error = dlerror()) != NULL)
- {
- syslog(LOG_NOTICE, "dlclose error: %s", dl_error);
- return(0);
- }
- return(1);
- } /* If symbol found */
+ void (*handler)(char *cmdbuf);
+ char *cmd;
+ char *desc;
+ struct ProtoFunctionHook *next;
+} *ProtoHookList = NULL;
- return(0);
+void CtdlRegisterProtoHook(void (*handler)(char *), char *cmd, char *desc)
+{
+ struct ProtoFunctionHook *p = malloc(sizeof *p);
+
+ if (p == NULL)
+ {
+ fprintf(stderr, "can't malloc new ProtoFunctionHook\n");
+ exit(EXIT_FAILURE);
+ }
+
+ p->handler = handler;
+ p->cmd = cmd;
+ p->desc = desc;
+ p->next = ProtoHookList;
+ ProtoHookList = p;
}
-void add_symbol(char *fcn_name, char *server_cmd, char *info_msg, symtab **first_symtab)
+int DLoader_Exec_Cmd(char *cmdbuf)
{
- symtab *new_symtab, *t_sym, *last_sym;
-
- if (!(new_symtab = malloc(sizeof(symtab))))
- {
- perror("Malloc new symtab");
- exit(1);
- }
-
- new_symtab->fcn_name = strdup(fcn_name);
- new_symtab->server_cmd = strdup(server_cmd);
- new_symtab->info_msg = strdup(info_msg);
- new_symtab->next = NULL;
-
- if (!(*first_symtab))
- (*first_symtab) = new_symtab;
- else
- {
- last_sym = NULL;
- for (t_sym = (*first_symtab); (t_sym); t_sym = t_sym->next)
- last_sym = t_sym;
- last_sym->next = new_symtab;
- }
+ struct ProtoFunctionHook *p;
+
+ for (p = ProtoHookList; p; p = p->next)
+ {
+ if (!strncmp(cmdbuf, p->cmd, 4))
+ {
+ p->handler(&cmdbuf[5]);
+ return 1;
+ }
+ }
+ return 0;
}
-void DLoader_Init(char *pathname, symtab **my_symtab)
+void DLoader_Init(char *pathname)
{
void *fcn_handle;
- void (*h_init_fcn)(struct DLModule_Info *);
- void (*h_get_symtab)(symtab **);
char *dl_error;
- char *filename;
DIR *dir;
struct dirent *dptr;
-
- char pathbuf[512];
- struct DLModule_Info dl_info;
- symtab *stab = NULL;
- symtab *t_sym;
-
- global_symtab = NULL; /* Global symbol table */
+ struct DLModule_Info* (*h_init_fcn)(void);
+ struct DLModule_Info *dl_info;
+
+ char pathbuf[PATH_MAX];
if ((dir = opendir(pathname))==NULL)
{
if (dptr->d_name[0] == '.')
continue;
- filename = strdup(dptr->d_name);
- snprintf(pathbuf, 512, "%s/%s", pathname, filename);
+ snprintf(pathbuf, PATH_MAX, "%s/%s", pathname, dptr->d_name);
if (!(fcn_handle = dlopen(pathbuf, RTLD_NOW)))
{
dl_error = dlerror();
- fprintf(stderr, "DLoader_Init dlopen failed (%s)", dl_error);
+ fprintf(stderr, "DLoader_Init dlopen failed (%s)\n", dl_error);
continue;
}
h_init_fcn = dlsym(fcn_handle, "Dynamic_Module_Init");
if ((dl_error = dlerror()) != NULL)
{
- fprintf(stderr,"DLoader_Init dlsym failed (%s)", dl_error);
+ fprintf(stderr,"DLoader_Init dlsym failed (%s)\n", dl_error);
continue;
}
- (*h_init_fcn)(&dl_info);
-
- printf("Loaded module %s v%d.%d\nBy %s (%s)\n", dl_info.module_name,
- dl_info.major_version,
- dl_info.minor_version,
- dl_info.module_author,
- dl_info.module_author_email);
+ dl_info = h_init_fcn();
- h_get_symtab = dlsym(fcn_handle, "Get_Symtab");
- if ((dl_error = dlerror()) != NULL)
- {
- fprintf(stderr,"DLoader_Init dlsym failed for Get_Symtab (%s) on module %s", dl_error, dl_info.module_name);
- continue;
- }
-
-/* Get the symbol table for the current module and link it on */
-
- (*h_get_symtab)(&stab);
- if (!(*my_symtab))
- {
- (*my_symtab) = global_symtab = stab;
- }
- else
- {
- for (t_sym = (*my_symtab) ; t_sym->next; t_sym=t_sym->next);
- ;
- t_sym->next = stab;
- }
- for (t_sym = stab; t_sym; t_sym=t_sym->next)
- t_sym->module_path = (char *)strdup(pathbuf);
- dlclose(fcn_handle);
- if ((dl_error = dlerror()) != NULL)
- {
- fprintf(stderr,"DLoader_Init dlclose failed (%s)", dl_error);
- continue;
- }
-
+ printf("Loaded module %s v%d.%d\nBy %s (%s)\n", dl_info->module_name,
+ dl_info->major_version, dl_info->minor_version,
+ dl_info->module_author, dl_info->module_author_email);
} /* While */
-
}
struct DLModule_Info
{
- char module_name[30];
- char module_author[30];
- char module_author_email[30];
+ char *module_name;
+ char *module_author;
+ char *module_author_email;
int major_version, minor_version;
};
-typedef struct s_symtab
-{
- char *fcn_name;
- char *server_cmd;
- char *info_msg;
- char *module_path;
- struct s_symtab *next;
-} symtab;
-
-void DLoader_Init(char *pathname, symtab **);
+void DLoader_Init(char *pathname);
int DLoader_Exec_Cmd(char *cmdbuf);
-void add_symbol(char *fcn_name, char *server_cmd, char *info_msg, symtab **);
void CtdlRegisterCleanupHook(void *fcn_ptr);
void CtdlRegisterNewRoomHook(void *fcn_ptr);
void CtdlRegisterSessionHook(void *fcn_ptr, int StartStop);
void CtdlRegisterLoginHook(void *fcn_ptr);
+void CtdlRegisterProtoHook(void (*handler)(char *), char *cmd, char *desc);
+struct DLModule_Info *Dynamic_Module_Init(void);
struct ChatLine *ChatQueue = NULL;
int ChatLastMsg = 0;
-symtab *My_Symtab = NULL; /* dyn */
extern struct CitContext *ContextList;
#define MAJOR_VERSION 0
#define MINOR_VERSION 2
-
-void Dynamic_Module_Init(struct DLModule_Info *info)
+static struct DLModule_Info info =
{
- add_symbol("cmd_chat", "CHAT", "Initiates a real-time chat session", &My_Symtab);
- add_symbol("cmd_pexp", "PEXP", "Poll for express messages", &My_Symtab);
- add_symbol("cmd_sexp", "SEXP", "Send an express message", &My_Symtab);
- strncpy(info->module_name, MODULE_NAME, 30);
- strncpy(info->module_author, MODULE_AUTHOR, 30);
- strncpy(info->module_author_email, MODULE_EMAIL, 30);
- info->major_version = MAJOR_VERSION;
- info->minor_version = MINOR_VERSION;
-
-}
-
-void Get_Symtab(symtab **the_symtab)
+ MODULE_NAME,
+ MODULE_AUTHOR,
+ MODULE_EMAIL,
+ MAJOR_VERSION,
+ MINOR_VERSION
+};
+
+struct DLModule_Info *Dynamic_Module_Init(void)
{
- (*the_symtab) = My_Symtab;
- return;
+ CtdlRegisterProtoHook(cmd_chat, "CHAT",
+ "Initiates a real-time chat session");
+ CtdlRegisterProtoHook(cmd_pexp, "PEXP", "Poll for express messages");
+ CtdlRegisterProtoHook(cmd_sexp, "SEXP", "Send an express message");
+ return &info;
}
-
-
void allwrite(char *cmdbuf, int flag, char *roomname, char *username)
{
FILE *fp;
/*
* poll for express messages
*/
-void cmd_pexp(void) {
+void cmd_pexp(char *argbuf) /* arg unused */ {
struct ExpressMessage *emptr;
if (CC->FirstExpressMessage == NULL) {
t_context *find_context (char **unstr);
void do_chat_listing (int allflag);
void cmd_chat (char *argbuf);
-void cmd_pexp (void);
+void cmd_pexp (char *argbuf); /* arg unused */
char check_express (void);
void cmd_sexp (char *argbuf);
#include "config.h"
#include "dynloader.h"
-symtab *My_Symtab = NULL; /* dyn */
-
extern struct CitContext *ContextList;
#define MODULE_NAME "Dummy test module"
#define MAJOR_VERSION 0
#define MINOR_VERSION 1
+static struct DLModule_Info info = {
+ MODULE_NAME,
+ MODULE_AUTHOR,
+ MODULE_EMAIL,
+ MAJOR_VERSION,
+ MINOR_VERSION
+};
+
void CleanupTest(void) {
lprintf(9, "--- test of adding an unload hook --- \n");
}
lprintf(9, "--- Hello, %s ---\n", CC->curr_user);
}
-void Dynamic_Module_Init(struct DLModule_Info *info)
+struct DLModule_Info *Dynamic_Module_Init(void)
{
- strncpy(info->module_name, MODULE_NAME, 30);
- strncpy(info->module_author, MODULE_AUTHOR, 30);
- strncpy(info->module_author_email, MODULE_EMAIL, 30);
- info->major_version = MAJOR_VERSION;
- info->minor_version = MINOR_VERSION;
-
CtdlRegisterCleanupHook(CleanupTest);
CtdlRegisterNewRoomHook(NewRoomTest);
CtdlRegisterSessionHook(SessionStartTest, 1);
CtdlRegisterSessionHook(SessionStopTest, 0);
CtdlRegisterLoginHook(LoginTest);
-
-}
-
-void Get_Symtab(symtab **the_symtab)
-{
- (*the_symtab) = My_Symtab;
- return;
+ return &info;
}
pthread_mutex_t Critters[MAX_SEMAPHORES]; /* Things needing locking */
pthread_key_t MyConKey; /* TSD key for MyContext() */
-symtab *my_symtab; /* Dynamic modules symbol table */
int msock; /* master listening socket */
int verbosity = 3; /* Logging level */
openlog("citserver",LOG_PID,LOG_USER);
lprintf(1, "Initting modules...\n");
snprintf(modpath, 128, "%s/modules", BBSDIR);
- DLoader_Init(modpath, &my_symtab);
+ DLoader_Init(modpath);
lprintf(1, "Modules done initializing...\n");
/*
lprintf(1, "First symtab item:");