From 9fef5a7b2982d1179283b1dbd1195ca1e967148a Mon Sep 17 00:00:00 2001 From: Henri DF Date: Sat, 20 Feb 2016 16:21:56 -0800 Subject: [PATCH] Rework loading of Lua and rules files --- userspace/digwatch/CMakeLists.txt | 1 + userspace/digwatch/config_digwatch.h.in | 2 + userspace/digwatch/digwatch.cpp | 66 +++++++++++++++------- userspace/digwatch/rules.cpp | 73 ++++++++++++++++++++++--- userspace/digwatch/rules.h | 9 ++- 5 files changed, 121 insertions(+), 30 deletions(-) diff --git a/userspace/digwatch/CMakeLists.txt b/userspace/digwatch/CMakeLists.txt index c609de17..09d3655d 100644 --- a/userspace/digwatch/CMakeLists.txt +++ b/userspace/digwatch/CMakeLists.txt @@ -15,4 +15,5 @@ add_executable(digwatch rules.cpp digwatch.cpp) target_link_libraries(digwatch sinsp) +set(DIGWATCH_LUA_MAIN "rule_loader.lua") configure_file(config_digwatch.h.in config_digwatch.h) diff --git a/userspace/digwatch/config_digwatch.h.in b/userspace/digwatch/config_digwatch.h.in index ec56e866..4b887cd3 100644 --- a/userspace/digwatch/config_digwatch.h.in +++ b/userspace/digwatch/config_digwatch.h.in @@ -3,3 +3,5 @@ #define DIGWATCH_VERSION "${DIGWATCH_VERSION}" #define DIGWATCH_INSTALLATION_DIR "${CMAKE_INSTALL_PREFIX}" + +#define DIGWATCH_LUA_MAIN "${DIGWATCH_LUA_MAIN}" diff --git a/userspace/digwatch/digwatch.cpp b/userspace/digwatch/digwatch.cpp index 06f53676..75655ca2 100644 --- a/userspace/digwatch/digwatch.cpp +++ b/userspace/digwatch/digwatch.cpp @@ -6,16 +6,21 @@ #include #include #include +#include +#include + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} #include +#include #include "rules.h" #include "digwatch.h" #include "utils.h" -#include -#include - -static void usage(); // // Program help @@ -23,15 +28,16 @@ static void usage(); static void usage() { printf( - "Usage: digwatch [options] [-p ] [filter]\n\n" + "Usage: digwatch [options] [-p ] rules_filename\n\n" "Options:\n" " -h, --help Print this page\n" + " -m , --main-lua \n" + " Name of lua compiler main file\n" + " (default: rules_loader.lua\n" " -M Stop collecting after reached.\n" " -N Don't convert port numbers to names.\n" " -n , --numevents=\n" " Stop capturing after events\n" - " -u , --user-parser \n" - " Name of lua file containing parser\n" " -r , --read=\n" " Read the events from .\n" " --unbuffered Turn off output buffering. This causes every single line\n" @@ -133,13 +139,14 @@ int digwatch_init(int argc, char **argv) captureinfo cinfo; string output_format; int long_index = 0; - string user_parser; + string lua_main_filename; + string lua_dir = DIGWATCH_INSTALLATION_DIR; static struct option long_options[] = { {"help", no_argument, 0, 'h' }, {"numevents", required_argument, 0, 'n' }, - {"user-parser", required_argument, 0, 'u' }, + {"main-lua", required_argument, 0, 'u' }, {"readfile", required_argument, 0, 'r' }, {"unbuffered", no_argument, 0, 0 }, {0, 0, 0, 0} @@ -156,7 +163,7 @@ int digwatch_init(int argc, char **argv) // Parse the args // while((op = getopt_long(argc, argv, - "hM:Nn:r:u:", + "hm:M:Nn:r:", long_options, &long_index)) != -1) { switch(op) @@ -165,6 +172,9 @@ int digwatch_init(int argc, char **argv) usage(); result = EXIT_SUCCESS; goto exit; + case 'm': + lua_main_filename = optarg; + break; case 'M': duration_to_tot = atoi(optarg); if(duration_to_tot <= 0) @@ -190,9 +200,6 @@ int digwatch_init(int argc, char **argv) throw sinsp_exception(string("invalid event count ") + optarg); } break; - case 'u': - user_parser = optarg; - break; case '?': result = EXIT_FAILURE; goto exit; @@ -204,20 +211,17 @@ int digwatch_init(int argc, char **argv) inspector->set_buffer_format(event_buffer_format); - string filter; + string rules_file; - // - // the filter is at the end of the command line - // if(optind < argc) { #ifdef HAS_FILTERING for(int32_t j = optind ; j < argc; j++) { - filter += argv[j]; + rules_file += argv[j]; if(j < argc - 1) { - filter += " "; + rules_file += " "; } } @@ -228,13 +232,33 @@ int digwatch_init(int argc, char **argv) #endif } + if (rules_file.size() == 0) { + usage(); + result = EXIT_FAILURE; + goto exit; + + } + // // Create the event formatter // sinsp_evt_formatter formatter(inspector, output_format); - rules = new digwatch_rules(inspector, user_parser); + trim(lua_main_filename); + if (lua_main_filename.size() == 0) + { + lua_main_filename = DIGWATCH_LUA_MAIN; + } + char* env_lua_dir = getenv("DIGWATCH_LUA_DIR"); + if (env_lua_dir) + { + lua_dir = string(env_lua_dir); + } + + rules = new digwatch_rules(inspector, lua_main_filename, lua_dir); + + rules->load_rules(rules_file); inspector->set_filter(rules->get_filter()); inspector->open(""); @@ -252,7 +276,7 @@ int digwatch_init(int argc, char **argv) } catch(...) { - printf("Exeception\n"); + printf("Exception\n"); result = EXIT_FAILURE; } diff --git a/userspace/digwatch/rules.cpp b/userspace/digwatch/rules.cpp index 7eea6f19..c1179bce 100644 --- a/userspace/digwatch/rules.cpp +++ b/userspace/digwatch/rules.cpp @@ -6,18 +6,43 @@ extern "C" { #include "lauxlib.h" } -digwatch_rules::digwatch_rules(sinsp* inspector, string compiler_filename) +digwatch_rules::digwatch_rules(sinsp* inspector, string lua_main_filename, string lua_dir) { - m_lua_parser = new lua_parser(inspector); - m_ls = m_lua_parser->m_ls; + // Initialize Lua interpreter + m_ls = lua_open(); + luaL_openlibs(m_ls); - trim(compiler_filename); + m_lua_parser = new lua_parser(inspector, m_ls); + add_lua_path(lua_dir); + load_compiler(lua_main_filename); +} + +void digwatch_rules::add_lua_path(string path) +{ + path += "?.lua"; + + lua_getglobal(m_ls, "package"); + lua_getfield(m_ls, -1, "path"); + + string cur_path = lua_tostring(m_ls, -1 ); + cur_path += ';'; + + cur_path.append(path.c_str()); + lua_pop(m_ls, 1); + + lua_pushstring(m_ls, cur_path.c_str()); + lua_setfield(m_ls, -2, "path"); + lua_pop(m_ls, 1); +} + +void digwatch_rules::load_compiler(string lua_main_filename) +{ ifstream is; - is.open(compiler_filename); + is.open(lua_main_filename); if(!is.is_open()) { - throw sinsp_exception("can't open file " + compiler_filename); + throw sinsp_exception("can't open file " + lua_main_filename); } string scriptstr((istreambuf_iterator(is)), @@ -29,10 +54,44 @@ digwatch_rules::digwatch_rules(sinsp* inspector, string compiler_filename) if(luaL_loadstring(m_ls, scriptstr.c_str()) || lua_pcall(m_ls, 0, 0, 0)) { throw sinsp_exception("Failed to load script " + - compiler_filename + ": " + lua_tostring(m_ls, -1)); + lua_main_filename + ": " + lua_tostring(m_ls, -1)); } } +void digwatch_rules::load_rules(string rules_filename) +{ + ifstream is; + is.open(rules_filename); + if(!is.is_open()) + { + throw sinsp_exception("can't open file " + rules_filename); + } + + lua_getglobal(m_ls, m_lua_compiler_cb.c_str()); + if(lua_isfunction(m_ls, -1)) + { + lua_pop(m_ls, 1); + } else { + throw sinsp_exception("No function " + m_lua_compiler_cb + " found in lua compiler module"); + } + + std::string line; + while (std::getline(is, line)) + { + lua_getglobal(m_ls, m_lua_compiler_cb.c_str()); + lua_pushstring(m_ls, line.c_str()); + + if(lua_pcall(m_ls, 1, 0, 0) != 0) + { + const char* lerr = lua_tostring(m_ls, -1); + string err = "Error loading rule: " + string(lerr); + throw sinsp_exception(err); + } + } + + +} + sinsp_filter* digwatch_rules::get_filter() { return m_lua_parser->get_filter(); diff --git a/userspace/digwatch/rules.h b/userspace/digwatch/rules.h index 471a1490..cc0b0983 100644 --- a/userspace/digwatch/rules.h +++ b/userspace/digwatch/rules.h @@ -6,12 +6,17 @@ class digwatch_rules { public: - digwatch_rules(sinsp* inspector, string compiler_filename); + digwatch_rules(sinsp* inspector, string lua_main_filename, string lua_dir); ~digwatch_rules(); - void load(string rules_filename); + void load_rules(string rules_filename); sinsp_filter* get_filter(); private: + void add_lua_path(string path); + void load_compiler(string lua_main_filename); + lua_parser* m_lua_parser; lua_State* m_ls; + string m_lua_compiler_cb = "load_rules"; + string m_lua_; };