/* * plugin.c -- enfle plugin interface * (C)Copyright 1999 by Hiroshi Takekawa * This file is part of Enfle. * * Last Modified: Fri Sep 1 00:56:32 2000. * $Id: plugin.c,v 1.11 2000/09/08 23:12:48 sian Exp $ * * Enfle 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. * * Enfle 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 */ #include "plugin.h" #include static PluginInfo * plugin_allocate(void) { return malloc(sizeof(PluginInfo)); } int plugin_install(Dlist *plist, PluginInfo *pinfo) { Dlist_data *t; PluginInfo *p; for (t = dlist_gettop(plist); t != NULL; t = t->next) { p = t->data; if (p->type == pinfo->type && !strcmp(p->pluginshortname, pinfo->pluginshortname)) { free(pinfo); return 1; /* already installed */ } } return (dlist_add(plist, (void *)pinfo) != NULL) ? 1 : 0; } int plugin_uninstall(PluginInfo *pinfo) { int f = 1; if (pinfo->dlhandle != NULL) f = dlclose(pinfo->dlhandle); free(pinfo); return f; } PluginInfo * plugin_retrieve_info(int (*get_plugininfo)(PluginInfo *)) { PluginInfo *p; if ((p = plugin_allocate()) == NULL) { fprintf(stderr, "plugin_retrieve_info: FATAL: No enough memory for PluginInfo\n"); exit(1); } if (!(*get_plugininfo)(p)) { fprintf(stderr, "plugin_retrieve_info: get_plugininfo: returns 0\n"); free(p); return NULL; } if (p->version != 1) { fprintf(stderr, "plugin_retrieve_info: Invalid version %d\n", p->version); free(p); return NULL; } if (p->type != _Loader && p->type != _Saver && p->type != _Archiver) { fprintf(stderr, "plugin_retrieve_info: Invalid plugin type %d\n", p->type); free(p); return NULL; } if (p->pluginname == NULL) { fprintf(stderr, "plugin_retrieve_info: p->pluginname null\n"); free(p); return NULL; } if (p->author == NULL) { fprintf(stderr, "plugin_retrieve_info: p->author null\n"); free(p); return NULL; } return p; } int plugin_load(Dlist *plist, char *path) { void *handle; const char *error; int (*get_plugininfo)(PluginInfo *); PluginInfo *p; if ((handle = dlopen(path, RTLD_LAZY)) == NULL) { fprintf(stderr, "plugin_load: dlopen: %s\n", dlerror()); return 0; } if ((get_plugininfo = dlsym(handle, "get_plugininfo")) == NULL && ((error = dlerror()) != NULL)) { fprintf(stderr, "plugin_load: dlsym: %s: %s\n", path, error); return 0; } if ((p = plugin_retrieve_info(get_plugininfo)) == NULL) { fprintf(stderr, "plugin_load: plugin_retrieveinfo: returns NULL\n"); return 0; } p->dlhandle = handle; return plugin_install(plist, p); } int plugin_scan_directory(Dlist *plist, char *dirpath) { char *filename, *extname; DIR *dir; struct dirent *ent; struct stat statbuf; int count = 0; if ((dir = opendir(dirpath)) == NULL) { char buf[256]; sprintf(buf, "plugin_scan_directory: opendir: %s", dirpath); perror(buf); return 0; } while ((ent = readdir(dir))) { if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; if ((filename = malloc(strlen(dirpath) + strlen(ent->d_name) + 2)) == NULL) { fprintf(stderr, "plugin_scan_directory: FATAL: No enough memory for filename\n"); closedir(dir); exit(-1); } sprintf(filename, "%s/%s", dirpath, ent->d_name); if (!stat(filename, &statbuf)) { if (S_ISDIR(statbuf.st_mode)) count += plugin_scan_directory(plist, filename); else if (S_ISREG(statbuf.st_mode) && (extname = strchr(ent->d_name, '.')) && (!strncmp(extname, ".so", 3))) { plugin_load(plist, filename); count++; } } free(filename); } closedir(dir); return count; } int plugin_destroy(Dlist *plist) { Dlist_data *t; for (t = dlist_gettop(plist); t != NULL; t = t->next) { plugin_uninstall(t->data); t->data = NULL; } return dlist_destroy(plist, 1); }