]> code.citadel.org Git - citadel.git/commitdiff
The dynamic loader module which should have already been there (?)
authorBrian Costello <btx@uncensored.citadel.org>
Tue, 8 Sep 1998 03:13:21 +0000 (03:13 +0000)
committerBrian Costello <btx@uncensored.citadel.org>
Tue, 8 Sep 1998 03:13:21 +0000 (03:13 +0000)
citadel/dynloader.c [new file with mode: 0644]

diff --git a/citadel/dynloader.c b/citadel/dynloader.c
new file mode 100644 (file)
index 0000000..96a8aea
--- /dev/null
@@ -0,0 +1,169 @@
+/*******************************************************
+ *
+ * Citadel Dynamic Loading Module
+ * Written by Brian Costello
+ * btx@calyx.net
+ *
+ ******************************************************/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <strings.h>
+#include <syslog.h>
+#include "dynloader.h"
+
+symtab *global_symtab;
+
+int DLoader_Exec_Cmd(char *cmdbuf)
+{
+   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_LAZY)))
+      {
+         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 */
+
+   return(0);
+}
+
+void add_symbol(char *fcn_name, char *server_cmd, char *info_msg, symtab **first_symtab)
+{
+   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;
+   }
+}
+
+void DLoader_Init(char *pathname, symtab **my_symtab)
+{
+   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 */
+   
+   if ((dir = opendir(pathname))==NULL)
+   {
+      perror("opendir");
+      exit(1);
+   }
+   
+   while ((dptr=readdir(dir))!= NULL)
+   {
+      if (dptr->d_name[0] == '.')
+         continue;
+   
+      filename = strdup(dptr->d_name);
+      snprintf(pathbuf, 512, "%s/%s", pathname, filename);
+      if (!(fcn_handle = dlopen(pathbuf, RTLD_LAZY)))
+      {
+         dl_error = dlerror();
+         fprintf(stderr, "DLoader_Init dlopen failed (%s)", 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);
+         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);
+
+      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;
+      }
+      
+   }   /* While */
+   
+}
+