UnivesalDisassembler(2003)

plugins.cc

Go to the documentation of this file.
00001 // plugins.cc
00002 //
00003 // uda - universal disassembler
00004 // Date: 2003-05-04
00005 //
00006 // Copyright (c) 2002-2003 Ales Smrcka 
00007 //
00008 // This program is licensed under GNU Library GPL. See the file COPYING.
00009 //
00010 // This module contains administration of plugins (loading, syncing).
00011 //
00012 
00013 #include <iostream>
00014 #include <dlfcn.h>
00015 #include <stdio.h>
00016 #include <sys/types.h>
00017 #include <sys/stat.h>
00018 #include <unistd.h>
00019 #include <dirent.h>
00020 #include <libgen.h>
00021 #include "plugins.h"
00022 #include "shared.h"
00023 #include "udaclasses.h"
00024 using namespace std;
00025 
00026 const char *pluginsdir = "plugins/";
00027 const char *configfile = "plugins/list";
00028 
00029 // plugins array (not NULL are relevant)
00030 VPlugins plugins;
00031 
00032 int EvEmpty_data(void*)
00033 {
00034     return 0;
00035 }
00036 
00037 int EvEmpty_void()
00038 {
00039     return 0;
00040 }
00041 
00043 // Class Plugin
00044 
00045 Plugin::Plugin()
00046 {
00047     dynfile=NULL;
00048     IsFileDefined=(Ev_IsFileDefined)&EvEmpty_data;
00049     LoadSections=(Ev_LoadSections)&EvEmpty_data;
00050     LoadSymbols=(Ev_LoadSymbols)&EvEmpty_void;
00051 }
00052 
00053 Plugin::~Plugin()
00054 {
00055     Close();
00056 }
00057 
00059 int Plugin::Open(const char *file)
00060 {
00061     dynfile = dlopen(file, RTLD_LAZY);
00062     if (dynfile==NULL)
00063         return 0;
00064     Splugin_init plugin_init = (Splugin_init)dlsym(dynfile, "plugin_init");
00065     const char *error;
00066     if ((error=dlerror())!=NULL)
00067     {
00068         debug("plugin_init function mistakes in "<<basename((char*)file)<<endl);
00069         dlclose(dynfile);
00070         return 0;
00071     }
00072     plugin_init(type, ident, syntax, Params);
00073     if (type&PLUGIN_SECTIONS)
00074     {
00075         IsFileDefined = (Ev_IsFileDefined)dlsym(dynfile, "is_file_defined");
00076         if ((error=dlerror())!=NULL)
00077         {
00078             debug("is_file_defined function mistakes in "<<basename((char*)file)<<endl);
00079             dlclose(dynfile);
00080             return 0;
00081         }
00082         LoadSections = (Ev_LoadSections)dlsym(dynfile, "load_sections");
00083         if ((error=dlerror())!=NULL)
00084         {
00085             debug("load_sections function mistakes in "<<basename((char*)file)<<endl);
00086             dlclose(dynfile);
00087             return 0;
00088         }
00089     }
00090     if (type&PLUGIN_SYMTABLE)
00091     {
00092         LoadSymbols = (Ev_LoadSymbols)dlsym(dynfile, "load_symbols");
00093         if ((error=dlerror())!=NULL)
00094         {
00095             debug("load_symbols function mistakes in "<<basename((char*)file)<<endl);
00096             dlclose(dynfile);
00097             return 0;
00098         }
00099     }
00100     filename=basename((char*)file);
00101     debug("Loaded plugin: "<<filename<<endl);
00102     return 1;
00103 }
00104 
00105 void Plugin::Close()
00106 {
00107     if (dynfile!=NULL)
00108         dlclose(dynfile);
00109 }
00110 
00111 // Print plugin information
00112 void Plugin::Info()
00113 {
00114     cout<<"Plugin "<<filename<<":"<<endl;
00115     cout<<"  ID="<<ident<<endl;
00116     cout<<"  attributes=";
00117     if (type&PLUGIN_SECTIONS)
00118         cout<<"PLUGIN_SECTIONS";
00119     if (type&~PLUGIN_SECTIONS)
00120         cout<<", ";
00121     if (type&PLUGIN_SYMTABLE)
00122         cout<<"PLUGIN_SYMTABLE";
00123     cout<<endl;
00124     cout<<"  options=";
00125     if (syntax!=NULL)
00126         cout<<syntax;
00127     else
00128         cout<<"<none>";
00129     cout<<endl;
00130 }
00131 
00133 // OpenPlugins() and ClosePlugins()
00134 
00135 // Load all plugins
00136 int OpenPlugins()
00137 {
00138     int actualpl=0;
00139     FILE *cfg;
00140     char file[1024];
00141     Plugin *pl;
00142     debug("Opening plugins from config file...\n");
00143     //open config file (list of plugins)
00144     if ((cfg=fopen((basedir+configfile).c_str(), "r"))!=NULL)
00145     {
00146         while (fgets(file, 1023, cfg)!=NULL)
00147         {
00148             //get C string from line
00149             file[1023]=0;
00150             for (int i=0;i<1024;i++)
00151                 if (file[i]=='\n')
00152                 {
00153                     file[i]=0;
00154                     break;
00155                 }
00156             //create plugin info
00157             pl=new Plugin;
00158             //load plugin info
00159             debug("Plugins::Open(): try to open "<<file<<endl);
00160             if (!pl->Open(file) && !pl->Open((basedir+pluginsdir+file).c_str()))
00161             {
00162                 debug("Can not open plugin "<<file<<endl);
00163                 delete pl; //bad plugin
00164             }
00165             else
00166                 plugins.push_back(pl);
00167         } //while load line
00168         fclose(cfg);
00169     }
00170     debug("Opening plugins from plugins directory...\n");
00171     
00172     //load plugins from plugin directory
00173     DIR *dir;
00174     struct dirent *dp;
00175     struct stat buf;
00176     char olddir[1024];
00177     getcwd(olddir, 1023);
00178     if (chdir((basedir+pluginsdir).c_str()))
00179         return actualpl;
00180     if ((dir=opendir("."))==NULL)
00181         return actualpl;
00182     file[0]='.';file[1]='/';
00183     //read files
00184     while ((dp=readdir(dir))!=NULL)
00185         if ((stat(dp->d_name, &buf)==0) && (S_ISREG(buf.st_mode)))//is regular (symlink included)
00186         {
00187             register bool already_loaded=false;
00188             VPlugins::iterator i;
00189             for (i=plugins.begin();i!=plugins.end();i++)
00190                 if ((already_loaded = (*i)->filename==dp->d_name))
00191                     break;
00192             if (!already_loaded)
00193             {
00194                 strncpy(&file[2], dp->d_name, 1020);
00195                 //create plugin info
00196                 pl=new Plugin;
00197                 //load plugin info
00198                 debug("Plugins::Open(): try to open "<<&file[2]<<endl);
00199                 if (!pl->Open(file))
00200                 {
00201                     debug("Can not open plugin "<<file<<endl);
00202                     delete pl; //bad plugin
00203                 }
00204                 else
00205                     plugins.push_back(pl);
00206             }
00207         }
00208     closedir(dir);
00209     chdir(olddir);
00210     return plugins.size();
00211 } //OpenPlugins
00212 
00213 void ClosePlugins()
00214 {
00215     VPlugins::iterator i;
00216     for (i=plugins.begin();i!=plugins.end();i++)
00217         delete *i;
00218     plugins.clear();
00219 }
00220 
00221 void PluginsInfo()
00222 {
00223     VPlugins::iterator i;
00224     for (i=plugins.begin();i!=plugins.end();i++)
00225         (*i)->Info();
00226 }
00227