Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "t_ruleparser.h" 6 : #include <boost/python.hpp> 7 : #include <boost/python/object.hpp> 8 : #include <boost/python/handle.hpp> 9 : 10 0 : void t_ruleaction::execute(const RuleMsg& rmsg) { 11 0 : if (actionid_ == "echoaction") { 12 0 : RuleActionEchoResult.append(" "); 13 0 : RuleActionEchoResult.append(actionid_); 14 : 15 0 : std::vector<std::string>::const_iterator iter; 16 0 : for (iter = paramlist_.begin(); iter != paramlist_.end(); iter++) { 17 0 : RuleActionEchoResult.append(" "); 18 0 : RuleActionEchoResult.append((*iter)); 19 : } 20 : } 21 : 22 0 : if (actionid_ == "echoaction.py") { 23 : using namespace boost::python; 24 0 : object main_module = import("__main__"); 25 0 : dict main_namespace = static_cast<dict>(main_module.attr("__dict__")); 26 : 27 0 : char *rpath = getenv("RULEENGPATH"); 28 0 : std::string commandstr; 29 0 : if (rpath != NULL) { 30 0 : commandstr.append(rpath); 31 0 : commandstr.append("/echoaction.py"); 32 : } else { 33 0 : commandstr.append("echoaction.py"); 34 : } 35 : 36 0 : if (access(commandstr.c_str(), R_OK)) { 37 0 : std::cout << "File error: " << commandstr << std::endl; 38 : 39 0 : RuleActionEchoResult.append(" "); 40 0 : RuleActionEchoResult.append(actionid_); 41 : 42 0 : std::vector<std::string>::const_iterator iter; 43 0 : for (iter = paramlist_.begin(); iter != paramlist_.end(); iter++) { 44 0 : RuleActionEchoResult.append(" "); 45 0 : RuleActionEchoResult.append((*iter)); 46 : } 47 : 48 0 : return; 49 : } 50 : 51 0 : boost::python::str command(commandstr); 52 0 : list param_list; 53 0 : std::vector<std::string>::const_iterator iter; 54 0 : for (iter = paramlist_.begin(); iter != paramlist_.end(); iter++) { 55 0 : param_list.append((*iter)); 56 : } 57 0 : main_namespace["paramlist"] = param_list; 58 : 59 0 : std::string cmdouts; 60 0 : object cmdout; 61 : try { 62 0 : cmdout = exec_file(command, main_namespace, main_namespace); 63 0 : } catch(error_already_set const &){ 64 0 : std::string perror_str = parse_python_exception(); 65 0 : std::cout << "Error in Python exec_file: " << perror_str << std::endl; 66 0 : } 67 : 68 : try { 69 0 : if (main_namespace.has_key("actionresult")) 70 0 : cmdouts = extract<std::string>(main_namespace["actionresult"]); 71 : else 72 0 : cmdouts = "actionresultNone"; 73 0 : } catch(error_already_set const &) { 74 0 : std::string perror_str = parse_python_exception(); 75 0 : std::cout << "Error in boost extract: " << perror_str << std::endl; 76 0 : } 77 0 : RuleActionEchoResult.append(" "); 78 0 : RuleActionEchoResult.append(cmdouts); 79 0 : } 80 0 : syslog(LOG_ERR, "%s action called\n", actionid_.c_str()); 81 : } 82 : 83 0 : std::string t_ruleaction::parse_python_exception() { 84 : namespace py = boost::python; 85 : 86 0 : PyObject *type_ptr = NULL, *value_ptr = NULL, *traceback_ptr = NULL; 87 0 : PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr); 88 0 : std::string ret("Unfetchable Python error"); 89 : 90 0 : if(type_ptr != NULL) { 91 0 : py::handle<> h_type(type_ptr); 92 0 : py::str type_pstr(h_type); 93 0 : py::extract<std::string> e_type_pstr(type_pstr); 94 0 : if(e_type_pstr.check()) 95 0 : ret = e_type_pstr(); 96 : else 97 0 : ret = "Unknown exception type"; 98 0 : } 99 : 100 0 : if(value_ptr != NULL) { 101 0 : py::handle<> h_val(value_ptr); 102 0 : py::str a(h_val); 103 0 : py::extract<std::string> returned(a); 104 0 : if(returned.check()) 105 0 : ret += ": " + returned(); 106 : else 107 0 : ret += std::string(": Unparseable Python error: "); 108 0 : } 109 : 110 0 : if(traceback_ptr != NULL){ 111 0 : py::handle<> h_tb(traceback_ptr); 112 0 : py::object tb(py::import("traceback")); 113 0 : py::object fmt_tb(tb.attr("format_tb")); 114 0 : py::object tb_list(fmt_tb(h_tb)); 115 0 : py::object tb_str(py::str("\n").join(tb_list)); 116 0 : py::extract<std::string> returned(tb_str); 117 0 : if(returned.check()) 118 0 : ret += ": " + returned(); 119 : else 120 0 : ret += std::string(": Unparseable Python traceback"); 121 0 : } 122 0 : return ret; 123 0 : } 124 :