diff --git a/src/Debug.cc b/src/Debug.cc index 54a40c58d1..a45c27888e 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -348,7 +348,7 @@ vector parse_location_string(const string& s) if ( ! sscanf(line_string.c_str(), "%d", &plr.line) ) plr.type = plrUnknown; - string path(find_file(filename, bro_path(), "bro")); + string path(find_script_file(filename, bro_path())); if ( path.empty() ) { diff --git a/src/OSFinger.cc b/src/OSFinger.cc index df5f30b0cc..1b540a1fd0 100644 --- a/src/OSFinger.cc +++ b/src/OSFinger.cc @@ -295,7 +295,7 @@ void OSFingerprint::load_config(const char* file) char buf[MAXLINE]; char* p; - FILE* c = open_file(find_file(file, bro_path(), "osf")); + FILE* c = open_file(find_file(file, bro_path(), ".osf")); if (!c) { diff --git a/src/RuleMatcher.cc b/src/RuleMatcher.cc index 54228d58dd..5b72264926 100644 --- a/src/RuleMatcher.cc +++ b/src/RuleMatcher.cc @@ -235,7 +235,7 @@ bool RuleMatcher::ReadFiles(const name_list& files) for ( int i = 0; i < files.length(); ++i ) { - rules_in = open_file(find_file(files[i], bro_path(), "sig")); + rules_in = open_file(find_file(files[i], bro_path(), ".sig")); if ( ! rules_in ) { diff --git a/src/broxygen/ScriptInfo.cc b/src/broxygen/ScriptInfo.cc index a32d96cdd5..da6ba6b44a 100644 --- a/src/broxygen/ScriptInfo.cc +++ b/src/broxygen/ScriptInfo.cc @@ -158,7 +158,7 @@ static string make_redef_details(const string& heading, char underline, ScriptInfo::ScriptInfo(const string& arg_name, const string& arg_path) : Info(), name(arg_name), path(arg_path), - is_pkg_loader(SafeBasename(name).result == PACKAGE_LOADER), + is_pkg_loader(is_package_loader(SafeBasename(name).result)), dependencies(), module_usages(), comments(), id_info(), redef_options(), constants(), state_vars(), types(), events(), hooks(), functions(), redefs() @@ -314,7 +314,7 @@ string ScriptInfo::DoReStructuredText(bool roles_only) const if ( it != dependencies.begin() ) rval += ", "; - string path = find_file(*it, bro_path(), "bro"); + string path = find_script_file(*it, bro_path()); string doc = *it; if ( ! path.empty() && is_dir(path.c_str()) ) @@ -365,8 +365,13 @@ time_t ScriptInfo::DoGetModificationTime() const if ( ! info ) { - string pkg_name = *it + "/" + PACKAGE_LOADER; - info = broxygen_mgr->GetScriptInfo(pkg_name); + for (const string& ext : script_extensions) + { + string pkg_name = *it + "/__load__" + ext; + info = broxygen_mgr->GetScriptInfo(pkg_name); + if ( info ) + break; + } if ( ! info ) reporter->InternalWarning("Broxygen failed to get mtime of %s", diff --git a/src/broxygen/Target.cc b/src/broxygen/Target.cc index dba0d67d6c..2610f648e7 100644 --- a/src/broxygen/Target.cc +++ b/src/broxygen/Target.cc @@ -410,7 +410,7 @@ void ScriptTarget::DoFindDependencies(const vector& infos) for ( size_t i = 0; i < script_deps.size(); ++i ) { - if ( SafeBasename(script_deps[i]->Name()).result == PACKAGE_LOADER ) + if ( is_package_loader(SafeBasename(script_deps[i]->Name()).result) ) { string pkg_dir = SafeDirname(script_deps[i]->Name()).result; string target_file = Name() + pkg_dir + "/index.rst"; diff --git a/src/plugin/Manager.cc b/src/plugin/Manager.cc index 836520d03a..e098d955c1 100644 --- a/src/plugin/Manager.cc +++ b/src/plugin/Manager.cc @@ -13,6 +13,7 @@ #include "../Reporter.h" #include "../Func.h" #include "../Event.h" +#include "../util.h" using namespace plugin; @@ -182,30 +183,44 @@ bool Manager::ActivateDynamicPluginInternal(const std::string& name, bool ok_if_ add_to_bro_path(scripts); } - // First load {scripts}/__preload__.bro automatically. - string init = dir + "scripts/__preload__.bro"; + string init; - if ( is_file(init) ) + // First load {scripts}/__preload__.bro automatically. + for (const string& ext : script_extensions) { - DBG_LOG(DBG_PLUGINS, " Loading %s", init.c_str()); - scripts_to_load.push_back(init); + init = dir + "scripts/__preload__" + ext; + + if ( is_file(init) ) + { + DBG_LOG(DBG_PLUGINS, " Loading %s", init.c_str()); + scripts_to_load.push_back(init); + break; + } } // Load {bif,scripts}/__load__.bro automatically. - init = dir + "lib/bif/__load__.bro"; - - if ( is_file(init) ) + for (const string& ext : script_extensions) { - DBG_LOG(DBG_PLUGINS, " Loading %s", init.c_str()); - scripts_to_load.push_back(init); + init = dir + "lib/bif/__load__" + ext; + + if ( is_file(init) ) + { + DBG_LOG(DBG_PLUGINS, " Loading %s", init.c_str()); + scripts_to_load.push_back(init); + break; + } } - init = dir + "scripts/__load__.bro"; - - if ( is_file(init) ) + for (const string& ext : script_extensions) { - DBG_LOG(DBG_PLUGINS, " Loading %s", init.c_str()); - scripts_to_load.push_back(init); + init = dir + "scripts/__load__" + ext; + + if ( is_file(init) ) + { + DBG_LOG(DBG_PLUGINS, " Loading %s", init.c_str()); + scripts_to_load.push_back(init); + break; + } } // Load shared libraries. diff --git a/src/scan.l b/src/scan.l index c2be426044..4da18b125f 100644 --- a/src/scan.l +++ b/src/scan.l @@ -77,6 +77,17 @@ static string find_relative_file(const string& filename, const string& ext) return find_file(filename, bro_path(), ext); } +static string find_relative_script_file(const string& filename) + { + if ( filename.empty() ) + return string(); + + if ( filename[0] == '.' ) + return find_script_file(filename, SafeDirname(::filename).result); + else + return find_script_file(filename, bro_path()); + } + static ino_t get_inode_num(FILE* f, const string& path) { struct stat b; @@ -363,14 +374,14 @@ when return TOK_WHEN; @load{WS}{FILE} { const char* new_file = skip_whitespace(yytext + 5); // Skip "@load". string loader = ::filename; // load_files may change ::filename, save copy - string loading = find_relative_file(new_file, "bro"); + string loading = find_relative_script_file(new_file); (void) load_files(new_file); broxygen_mgr->ScriptDependency(loader, loading); } @load-sigs{WS}{FILE} { const char* file = skip_whitespace(yytext + 10); - string path = find_relative_file(file, "sig"); + string path = find_relative_file(file, ".sig"); int rc = PLUGIN_HOOK_WITH_RESULT(HOOK_LOAD_FILE, HookLoadFile(plugin::Plugin::SIGNATURES, file, path), -1); switch ( rc ) { @@ -430,7 +441,7 @@ when return TOK_WHEN; @unload{WS}{FILE} { // Skip "@unload". const char* file = skip_whitespace(yytext + 7); - string path = find_relative_file(file, "bro"); + string path = find_relative_script_file(file); if ( path.empty() ) reporter->Error("failed find file associated with @unload %s", file); @@ -624,7 +635,7 @@ static bool already_scanned(const string& path) static int load_files(const char* orig_file) { - string file_path = find_relative_file(orig_file, "bro"); + string file_path = find_relative_script_file(orig_file); int rc = PLUGIN_HOOK_WITH_RESULT(HOOK_LOAD_FILE, HookLoadFile(plugin::Plugin::SCRIPT, orig_file, file_path), -1); if ( rc == 1 ) @@ -970,7 +981,7 @@ int yywrap() string canon = without_bropath_component(it->name); string flat = flatten_script_name(canon, prefixes[i]); - string path = find_relative_file(flat, "bro"); + string path = find_relative_script_file(flat); if ( ! path.empty() ) { diff --git a/src/util.cc b/src/util.cc index cce49a7f6d..227faa9c1f 100644 --- a/src/util.cc +++ b/src/util.cc @@ -20,6 +20,7 @@ #endif #include +#include #include #include #include @@ -1007,7 +1008,18 @@ string bro_prefixes() return rval; } -const char* PACKAGE_LOADER = "__load__.bro"; +const array script_extensions = {".zeek", ".bro"}; + +bool is_package_loader(const string& path) + { + for (const string& ext : script_extensions) + { + if (path == "__load__" + ext) + return true; + } + + return false; + } FILE* open_file(const string& path, const string& mode) { @@ -1034,13 +1046,22 @@ static bool can_read(const string& path) FILE* open_package(string& path, const string& mode) { string arg_path = path; - path.append("/").append(PACKAGE_LOADER); + path.append("/__load__"); - if ( can_read(path) ) - return open_file(path, mode); + for (const string& ext : script_extensions) + { + string p = path + ext; + if ( can_read(p) ) + { + path.append(ext); + return open_file(path, mode); + } + } + path.append(script_extensions[0]); + string package_loader = "__load__" + script_extensions[0]; reporter->Error("Failed to open package '%s': missing '%s' file", - arg_path.c_str(), PACKAGE_LOADER); + arg_path.c_str(), package_loader.c_str()); return 0; } @@ -1123,7 +1144,7 @@ string flatten_script_name(const string& name, const string& prefix) if ( ! rval.empty() ) rval.append("."); - if ( SafeBasename(name).result == PACKAGE_LOADER ) + if ( is_package_loader(SafeBasename(name).result) ) rval.append(SafeDirname(name).result); else rval.append(name); @@ -1221,7 +1242,7 @@ string without_bropath_component(const string& path) } static string find_file_in_path(const string& filename, const string& path, - const string& opt_ext = "") + const vector& opt_ext) { if ( filename.empty() ) return string(); @@ -1239,10 +1260,13 @@ static string find_file_in_path(const string& filename, const string& path, if ( ! opt_ext.empty() ) { - string with_ext = abs_path + '.' + opt_ext; + for (const string& ext : opt_ext) + { + string with_ext = abs_path + ext; - if ( can_read(with_ext) ) - return with_ext; + if ( can_read(with_ext) ) + return with_ext; + } } if ( can_read(abs_path) ) @@ -1257,9 +1281,31 @@ string find_file(const string& filename, const string& path_set, vector paths; tokenize_string(path_set, ":", &paths); + vector ext; + if ( ! opt_ext.empty() ) + ext.push_back(opt_ext); + for ( size_t n = 0; n < paths.size(); ++n ) { - string f = find_file_in_path(filename, paths[n], opt_ext); + string f = find_file_in_path(filename, paths[n], ext); + + if ( ! f.empty() ) + return f; + } + + return string(); + } + +string find_script_file(const string& filename, const string& path_set) + { + vector paths; + tokenize_string(path_set, ":", &paths); + + vector ext(script_extensions.begin(), script_extensions.end()); + + for ( size_t n = 0; n < paths.size(); ++n ) + { + string f = find_file_in_path(filename, paths[n], ext); if ( ! f.empty() ) return f; diff --git a/src/util.h b/src/util.h index 232275d9c9..bd1566080f 100644 --- a/src/util.h +++ b/src/util.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -248,16 +249,16 @@ static const SourceID SOURCE_BROKER = 0xffffffff; extern void pinpoint(); extern int int_list_cmp(const void* v1, const void* v2); -// Contains the name of the script file that gets read -// when a package is loaded (i.e., "__load__.bro). -extern const char* PACKAGE_LOADER; - extern const std::string& bro_path(); extern const char* bro_magic_path(); extern const char* bro_plugin_path(); extern const char* bro_plugin_activate(); extern std::string bro_prefixes(); +extern const std::array script_extensions; + +bool is_package_loader(const std::string& path); + extern void add_to_bro_path(const std::string& dir); @@ -341,6 +342,14 @@ std::string without_bropath_component(const std::string& path); std::string find_file(const std::string& filename, const std::string& path_set, const std::string& opt_ext = ""); +/** + * Locate a script file within a given search path. + * @param filename Name of a file to find. + * @param path_set Colon-delimited set of paths to search for the file. + * @return Path to the found file, or an empty string if not found. + */ +std::string find_script_file(const std::string& filename, const std::string& path_set); + // Wrapper around fopen(3). Emits an error when failing to open. FILE* open_file(const std::string& path, const std::string& mode = "r");