11401458bSopenharmony_ci/* 21401458bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 31401458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 41401458bSopenharmony_ci * you may not use this file except in compliance with the License. 51401458bSopenharmony_ci * You may obtain a copy of the License at 61401458bSopenharmony_ci * 71401458bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 81401458bSopenharmony_ci * 91401458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 101401458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 111401458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 121401458bSopenharmony_ci * See the License for the specific language governing permissions and 131401458bSopenharmony_ci * limitations under the License. 141401458bSopenharmony_ci */ 151401458bSopenharmony_ci 161401458bSopenharmony_ci#include "hisysevent_tool.h" 171401458bSopenharmony_ci 181401458bSopenharmony_ci#include <getopt.h> 191401458bSopenharmony_ci#include <iomanip> 201401458bSopenharmony_ci#include <iostream> 211401458bSopenharmony_ci#include <regex> 221401458bSopenharmony_ci#include <regex.h> 231401458bSopenharmony_ci#include <sstream> 241401458bSopenharmony_ci#include <unistd.h> 251401458bSopenharmony_ci 261401458bSopenharmony_ci#include "hisysevent.h" 271401458bSopenharmony_ci#include "hisysevent_tool_listener.h" 281401458bSopenharmony_ci#include "hisysevent_tool_query.h" 291401458bSopenharmony_ci 301401458bSopenharmony_ci#include "ret_code.h" 311401458bSopenharmony_ci 321401458bSopenharmony_ciusing namespace std; 331401458bSopenharmony_ci 341401458bSopenharmony_cinamespace OHOS { 351401458bSopenharmony_cinamespace HiviewDFX { 361401458bSopenharmony_cinamespace { 371401458bSopenharmony_ciconstexpr char ARG_SELECTION[] = "vrc:o:n:t:lS:s:E:e:m:dhg:"; 381401458bSopenharmony_ciconstexpr uint32_t INVALID_EVENT_TYPE = 0; 391401458bSopenharmony_ciconstexpr int INVALID_ARG_OPT = -1; 401401458bSopenharmony_ciconstexpr long long DEFAULT_TIME_STAMP = -1; 411401458bSopenharmony_ciconstexpr long long SECONDS_2_MILLS = 1000; 421401458bSopenharmony_ci 431401458bSopenharmony_ciRuleType GetRuleTypeFromArg(const string& fromArgs) 441401458bSopenharmony_ci{ 451401458bSopenharmony_ci static std::map<const string, RuleType> ruleTypeMap { 461401458bSopenharmony_ci { "WHOLE_WORD", RuleType::WHOLE_WORD }, 471401458bSopenharmony_ci { "PREFIX", RuleType::PREFIX }, 481401458bSopenharmony_ci { "REGULAR", RuleType::REGULAR } 491401458bSopenharmony_ci }; 501401458bSopenharmony_ci if (ruleTypeMap.find(fromArgs) != ruleTypeMap.end()) { 511401458bSopenharmony_ci return ruleTypeMap[fromArgs]; 521401458bSopenharmony_ci } 531401458bSopenharmony_ci return RuleType::WHOLE_WORD; 541401458bSopenharmony_ci} 551401458bSopenharmony_ci 561401458bSopenharmony_ciuint32_t GetEventTypeFromArg(const string& fromArgs) 571401458bSopenharmony_ci{ 581401458bSopenharmony_ci static std::map<const string, HiSysEvent::EventType> eventTypeMap { 591401458bSopenharmony_ci { "FAULT", HiSysEvent::EventType::FAULT }, 601401458bSopenharmony_ci { "STATISTIC", HiSysEvent::EventType::STATISTIC }, 611401458bSopenharmony_ci { "SECURITY", HiSysEvent::EventType::SECURITY }, 621401458bSopenharmony_ci { "BEHAVIOR", HiSysEvent::EventType::BEHAVIOR } 631401458bSopenharmony_ci }; 641401458bSopenharmony_ci if (eventTypeMap.find(fromArgs) != eventTypeMap.end()) { 651401458bSopenharmony_ci return static_cast<uint32_t>(eventTypeMap[fromArgs]); 661401458bSopenharmony_ci } 671401458bSopenharmony_ci return INVALID_EVENT_TYPE; 681401458bSopenharmony_ci} 691401458bSopenharmony_ci 701401458bSopenharmony_cilong long ParseTimeStampFromArgs(const string& fromArgs) 711401458bSopenharmony_ci{ 721401458bSopenharmony_ci regex formatRegex("[0-9]{4}-" 731401458bSopenharmony_ci "((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01])|(0[2469]|11)-(0[1-9]|[12][0-9]|30))" 741401458bSopenharmony_ci " ([01][0-9]|2[0-3])(:[0-5][0-9]){2}"); 751401458bSopenharmony_ci smatch matchRet; 761401458bSopenharmony_ci if (!std::regex_match(fromArgs, matchRet, formatRegex)) { 771401458bSopenharmony_ci return DEFAULT_TIME_STAMP; 781401458bSopenharmony_ci } 791401458bSopenharmony_ci std::istringstream is(fromArgs); 801401458bSopenharmony_ci struct tm time = {}; 811401458bSopenharmony_ci is >> std::get_time(&time, "%Y-%m-%d %H:%M:%S"); 821401458bSopenharmony_ci return static_cast<long long>(mktime(&time)) * SECONDS_2_MILLS; 831401458bSopenharmony_ci} 841401458bSopenharmony_ci 851401458bSopenharmony_cistd::string GetErrorDescription(int32_t errCode) 861401458bSopenharmony_ci{ 871401458bSopenharmony_ci std::map<int32_t, std::string> errMap = { 881401458bSopenharmony_ci { ERR_SYS_EVENT_SERVICE_NOT_FOUND, "service not found." }, 891401458bSopenharmony_ci { ERR_PARCEL_DATA_IS_NULL, "parcel data is null." }, 901401458bSopenharmony_ci { ERR_REMOTE_SERVICE_IS_NULL, "remote service is null." }, 911401458bSopenharmony_ci { ERR_CAN_NOT_WRITE_DESCRIPTOR, "descriptor wrote failed." }, 921401458bSopenharmony_ci { ERR_CAN_NOT_WRITE_PARCEL, "parcel wrote failed." }, 931401458bSopenharmony_ci { ERR_CAN_NOT_WRITE_REMOTE_OBJECT, "remote object wrote failed." }, 941401458bSopenharmony_ci { ERR_CAN_NOT_SEND_REQ, "request sent failed." }, 951401458bSopenharmony_ci { ERR_CAN_NOT_READ_PARCEL, "parcel read failed." }, 961401458bSopenharmony_ci { ERR_ADD_DEATH_RECIPIENT, "add death recipient failed." }, 971401458bSopenharmony_ci { ERR_QUERY_RULE_INVALID, "invalid query rule." }, 981401458bSopenharmony_ci { ERR_TOO_MANY_WATCHERS, "too many wathers subscribed." }, 991401458bSopenharmony_ci { ERR_QUERY_TOO_FREQUENTLY, "query too frequently." }, 1001401458bSopenharmony_ci }; 1011401458bSopenharmony_ci return errMap.find(errCode) == errMap.end() ? 1021401458bSopenharmony_ci "unknown error." : errMap.at(errCode); 1031401458bSopenharmony_ci} 1041401458bSopenharmony_ci 1051401458bSopenharmony_civoid InitOptHandlers(std::map<int, OptHandler>& optHandlers) 1061401458bSopenharmony_ci{ 1071401458bSopenharmony_ci std::map<int, OptHandler> tmpHandlers = { 1081401458bSopenharmony_ci {'v', [] (struct ArgStuct& cmdArg, const char* optarg) { 1091401458bSopenharmony_ci cmdArg.checkValidEvent = true; 1101401458bSopenharmony_ci }}, {'r', [] (struct ArgStuct& cmdArg, const char* optarg) { 1111401458bSopenharmony_ci cmdArg.real = true; 1121401458bSopenharmony_ci }}, {'c', [] (struct ArgStuct& cmdArg, const char* optarg) { 1131401458bSopenharmony_ci cmdArg.ruleType = GetRuleTypeFromArg(optarg); 1141401458bSopenharmony_ci }}, {'o', [] (struct ArgStuct& cmdArg, const char* optarg) { 1151401458bSopenharmony_ci cmdArg.domain = optarg; 1161401458bSopenharmony_ci }}, {'n', [] (struct ArgStuct& cmdArg, const char* optarg) { 1171401458bSopenharmony_ci cmdArg.eventName = optarg; 1181401458bSopenharmony_ci }}, {'t', [] (struct ArgStuct& cmdArg, const char* optarg) { 1191401458bSopenharmony_ci cmdArg.tag = optarg; 1201401458bSopenharmony_ci }}, {'l', [] (struct ArgStuct& cmdArg, const char* optarg) { 1211401458bSopenharmony_ci cmdArg.history = true; 1221401458bSopenharmony_ci }}, {'s', [] (struct ArgStuct& cmdArg, const char* optarg) { 1231401458bSopenharmony_ci cmdArg.beginTime = strtoll(optarg, nullptr, 0); 1241401458bSopenharmony_ci }}, {'S', [] (struct ArgStuct& cmdArg, const char* optarg) { 1251401458bSopenharmony_ci cmdArg.beginTime = ParseTimeStampFromArgs(std::string(optarg)); 1261401458bSopenharmony_ci }}, {'e', [] (struct ArgStuct& cmdArg, const char* optarg) { 1271401458bSopenharmony_ci cmdArg.endTime = strtoll(optarg, nullptr, 0); 1281401458bSopenharmony_ci }}, {'E', [] (struct ArgStuct& cmdArg, const char* optarg) { 1291401458bSopenharmony_ci cmdArg.endTime = ParseTimeStampFromArgs(std::string(optarg)); 1301401458bSopenharmony_ci }}, {'m', [] (struct ArgStuct& cmdArg, const char* optarg) { 1311401458bSopenharmony_ci cmdArg.maxEvents = strtol(optarg, nullptr, 0); 1321401458bSopenharmony_ci }}, {'d', [] (struct ArgStuct& cmdArg, const char* optarg) { 1331401458bSopenharmony_ci cmdArg.isDebug = true; 1341401458bSopenharmony_ci }}, {'g', [] (struct ArgStuct& cmdArg, const char* optarg) { 1351401458bSopenharmony_ci cmdArg.eventType = GetEventTypeFromArg(optarg); 1361401458bSopenharmony_ci }}, 1371401458bSopenharmony_ci }; 1381401458bSopenharmony_ci optHandlers.insert(tmpHandlers.begin(), tmpHandlers.end()); 1391401458bSopenharmony_ci} 1401401458bSopenharmony_ci 1411401458bSopenharmony_cibool IsValidRegex(const std::string& regStr) 1421401458bSopenharmony_ci{ 1431401458bSopenharmony_ci if (regStr.length() > 32) { // 32 is the length limit of regex 1441401458bSopenharmony_ci return false; 1451401458bSopenharmony_ci } 1461401458bSopenharmony_ci int flags = REG_EXTENDED; 1471401458bSopenharmony_ci regex_t reg; 1481401458bSopenharmony_ci // check whether the pattern is valid 1491401458bSopenharmony_ci int status = regcomp(®, regStr.c_str(), flags); 1501401458bSopenharmony_ci // free regex 1511401458bSopenharmony_ci regfree(®); 1521401458bSopenharmony_ci return (status == REG_OK); 1531401458bSopenharmony_ci} 1541401458bSopenharmony_ci} 1551401458bSopenharmony_ci 1561401458bSopenharmony_ciHiSysEventTool::HiSysEventTool(bool autoExit) : clientCmdArg { 1571401458bSopenharmony_ci false, false, "", "", "", RuleType::WHOLE_WORD, 1581401458bSopenharmony_ci false, false, -1, -1, 10000, 0}, autoExit(autoExit) 1591401458bSopenharmony_ci{ 1601401458bSopenharmony_ci InitOptHandlers(optHandlers); 1611401458bSopenharmony_ci} 1621401458bSopenharmony_ci 1631401458bSopenharmony_cibool HiSysEventTool::ParseCmdLine(int argc, char** argv) 1641401458bSopenharmony_ci{ 1651401458bSopenharmony_ci if (argv == nullptr) { 1661401458bSopenharmony_ci return false; 1671401458bSopenharmony_ci } 1681401458bSopenharmony_ci if (argc > 1) { 1691401458bSopenharmony_ci HandleInput(argc, argv, ARG_SELECTION); 1701401458bSopenharmony_ci } 1711401458bSopenharmony_ci return CheckCmdLine(); 1721401458bSopenharmony_ci} 1731401458bSopenharmony_ci 1741401458bSopenharmony_cibool HiSysEventTool::CheckCmdLine() 1751401458bSopenharmony_ci{ 1761401458bSopenharmony_ci if (!clientCmdArg.real && !clientCmdArg.history) { 1771401458bSopenharmony_ci return false; 1781401458bSopenharmony_ci } 1791401458bSopenharmony_ci 1801401458bSopenharmony_ci if (clientCmdArg.real && clientCmdArg.history) { 1811401458bSopenharmony_ci cout << "canot read both read && history hisysevent" << endl; 1821401458bSopenharmony_ci return false; 1831401458bSopenharmony_ci } 1841401458bSopenharmony_ci 1851401458bSopenharmony_ci if (clientCmdArg.isDebug && !clientCmdArg.real) { 1861401458bSopenharmony_ci cout << "debug must follow with real log" << endl; 1871401458bSopenharmony_ci return false; 1881401458bSopenharmony_ci } 1891401458bSopenharmony_ci 1901401458bSopenharmony_ci if (clientCmdArg.history) { 1911401458bSopenharmony_ci auto timestampValidCheck = clientCmdArg.endTime > 0 1921401458bSopenharmony_ci && clientCmdArg.beginTime > clientCmdArg.endTime; 1931401458bSopenharmony_ci if (timestampValidCheck) { 1941401458bSopenharmony_ci cout << "invalid time startTime must less than endTime("; 1951401458bSopenharmony_ci cout << clientCmdArg.beginTime << " > " << clientCmdArg.endTime << ")." << endl; 1961401458bSopenharmony_ci return false; 1971401458bSopenharmony_ci } 1981401458bSopenharmony_ci } 1991401458bSopenharmony_ci return true; 2001401458bSopenharmony_ci} 2011401458bSopenharmony_ci 2021401458bSopenharmony_civoid HiSysEventTool::HandleInput(int argc, char** argv, const char* selection) 2031401458bSopenharmony_ci{ 2041401458bSopenharmony_ci int opt; 2051401458bSopenharmony_ci while ((opt = getopt(argc, argv, selection)) != INVALID_ARG_OPT) { 2061401458bSopenharmony_ci if (opt == 'h') { 2071401458bSopenharmony_ci DoCmdHelp(); 2081401458bSopenharmony_ci if (autoExit) { 2091401458bSopenharmony_ci _exit(0); 2101401458bSopenharmony_ci } 2111401458bSopenharmony_ci } 2121401458bSopenharmony_ci if (optHandlers.find(opt) != optHandlers.end()) { 2131401458bSopenharmony_ci optHandlers.at(opt)(clientCmdArg, optarg); 2141401458bSopenharmony_ci } 2151401458bSopenharmony_ci } 2161401458bSopenharmony_ci} 2171401458bSopenharmony_ci 2181401458bSopenharmony_civoid HiSysEventTool::DoCmdHelp() 2191401458bSopenharmony_ci{ 2201401458bSopenharmony_ci cout << "hisysevent [[-v] -r [-d | -c [WHOLE_WORD|PREFIX|REGULAR] -t <tag> " 2211401458bSopenharmony_ci << "| -c [WHOLE_WORD|PREFIX|REGULAR] -o <domain> -n <eventName> " 2221401458bSopenharmony_ci << "| -g [FAULT|STATISTIC|SECURITY|BEHAVIOR]] " 2231401458bSopenharmony_ci << "| -l [[-s <begin time> -e <end time> | -S <formatted begin time> -E <formatted end time>] " 2241401458bSopenharmony_ci << "-m <count> -c [WHOLE_WORD] -o <domain> -n <eventName> -g [FAULT|STATISTIC|SECURITY|BEHAVIOR]]]" << endl; 2251401458bSopenharmony_ci cout << "-r, subscribe on all domains, event names and tags." << endl; 2261401458bSopenharmony_ci cout << "-r -c [WHOLE_WORD|PREFIX|REGULAR] -t <tag>" 2271401458bSopenharmony_ci << ", subscribe on tag." << endl; 2281401458bSopenharmony_ci cout << "-r -c [WHOLE_WORD|PREFIX|REGULAR] -o <domain> -n <eventName>" 2291401458bSopenharmony_ci << ", subscribe on domain and event name." << endl; 2301401458bSopenharmony_ci cout << "-r -g [FAULT|STATISTIC|SECURITY|BEHAVIOR]" 2311401458bSopenharmony_ci << ", subscribe on event type." << endl; 2321401458bSopenharmony_ci cout << "-r -d set debug mode, both options must appear at the same time." << endl; 2331401458bSopenharmony_ci cout << "-l -s <begin time> -e <end time> -m <max hisysevent count>" 2341401458bSopenharmony_ci << ", get history hisysevent log with time stamps, end time should not be " 2351401458bSopenharmony_ci << "earlier than begin time." << endl; 2361401458bSopenharmony_ci cout << "-l -S <formatted begin time> -E <formatted end time> -m <max hisysevent count>" 2371401458bSopenharmony_ci << ", get history hisysevent log with formatted time string, end time should not be " 2381401458bSopenharmony_ci << "earlier than begin time." << endl; 2391401458bSopenharmony_ci cout << "-l -c [WHOLE_WORD] -o <domain> -n <eventName> -m <max hisysevent count>" 2401401458bSopenharmony_ci << ", get history hisysevent log with domain and event name." << endl; 2411401458bSopenharmony_ci cout << "-l -g [FAULT|STATISTIC|SECURITY|BEHAVIOR] -m <max hisysevent count>" 2421401458bSopenharmony_ci << ", get history hisysevent log with event type." << endl; 2431401458bSopenharmony_ci cout << "-v, open valid event checking mode." << endl; 2441401458bSopenharmony_ci cout << "-h, help manual." << endl; 2451401458bSopenharmony_ci} 2461401458bSopenharmony_ci 2471401458bSopenharmony_cibool HiSysEventTool::DoAction() 2481401458bSopenharmony_ci{ 2491401458bSopenharmony_ci if (clientCmdArg.ruleType == RuleType::REGULAR && (!IsValidRegex(clientCmdArg.domain) 2501401458bSopenharmony_ci || !IsValidRegex(clientCmdArg.eventName) || !IsValidRegex(clientCmdArg.tag))) { 2511401458bSopenharmony_ci cout << "invalid regex" << endl; 2521401458bSopenharmony_ci return false; 2531401458bSopenharmony_ci } 2541401458bSopenharmony_ci if (clientCmdArg.real) { 2551401458bSopenharmony_ci auto toolListener = std::make_shared<HiSysEventToolListener>(clientCmdArg.checkValidEvent); 2561401458bSopenharmony_ci if (toolListener == nullptr) { 2571401458bSopenharmony_ci return false; 2581401458bSopenharmony_ci } 2591401458bSopenharmony_ci std::vector<ListenerRule> sysRules; 2601401458bSopenharmony_ci ListenerRule listenerRule(clientCmdArg.domain, clientCmdArg.eventName, 2611401458bSopenharmony_ci clientCmdArg.tag, clientCmdArg.ruleType, clientCmdArg.eventType); 2621401458bSopenharmony_ci sysRules.emplace_back(listenerRule); 2631401458bSopenharmony_ci auto retCode = HiSysEventManager::AddListener(toolListener, sysRules); 2641401458bSopenharmony_ci if (retCode != IPC_CALL_SUCCEED || 2651401458bSopenharmony_ci (clientCmdArg.isDebug && HiSysEventManager::SetDebugMode(toolListener, true) != 0)) { 2661401458bSopenharmony_ci cout << "failed to subscribe system event: " << GetErrorDescription(retCode) << endl; 2671401458bSopenharmony_ci } 2681401458bSopenharmony_ci return true; 2691401458bSopenharmony_ci } 2701401458bSopenharmony_ci 2711401458bSopenharmony_ci if (clientCmdArg.history) { 2721401458bSopenharmony_ci auto queryCallBack = std::make_shared<HiSysEventToolQuery>(clientCmdArg.checkValidEvent, autoExit); 2731401458bSopenharmony_ci if (queryCallBack == nullptr) { 2741401458bSopenharmony_ci return false; 2751401458bSopenharmony_ci } 2761401458bSopenharmony_ci struct QueryArg args(clientCmdArg.beginTime, clientCmdArg.endTime, clientCmdArg.maxEvents); 2771401458bSopenharmony_ci std::vector<QueryRule> queryRules; 2781401458bSopenharmony_ci if (clientCmdArg.ruleType != RuleType::WHOLE_WORD) { 2791401458bSopenharmony_ci cout << "only \"-c WHOLE_WORD\" supported with \"hisysevent -l\" cmd." << endl; 2801401458bSopenharmony_ci return false; 2811401458bSopenharmony_ci } 2821401458bSopenharmony_ci if (!clientCmdArg.domain.empty() || !clientCmdArg.eventName.empty() || 2831401458bSopenharmony_ci clientCmdArg.eventType != INVALID_EVENT_TYPE) { 2841401458bSopenharmony_ci QueryRule rule(clientCmdArg.domain, { clientCmdArg.eventName }, 2851401458bSopenharmony_ci clientCmdArg.ruleType, clientCmdArg.eventType); 2861401458bSopenharmony_ci queryRules.push_back(rule); 2871401458bSopenharmony_ci } 2881401458bSopenharmony_ci auto retCode = HiSysEventManager::Query(args, queryRules, queryCallBack); 2891401458bSopenharmony_ci if (retCode != IPC_CALL_SUCCEED) { 2901401458bSopenharmony_ci cout << "failed to query system event: " << GetErrorDescription(retCode) << endl; 2911401458bSopenharmony_ci } 2921401458bSopenharmony_ci return true; 2931401458bSopenharmony_ci } 2941401458bSopenharmony_ci return false; 2951401458bSopenharmony_ci} 2961401458bSopenharmony_ci 2971401458bSopenharmony_civoid HiSysEventTool::WaitClient() 2981401458bSopenharmony_ci{ 2991401458bSopenharmony_ci unique_lock<mutex> lock(mutexClient); 3001401458bSopenharmony_ci condvClient.wait(lock); 3011401458bSopenharmony_ci} 3021401458bSopenharmony_ci 3031401458bSopenharmony_civoid HiSysEventTool::NotifyClient() 3041401458bSopenharmony_ci{ 3051401458bSopenharmony_ci condvClient.notify_one(); 3061401458bSopenharmony_ci} 3071401458bSopenharmony_ci} // namespace HiviewDFX 3081401458bSopenharmony_ci} // namespace OHOS 309