diff --git a/CMakeLists.txt b/CMakeLists.txt index c006237850..c71762e112 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,10 +22,11 @@ set(BRO_SCRIPT_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/scripts) get_filename_component(BRO_SCRIPT_INSTALL_PATH ${BRO_SCRIPT_INSTALL_PATH} ABSOLUTE) -set(BRO_PLUGIN_INSTALL_PATH ${BRO_ROOT_DIR}/lib/bro/plugins) +set(BRO_PLUGIN_INSTALL_PATH ${BRO_ROOT_DIR}/lib/bro/plugins CACHE STRING "Installation path for plugins" FORCE) set(BRO_MAGIC_INSTALL_PATH ${BRO_ROOT_DIR}/share/bro/magic) set(BRO_MAGIC_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/magic/database) + configure_file(bro-path-dev.in ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.sh "export BROPATH=`${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n" diff --git a/aux/bro-aux b/aux/bro-aux index 715937ad72..f89d870437 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 715937ad72d9158d8c3142f81ee7005601d75db8 +Subproject commit f89d870437dbbbb107fd29f1085aef070e3bf373 diff --git a/cmake b/cmake index 6eb4cbfbc7..763b6d2574 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 6eb4cbfbc75f0bd13e247150b19932905a85e10c +Subproject commit 763b6d2574294e62f116e167c564a6292206a655 diff --git a/config.h.in b/config.h.in index 61124d2f67..d3889a2d90 100644 --- a/config.h.in +++ b/config.h.in @@ -214,7 +214,7 @@ #define HOST_ARCHITECTURE "@HOST_ARCHITECTURE@" /* String with extension of dynamic libraries (e.g., ".so") */ -#define SHARED_LIBRARY_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@" +#define DYNAMIC_PLUGIN_SUFFIX "@CMAKE_SHARED_MODULE_SUFFIX@" /* True if we're building outside of the main Bro source code tree. */ #ifndef BRO_PLUGIN_INTERNAL_BUILD diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 0a1006bd07..03c29d2201 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -467,7 +467,7 @@ static void WritePluginSectionHeading(FILE* f, const plugin::Plugin* p) fprintf(f, "-"); fprintf(f, "\n\n"); - fprintf(f, "%s\n\n", p->Description()); + fprintf(f, "%s\n\n", p->Description().c_str()); } static void WriteAnalyzerComponent(FILE* f, const analyzer::Component* c) @@ -568,7 +568,7 @@ static void WritePluginBifItems(FILE* f, const plugin::Plugin* p, if ( o ) o->WriteReST(f); else - reporter->Warning("No docs for ID: %s\n", it->GetID()); + reporter->Warning("No docs for ID: %s\n", it->GetID().c_str()); } } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 34af4eb974..8a0b9836c7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -389,6 +389,9 @@ install(TARGETS bro DESTINATION bin) set(BRO_EXE bro CACHE STRING "Bro executable binary" FORCE) +set(BRO_EXE_PATH ${CMAKE_CURRENT_BINARY_DIR}/bro + CACHE STRING "Path to Bro executable binary" FORCE) + # Target to create all the autogenerated files. add_custom_target(generate_outputs_stage1) add_dependencies(generate_outputs_stage1 ${bro_ALL_GENERATED_OUTPUTS}) diff --git a/src/DebugLogger.cc b/src/DebugLogger.cc index 267383503d..88635a6fee 100644 --- a/src/DebugLogger.cc +++ b/src/DebugLogger.cc @@ -117,7 +117,7 @@ void DebugLogger::Log(const plugin::Plugin& plugin, const char* fmt, ...) return; fprintf(file, "%17.06f/%17.06f [plugin %s] ", - network_time, current_time(true), plugin.Name()); + network_time, current_time(true), plugin.Name().c_str()); va_list ap; va_start(ap, fmt); diff --git a/src/input.h b/src/input.h index 8fcceb256b..d07a82f2ee 100644 --- a/src/input.h +++ b/src/input.h @@ -15,6 +15,7 @@ extern int brolex(); extern char last_tok[128]; extern void add_input_file(const char* file); +extern void add_input_file_at_front(const char* file); // Adds the substrings (using the given delimiter) in a string to the // given namelist. diff --git a/src/main.cc b/src/main.cc index c3c32a4b14..abafff5a85 100644 --- a/src/main.cc +++ b/src/main.cc @@ -223,7 +223,7 @@ void usage() fprintf(stderr, " $BROPATH | file search path (%s)\n", bro_path().c_str()); fprintf(stderr, " $BROMAGIC | libmagic mime magic database search path (%s)\n", bro_magic_path()); - fprintf(stderr, " $BRO_PLUGINS | plugin search path (%s)\n", bro_plugin_path()); + fprintf(stderr, " $BRO_PLUGIN_PATH | plugin search path (%s)\n", bro_plugin_path()); fprintf(stderr, " $BRO_PREFIXES | prefix list (%s)\n", bro_prefixes().c_str()); fprintf(stderr, " $BRO_DNS_FAKE | disable DNS lookups (%s)\n", bro_dns_fake()); fprintf(stderr, " $BRO_SEED_FILE | file to load seeds from (not set)\n"); @@ -820,7 +820,7 @@ int main(int argc, char** argv) if ( ! bare_mode ) add_input_file("base/init-default.bro"); - plugin_mgr->LoadPluginsFrom(bro_plugin_path()); + plugin_mgr->SearchDynamicPlugins(bro_plugin_path()); if ( optind == argc && read_files.length() == 0 && flow_files.length() == 0 && @@ -860,6 +860,9 @@ int main(int argc, char** argv) analyzer_mgr->InitPreScript(); file_mgr->InitPreScript(); + if ( ! bare_mode ) + plugin_mgr->ActivateAllDynamicPlugins(); + if ( events_file ) event_player = new EventPlayer(events_file); @@ -896,13 +899,14 @@ int main(int argc, char** argv) if ( reporter->Errors() > 0 ) exit(1); + plugin_mgr->InitPostScript(); + if ( print_plugins ) { show_plugins(print_plugins); exit(1); } - plugin_mgr->InitPostScript(); analyzer_mgr->InitPostScript(); file_mgr->InitPostScript(); diff --git a/src/plugin/Manager.cc b/src/plugin/Manager.cc index be1d7827a5..76e154067a 100644 --- a/src/plugin/Manager.cc +++ b/src/plugin/Manager.cc @@ -1,6 +1,7 @@ // See the file "COPYING" in the main distribution directory for copyright. #include +#include #include #include #include @@ -15,6 +16,7 @@ using namespace plugin; +Plugin* Manager::current_plugin = 0; string Manager::current_dir; string Manager::current_sopath; @@ -37,7 +39,7 @@ Manager::~Manager() delete [] hooks; } -void Manager::LoadPluginsFrom(const string& dir) +void Manager::SearchDynamicPlugins(const std::string& dir) { assert(! init); @@ -51,7 +53,7 @@ void Manager::LoadPluginsFrom(const string& dir) std::string d; while ( std::getline(s, d, ':') ) - LoadPluginsFrom(d); + SearchDynamicPlugins(d); return; } @@ -62,12 +64,34 @@ void Manager::LoadPluginsFrom(const string& dir) return; } - int rc = LoadPlugin(dir); + // Check if it's a plugin dirctory. - if ( rc >= 0 ) + const std::string magic = dir + "/__bro_plugin__"; + + if ( is_file(magic) ) + { + // It's a plugin, get it's name. + std::ifstream in(magic); + + if ( in.fail() ) + reporter->FatalError("cannot open plugin magic file %s", magic.c_str()); + + std::string name; + std::getline(in, name); + strstrip(name); + + if ( name.empty() ) + reporter->FatalError("empty plugin magic file %s", magic.c_str()); + + // Record it, so that we can later activate it. + + dynamic_plugins.insert(std::make_pair(name, dir)); + + DBG_LOG(DBG_PLUGINS, "Found plugin %s in %s", name.c_str(), dir.c_str()); return; + } - DBG_LOG(DBG_PLUGINS, "Searching directory %s recursively for plugins", dir.c_str()); + // No plugin here, traverse subirectories. DIR* d = opendir(dir.c_str()); @@ -98,22 +122,33 @@ void Manager::LoadPluginsFrom(const string& dir) } if ( st.st_mode & S_IFDIR ) - LoadPluginsFrom(path); + SearchDynamicPlugins(path); } } -int Manager::LoadPlugin(const std::string& dir) +bool Manager::ActivateDynamicPluginInternal(const std::string& name) { - assert(! init); + dynamic_plugin_map::iterator m = dynamic_plugins.find(name); - // Check if it's a plugin dirctory. - if ( ! is_file(dir + "/__bro_plugin__") ) - return -1; + if ( m == dynamic_plugins.end() ) + { + reporter->Error("plugin %s is not available", name.c_str()); + return false; + } - DBG_LOG(DBG_PLUGINS, "Loading plugin from %s", dir.c_str()); + std::string dir = m->second + "/"; + + if ( dir.empty() ) + { + // That's our marker that we have already activated this + // plugin. Silently ignore the new request. + return true; + } + + DBG_LOG(DBG_PLUGINS, "Activating plugin %s", name.c_str()); // Add the "scripts" and "bif" directories to BROPATH. - string scripts = dir + "/scripts"; + std::string scripts = dir + "scripts"; if ( is_dir(scripts) ) { @@ -121,44 +156,27 @@ int Manager::LoadPlugin(const std::string& dir) add_to_bro_path(scripts); } - string bif = dir + "/bif"; + // Load {bif,scripts}/__load__.bro automatically. - if ( is_dir(bif) ) - { - DBG_LOG(DBG_PLUGINS, " Adding %s to BROPATH", bif.c_str()); - add_to_bro_path(bif); - } - - // Load dylib/scripts/__load__.bro automatically. - string dyinit = dir + "/dylib/scripts/__load__.bro"; - - if ( is_file(dyinit) ) - { - DBG_LOG(DBG_PLUGINS, " Adding %s for loading", dyinit.c_str()); - add_input_file(dyinit.c_str()); - } - - // Load scripts/__load__.bro automatically. - string init = scripts + "/__load__.bro"; + string init = dir + "lib/bif/__load__.bro"; if ( is_file(init) ) { - DBG_LOG(DBG_PLUGINS, " Adding %s for loading", init.c_str()); - add_input_file(init.c_str()); + DBG_LOG(DBG_PLUGINS, " Loading %s", init.c_str()); + scripts_to_load.push_back(init); } - // Load bif/__load__.bro automatically. - init = bif + "/__load__.bro"; + init = dir + "scripts/__load__.bro"; if ( is_file(init) ) { - DBG_LOG(DBG_PLUGINS, " Adding %s for loading", init.c_str()); - add_input_file(init.c_str()); + DBG_LOG(DBG_PLUGINS, " Loading %s", init.c_str()); + scripts_to_load.push_back(init); } // Load shared libraries. - string dypattern = dir + "/dylib/*." + HOST_ARCHITECTURE + SHARED_LIBRARY_SUFFIX; + string dypattern = dir + "/lib/*." + HOST_ARCHITECTURE + DYNAMIC_PLUGIN_SUFFIX; DBG_LOG(DBG_PLUGINS, " Searching for shared libraries %s", dypattern.c_str()); @@ -170,11 +188,10 @@ int Manager::LoadPlugin(const std::string& dir) { const char* path = gl.gl_pathv[i]; + current_plugin = 0; current_dir = dir; current_sopath = path; void* hdl = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); - current_dir.clear(); - current_sopath.clear(); if ( ! hdl ) { @@ -182,6 +199,24 @@ int Manager::LoadPlugin(const std::string& dir) reporter->FatalError("cannot load plugin library %s: %s", path, err ? err : ""); } + if ( ! current_plugin ) + reporter->FatalError("load plugin library %s did not instantiate a plugin", path); + + // We execute the pre-script initialization here; this in + // fact could be *during* script initialization if we got + // triggered via @load-plugin. + current_plugin->InitPreScript(); + + // Make sure the name the plugin reports is consistent with + // what we expect from its magic file. + if ( string(current_plugin->Name()) != name ) + reporter->FatalError("inconsistent plugin name: %s vs %s", + current_plugin->Name().c_str(), name.c_str()); + + current_dir.clear(); + current_sopath.clear(); + current_plugin = 0; + DBG_LOG(DBG_PLUGINS, " Loaded %s", path); } } @@ -189,10 +224,42 @@ int Manager::LoadPlugin(const std::string& dir) else { DBG_LOG(DBG_PLUGINS, " No shared library found"); - return 1; } - return 1; + // Mark this plugin as activated by clearing the path. + m->second.clear(); + + return true; + } + +bool Manager::ActivateDynamicPlugin(const std::string& name) + { + if ( ! ActivateDynamicPluginInternal(name) ) + return false; + + UpdateInputFiles(); + return true; + } + +bool Manager::ActivateAllDynamicPlugins() + { + for ( dynamic_plugin_map::const_iterator i = dynamic_plugins.begin(); + i != dynamic_plugins.end(); i++ ) + { + if ( ! ActivateDynamicPluginInternal(i->first) ) + return false; + } + + UpdateInputFiles(); + + return true; + } + +void Manager::UpdateInputFiles() + { + for ( file_list::const_reverse_iterator i = scripts_to_load.rbegin(); + i != scripts_to_load.rend(); i++ ) + add_input_file_at_front((*i).c_str()); } static bool plugin_cmp(const Plugin* a, const Plugin* b) @@ -205,11 +272,13 @@ bool Manager::RegisterPlugin(Plugin *plugin) Manager::PluginsInternal()->push_back(plugin); if ( current_dir.size() && current_sopath.size() ) + // A dynamic plugin, record its location. plugin->SetPluginLocation(current_dir.c_str(), current_sopath.c_str()); // Sort plugins by name to make sure we have a deterministic order. PluginsInternal()->sort(plugin_cmp); + current_plugin = plugin; return true; } @@ -220,7 +289,6 @@ void Manager::InitPreScript() for ( plugin_list::iterator i = Manager::PluginsInternal()->begin(); i != Manager::PluginsInternal()->end(); i++ ) { Plugin* plugin = *i; - plugin->InitPreScript(); } @@ -333,7 +401,7 @@ void Manager::DisableHook(HookType hook, Plugin* plugin) } } -int Manager::HookLoadFile(const char* file) +int Manager::HookLoadFile(const string& file) { hook_list* l = hooks[HOOK_LOAD_FILE]; diff --git a/src/plugin/Manager.h b/src/plugin/Manager.h index 0c52679a64..5c5c7430be 100644 --- a/src/plugin/Manager.h +++ b/src/plugin/Manager.h @@ -40,17 +40,41 @@ public: virtual ~Manager(); /** - * Loads all plugins dynamically from a set of directories. Multiple - * directories are split by ':'. If a directory does not contain a - * plugin itself, the method searches for plugins recursively. For - * plugins found, the method loads the plugin's shared library and - * makes its scripts available to the interpreter. + * Searches a set of directories for plugins. If a specificed + * directory does not contain a plugin itself, the method searches + * for plugins recursively. For plugins found, the method makes them + * available for later activation via ActivatePlugin(). * * This must be called only before InitPluginsPreScript(). * - * @param dir The directory to search for plugins. + * @param dir The directory to search for plugins. Multiple + * directories are split by ':'. */ - void LoadPluginsFrom(const std::string& dir); + void SearchDynamicPlugins(const std::string& dir); + + /** + * Activates a plugin that SearchPlugins() has previously discovered. + * Activing a plugin involved loading its dynamic module, making its + * bifs available, and adding its script paths to BROPATH. + * + * @param name The name of the plugin, as determined previously by + * SearchPlugin(). + * + * @return True if the plugin has been loaded successfully. + * + */ + bool ActivateDynamicPlugin(const std::string& name); + + /** + * Activates all plugins that SearchPlugins() has previously + * discovered. The effect is the same all calling \a + * ActivePlugin(name) for every plugin. + * + * @return True if all plugins have been loaded successfully. If one + * fail to load, the method stops there without loading any furthers + * and returns false. + */ + bool ActivateAllDynamicPlugins(); /** * First-stage initializion of the manager. This is called early on @@ -148,7 +172,7 @@ public: * successfully; 0 if a plugin took over the file but had trouble * loading it; and -1 if no plugin was interested in the file at all. */ - virtual int HookLoadFile(const char* file); + virtual int HookLoadFile(const string& file); /** * Hook that filters calls to a script function/event/hook. @@ -196,40 +220,37 @@ public: */ static bool RegisterPlugin(Plugin* plugin); -protected: - /** - * Loads a plugin dynamically from a given directory. It loads the - * plugin's shared library, and makes its scripts available to the - * interpreter. Different from LoadPluginsFrom() this method does not - * further descend the directory tree recursively to search for - * plugins. - * - * This must be called only before InitPluginsPreScript() - * - * @param file The path to the plugin to load. - * - * @return 0 if there's a plugin in this directory, but there was a - * problem loading it; -1 if there's no plugin at all in this - * directory; 1 if there's a plugin in this directory and we loaded - * it successfully. - */ - int LoadPlugin(const std::string& dir); - private: + bool ActivateDynamicPluginInternal(const std::string& name); + void UpdateInputFiles(); + + // All found dynamic plugins, mapping their names to base directory. + typedef std::map dynamic_plugin_map; + dynamic_plugin_map dynamic_plugins; + + // We buffer scripts to load temporarliy to get them to load in the + // right order. + typedef std::list file_list; + file_list scripts_to_load; + + bool init; + // A hook list keeps pairs of plugin and priority interested in a // given hook. typedef std::list > hook_list; - static plugin_list* PluginsInternal(); - - bool init; - // An array indexed by HookType. An entry is null if there's no hook // of that type enabled. hook_list** hooks; + static Plugin* current_plugin; static string current_dir; static string current_sopath; + + // Returns a modifiable list of all plugins, both static and dynamic. + // This is a static method so that plugins can register themselves + // even before the manager exists. + static plugin_list* PluginsInternal(); }; template diff --git a/src/plugin/Plugin.cc b/src/plugin/Plugin.cc index 20d436907b..000bb2af52 100644 --- a/src/plugin/Plugin.cc +++ b/src/plugin/Plugin.cc @@ -26,15 +26,15 @@ const char* hook_name(HookType h) return hook_names[int(h)]; } -BifItem::BifItem(const char* arg_id, Type arg_type) +BifItem::BifItem(const std::string& arg_id, Type arg_type) { - id = copy_string(arg_id); + id = arg_id; type = arg_type; } BifItem::BifItem(const BifItem& other) { - id = copy_string(other.id); + id = other.id; type = other.type; } @@ -42,7 +42,7 @@ BifItem& BifItem::operator=(const BifItem& other) { if ( this != &other ) { - id = copy_string(other.id); + id = other.id; type = other.type; } @@ -51,20 +51,19 @@ BifItem& BifItem::operator=(const BifItem& other) BifItem::~BifItem() { - delete [] id; } Plugin::Plugin() { - name = copy_string(""); - description = copy_string(""); + name = ""; + description = ""; // These will be reset by the BRO_PLUGIN_* macros. version = -9999; api_version = -9999; dynamic = false; - base_dir = 0; - sopath = 0; + base_dir = ""; + sopath = ""; Manager::RegisterPlugin(this); } @@ -72,33 +71,26 @@ Plugin::Plugin() Plugin::~Plugin() { Done(); - - delete [] name; - delete [] description; - delete [] base_dir; - delete [] sopath; } -const char* Plugin::Name() const +const std::string& Plugin::Name() const { return name; } -void Plugin::SetName(const char* arg_name) +void Plugin::SetName(const std::string& arg_name) { - delete [] name; - name = copy_string(arg_name); + name = arg_name; } -const char* Plugin::Description() const +const std::string& Plugin::Description() const { return description; } -void Plugin::SetDescription(const char* arg_description) +void Plugin::SetDescription(const std::string& arg_description) { - delete [] description; - description = copy_string(arg_description); + description = arg_description; } int Plugin::Version() const @@ -121,12 +113,12 @@ bool Plugin::DynamicPlugin() const return dynamic; } -const char* Plugin::PluginDirectory() const +const std::string& Plugin::PluginDirectory() const { return base_dir; } -const char* Plugin::PluginPath() const +const std::string& Plugin::PluginPath() const { return sopath; } @@ -141,12 +133,10 @@ void Plugin::SetDynamicPlugin(bool arg_dynamic) dynamic = arg_dynamic; } -void Plugin::SetPluginLocation(const char* arg_dir, const char* arg_sopath) +void Plugin::SetPluginLocation(const std::string& arg_dir, const std::string& arg_sopath) { - delete [] base_dir; - delete [] sopath; - base_dir = copy_string(arg_dir); - sopath = copy_string(arg_sopath); + base_dir = arg_dir; + sopath = arg_sopath; } void Plugin::InitPreScript() @@ -197,9 +187,9 @@ static bool component_cmp(const Component* a, const Component* b) return a->Name() < b->Name(); } -bool Plugin::LoadBroFile(const char* file) +bool Plugin::LoadBroFile(const std::string& file) { - ::add_input_file(file); + ::add_input_file(file.c_str()); return true; } @@ -208,7 +198,7 @@ void Plugin::__AddBifInitFunction(bif_init_func c) bif_inits.push_back(c); } -void Plugin::AddBifItem(const char* name, BifItem::Type type) +void Plugin::AddBifItem(const std::string& name, BifItem::Type type) { BifItem bi(name, (BifItem::Type)type); bif_items.push_back(bi); @@ -238,7 +228,7 @@ void Plugin::DisableHook(HookType hook) plugin_mgr->DisableHook(hook, this); } -int Plugin::HookLoadFile(const char* file) +int Plugin::HookLoadFile(const std::string& file) { return -1; } @@ -266,7 +256,7 @@ void Plugin::Describe(ODesc* d) const d->Add("Plugin: "); d->Add(name); - if ( description && *description ) + if ( description.size() ) { d->Add(" - "); d->Add(description); diff --git a/src/plugin/Plugin.h b/src/plugin/Plugin.h index 915563e98c..7da5a74c6f 100644 --- a/src/plugin/Plugin.h +++ b/src/plugin/Plugin.h @@ -50,7 +50,7 @@ public: * * @param type The type of the item. */ - BifItem(const char* id, Type type); + BifItem(const std::string& id, Type type); /** * Copy constructor. @@ -70,7 +70,7 @@ public: /** * Returns the script-level ID as passed into the constructor. */ - const char* GetID() const { return id; } + const std::string& GetID() const { return id; } /** * Returns the type as passed into the constructor. @@ -78,7 +78,7 @@ public: Type GetType() const { return type; } private: - const char* id; + std::string id; Type type; }; @@ -113,7 +113,7 @@ public: typedef std::list component_list; typedef std::list bif_item_list; typedef std::list > hook_list; - typedef std::list > bif_init_func_result; + typedef std::list > bif_init_func_result; typedef void (*bif_init_func)(Plugin *); /** @@ -129,12 +129,12 @@ public: /** * Returns the name of the plugin. */ - const char* Name() const; + const std::string& Name() const; /** * Returns a short textual description of the plugin, if provided. */ - const char* Description() const; + const std::string& Description() const; /** * Returns the version of the plugin. Version are only meaningful for @@ -152,13 +152,13 @@ public: * For dynamic plugins, returns the base directory from which it was * loaded. For static plugins, returns null. **/ - const char* PluginDirectory() const; + const std::string& PluginDirectory() const; /** * For dynamic plugins, returns the full path to the shared library * from which it was loaded. For static plugins, returns null. **/ - const char* PluginPath() const; + const std::string& PluginPath() const; /** * Returns the internal API version that this plugin relies on. Only @@ -225,7 +225,7 @@ public: * * @param type The item's type. */ - void AddBifItem(const char* name, BifItem::Type type); + void AddBifItem(const std::string& name, BifItem::Type type); /** * Adds a file to the list of files that Bro loads at startup. This @@ -242,7 +242,7 @@ public: * @return True if successful (which however may only mean * "successfully queued"). */ - bool LoadBroFile(const char* file); + bool LoadBroFile(const std::string& file); /** * Internal function adding an entry point for registering @@ -324,7 +324,7 @@ protected: * printed an error message); and -1 if the plugin wasn't interested * in the file at all. */ - virtual int HookLoadFile(const char* file); + virtual int HookLoadFile(const std::string& file); /** * Hook into executing a script-level function/event/hook. Whenever @@ -396,7 +396,7 @@ protected: * * @param name The name. Makes a copy internally. */ - void SetName(const char* name); + void SetName(const std::string& name); /** * Sets the plugin's textual description. @@ -406,7 +406,7 @@ protected: * * @param name The description. Makes a copy internally. */ - void SetDescription(const char* descr); + void SetDescription(const std::string& descr); /** * Sets the plugin's version. @@ -454,7 +454,7 @@ protected: * @param sopath The full path the shared library loaded. The * functions makes an internal copy of string. */ - void SetPluginLocation(const char* dir, const char* sopath); + void SetPluginLocation(const std::string& dir, const std::string& sopath); private: /** @@ -465,10 +465,10 @@ private: typedef std::list bif_init_func_list; - const char* name; - const char* description; - const char* base_dir; - const char* sopath; + std::string name; + std::string description; + std::string base_dir; + std::string sopath; int version; int api_version; bool dynamic; diff --git a/src/scan.l b/src/scan.l index 599a660fee..d5eedc83c3 100644 --- a/src/scan.l +++ b/src/scan.l @@ -407,6 +407,11 @@ when return TOK_WHEN; new_sig_file); } +@load-plugin{WS}{ID} { + const char* plugin = skip_whitespace(yytext + 12); + plugin_mgr->ActivateDynamicPlugin(plugin); +} + @unload{WS}{FILE} { // Skip "@unload". const char* new_file = skip_whitespace(yytext + 7); @@ -829,6 +834,17 @@ void add_input_file(const char* file) input_files.append(copy_string(file)); } +void add_input_file_at_front(const char* file) + { + if ( ! file ) + reporter->InternalError("empty filename"); + + if ( ! filename ) + (void) load_files(file); + else + input_files.insert(copy_string(file)); + } + void add_to_name_list(char* s, char delim, name_list& nl) { while ( s ) diff --git a/src/util.cc b/src/util.cc index e41925a414..917ddf9388 100644 --- a/src/util.cc +++ b/src/util.cc @@ -664,6 +664,13 @@ string strreplace(const string& s, const string& o, const string& n) return r; } +std::string strstrip(std::string s) + { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; + } + int hmac_key_set = 0; uint8 shared_hmac_md5_key[16]; @@ -942,7 +949,7 @@ const char* bro_magic_path() const char* bro_plugin_path() { - const char* path = getenv("BRO_PLUGINS"); + const char* path = getenv("BRO_PLUGIN_PATH"); if ( ! path ) path = BRO_PLUGIN_INSTALL_PATH; diff --git a/src/util.h b/src/util.h index e8bce8221d..feae01c0fb 100644 --- a/src/util.h +++ b/src/util.h @@ -155,6 +155,9 @@ bool is_file(const std::string& path); // Replaces all occurences of *o* in *s* with *n*. extern std::string strreplace(const std::string& s, const std::string& o, const std::string& n); +// Remove all leading and trainling white space from string. +extern std::string strstrip(std::string s); + extern uint8 shared_hmac_md5_key[16]; extern int hmac_key_set; diff --git a/testing/btest/core/plugins/analyzer.bro b/testing/btest/core/plugins/analyzer.bro index 2a72797564..c9831ad269 100644 --- a/testing/btest/core/plugins/analyzer.bro +++ b/testing/btest/core/plugins/analyzer.bro @@ -1,9 +1,9 @@ # @TEST-EXEC: ${DIST}/aux/bro-aux/plugin-support/init-plugin Demo Foo # @TEST-EXEC: cp -r %DIR/analyzer-plugin/* . # @TEST-EXEC: make BRO=${DIST} -# @TEST-EXEC: BROPLUGINS=`pwd` bro -NN | awk '/^Plugin:.*Demo/ {p=1; print; next} /^Plugin:/{p=0} p==1{print}' >>output +# @TEST-EXEC: BRO_PLUGIN_PATH=`pwd` bro -NN | awk '/^Plugin:.*Demo/ {p=1; print; next} /^Plugin:/{p=0} p==1{print}' >>output # @TEST-EXEC: echo === >>output -# @TEST-EXEC: BROPLUGINS=`pwd` bro -r $TRACES/port4242.trace %INPUT >>output +# @TEST-EXEC: BRO_PLUGIN_PATH=`pwd` bro -r $TRACES/port4242.trace %INPUT >>output # @TEST-EXEC: btest-diff output event foo_message(c: connection, data: string) diff --git a/testing/btest/core/plugins/test-plugin.sh b/testing/btest/core/plugins/test-plugin.sh index 87b09b2e4d..3b67b9454f 100644 --- a/testing/btest/core/plugins/test-plugin.sh +++ b/testing/btest/core/plugins/test-plugin.sh @@ -1,11 +1,11 @@ # @TEST-EXEC: ${DIST}/aux/bro-aux/plugin-support/init-plugin Demo Foo # @TEST-EXEC: bash %INPUT # @TEST-EXEC: make BRO=${DIST} -# @TEST-EXEC: BROPLUGINS=`pwd` bro -NN | awk '/^Plugin:.*Demo/ {p=1; print; next} /^Plugin:/{p=0} p==1{print}' >>output +# @TEST-EXEC: BRO_PLUGIN_PATH=`pwd` bro -NN | awk '/^Plugin:.*Demo/ {p=1; print; next} /^Plugin:/{p=0} p==1{print}' >>output # @TEST-EXEC: echo === >>output -# @TEST-EXEC: BROPLUGINS=`pwd` bro -r $TRACES/empty.trace >>output +# @TEST-EXEC: BRO_PLUGIN_PATH=`pwd` bro -r $TRACES/empty.trace >>output # @TEST-EXEC: echo === >>output -# @TEST-EXEC: BROPLUGINS=`pwd` bro demo/foo -r $TRACES/empty.trace >>output +# @TEST-EXEC: BRO_PLUGIN_PATH=`pwd` bro demo/foo -r $TRACES/empty.trace >>output # @TEST-EXEC: btest-diff output cat >scripts/__load__.bro <