12498b56bSopenharmony_ci/*
22498b56bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42498b56bSopenharmony_ci * you may not use this file except in compliance with the License.
52498b56bSopenharmony_ci * You may obtain a copy of the License at
62498b56bSopenharmony_ci *
72498b56bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
82498b56bSopenharmony_ci *
92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122498b56bSopenharmony_ci * See the License for the specific language governing permissions and
132498b56bSopenharmony_ci * limitations under the License.
142498b56bSopenharmony_ci */
152498b56bSopenharmony_ci#include <cstdlib>
162498b56bSopenharmony_ci#include <getopt.h>
172498b56bSopenharmony_ci#include <iostream>
182498b56bSopenharmony_ci#include <iomanip>
192498b56bSopenharmony_ci#include <ctime>
202498b56bSopenharmony_ci#include <functional>
212498b56bSopenharmony_ci#include <string_ex.h>
222498b56bSopenharmony_ci#include <securec.h>
232498b56bSopenharmony_ci#include <list>
242498b56bSopenharmony_ci
252498b56bSopenharmony_ci#include <hilog/log.h>
262498b56bSopenharmony_ci#include <hilog_common.h>
272498b56bSopenharmony_ci#include <log_utils.h>
282498b56bSopenharmony_ci#include <log_ioctl.h>
292498b56bSopenharmony_ci#include <log_print.h>
302498b56bSopenharmony_ci#include <properties.h>
312498b56bSopenharmony_ci
322498b56bSopenharmony_ci#include "log_display.h"
332498b56bSopenharmony_ci
342498b56bSopenharmony_cinamespace OHOS {
352498b56bSopenharmony_cinamespace HiviewDFX {
362498b56bSopenharmony_ciusing namespace std;
372498b56bSopenharmony_cistatic void FormatHelper()
382498b56bSopenharmony_ci{
392498b56bSopenharmony_ci    cout
402498b56bSopenharmony_ci    << "  -v <format>, --format=<format>" << endl
412498b56bSopenharmony_ci    << "    Show logs in different formats, options are:" << endl
422498b56bSopenharmony_ci    << "      color or colour      display colorful logs by log level.i.e." << endl
432498b56bSopenharmony_ci    << "        \x1B[38;5;75mDEBUG        \x1B[38;5;40mINFO        \x1B[38;5;166mWARN"
442498b56bSopenharmony_ci    << "        \x1B[38;5;196mERROR       \x1B[38;5;226mFATAL\x1B[0m" << endl
452498b56bSopenharmony_ci    << "      time format options are(single accepted):" << endl
462498b56bSopenharmony_ci    << "        time       display local time, this is default." << endl
472498b56bSopenharmony_ci    << "        epoch      display the time from 1970/1/1." << endl
482498b56bSopenharmony_ci    << "        monotonic  display the cpu time from bootup." << endl
492498b56bSopenharmony_ci    << "      time accuracy format options are(single accepted):" << endl
502498b56bSopenharmony_ci    << "        msec       display time by millisecond, this is default." << endl
512498b56bSopenharmony_ci    << "        usec       display time by microsecond." << endl
522498b56bSopenharmony_ci    << "        nsec       display time by nanosecond." << endl
532498b56bSopenharmony_ci    << "      year       display the year when -v time is specified." << endl
542498b56bSopenharmony_ci    << "      zone       display the time zone when -v time is specified." << endl
552498b56bSopenharmony_ci    << "      wrap       display the log without prefix when a log line is wrapped." << endl
562498b56bSopenharmony_ci    << "    Different types of formats can be combined, such as:" << endl
572498b56bSopenharmony_ci    << "    -v color -v time -v msec -v year -v zone." << endl;
582498b56bSopenharmony_ci}
592498b56bSopenharmony_ci
602498b56bSopenharmony_cistatic void QueryHelper()
612498b56bSopenharmony_ci{
622498b56bSopenharmony_ci    cout
632498b56bSopenharmony_ci    << "Querying logs options:" << endl
642498b56bSopenharmony_ci    << "  No option performs a blocking read and keeps printing." << endl
652498b56bSopenharmony_ci    << "  -x --exit" << endl
662498b56bSopenharmony_ci    << "    Performs a non-blocking read and exits when all logs in buffer are printed." << endl
672498b56bSopenharmony_ci    << "  -a <n>, --head=<n>" << endl
682498b56bSopenharmony_ci    << "    Show n lines logs on head of buffer." << endl
692498b56bSopenharmony_ci    << "  -z <n>, --tail=<n>" << endl
702498b56bSopenharmony_ci    << "    Show n lines logs on tail of buffer." << endl
712498b56bSopenharmony_ci    << "  -t <type>, --type=<type>" << endl
722498b56bSopenharmony_ci    << "    Show specific type/types logs with format: type1,type2,type3" << endl
732498b56bSopenharmony_ci    << "    Don't show specific type/types logs with format: ^type1,type2,type3" << endl
742498b56bSopenharmony_ci    << "    Type coule be: app/core/init/kmsg/only_prerelease, kmsg can't combine with others." << endl
752498b56bSopenharmony_ci    << "    Default types are: app,core,init,only_prerelease." << endl
762498b56bSopenharmony_ci    << "  -L <level>, --level=<level>" << endl
772498b56bSopenharmony_ci    << "    Show specific level/levels logs with format: level1,level2,level3" << endl
782498b56bSopenharmony_ci    << "    Don't show specific level/levels logs with format: ^level1,level2,level3" << endl
792498b56bSopenharmony_ci    << "    Long and short level string are both accepted" << endl
802498b56bSopenharmony_ci    << "    Long level string coule be: DEBUG/INFO/WARN/ERROR/FATAL." << endl
812498b56bSopenharmony_ci    << "    Short level string coule be: D/I/W/E/F." << endl
822498b56bSopenharmony_ci    << "    Default levels are all levels." << endl
832498b56bSopenharmony_ci    << "  -D <domain>, --domain=<domain>" << endl
842498b56bSopenharmony_ci    << "    Show specific domain/domains logs with format: domain1,domain2,doman3" << endl
852498b56bSopenharmony_ci    << "    Don't show specific domain/domains logs with format: ^domain1,domain2,doman3" << endl
862498b56bSopenharmony_ci    << "    Max domain count is " << MAX_DOMAINS << "." << endl
872498b56bSopenharmony_ci    << "    See domain description at the end of this message." << endl
882498b56bSopenharmony_ci    << "  -T <tag>, --tag=<tag>" << endl
892498b56bSopenharmony_ci    << "    Show specific tag/tags logs with format: tag1,tag2,tag3" << endl
902498b56bSopenharmony_ci    << "    Don't show specific tag/tags logs with format: ^tag1,tag2,tag3" << endl
912498b56bSopenharmony_ci    << "    Max tag count is " << MAX_TAGS << "." << endl
922498b56bSopenharmony_ci    << "  -P <pid>, --pid=<pid>" << endl
932498b56bSopenharmony_ci    << "    Show specific pid/pids logs with format: pid1,pid2,pid3" << endl
942498b56bSopenharmony_ci    << "    Don't show specific domain/domains logs with format: ^pid1,pid2,pid3" << endl
952498b56bSopenharmony_ci    << "    Max pid count is " << MAX_PIDS << "." << endl
962498b56bSopenharmony_ci    << "  -e <expr>, --regex=<expr>" << endl
972498b56bSopenharmony_ci    << "    Show the logs which match the regular expression <expr>." << endl;
982498b56bSopenharmony_ci    FormatHelper();
992498b56bSopenharmony_ci}
1002498b56bSopenharmony_ci
1012498b56bSopenharmony_cistatic void ClearHelper()
1022498b56bSopenharmony_ci{
1032498b56bSopenharmony_ci    cout
1042498b56bSopenharmony_ci    << "-r" << endl
1052498b56bSopenharmony_ci    << "  Remove all logs in hilogd buffer, advanced option:" << endl
1062498b56bSopenharmony_ci    << "  -t <type>, --type=<type>" << endl
1072498b56bSopenharmony_ci    << "    Remove specific type/types logs in buffer with format: type1,type2,type3" << endl
1082498b56bSopenharmony_ci    << "    Type coule be: app/core/init/kmsg/only_prerelease." << endl
1092498b56bSopenharmony_ci    << "    Default types are: app,core,only_prerelease" << endl;
1102498b56bSopenharmony_ci}
1112498b56bSopenharmony_ci
1122498b56bSopenharmony_cistatic void BufferHelper()
1132498b56bSopenharmony_ci{
1142498b56bSopenharmony_ci    cout
1152498b56bSopenharmony_ci    << "-g" << endl
1162498b56bSopenharmony_ci    << "  Query hilogd buffer size, advanced option:" << endl
1172498b56bSopenharmony_ci    << "  -t <type>, --type=<type>" << endl
1182498b56bSopenharmony_ci    << "    Query specific type/types buffer size with format: type1,type2,type3" << endl
1192498b56bSopenharmony_ci    << "    Type coule be: app/core/init/kmsg/only_prerelease." << endl
1202498b56bSopenharmony_ci    << "    Default types are: app,core,only_prerelease" << endl
1212498b56bSopenharmony_ci    << "-G <size>, --buffer-size=<size>" << endl
1222498b56bSopenharmony_ci    << "  Set hilogd buffer size, <size> could be number or number with unit." << endl
1232498b56bSopenharmony_ci    << "  Unit could be: B/K/M/G which represents Byte/Kilobyte/Megabyte/Gigabyte." << endl
1242498b56bSopenharmony_ci    << "  <size> range: [" << Size2Str(MIN_BUFFER_SIZE) << "," << Size2Str(MAX_BUFFER_SIZE) << "]." << endl
1252498b56bSopenharmony_ci    << "  Advanced option:" << endl
1262498b56bSopenharmony_ci    << "  -t <type>, --type=<type>" << endl
1272498b56bSopenharmony_ci    << "    Set specific type/types log buffer size with format: type1,type2,type3" << endl
1282498b56bSopenharmony_ci    << "    Type coule be: app/core/init/kmsg/only_prerelease." << endl
1292498b56bSopenharmony_ci    << "    Default types are: app,core,only_prerelease" << endl
1302498b56bSopenharmony_ci    << "  **It's a persistant configuration**" << endl;
1312498b56bSopenharmony_ci}
1322498b56bSopenharmony_ci
1332498b56bSopenharmony_cistatic void StatisticHelper()
1342498b56bSopenharmony_ci{
1352498b56bSopenharmony_ci    cout
1362498b56bSopenharmony_ci    << "-s, --statistics" << endl
1372498b56bSopenharmony_ci    << "  Query log statistic information." << endl
1382498b56bSopenharmony_ci    << "  Set param persist.sys.hilog.stats true to enable statistic." << endl
1392498b56bSopenharmony_ci    << "  Set param persist.sys.hilog.stats.tag true to enable statistic of log tag." << endl
1402498b56bSopenharmony_ci    << "-S" << endl
1412498b56bSopenharmony_ci    << "  Clear hilogd statistic information." << endl;
1422498b56bSopenharmony_ci}
1432498b56bSopenharmony_ci
1442498b56bSopenharmony_cistatic void PersistTaskHelper()
1452498b56bSopenharmony_ci{
1462498b56bSopenharmony_ci    cout
1472498b56bSopenharmony_ci    << "-w <control>,--write=<control>" << endl
1482498b56bSopenharmony_ci    << "  Log persistance task control, options are:" << endl
1492498b56bSopenharmony_ci    << "    query      query tasks informations" << endl
1502498b56bSopenharmony_ci    << "    stop       stop all tasks" << endl
1512498b56bSopenharmony_ci    << "    start      start one task" << endl
1522498b56bSopenharmony_ci    << "    refresh    refresh buffer content to file" << endl
1532498b56bSopenharmony_ci    << "    clear      clear /data/log/hilog/hilog*.gz" << endl
1542498b56bSopenharmony_ci    << "  Persistance task is used for saving logs in files." << endl
1552498b56bSopenharmony_ci    << "  The files are saved in directory: " << HILOG_FILE_DIR << endl
1562498b56bSopenharmony_ci    << "  Advanced options:" << endl
1572498b56bSopenharmony_ci    << "  -f <filename>, --filename=<filename>" << endl
1582498b56bSopenharmony_ci    << "    Set log file name, name should be valid of Linux FS." << endl
1592498b56bSopenharmony_ci    << "  -l <length>, --length=<length>" << endl
1602498b56bSopenharmony_ci    << "    Set single log file size. <length> could be number or number with unit." << endl
1612498b56bSopenharmony_ci    << "    Unit could be: B/K/M/G which represents Byte/Kilobyte/Megabyte/Gigabyte." << endl
1622498b56bSopenharmony_ci    << "    <length> range: [" << Size2Str(MIN_LOG_FILE_SIZE) <<", " << Size2Str(MAX_LOG_FILE_SIZE) << "]." << endl
1632498b56bSopenharmony_ci    << "  -n <number>, --number<number>" << endl
1642498b56bSopenharmony_ci    << "    Set max log file numbers, log file rotate when files count over this number." << endl
1652498b56bSopenharmony_ci    << "    <number> range: [" << MIN_LOG_FILE_NUM << ", " << MAX_LOG_FILE_NUM << "]." << endl
1662498b56bSopenharmony_ci    << "  -m <compress algorithm>,--stream=<compress algorithm>" << endl
1672498b56bSopenharmony_ci    << "    Set log file compressed algorithm, options are:" << endl
1682498b56bSopenharmony_ci    << "      none       write file with non-compressed logs." << endl
1692498b56bSopenharmony_ci    << "      zlib       write file with zlib compressed logs." << endl
1702498b56bSopenharmony_ci    << "  -j <jobid>, --jobid<jobid>" << endl
1712498b56bSopenharmony_ci    << "    Start/stop specific task of <jobid>." << endl
1722498b56bSopenharmony_ci    << "    <jobid> range: [" << JOB_ID_MIN << ", 0x" << hex << JOB_ID_MAX << dec << ")." << endl
1732498b56bSopenharmony_ci    << "  User can start task with options (t/L/D/T/P/e/v) as if using them when \"Query logs\" too." << endl
1742498b56bSopenharmony_ci    << "  **It's a persistant configuration**" << endl;
1752498b56bSopenharmony_ci}
1762498b56bSopenharmony_ci
1772498b56bSopenharmony_cistatic void PrivateHelper()
1782498b56bSopenharmony_ci{
1792498b56bSopenharmony_ci    cout
1802498b56bSopenharmony_ci    << "-p <on/off>, --privacy <on/off>" << endl
1812498b56bSopenharmony_ci    << "  Set HILOG api privacy formatter feature on or off." << endl
1822498b56bSopenharmony_ci    << "  **It's a temporary configuration, will be lost after reboot**" << endl;
1832498b56bSopenharmony_ci}
1842498b56bSopenharmony_ci
1852498b56bSopenharmony_cistatic void KmsgHelper()
1862498b56bSopenharmony_ci{
1872498b56bSopenharmony_ci    cout
1882498b56bSopenharmony_ci    << "-k <on/off>, --kmsg <on/off>" << endl
1892498b56bSopenharmony_ci    << "  Set hilogd storing kmsg log feature on or off" << endl
1902498b56bSopenharmony_ci    << "  **It's a persistant configuration**" << endl;
1912498b56bSopenharmony_ci}
1922498b56bSopenharmony_ci
1932498b56bSopenharmony_cistatic void FlowControlHelper()
1942498b56bSopenharmony_ci{
1952498b56bSopenharmony_ci    cout
1962498b56bSopenharmony_ci    << "-Q <control-type>" << endl
1972498b56bSopenharmony_ci    << "  Set log flow-control feature on or off, options are:" << endl
1982498b56bSopenharmony_ci    << "    pidon     process flow control on" << endl
1992498b56bSopenharmony_ci    << "    pidoff    process flow control off" << endl
2002498b56bSopenharmony_ci    << "    domainon  domain flow control on" << endl
2012498b56bSopenharmony_ci    << "    domainoff domain flow control off" << endl
2022498b56bSopenharmony_ci    << "  **It's a temporary configuration, will be lost after reboot**" << endl;
2032498b56bSopenharmony_ci}
2042498b56bSopenharmony_ci
2052498b56bSopenharmony_cistatic void BaseLevelHelper()
2062498b56bSopenharmony_ci{
2072498b56bSopenharmony_ci    cout
2082498b56bSopenharmony_ci    << "-b <loglevel>, --baselevel=<loglevel>" << endl
2092498b56bSopenharmony_ci    << "  Set global loggable level to <loglevel>" << endl
2102498b56bSopenharmony_ci    << "  Long and short level string are both accepted." << endl
2112498b56bSopenharmony_ci    << "  Long level string coule be: DEBUG/INFO/WARN/ERROR/FATAL/X." << endl
2122498b56bSopenharmony_ci    << "  Short level string coule be: D/I/W/E/F/X." << endl
2132498b56bSopenharmony_ci    << "  X means that loggable level is higher than the max level, no log could be printed." << endl
2142498b56bSopenharmony_ci    << "  Advanced options:" << endl
2152498b56bSopenharmony_ci    << "  -D <domain>, --domain=<domain>" << endl
2162498b56bSopenharmony_ci    << "    Set specific domain loggable level." << endl
2172498b56bSopenharmony_ci    << "    See domain description at the end of this message." << endl
2182498b56bSopenharmony_ci    << "  -T <tag>, --tag=<tag>" << endl
2192498b56bSopenharmony_ci    << "    Set specific tag loggable level." << endl
2202498b56bSopenharmony_ci    << "    The priority is: tag level > domain level > global level." << endl
2212498b56bSopenharmony_ci    << "  **It's a temporary configuration, will be lost after reboot**" << endl;
2222498b56bSopenharmony_ci}
2232498b56bSopenharmony_ci
2242498b56bSopenharmony_cistatic void DomainHelper()
2252498b56bSopenharmony_ci{
2262498b56bSopenharmony_ci    cout
2272498b56bSopenharmony_ci    << endl << endl
2282498b56bSopenharmony_ci    << "Domain description:" << endl
2292498b56bSopenharmony_ci    << "  Log type \"core\" & \"init\" & \"only_prerelease\" are used for OS subsystems, the range is"
2302498b56bSopenharmony_ci    << "  [0x" << hex << DOMAIN_OS_MIN << ",  0x" << DOMAIN_OS_MAX << "]" << endl
2312498b56bSopenharmony_ci    << "  Log type \"app\" is used for applications, the range is [0x" << DOMAIN_APP_MIN << ","
2322498b56bSopenharmony_ci    << "  0x" << DOMAIN_APP_MAX << "]" << dec << endl
2332498b56bSopenharmony_ci    << "  To reduce redundant info when printing logs, only last five hex numbers of domain are printed" << endl
2342498b56bSopenharmony_ci    << "  So if user wants to use -D option to filter OS logs, user should add 0xD0 as prefix to the printed domain:"
2352498b56bSopenharmony_ci    << endl
2362498b56bSopenharmony_ci    << "  Exapmle: hilog -D 0xD0xxxxx" << endl
2372498b56bSopenharmony_ci    << "  The xxxxx is the domain string printed in logs." << endl;
2382498b56bSopenharmony_ci}
2392498b56bSopenharmony_ci
2402498b56bSopenharmony_cistatic void ComboHelper()
2412498b56bSopenharmony_ci{
2422498b56bSopenharmony_ci    cout
2432498b56bSopenharmony_ci    << "The first layer options can't be used in combination, ILLEGAL expamples:" << endl
2442498b56bSopenharmony_ci    << "    hilog -S -s; hilog -w start -r; hilog -p on -k on -b D" << endl;
2452498b56bSopenharmony_ci}
2462498b56bSopenharmony_ci
2472498b56bSopenharmony_ciusing HelperFunc = std::function<void()>;
2482498b56bSopenharmony_cistatic const std::list<pair<string, HelperFunc>> g_HelperList = {
2492498b56bSopenharmony_ci    {"query", QueryHelper},
2502498b56bSopenharmony_ci    {"clear", ClearHelper},
2512498b56bSopenharmony_ci    {"buffer", BufferHelper},
2522498b56bSopenharmony_ci    {"stats", StatisticHelper},
2532498b56bSopenharmony_ci    {"persist", PersistTaskHelper},
2542498b56bSopenharmony_ci    {"private", PrivateHelper},
2552498b56bSopenharmony_ci    {"kmsg", KmsgHelper},
2562498b56bSopenharmony_ci    {"flowcontrol", FlowControlHelper},
2572498b56bSopenharmony_ci    {"baselevel", BaseLevelHelper},
2582498b56bSopenharmony_ci    {"combo", ComboHelper},
2592498b56bSopenharmony_ci    {"domain", DomainHelper},
2602498b56bSopenharmony_ci};
2612498b56bSopenharmony_ci
2622498b56bSopenharmony_cistatic void Helper(const string& arg)
2632498b56bSopenharmony_ci{
2642498b56bSopenharmony_ci    cout << "Usage:" << endl
2652498b56bSopenharmony_ci    << "-h --help" << endl
2662498b56bSopenharmony_ci    << "  Show all help information." << endl
2672498b56bSopenharmony_ci    << "  Show single help information with option: " << endl
2682498b56bSopenharmony_ci    << "  query/clear/buffer/stats/persist/private/kmsg/flowcontrol/baselevel/domain/combo" << endl;
2692498b56bSopenharmony_ci    for (auto &it : g_HelperList) {
2702498b56bSopenharmony_ci        if (arg == "" || arg == it.first) {
2712498b56bSopenharmony_ci            it.second();
2722498b56bSopenharmony_ci        }
2732498b56bSopenharmony_ci    }
2742498b56bSopenharmony_ci    return;
2752498b56bSopenharmony_ci}
2762498b56bSopenharmony_ci
2772498b56bSopenharmony_cistatic void PrintErr(int error)
2782498b56bSopenharmony_ci{
2792498b56bSopenharmony_ci    cerr << ErrorCode2Str(error) << endl;
2802498b56bSopenharmony_ci}
2812498b56bSopenharmony_ci
2822498b56bSopenharmony_cistatic void PrintResult(int ret, const string& msg)
2832498b56bSopenharmony_ci{
2842498b56bSopenharmony_ci    cout << msg << ((ret == RET_SUCCESS) ? " successfully" : " failed") << endl;
2852498b56bSopenharmony_ci}
2862498b56bSopenharmony_ci
2872498b56bSopenharmony_cienum class ControlCmd {
2882498b56bSopenharmony_ci    NOT_CMD = -1,
2892498b56bSopenharmony_ci    CMD_HELP = 0,
2902498b56bSopenharmony_ci    CMD_QUERY,
2912498b56bSopenharmony_ci    CMD_REMOVE,
2922498b56bSopenharmony_ci    CMD_BUFFER_SIZE_QUERY,
2932498b56bSopenharmony_ci    CMD_BUFFER_SIZE_SET,
2942498b56bSopenharmony_ci    CMD_STATS_INFO_QUERY,
2952498b56bSopenharmony_ci    CMD_STATS_INFO_CLEAR,
2962498b56bSopenharmony_ci    CMD_PERSIST_TASK,
2972498b56bSopenharmony_ci    CMD_PRIVATE_FEATURE_SET,
2982498b56bSopenharmony_ci    CMD_KMSG_FEATURE_SET,
2992498b56bSopenharmony_ci    CMD_FLOWCONTROL_FEATURE_SET,
3002498b56bSopenharmony_ci    CMD_LOGLEVEL_SET,
3012498b56bSopenharmony_ci};
3022498b56bSopenharmony_ci
3032498b56bSopenharmony_cistruct HilogArgs {
3042498b56bSopenharmony_ci    uint16_t headLines;
3052498b56bSopenharmony_ci    uint16_t baseLevel;
3062498b56bSopenharmony_ci    bool blackDomain;
3072498b56bSopenharmony_ci    int domainCount;
3082498b56bSopenharmony_ci    uint32_t domains[MAX_DOMAINS];
3092498b56bSopenharmony_ci    string regex;
3102498b56bSopenharmony_ci    string fileName;
3112498b56bSopenharmony_ci    int32_t buffSize;
3122498b56bSopenharmony_ci    uint32_t jobId;
3132498b56bSopenharmony_ci    uint32_t fileSize;
3142498b56bSopenharmony_ci    uint16_t levels;
3152498b56bSopenharmony_ci    string stream;
3162498b56bSopenharmony_ci    uint16_t fileNum;
3172498b56bSopenharmony_ci    bool blackPid;
3182498b56bSopenharmony_ci    int pidCount;
3192498b56bSopenharmony_ci    uint32_t pids[MAX_PIDS];
3202498b56bSopenharmony_ci    uint16_t types;
3212498b56bSopenharmony_ci    bool blackTag;
3222498b56bSopenharmony_ci    int tagCount;
3232498b56bSopenharmony_ci    string tags[MAX_TAGS];
3242498b56bSopenharmony_ci    bool colorful;
3252498b56bSopenharmony_ci    FormatTime timeFormat;
3262498b56bSopenharmony_ci    FormatTimeAccu timeAccuFormat;
3272498b56bSopenharmony_ci    bool year;
3282498b56bSopenharmony_ci    bool zone;
3292498b56bSopenharmony_ci    bool wrap;
3302498b56bSopenharmony_ci    bool noBlock;
3312498b56bSopenharmony_ci    uint16_t tailLines;
3322498b56bSopenharmony_ci
3332498b56bSopenharmony_ci    HilogArgs() : headLines (0), baseLevel(0), blackDomain(false), domainCount(0), domains { 0 }, regex(""),
3342498b56bSopenharmony_ci        fileName(""), buffSize(0), jobId(0), fileSize(0), levels(0), stream(""), fileNum(0), blackPid(false),
3352498b56bSopenharmony_ci        pidCount(0), pids { 0 }, types(0), blackTag(false), tagCount(0), tags { "" }, colorful(false),
3362498b56bSopenharmony_ci        timeFormat(FormatTime::INVALID), timeAccuFormat(FormatTimeAccu::INVALID), year(false), zone(false),
3372498b56bSopenharmony_ci        wrap(false), noBlock(false), tailLines(0) {}
3382498b56bSopenharmony_ci
3392498b56bSopenharmony_ci    void ToOutputRqst(OutputRqst& rqst)
3402498b56bSopenharmony_ci    {
3412498b56bSopenharmony_ci        rqst.headLines = headLines;
3422498b56bSopenharmony_ci        rqst.types = types;
3432498b56bSopenharmony_ci        rqst.levels = levels;
3442498b56bSopenharmony_ci        rqst.blackDomain = blackDomain;
3452498b56bSopenharmony_ci        rqst.domainCount = static_cast<uint8_t>(domainCount);
3462498b56bSopenharmony_ci        int i;
3472498b56bSopenharmony_ci        for (i = 0; i < domainCount; i++) {
3482498b56bSopenharmony_ci            rqst.domains[i] = domains[i];
3492498b56bSopenharmony_ci        }
3502498b56bSopenharmony_ci        rqst.blackTag = blackTag;
3512498b56bSopenharmony_ci        rqst.tagCount = tagCount;
3522498b56bSopenharmony_ci        for (i = 0; i < tagCount; i++) {
3532498b56bSopenharmony_ci            (void)strncpy_s(rqst.tags[i], MAX_TAG_LEN, tags[i].c_str(), tags[i].length());
3542498b56bSopenharmony_ci        }
3552498b56bSopenharmony_ci        rqst.blackPid = blackPid;
3562498b56bSopenharmony_ci        rqst.pidCount = pidCount;
3572498b56bSopenharmony_ci        for (i = 0; i < pidCount; i++) {
3582498b56bSopenharmony_ci            rqst.pids[i] = pids[i];
3592498b56bSopenharmony_ci        }
3602498b56bSopenharmony_ci        (void)strncpy_s(rqst.regex, MAX_REGEX_STR_LEN, regex.c_str(), regex.length());
3612498b56bSopenharmony_ci        rqst.noBlock = noBlock;
3622498b56bSopenharmony_ci        rqst.tailLines = tailLines;
3632498b56bSopenharmony_ci    }
3642498b56bSopenharmony_ci
3652498b56bSopenharmony_ci    void ToPersistStartRqst(PersistStartRqst& rqst)
3662498b56bSopenharmony_ci    {
3672498b56bSopenharmony_ci        ToOutputRqst(rqst.outputFilter);
3682498b56bSopenharmony_ci        rqst.jobId = jobId;
3692498b56bSopenharmony_ci        rqst.fileNum = fileNum;
3702498b56bSopenharmony_ci        rqst.fileSize = fileSize;
3712498b56bSopenharmony_ci        (void)strncpy_s(rqst.fileName, MAX_FILE_NAME_LEN, fileName.c_str(), fileName.length());
3722498b56bSopenharmony_ci        (void)strncpy_s(rqst.stream, MAX_STREAM_NAME_LEN, stream.c_str(), stream.length());
3732498b56bSopenharmony_ci    }
3742498b56bSopenharmony_ci
3752498b56bSopenharmony_ci    void ToPersistStopRqst(PersistStopRqst& rqst)
3762498b56bSopenharmony_ci    {
3772498b56bSopenharmony_ci        rqst.jobId = jobId;
3782498b56bSopenharmony_ci    }
3792498b56bSopenharmony_ci
3802498b56bSopenharmony_ci    void ToBufferSizeSetRqst(BufferSizeSetRqst& rqst)
3812498b56bSopenharmony_ci    {
3822498b56bSopenharmony_ci        rqst.types = types;
3832498b56bSopenharmony_ci        rqst.size = buffSize;
3842498b56bSopenharmony_ci    }
3852498b56bSopenharmony_ci
3862498b56bSopenharmony_ci    void ToBufferSizeGetRqst(BufferSizeGetRqst& rqst)
3872498b56bSopenharmony_ci    {
3882498b56bSopenharmony_ci        rqst.types = types;
3892498b56bSopenharmony_ci    }
3902498b56bSopenharmony_ci
3912498b56bSopenharmony_ci    void ToStatsQueryRqst(StatsQueryRqst& rqst)
3922498b56bSopenharmony_ci    {
3932498b56bSopenharmony_ci        rqst.types = types;
3942498b56bSopenharmony_ci        rqst.domainCount = static_cast<uint8_t>(domainCount);
3952498b56bSopenharmony_ci        int i;
3962498b56bSopenharmony_ci        for (i = 0; i < domainCount; i++) {
3972498b56bSopenharmony_ci            rqst.domains[i] = domains[i];
3982498b56bSopenharmony_ci        }
3992498b56bSopenharmony_ci    }
4002498b56bSopenharmony_ci
4012498b56bSopenharmony_ci    void ToLogRemoveRqst(LogRemoveRqst& rqst)
4022498b56bSopenharmony_ci    {
4032498b56bSopenharmony_ci        rqst.types = types;
4042498b56bSopenharmony_ci    }
4052498b56bSopenharmony_ci};
4062498b56bSopenharmony_ci
4072498b56bSopenharmony_ciusing OptHandler = std::function<int(HilogArgs& context, const char *arg)>;
4082498b56bSopenharmony_ci
4092498b56bSopenharmony_cistatic int QueryLogHandler(HilogArgs& context, const char *arg)
4102498b56bSopenharmony_ci{
4112498b56bSopenharmony_ci    OutputRqst rqst = { 0 };
4122498b56bSopenharmony_ci    context.ToOutputRqst(rqst);
4132498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::OUTPUT_RQST, IoctlCmd::OUTPUT_RSP);
4142498b56bSopenharmony_ci    int ret = ioctl.RequestOutput(rqst, [&context](const OutputRsp& rsp) {
4152498b56bSopenharmony_ci        if (rsp.end) {
4162498b56bSopenharmony_ci            return RET_SUCCESS;
4172498b56bSopenharmony_ci        }
4182498b56bSopenharmony_ci        LogContent content = {
4192498b56bSopenharmony_ci            .level = rsp.level,
4202498b56bSopenharmony_ci            .type = rsp.type,
4212498b56bSopenharmony_ci            .pid = rsp.pid,
4222498b56bSopenharmony_ci            .tid = rsp.tid,
4232498b56bSopenharmony_ci            .domain = rsp.domain,
4242498b56bSopenharmony_ci            .tv_sec = rsp.tv_sec,
4252498b56bSopenharmony_ci            .tv_nsec = rsp.tv_nsec,
4262498b56bSopenharmony_ci            .mono_sec = rsp.mono_sec,
4272498b56bSopenharmony_ci            .tag = rsp.data,
4282498b56bSopenharmony_ci            .log = (rsp.data + rsp.tagLen)
4292498b56bSopenharmony_ci        };
4302498b56bSopenharmony_ci        LogFormat format = {
4312498b56bSopenharmony_ci            .colorful = context.colorful,
4322498b56bSopenharmony_ci            .timeFormat = ((context.timeFormat == FormatTime::INVALID) ? FormatTime::TIME : context.timeFormat),
4332498b56bSopenharmony_ci            .timeAccuFormat =
4342498b56bSopenharmony_ci                ((context.timeAccuFormat == FormatTimeAccu::INVALID) ? FormatTimeAccu::MSEC : context.timeAccuFormat),
4352498b56bSopenharmony_ci            .year = context.year,
4362498b56bSopenharmony_ci            .zone = context.zone,
4372498b56bSopenharmony_ci            .wrap = context.wrap
4382498b56bSopenharmony_ci        };
4392498b56bSopenharmony_ci        LogPrintWithFormat(content, format);
4402498b56bSopenharmony_ci        return static_cast<int>(SUCCESS_CONTINUE);
4412498b56bSopenharmony_ci    });
4422498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
4432498b56bSopenharmony_ci        return ret;
4442498b56bSopenharmony_ci    }
4452498b56bSopenharmony_ci    return RET_SUCCESS;
4462498b56bSopenharmony_ci}
4472498b56bSopenharmony_ci
4482498b56bSopenharmony_cistatic int HeadHandler(HilogArgs& context, const char *arg)
4492498b56bSopenharmony_ci{
4502498b56bSopenharmony_ci    if (IsNumericStr(arg) == false) {
4512498b56bSopenharmony_ci        return ERR_NOT_NUMBER_STR;
4522498b56bSopenharmony_ci    }
4532498b56bSopenharmony_ci    int lines = 0;
4542498b56bSopenharmony_ci    (void)StrToInt(arg, lines);
4552498b56bSopenharmony_ci    context.headLines = static_cast<uint16_t>(lines);
4562498b56bSopenharmony_ci    context.noBlock = true; // don't block implicitly
4572498b56bSopenharmony_ci    return QueryLogHandler(context, arg);
4582498b56bSopenharmony_ci}
4592498b56bSopenharmony_ci
4602498b56bSopenharmony_cistatic int BaseLogLevelHandler(HilogArgs& context, const char *arg)
4612498b56bSopenharmony_ci{
4622498b56bSopenharmony_ci    uint16_t baseLevel = PrettyStr2LogLevel(arg);
4632498b56bSopenharmony_ci    if (baseLevel == LOG_LEVEL_MIN) {
4642498b56bSopenharmony_ci        return ERR_LOG_LEVEL_INVALID;
4652498b56bSopenharmony_ci    }
4662498b56bSopenharmony_ci    context.baseLevel = baseLevel;
4672498b56bSopenharmony_ci    int ret;
4682498b56bSopenharmony_ci    if (context.domainCount == 0 && context.tagCount == 0) {
4692498b56bSopenharmony_ci        ret = SetGlobalLevel(context.baseLevel);
4702498b56bSopenharmony_ci        PrintResult(ret, (string("Set global log level to ") + arg));
4712498b56bSopenharmony_ci    }
4722498b56bSopenharmony_ci    if (context.domainCount != 0) {
4732498b56bSopenharmony_ci        for (int i = 0; i < context.domainCount; i++) {
4742498b56bSopenharmony_ci            ret = SetDomainLevel(context.domains[i], context.baseLevel);
4752498b56bSopenharmony_ci            PrintResult(ret, (string("Set domain 0x") + Uint2HexStr(context.domains[i]) +  " log level to " + arg));
4762498b56bSopenharmony_ci        }
4772498b56bSopenharmony_ci    }
4782498b56bSopenharmony_ci    if (context.tagCount != 0) {
4792498b56bSopenharmony_ci        for (int i = 0; i < context.tagCount; i++) {
4802498b56bSopenharmony_ci            ret = SetTagLevel(context.tags[i], context.baseLevel);
4812498b56bSopenharmony_ci            PrintResult(ret, (string("Set tag ") + context.tags[i] +  " log level to " + arg));
4822498b56bSopenharmony_ci        }
4832498b56bSopenharmony_ci    }
4842498b56bSopenharmony_ci    return RET_SUCCESS;
4852498b56bSopenharmony_ci}
4862498b56bSopenharmony_ci
4872498b56bSopenharmony_cistatic constexpr char BLACK_PREFIX = '^';
4882498b56bSopenharmony_cistatic int DomainHandler(HilogArgs& context, const char *arg)
4892498b56bSopenharmony_ci{
4902498b56bSopenharmony_ci    context.blackDomain = (arg[0] == BLACK_PREFIX);
4912498b56bSopenharmony_ci    std::vector<std::string> domains;
4922498b56bSopenharmony_ci    Split(context.blackDomain ? arg + 1 : arg, domains);
4932498b56bSopenharmony_ci    if (domains.size() == 0) {
4942498b56bSopenharmony_ci        return ERR_INVALID_ARGUMENT;
4952498b56bSopenharmony_ci    }
4962498b56bSopenharmony_ci    int index = 0;
4972498b56bSopenharmony_ci    for (string d : domains) {
4982498b56bSopenharmony_ci        if (index >= MAX_DOMAINS) {
4992498b56bSopenharmony_ci            return ERR_TOO_MANY_DOMAINS;
5002498b56bSopenharmony_ci        }
5012498b56bSopenharmony_ci        uint32_t domain = HexStr2Uint(d);
5022498b56bSopenharmony_ci        if (domain == 0) {
5032498b56bSopenharmony_ci            return ERR_INVALID_DOMAIN_STR;
5042498b56bSopenharmony_ci        }
5052498b56bSopenharmony_ci        context.domains[index++] = domain;
5062498b56bSopenharmony_ci    }
5072498b56bSopenharmony_ci    context.domainCount = index;
5082498b56bSopenharmony_ci    return RET_SUCCESS;
5092498b56bSopenharmony_ci}
5102498b56bSopenharmony_ci
5112498b56bSopenharmony_cistatic int RegexHandler(HilogArgs& context, const char *arg)
5122498b56bSopenharmony_ci{
5132498b56bSopenharmony_ci    context.regex = arg;
5142498b56bSopenharmony_ci    if (context.regex.length() >= MAX_REGEX_STR_LEN) {
5152498b56bSopenharmony_ci        return ERR_REGEX_STR_TOO_LONG;
5162498b56bSopenharmony_ci    }
5172498b56bSopenharmony_ci    return RET_SUCCESS;
5182498b56bSopenharmony_ci}
5192498b56bSopenharmony_ci
5202498b56bSopenharmony_cistatic int FileNameHandler(HilogArgs& context, const char *arg)
5212498b56bSopenharmony_ci{
5222498b56bSopenharmony_ci    context.fileName = arg;
5232498b56bSopenharmony_ci    if (context.fileName.length() >= MAX_FILE_NAME_LEN) {
5242498b56bSopenharmony_ci        return ERR_FILE_NAME_TOO_LONG;
5252498b56bSopenharmony_ci    }
5262498b56bSopenharmony_ci    return RET_SUCCESS;
5272498b56bSopenharmony_ci}
5282498b56bSopenharmony_ci
5292498b56bSopenharmony_cistatic int BufferSizeGetHandler(HilogArgs& context, const char *arg)
5302498b56bSopenharmony_ci{
5312498b56bSopenharmony_ci    BufferSizeGetRqst rqst = { 0 };
5322498b56bSopenharmony_ci    context.ToBufferSizeGetRqst(rqst);
5332498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::BUFFERSIZE_GET_RQST, IoctlCmd::BUFFERSIZE_GET_RSP);
5342498b56bSopenharmony_ci    int ret = ioctl.Request<BufferSizeGetRqst, BufferSizeGetRsp>(rqst, [&rqst](const BufferSizeGetRsp& rsp) {
5352498b56bSopenharmony_ci        for (uint16_t i = 0; i < static_cast<uint16_t>(LOG_TYPE_MAX); i++) {
5362498b56bSopenharmony_ci            if (rsp.size[i] > 0) {
5372498b56bSopenharmony_ci                cout << "Log type " << LogType2Str(i) << " buffer size is " << Size2Str(rsp.size[i]) << endl;
5382498b56bSopenharmony_ci            }
5392498b56bSopenharmony_ci        }
5402498b56bSopenharmony_ci        return RET_SUCCESS;
5412498b56bSopenharmony_ci    });
5422498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
5432498b56bSopenharmony_ci        cout << "Get " << ComboLogType2Str(rqst.types) << " buffer size failed" << endl;
5442498b56bSopenharmony_ci    }
5452498b56bSopenharmony_ci    return ret;
5462498b56bSopenharmony_ci}
5472498b56bSopenharmony_ci
5482498b56bSopenharmony_cistatic int BufferSizeSetHandler(HilogArgs& context, const char *arg)
5492498b56bSopenharmony_ci{
5502498b56bSopenharmony_ci    uint64_t size = Str2Size(arg);
5512498b56bSopenharmony_ci    if (size == 0) {
5522498b56bSopenharmony_ci        return ERR_INVALID_SIZE_STR;
5532498b56bSopenharmony_ci    }
5542498b56bSopenharmony_ci    context.buffSize = static_cast<int32_t>(size);
5552498b56bSopenharmony_ci    BufferSizeSetRqst rqst;
5562498b56bSopenharmony_ci    context.ToBufferSizeSetRqst(rqst);
5572498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::BUFFERSIZE_SET_RQST, IoctlCmd::BUFFERSIZE_SET_RSP);
5582498b56bSopenharmony_ci    int ret = ioctl.Request<BufferSizeSetRqst, BufferSizeSetRsp>(rqst, [&rqst](const BufferSizeSetRsp& rsp) {
5592498b56bSopenharmony_ci        for (uint16_t i = 0; i < static_cast<uint16_t>(LOG_TYPE_MAX); i++) {
5602498b56bSopenharmony_ci            if (rsp.size[i] > 0) {
5612498b56bSopenharmony_ci                cout << "Set log type " << LogType2Str(i) << " buffer size to "
5622498b56bSopenharmony_ci                << Size2Str(rsp.size[i]) << " successfully" << endl;
5632498b56bSopenharmony_ci            } else if (rsp.size[i] < 0) {
5642498b56bSopenharmony_ci                cout << "Set log type " << LogType2Str(i) << " buffer size to "
5652498b56bSopenharmony_ci                << Size2Str(rqst.size) << " failed" << endl;
5662498b56bSopenharmony_ci                PrintErr(rsp.size[i]);
5672498b56bSopenharmony_ci            }
5682498b56bSopenharmony_ci        }
5692498b56bSopenharmony_ci        return RET_SUCCESS;
5702498b56bSopenharmony_ci    });
5712498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
5722498b56bSopenharmony_ci        cout << "Set buffer size failed" << endl;
5732498b56bSopenharmony_ci    }
5742498b56bSopenharmony_ci    return ret;
5752498b56bSopenharmony_ci}
5762498b56bSopenharmony_ci
5772498b56bSopenharmony_cistatic int HelpHandler(HilogArgs& context, const char *arg)
5782498b56bSopenharmony_ci{
5792498b56bSopenharmony_ci    Helper("");
5802498b56bSopenharmony_ci    return RET_SUCCESS;
5812498b56bSopenharmony_ci}
5822498b56bSopenharmony_ci
5832498b56bSopenharmony_cistatic int JobIdHandler(HilogArgs& context, const char *arg)
5842498b56bSopenharmony_ci{
5852498b56bSopenharmony_ci    if (IsNumericStr(arg) == false) {
5862498b56bSopenharmony_ci        return ERR_NOT_NUMBER_STR;
5872498b56bSopenharmony_ci    }
5882498b56bSopenharmony_ci    int jobId = 0;
5892498b56bSopenharmony_ci    (void)StrToInt(arg, jobId);
5902498b56bSopenharmony_ci    context.jobId = static_cast<uint32_t>(jobId);
5912498b56bSopenharmony_ci    return RET_SUCCESS;
5922498b56bSopenharmony_ci}
5932498b56bSopenharmony_ci
5942498b56bSopenharmony_cistatic const string FEATURE_ON = "on";
5952498b56bSopenharmony_cistatic const string FEATURE_OFF = "off";
5962498b56bSopenharmony_cistatic int KmsgFeatureSetHandler(HilogArgs& context, const char *arg)
5972498b56bSopenharmony_ci{
5982498b56bSopenharmony_ci    string argStr = arg;
5992498b56bSopenharmony_ci    bool kmsgOn = true;
6002498b56bSopenharmony_ci    if (argStr == FEATURE_ON) {
6012498b56bSopenharmony_ci        kmsgOn = true;
6022498b56bSopenharmony_ci    } else if (argStr == FEATURE_OFF) {
6032498b56bSopenharmony_ci        kmsgOn = false;
6042498b56bSopenharmony_ci    } else {
6052498b56bSopenharmony_ci        return ERR_INVALID_ARGUMENT;
6062498b56bSopenharmony_ci    }
6072498b56bSopenharmony_ci    KmsgEnableRqst rqst = { kmsgOn };
6082498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::KMSG_ENABLE_RQST, IoctlCmd::KMSG_ENABLE_RSP);
6092498b56bSopenharmony_ci    int ret = ioctl.Request<KmsgEnableRqst, KmsgEnableRsp>(rqst, [&rqst](const KmsgEnableRsp& rsp) {
6102498b56bSopenharmony_ci        return RET_SUCCESS;
6112498b56bSopenharmony_ci    });
6122498b56bSopenharmony_ci    PrintResult(ret, (string("Set hilogd storing kmsg log ") + arg));
6132498b56bSopenharmony_ci    return ret;
6142498b56bSopenharmony_ci}
6152498b56bSopenharmony_ci
6162498b56bSopenharmony_cistatic int FileLengthHandler(HilogArgs& context, const char *arg)
6172498b56bSopenharmony_ci{
6182498b56bSopenharmony_ci    uint64_t size = Str2Size(arg);
6192498b56bSopenharmony_ci    if (size == 0) {
6202498b56bSopenharmony_ci        return ERR_INVALID_SIZE_STR;
6212498b56bSopenharmony_ci    }
6222498b56bSopenharmony_ci    context.fileSize = size;
6232498b56bSopenharmony_ci    return RET_SUCCESS;
6242498b56bSopenharmony_ci}
6252498b56bSopenharmony_ci
6262498b56bSopenharmony_cistatic int LevelHandler(HilogArgs& context, const char *arg)
6272498b56bSopenharmony_ci{
6282498b56bSopenharmony_ci    uint16_t levels = Str2ComboLogLevel(arg);
6292498b56bSopenharmony_ci    if (levels == 0) {
6302498b56bSopenharmony_ci        return ERR_LOG_LEVEL_INVALID;
6312498b56bSopenharmony_ci    }
6322498b56bSopenharmony_ci    context.levels = levels;
6332498b56bSopenharmony_ci    return RET_SUCCESS;
6342498b56bSopenharmony_ci}
6352498b56bSopenharmony_ci
6362498b56bSopenharmony_cistatic int FileCompressHandler(HilogArgs& context, const char *arg)
6372498b56bSopenharmony_ci{
6382498b56bSopenharmony_ci    context.stream = arg;
6392498b56bSopenharmony_ci    return RET_SUCCESS;
6402498b56bSopenharmony_ci}
6412498b56bSopenharmony_ci
6422498b56bSopenharmony_cistatic int FileNumberHandler(HilogArgs& context, const char *arg)
6432498b56bSopenharmony_ci{
6442498b56bSopenharmony_ci    if (IsNumericStr(arg) == false) {
6452498b56bSopenharmony_ci        return ERR_NOT_NUMBER_STR;
6462498b56bSopenharmony_ci    }
6472498b56bSopenharmony_ci    int fileNum = 0;
6482498b56bSopenharmony_ci    (void)StrToInt(arg, fileNum);
6492498b56bSopenharmony_ci    context.fileNum = static_cast<uint16_t>(fileNum);
6502498b56bSopenharmony_ci    return RET_SUCCESS;
6512498b56bSopenharmony_ci}
6522498b56bSopenharmony_ci
6532498b56bSopenharmony_cistatic int PrivateFeatureSetHandler(HilogArgs& context, const char *arg)
6542498b56bSopenharmony_ci{
6552498b56bSopenharmony_ci    string argStr = arg;
6562498b56bSopenharmony_ci    bool privateOn = true;
6572498b56bSopenharmony_ci    if (argStr == FEATURE_ON) {
6582498b56bSopenharmony_ci        privateOn = true;
6592498b56bSopenharmony_ci    } else if (argStr == FEATURE_OFF) {
6602498b56bSopenharmony_ci        privateOn = false;
6612498b56bSopenharmony_ci    } else {
6622498b56bSopenharmony_ci        return ERR_INVALID_ARGUMENT;
6632498b56bSopenharmony_ci    }
6642498b56bSopenharmony_ci    int ret = SetPrivateSwitchOn(privateOn);
6652498b56bSopenharmony_ci    PrintResult(ret, (string("Set hilog privacy format ") + arg));
6662498b56bSopenharmony_ci    return RET_SUCCESS;
6672498b56bSopenharmony_ci}
6682498b56bSopenharmony_ci
6692498b56bSopenharmony_cistatic int PidHandler(HilogArgs& context, const char *arg)
6702498b56bSopenharmony_ci{
6712498b56bSopenharmony_ci    context.blackPid = (arg[0] == BLACK_PREFIX);
6722498b56bSopenharmony_ci    std::vector<std::string> pids;
6732498b56bSopenharmony_ci    Split(context.blackPid ? arg + 1 : arg, pids);
6742498b56bSopenharmony_ci    if (pids.size() == 0) {
6752498b56bSopenharmony_ci        return ERR_INVALID_ARGUMENT;
6762498b56bSopenharmony_ci    }
6772498b56bSopenharmony_ci    int index = 0;
6782498b56bSopenharmony_ci    for (string p : pids) {
6792498b56bSopenharmony_ci        if (index >= MAX_PIDS) {
6802498b56bSopenharmony_ci            return ERR_TOO_MANY_PIDS;
6812498b56bSopenharmony_ci        }
6822498b56bSopenharmony_ci        if (IsNumericStr(p) == false) {
6832498b56bSopenharmony_ci            return ERR_NOT_NUMBER_STR;
6842498b56bSopenharmony_ci        }
6852498b56bSopenharmony_ci        int pid = 0;
6862498b56bSopenharmony_ci        (void)StrToInt(p, pid);
6872498b56bSopenharmony_ci        context.pids[index++] = static_cast<uint32_t>(pid);
6882498b56bSopenharmony_ci    }
6892498b56bSopenharmony_ci    context.pidCount = index;
6902498b56bSopenharmony_ci    return RET_SUCCESS;
6912498b56bSopenharmony_ci}
6922498b56bSopenharmony_ci
6932498b56bSopenharmony_cistatic int SetDomainFlowCtrl(bool on)
6942498b56bSopenharmony_ci{
6952498b56bSopenharmony_ci    DomainFlowCtrlRqst rqst = { 0 };
6962498b56bSopenharmony_ci    rqst.on = on;
6972498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::DOMAIN_FLOWCTRL_RQST, IoctlCmd::DOMAIN_FLOWCTRL_RSP);
6982498b56bSopenharmony_ci    int ret = ioctl.Request<DomainFlowCtrlRqst, DomainFlowCtrlRsp>(rqst, [&rqst](const DomainFlowCtrlRsp& rsp) {
6992498b56bSopenharmony_ci        return RET_SUCCESS;
7002498b56bSopenharmony_ci    });
7012498b56bSopenharmony_ci    return ret;
7022498b56bSopenharmony_ci}
7032498b56bSopenharmony_cistatic int FlowControlFeatureSetHandler(HilogArgs& context, const char *arg)
7042498b56bSopenharmony_ci{
7052498b56bSopenharmony_ci    string pid = "pid";
7062498b56bSopenharmony_ci    string domain = "domain";
7072498b56bSopenharmony_ci    string argStr = arg;
7082498b56bSopenharmony_ci    int ret;
7092498b56bSopenharmony_ci    if (argStr == (pid + FEATURE_ON)) {
7102498b56bSopenharmony_ci        ret = SetProcessSwitchOn(true);
7112498b56bSopenharmony_ci        cout << "Set flow control by process to enabled, result: " << ErrorCode2Str(ret) << endl;
7122498b56bSopenharmony_ci    } else if (argStr == (pid + FEATURE_OFF)) {
7132498b56bSopenharmony_ci        ret = SetProcessSwitchOn(false);
7142498b56bSopenharmony_ci        cout << "Set flow control by process to disabled, result: " << ErrorCode2Str(ret) << endl;
7152498b56bSopenharmony_ci    } else if (argStr == (domain + FEATURE_ON)) {
7162498b56bSopenharmony_ci        ret = SetDomainFlowCtrl(true);
7172498b56bSopenharmony_ci        cout << "Set flow control by domain to enabled, result: " << ErrorCode2Str(ret) << endl;
7182498b56bSopenharmony_ci    } else if (argStr == (domain + FEATURE_OFF)) {
7192498b56bSopenharmony_ci        ret = SetDomainFlowCtrl(false);
7202498b56bSopenharmony_ci        cout << "Set flow control by domain to disabled, result: " << ErrorCode2Str(ret) << endl;
7212498b56bSopenharmony_ci    } else {
7222498b56bSopenharmony_ci        return ERR_INVALID_ARGUMENT;
7232498b56bSopenharmony_ci    }
7242498b56bSopenharmony_ci    return ret;
7252498b56bSopenharmony_ci}
7262498b56bSopenharmony_ci
7272498b56bSopenharmony_cistatic int RemoveHandler(HilogArgs& context, const char *arg)
7282498b56bSopenharmony_ci{
7292498b56bSopenharmony_ci    LogRemoveRqst rqst = { 0 };
7302498b56bSopenharmony_ci    context.ToLogRemoveRqst(rqst);
7312498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::LOG_REMOVE_RQST, IoctlCmd::LOG_REMOVE_RSP);
7322498b56bSopenharmony_ci    int ret = ioctl.Request<LogRemoveRqst, LogRemoveRsp>(rqst, [&rqst](const LogRemoveRsp& rsp) {
7332498b56bSopenharmony_ci        cout << "Log type " << ComboLogType2Str(rsp.types) << " buffer clear successfully" << endl;
7342498b56bSopenharmony_ci        return RET_SUCCESS;
7352498b56bSopenharmony_ci    });
7362498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
7372498b56bSopenharmony_ci        cout << "Log buffer clear failed" << endl;
7382498b56bSopenharmony_ci    }
7392498b56bSopenharmony_ci    return ret;
7402498b56bSopenharmony_ci}
7412498b56bSopenharmony_ci
7422498b56bSopenharmony_cistatic int StatsInfoQueryHandler(HilogArgs& context, const char *arg)
7432498b56bSopenharmony_ci{
7442498b56bSopenharmony_ci    StatsQueryRqst rqst = { 0 };
7452498b56bSopenharmony_ci    context.ToStatsQueryRqst(rqst);
7462498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::STATS_QUERY_RQST, IoctlCmd::STATS_QUERY_RSP);
7472498b56bSopenharmony_ci    int ret = ioctl.RequestStatsQuery(rqst, [&rqst](const StatsQueryRsp& rsp) {
7482498b56bSopenharmony_ci        HilogShowLogStatsInfo(rsp);
7492498b56bSopenharmony_ci        return RET_SUCCESS;
7502498b56bSopenharmony_ci    });
7512498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
7522498b56bSopenharmony_ci        cout << "Statistic info query failed" << endl;
7532498b56bSopenharmony_ci    }
7542498b56bSopenharmony_ci    return ret;
7552498b56bSopenharmony_ci}
7562498b56bSopenharmony_ci
7572498b56bSopenharmony_cistatic int StatsInfoClearHandler(HilogArgs& context, const char *arg)
7582498b56bSopenharmony_ci{
7592498b56bSopenharmony_ci    StatsClearRqst rqst = { 0 };
7602498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::STATS_CLEAR_RQST, IoctlCmd::STATS_CLEAR_RSP);
7612498b56bSopenharmony_ci    int ret = ioctl.Request<StatsClearRqst, StatsClearRsp>(rqst, [&rqst](const StatsClearRsp& rsp) {
7622498b56bSopenharmony_ci        cout << "Statistic info clear successfully" << endl;
7632498b56bSopenharmony_ci        return RET_SUCCESS;
7642498b56bSopenharmony_ci    });
7652498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
7662498b56bSopenharmony_ci        cout << "Statistic info clear failed" << endl;
7672498b56bSopenharmony_ci    }
7682498b56bSopenharmony_ci    return ret;
7692498b56bSopenharmony_ci}
7702498b56bSopenharmony_ci
7712498b56bSopenharmony_cistatic int TypeHandler(HilogArgs& context, const char *arg)
7722498b56bSopenharmony_ci{
7732498b56bSopenharmony_ci    uint16_t types = Str2ComboLogType(arg);
7742498b56bSopenharmony_ci    if (types == 0) {
7752498b56bSopenharmony_ci        return ERR_LOG_TYPE_INVALID;
7762498b56bSopenharmony_ci    }
7772498b56bSopenharmony_ci    context.types = types;
7782498b56bSopenharmony_ci    return RET_SUCCESS;
7792498b56bSopenharmony_ci}
7802498b56bSopenharmony_ci
7812498b56bSopenharmony_cistatic int TagHandler(HilogArgs& context, const char *arg)
7822498b56bSopenharmony_ci{
7832498b56bSopenharmony_ci    context.blackTag = (arg[0] == BLACK_PREFIX);
7842498b56bSopenharmony_ci    std::vector<std::string> tags;
7852498b56bSopenharmony_ci    Split(context.blackTag ? arg + 1 : arg, tags);
7862498b56bSopenharmony_ci    int index = 0;
7872498b56bSopenharmony_ci    for (string t : tags) {
7882498b56bSopenharmony_ci        if (index >= MAX_TAGS) {
7892498b56bSopenharmony_ci            return ERR_TOO_MANY_TAGS;
7902498b56bSopenharmony_ci        }
7912498b56bSopenharmony_ci        if (t.length() >= MAX_TAG_LEN) {
7922498b56bSopenharmony_ci            return ERR_TAG_STR_TOO_LONG;
7932498b56bSopenharmony_ci        }
7942498b56bSopenharmony_ci        context.tags[index++] = t;
7952498b56bSopenharmony_ci    }
7962498b56bSopenharmony_ci    context.tagCount = index;
7972498b56bSopenharmony_ci    return RET_SUCCESS;
7982498b56bSopenharmony_ci}
7992498b56bSopenharmony_ci
8002498b56bSopenharmony_cistatic int TimeHandler(HilogArgs& context, FormatTime value)
8012498b56bSopenharmony_ci{
8022498b56bSopenharmony_ci    if (context.timeFormat != FormatTime::INVALID) {
8032498b56bSopenharmony_ci        return ERR_DUPLICATE_OPTION;
8042498b56bSopenharmony_ci    }
8052498b56bSopenharmony_ci    context.timeFormat = value;
8062498b56bSopenharmony_ci    return RET_SUCCESS;
8072498b56bSopenharmony_ci}
8082498b56bSopenharmony_ci
8092498b56bSopenharmony_cistatic int TimeAccuHandler(HilogArgs& context, FormatTimeAccu value)
8102498b56bSopenharmony_ci{
8112498b56bSopenharmony_ci    if (context.timeAccuFormat != FormatTimeAccu::INVALID) {
8122498b56bSopenharmony_ci        return ERR_DUPLICATE_OPTION;
8132498b56bSopenharmony_ci    }
8142498b56bSopenharmony_ci    context.timeAccuFormat = value;
8152498b56bSopenharmony_ci    return RET_SUCCESS;
8162498b56bSopenharmony_ci}
8172498b56bSopenharmony_ci
8182498b56bSopenharmony_cistatic int FormatHandler(HilogArgs& context, const char *arg)
8192498b56bSopenharmony_ci{
8202498b56bSopenharmony_ci    static std::unordered_map<std::string, std::function<int(HilogArgs&, int)>> handlers = {
8212498b56bSopenharmony_ci        {"color", [] (HilogArgs& context, int value) {
8222498b56bSopenharmony_ci            context.colorful = true;
8232498b56bSopenharmony_ci            return RET_SUCCESS;
8242498b56bSopenharmony_ci        }},
8252498b56bSopenharmony_ci        {"colour", [] (HilogArgs& context, int value) {
8262498b56bSopenharmony_ci            context.colorful = true;
8272498b56bSopenharmony_ci            return RET_SUCCESS;
8282498b56bSopenharmony_ci        }},
8292498b56bSopenharmony_ci        {"time", [] (HilogArgs& context, int value) {
8302498b56bSopenharmony_ci            return TimeHandler(context, FormatTime::TIME);
8312498b56bSopenharmony_ci        }},
8322498b56bSopenharmony_ci        {"epoch", [] (HilogArgs& context, int value) {
8332498b56bSopenharmony_ci            return TimeHandler(context, FormatTime::EPOCH);
8342498b56bSopenharmony_ci        }},
8352498b56bSopenharmony_ci        {"monotonic", [] (HilogArgs& context, int value) {
8362498b56bSopenharmony_ci            return TimeHandler(context, FormatTime::MONOTONIC);
8372498b56bSopenharmony_ci        }},
8382498b56bSopenharmony_ci        {"msec", [] (HilogArgs& context, int value) {
8392498b56bSopenharmony_ci            return TimeAccuHandler(context, FormatTimeAccu::MSEC);
8402498b56bSopenharmony_ci        }},
8412498b56bSopenharmony_ci        {"usec", [] (HilogArgs& context, int value) {
8422498b56bSopenharmony_ci            return TimeAccuHandler(context, FormatTimeAccu::USEC);
8432498b56bSopenharmony_ci        }},
8442498b56bSopenharmony_ci        {"nsec", [] (HilogArgs& context, int value) {
8452498b56bSopenharmony_ci            return TimeAccuHandler(context, FormatTimeAccu::NSEC);
8462498b56bSopenharmony_ci        }},
8472498b56bSopenharmony_ci        {"year", [] (HilogArgs& context, int value) {
8482498b56bSopenharmony_ci            context.year = true;
8492498b56bSopenharmony_ci            return RET_SUCCESS;
8502498b56bSopenharmony_ci        }},
8512498b56bSopenharmony_ci        {"zone", [] (HilogArgs& context, int value) {
8522498b56bSopenharmony_ci            context.zone = true;
8532498b56bSopenharmony_ci            tzset();
8542498b56bSopenharmony_ci            return RET_SUCCESS;
8552498b56bSopenharmony_ci        }},
8562498b56bSopenharmony_ci        {"wrap", [] (HilogArgs& context, int value) {
8572498b56bSopenharmony_ci            context.wrap = true;
8582498b56bSopenharmony_ci            return RET_SUCCESS;
8592498b56bSopenharmony_ci        }},
8602498b56bSopenharmony_ci    };
8612498b56bSopenharmony_ci
8622498b56bSopenharmony_ci    auto handler = handlers.find(arg);
8632498b56bSopenharmony_ci    if (handler == handlers.end() || handler->second == nullptr) {
8642498b56bSopenharmony_ci        return ERR_INVALID_ARGUMENT;
8652498b56bSopenharmony_ci    }
8662498b56bSopenharmony_ci    return handler->second(context, 0);
8672498b56bSopenharmony_ci}
8682498b56bSopenharmony_ci
8692498b56bSopenharmony_cistatic int PersistTaskStart(HilogArgs& context)
8702498b56bSopenharmony_ci{
8712498b56bSopenharmony_ci    PersistStartRqst rqst = { { 0 }, 0 };
8722498b56bSopenharmony_ci    context.ToPersistStartRqst(rqst);
8732498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::PERSIST_START_RQST, IoctlCmd::PERSIST_START_RSP);
8742498b56bSopenharmony_ci    int ret = ioctl.Request<PersistStartRqst, PersistStartRsp>(rqst, [&rqst](const PersistStartRsp& rsp) {
8752498b56bSopenharmony_ci        cout << "Persist task [jobid:" << rsp.jobId << "] start successfully" << endl;
8762498b56bSopenharmony_ci        return RET_SUCCESS;
8772498b56bSopenharmony_ci    });
8782498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
8792498b56bSopenharmony_ci        cout << "Persist task start failed" << endl;
8802498b56bSopenharmony_ci    }
8812498b56bSopenharmony_ci    return ret;
8822498b56bSopenharmony_ci}
8832498b56bSopenharmony_ci
8842498b56bSopenharmony_cistatic int PersistTaskStop(HilogArgs& context)
8852498b56bSopenharmony_ci{
8862498b56bSopenharmony_ci    PersistStopRqst rqst = { 0 };
8872498b56bSopenharmony_ci    context.ToPersistStopRqst(rqst);
8882498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::PERSIST_STOP_RQST, IoctlCmd::PERSIST_STOP_RSP);
8892498b56bSopenharmony_ci    int ret = ioctl.Request<PersistStopRqst, PersistStopRsp>(rqst,  [&rqst](const PersistStopRsp& rsp) {
8902498b56bSopenharmony_ci        for (int i = 0; i < rsp.jobNum; i++) {
8912498b56bSopenharmony_ci            cout << "Persist task [jobid:" << rsp.jobId[i] << "] stop successfully" << endl;
8922498b56bSopenharmony_ci        }
8932498b56bSopenharmony_ci        return RET_SUCCESS;
8942498b56bSopenharmony_ci    });
8952498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
8962498b56bSopenharmony_ci        cout << "Persist task stop failed" << endl;
8972498b56bSopenharmony_ci    }
8982498b56bSopenharmony_ci    return ret;
8992498b56bSopenharmony_ci}
9002498b56bSopenharmony_ci
9012498b56bSopenharmony_cistatic void PrintTaskInfo(const PersistTaskInfo& task)
9022498b56bSopenharmony_ci{
9032498b56bSopenharmony_ci    cout << task.jobId << " " << ComboLogType2Str(task.outputFilter.types) << " " << task.stream << " ";
9042498b56bSopenharmony_ci    cout << task.fileName << " " << Size2Str(task.fileSize) << " " << to_string(task.fileNum) << endl;
9052498b56bSopenharmony_ci}
9062498b56bSopenharmony_ci
9072498b56bSopenharmony_cistatic int PersistTaskQuery()
9082498b56bSopenharmony_ci{
9092498b56bSopenharmony_ci    PersistQueryRqst rqst = { 0 };
9102498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::PERSIST_QUERY_RQST, IoctlCmd::PERSIST_QUERY_RSP);
9112498b56bSopenharmony_ci    int ret = ioctl.Request<PersistQueryRqst, PersistQueryRsp>(rqst,  [&rqst](const PersistQueryRsp& rsp) {
9122498b56bSopenharmony_ci        for (int i = 0; i < rsp.jobNum; i++) {
9132498b56bSopenharmony_ci            PrintTaskInfo(rsp.taskInfo[i]);
9142498b56bSopenharmony_ci        }
9152498b56bSopenharmony_ci        return RET_SUCCESS;
9162498b56bSopenharmony_ci    });
9172498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
9182498b56bSopenharmony_ci        cout << "Persist task query failed" << endl;
9192498b56bSopenharmony_ci    }
9202498b56bSopenharmony_ci    return ret;
9212498b56bSopenharmony_ci}
9222498b56bSopenharmony_ci
9232498b56bSopenharmony_cistatic int PersistTaskRefresh()
9242498b56bSopenharmony_ci{
9252498b56bSopenharmony_ci    PersistRefreshRqst rqst = { 0 };
9262498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::PERSIST_REFRESH_RQST, IoctlCmd::PERSIST_REFRESH_RSP);
9272498b56bSopenharmony_ci    int ret = ioctl.Request<PersistRefreshRqst, PersistRefreshRsp>(rqst, [&rqst](const PersistRefreshRsp& rsp) {
9282498b56bSopenharmony_ci        for (int i = 0; i < rsp.jobNum; i++) {
9292498b56bSopenharmony_ci            PrintResult(RET_SUCCESS, (string("Persist task [jobid:") + to_string(rsp.jobId[i]) + "] refresh"));
9302498b56bSopenharmony_ci        }
9312498b56bSopenharmony_ci        return RET_SUCCESS;
9322498b56bSopenharmony_ci    });
9332498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
9342498b56bSopenharmony_ci        PrintResult(RET_FAIL, (string("Persist task refresh")));
9352498b56bSopenharmony_ci    }
9362498b56bSopenharmony_ci    return ret;
9372498b56bSopenharmony_ci}
9382498b56bSopenharmony_ci
9392498b56bSopenharmony_cistatic int ClearPersistLog()
9402498b56bSopenharmony_ci{
9412498b56bSopenharmony_ci    PersistClearRqst rqst = { 0 };
9422498b56bSopenharmony_ci    LogIoctl ioctl(IoctlCmd::PERSIST_CLEAR_RQST, IoctlCmd::PERSIST_CLEAR_RSP);
9432498b56bSopenharmony_ci    int ret = ioctl.Request<PersistClearRqst, PersistClearRsp>(rqst, [&rqst](const PersistClearRsp& rsp) {
9442498b56bSopenharmony_ci        PrintResult(RET_SUCCESS, (string("Persist log /data/log/hilog clear")));
9452498b56bSopenharmony_ci        return RET_SUCCESS;
9462498b56bSopenharmony_ci    });
9472498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
9482498b56bSopenharmony_ci        PrintResult(RET_FAIL, (string("Persist log /data/log/hilog clear")));
9492498b56bSopenharmony_ci    }
9502498b56bSopenharmony_ci    return ret;
9512498b56bSopenharmony_ci}
9522498b56bSopenharmony_ci
9532498b56bSopenharmony_cistatic int PersistTaskHandler(HilogArgs& context, const char *arg)
9542498b56bSopenharmony_ci{
9552498b56bSopenharmony_ci    string strArg = arg;
9562498b56bSopenharmony_ci    if (strArg == "start") {
9572498b56bSopenharmony_ci        return PersistTaskStart(context);
9582498b56bSopenharmony_ci    } else if (strArg == "stop") {
9592498b56bSopenharmony_ci        return PersistTaskStop(context);
9602498b56bSopenharmony_ci    } else if (strArg == "query") {
9612498b56bSopenharmony_ci        return PersistTaskQuery();
9622498b56bSopenharmony_ci    } else if (strArg == "refresh") {
9632498b56bSopenharmony_ci        return PersistTaskRefresh();
9642498b56bSopenharmony_ci    } else if (strArg == "clear") {
9652498b56bSopenharmony_ci        return ClearPersistLog();
9662498b56bSopenharmony_ci    } else {
9672498b56bSopenharmony_ci        return ERR_INVALID_ARGUMENT;
9682498b56bSopenharmony_ci    }
9692498b56bSopenharmony_ci    return RET_SUCCESS;
9702498b56bSopenharmony_ci}
9712498b56bSopenharmony_ci
9722498b56bSopenharmony_cistatic int NoBlockHandler(HilogArgs& context, const char *arg)
9732498b56bSopenharmony_ci{
9742498b56bSopenharmony_ci    context.noBlock = true;
9752498b56bSopenharmony_ci    return QueryLogHandler(context, arg);
9762498b56bSopenharmony_ci}
9772498b56bSopenharmony_ci
9782498b56bSopenharmony_cistatic int TailHandler(HilogArgs& context, const char *arg)
9792498b56bSopenharmony_ci{
9802498b56bSopenharmony_ci    if (IsNumericStr(arg) == false) {
9812498b56bSopenharmony_ci        return ERR_NOT_NUMBER_STR;
9822498b56bSopenharmony_ci    }
9832498b56bSopenharmony_ci    int tailLines = 0;
9842498b56bSopenharmony_ci    (void)StrToInt(arg, tailLines);
9852498b56bSopenharmony_ci    context.tailLines = static_cast<uint16_t>(tailLines);
9862498b56bSopenharmony_ci    context.noBlock = true; // don't block implicitly
9872498b56bSopenharmony_ci    return QueryLogHandler(context, arg);
9882498b56bSopenharmony_ci}
9892498b56bSopenharmony_ci
9902498b56bSopenharmony_cistruct OptEntry {
9912498b56bSopenharmony_ci    const char opt;
9922498b56bSopenharmony_ci    const char *longOpt;
9932498b56bSopenharmony_ci    const ControlCmd cmd;
9942498b56bSopenharmony_ci    const OptHandler handler;
9952498b56bSopenharmony_ci    const bool needArg;
9962498b56bSopenharmony_ci    // how many times can this option be used, for example:
9972498b56bSopenharmony_ci    //   hilog -v msec -v color ...
9982498b56bSopenharmony_ci    uint32_t count;
9992498b56bSopenharmony_ci};
10002498b56bSopenharmony_cistatic OptEntry optEntries[] = {
10012498b56bSopenharmony_ci    {'a', "head", ControlCmd::CMD_QUERY, HeadHandler, true, 1},
10022498b56bSopenharmony_ci    {'b', "baselevel", ControlCmd::CMD_LOGLEVEL_SET, BaseLogLevelHandler, true, 1},
10032498b56bSopenharmony_ci    {'D', "domain", ControlCmd::NOT_CMD, DomainHandler, true, 1},
10042498b56bSopenharmony_ci    {'e', "regex", ControlCmd::NOT_CMD, RegexHandler, true, 1},
10052498b56bSopenharmony_ci    {'f', "filename", ControlCmd::NOT_CMD, FileNameHandler, true, 1},
10062498b56bSopenharmony_ci    {'g', nullptr, ControlCmd::CMD_BUFFER_SIZE_QUERY, BufferSizeGetHandler, false, 1},
10072498b56bSopenharmony_ci    {'G', "buffer-size", ControlCmd::CMD_BUFFER_SIZE_SET, BufferSizeSetHandler, true, 1},
10082498b56bSopenharmony_ci    {'h', "help", ControlCmd::CMD_HELP, HelpHandler, false, 1},
10092498b56bSopenharmony_ci    {'j', "jobid", ControlCmd::NOT_CMD, JobIdHandler, true, 1},
10102498b56bSopenharmony_ci    {'k', "kmsg", ControlCmd::CMD_KMSG_FEATURE_SET, KmsgFeatureSetHandler, true, 1},
10112498b56bSopenharmony_ci    {'l', "length", ControlCmd::NOT_CMD, FileLengthHandler, true, 1},
10122498b56bSopenharmony_ci    {'L', "level", ControlCmd::NOT_CMD, LevelHandler, true, 1},
10132498b56bSopenharmony_ci    {'m', "stream", ControlCmd::NOT_CMD, FileCompressHandler, true, 1},
10142498b56bSopenharmony_ci    {'n', "number", ControlCmd::NOT_CMD, FileNumberHandler, true, 1},
10152498b56bSopenharmony_ci    {'p', "private", ControlCmd::CMD_PRIVATE_FEATURE_SET, PrivateFeatureSetHandler, true, 1},
10162498b56bSopenharmony_ci    {'P', "pid", ControlCmd::NOT_CMD, PidHandler, true, 1},
10172498b56bSopenharmony_ci    {'Q', "flowctrl", ControlCmd::CMD_FLOWCONTROL_FEATURE_SET, FlowControlFeatureSetHandler, true, 1},
10182498b56bSopenharmony_ci    {'r', nullptr, ControlCmd::CMD_REMOVE, RemoveHandler, false, 1},
10192498b56bSopenharmony_ci    {'s', "statistics", ControlCmd::CMD_STATS_INFO_QUERY, StatsInfoQueryHandler, false, 1},
10202498b56bSopenharmony_ci    {'S', nullptr, ControlCmd::CMD_STATS_INFO_CLEAR, StatsInfoClearHandler, false, 1},
10212498b56bSopenharmony_ci    {'t', "type", ControlCmd::NOT_CMD, TypeHandler, true, 1},
10222498b56bSopenharmony_ci    {'T', "tag", ControlCmd::NOT_CMD, TagHandler, true, 1},
10232498b56bSopenharmony_ci    {'v', "format", ControlCmd::NOT_CMD, FormatHandler, true, 5},
10242498b56bSopenharmony_ci    {'w', "write", ControlCmd::CMD_PERSIST_TASK, PersistTaskHandler, true, 1},
10252498b56bSopenharmony_ci    {'x', "exit", ControlCmd::CMD_QUERY, NoBlockHandler, false, 1},
10262498b56bSopenharmony_ci    {'z', "tail", ControlCmd::CMD_QUERY, TailHandler, true, 1},
10272498b56bSopenharmony_ci    {0, nullptr, ControlCmd::NOT_CMD, nullptr, false, 1}, // End default entry
10282498b56bSopenharmony_ci}; // "hxz:grsSa:v:e:t:L:G:f:l:n:j:w:p:k:D:T:b:Q:m:P:"
10292498b56bSopenharmony_cistatic constexpr int OPT_ENTRY_CNT = sizeof(optEntries) / sizeof(OptEntry);
10302498b56bSopenharmony_ci
10312498b56bSopenharmony_cistatic void GetOpts(string& opts, struct option(&longOptions)[OPT_ENTRY_CNT])
10322498b56bSopenharmony_ci{
10332498b56bSopenharmony_ci    int longOptcount = 0;
10342498b56bSopenharmony_ci    opts = "";
10352498b56bSopenharmony_ci    int i;
10362498b56bSopenharmony_ci    for (i = 0; i < OPT_ENTRY_CNT; i++) {
10372498b56bSopenharmony_ci        if (optEntries[i].opt == 0) {
10382498b56bSopenharmony_ci            break;
10392498b56bSopenharmony_ci        }
10402498b56bSopenharmony_ci        // opts
10412498b56bSopenharmony_ci        opts += optEntries[i].opt;
10422498b56bSopenharmony_ci        if (optEntries[i].needArg) {
10432498b56bSopenharmony_ci            opts += ':';
10442498b56bSopenharmony_ci        }
10452498b56bSopenharmony_ci        // long option
10462498b56bSopenharmony_ci        if (optEntries[i].longOpt == nullptr) {
10472498b56bSopenharmony_ci            continue;
10482498b56bSopenharmony_ci        }
10492498b56bSopenharmony_ci        longOptions[longOptcount].name = optEntries[i].longOpt;
10502498b56bSopenharmony_ci        longOptions[longOptcount].has_arg = optEntries[i].needArg ? required_argument : no_argument;
10512498b56bSopenharmony_ci        longOptions[longOptcount].flag = nullptr;
10522498b56bSopenharmony_ci        longOptions[longOptcount].val = optEntries[i].opt;
10532498b56bSopenharmony_ci        longOptcount++;
10542498b56bSopenharmony_ci    }
10552498b56bSopenharmony_ci    longOptions[longOptcount].name = nullptr;
10562498b56bSopenharmony_ci    longOptions[longOptcount].has_arg = 0;
10572498b56bSopenharmony_ci    longOptions[longOptcount].flag = nullptr;
10582498b56bSopenharmony_ci    longOptions[longOptcount].val = 0;
10592498b56bSopenharmony_ci    return;
10602498b56bSopenharmony_ci}
10612498b56bSopenharmony_ci
10622498b56bSopenharmony_cistatic OptEntry* GetOptEntry(int choice)
10632498b56bSopenharmony_ci{
10642498b56bSopenharmony_ci    OptEntry *entry = &(optEntries[OPT_ENTRY_CNT - 1]);
10652498b56bSopenharmony_ci    int i = 0;
10662498b56bSopenharmony_ci    for (i = 0; i < OPT_ENTRY_CNT; i++) {
10672498b56bSopenharmony_ci        if (optEntries[i].opt == static_cast<char>(choice)) {
10682498b56bSopenharmony_ci            entry = &(optEntries[i]);
10692498b56bSopenharmony_ci            break;
10702498b56bSopenharmony_ci        }
10712498b56bSopenharmony_ci    }
10722498b56bSopenharmony_ci    return entry;
10732498b56bSopenharmony_ci}
10742498b56bSopenharmony_ci
10752498b56bSopenharmony_ciint HilogEntry(int argc, char* argv[])
10762498b56bSopenharmony_ci{
10772498b56bSopenharmony_ci    struct option longOptions[OPT_ENTRY_CNT];
10782498b56bSopenharmony_ci    string opts;
10792498b56bSopenharmony_ci    GetOpts(opts, longOptions);
10802498b56bSopenharmony_ci    HilogArgs context;
10812498b56bSopenharmony_ci    int optIndex = 0;
10822498b56bSopenharmony_ci
10832498b56bSopenharmony_ci    // 0. help has special case
10842498b56bSopenharmony_ci    static const int argCountHelp = 3;
10852498b56bSopenharmony_ci    if (argc == argCountHelp) {
10862498b56bSopenharmony_ci        string arg = argv[1];
10872498b56bSopenharmony_ci        if (arg == "--help" || arg == "-h") {
10882498b56bSopenharmony_ci            Helper(argv[argCountHelp - 1]);
10892498b56bSopenharmony_ci            return RET_SUCCESS;
10902498b56bSopenharmony_ci        }
10912498b56bSopenharmony_ci    }
10922498b56bSopenharmony_ci    // 1. Scan all options and process NOT_CMD options' arguments
10932498b56bSopenharmony_ci    int cmdCount = 0;
10942498b56bSopenharmony_ci    OptEntry queryEntry =  {' ', "", ControlCmd::CMD_QUERY, QueryLogHandler, false, 0};
10952498b56bSopenharmony_ci    OptEntry *cmdEntry = &queryEntry; // No cmd means CMD_QUERY cmd
10962498b56bSopenharmony_ci    string cmdArgs = "";
10972498b56bSopenharmony_ci    while (1) {
10982498b56bSopenharmony_ci        int choice = getopt_long(argc, argv, opts.c_str(), longOptions, &optIndex);
10992498b56bSopenharmony_ci        if (choice == -1) {
11002498b56bSopenharmony_ci            break;
11012498b56bSopenharmony_ci        }
11022498b56bSopenharmony_ci        if (choice == '?') {
11032498b56bSopenharmony_ci            return RET_FAIL;
11042498b56bSopenharmony_ci        }
11052498b56bSopenharmony_ci        OptEntry *entry = GetOptEntry(choice);
11062498b56bSopenharmony_ci        if (optind < argc && argv[optind][0] != '-') { // all options need only 1 argument
11072498b56bSopenharmony_ci            PrintErr(ERR_TOO_MANY_ARGUMENTS);
11082498b56bSopenharmony_ci            return ERR_TOO_MANY_ARGUMENTS;
11092498b56bSopenharmony_ci        }
11102498b56bSopenharmony_ci        if (entry->count == 0) {
11112498b56bSopenharmony_ci            PrintErr(ERR_DUPLICATE_OPTION);
11122498b56bSopenharmony_ci            return ERR_DUPLICATE_OPTION;
11132498b56bSopenharmony_ci        }
11142498b56bSopenharmony_ci        entry->count--;
11152498b56bSopenharmony_ci        if (entry->cmd == ControlCmd::NOT_CMD) {
11162498b56bSopenharmony_ci            int ret = entry->handler(context, optarg);
11172498b56bSopenharmony_ci            if (ret != RET_SUCCESS) {
11182498b56bSopenharmony_ci                PrintErr(ret);
11192498b56bSopenharmony_ci                return ret;
11202498b56bSopenharmony_ci            } else {
11212498b56bSopenharmony_ci                continue;
11222498b56bSopenharmony_ci            }
11232498b56bSopenharmony_ci        }
11242498b56bSopenharmony_ci        cmdEntry = entry;
11252498b56bSopenharmony_ci        cmdCount++;
11262498b56bSopenharmony_ci        if (optarg != nullptr) {
11272498b56bSopenharmony_ci            cmdArgs = optarg;
11282498b56bSopenharmony_ci        }
11292498b56bSopenharmony_ci    }
11302498b56bSopenharmony_ci    if (cmdCount > 1) {
11312498b56bSopenharmony_ci        cerr << ErrorCode2Str(ERR_COMMAND_INVALID) << endl;
11322498b56bSopenharmony_ci        return ERR_COMMAND_INVALID;
11332498b56bSopenharmony_ci    }
11342498b56bSopenharmony_ci    // 2. Process CMD_XXX
11352498b56bSopenharmony_ci    int ret = cmdEntry->handler(context, cmdArgs.c_str());
11362498b56bSopenharmony_ci    if (ret != RET_SUCCESS) {
11372498b56bSopenharmony_ci        PrintErr(ret);
11382498b56bSopenharmony_ci        return ret;
11392498b56bSopenharmony_ci    }
11402498b56bSopenharmony_ci    return RET_SUCCESS;
11412498b56bSopenharmony_ci}
11422498b56bSopenharmony_ci} // namespace HiviewDFX
11432498b56bSopenharmony_ci} // namespace OHOS
11442498b56bSopenharmony_ci
11452498b56bSopenharmony_ciint main(int argc, char* argv[])
11462498b56bSopenharmony_ci{
11472498b56bSopenharmony_ci    (void)OHOS::HiviewDFX::HilogEntry(argc, argv);
11482498b56bSopenharmony_ci    return 0;
11492498b56bSopenharmony_ci}
1150