1/*
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "hilog_command.h"
17
18#include <securec.h>
19#include <stdio.h>
20#include <stdbool.h>
21#include <string.h>
22#include <stdlib.h>
23#include <fcntl.h>
24#include <unistd.h>
25#include <getopt.h>
26
27#define OPTION_HELP 'h'
28#define OPTION_LEVEL 'L'
29#define OPTION_DOMAIN 'D'
30#define OPTION_SILENCE 'S'
31
32#define PARA_AUTO "auto"
33#define PARA_AUTO_LEN 4
34
35#define APPHILOGCAT_OFF 0
36
37#define HIVIEW_FEATURE_ON 1
38#define HIVIEW_FEATURE_OFF 0
39
40#define HILOG_MODULE_MAX "FFFFF"
41
42char g_logLevelInfo[HILOG_LEVEL_MAX] = {
43    'N', // "NONE"
44    'N', // "NONE"
45    'N', // "NONE"
46    'D', // "DEBUG"
47    'I', // "INFO"
48    'W', // "WARN"
49    'E', // "ERROR"
50    'F'  // "FATAL"
51};
52
53HiviewConfig g_hiviewConfig = {
54    .outputOption = OUTPUT_OPTION_FLOW,
55    .level = LOG_DEBUG,
56    .logSwitch = HIVIEW_FEATURE_ON,
57    .dumpSwitch = HIVIEW_FEATURE_OFF,
58    .silenceMod = SILENT_MODE_OFF,
59    .eventSwitch = HIVIEW_FEATURE_OFF,
60    .logOutputModule = HILOG_MODULE_MAX,
61};
62
63int HilogHelpProc(const char* tag)
64{
65    printf("Usage: %s [-h | --help] [-L <level> | --level=<level>] [--silence]\n", tag);
66    printf("          [-D <domain> | --domain=<domain>]\n");
67    printf("\n");
68    printf("Options:\n");
69    printf("-h, --help                         Help\n");
70    printf("-L <level>, --level=<level>        Outputs logs at a specific level\n");
71    printf("                                   Values of level :\n");
72    printf("                                        D, stands for Debug\n");
73    printf("                                        I, stands for Info\n");
74    printf("                                        W, stands for Warning\n");
75    printf("                                        E, stands for Error\n");
76    printf("                                        F, stands for Fatal\n");
77    printf("                                        auto, set log level with predefined macro\n");
78    printf("-D <domain>, --domain=<domain>     Outputs logs at a specific domain\n");
79    printf("--silence                          Silent mode, not output logs to the serial port\n");
80    return -1;
81}
82
83bool SetLogLevel(unsigned char level)
84{
85    if (level >= LOG_DEBUG && level < HILOG_LEVEL_MAX) {
86        g_hiviewConfig.level = level;
87        printf("Set log level : %d \n", level);
88        return true;
89    }
90    return false;
91}
92
93int SetOutputDomain(const char *mod)
94{
95    if ((mod == NULL) || (strlen(mod) == 1)) {
96        printf("Invalid command.\n");
97        return -1;
98    }
99    int len = strlen(mod);
100    int modSize = sizeof(g_hiviewConfig.logOutputModule);
101
102    (void)memset_s(g_hiviewConfig.logOutputModule, modSize, '0', modSize);
103
104    int destStart = ((DOMAIN_ID_LENGTH - len) > 0) ? (DOMAIN_ID_LENGTH - len) : 0;
105    int sourceStart = ((len - DOMAIN_ID_LENGTH) > 0) ? (len - DOMAIN_ID_LENGTH) : 0;
106    int copyLen = (len < DOMAIN_ID_LENGTH) ? len : DOMAIN_ID_LENGTH;
107
108    if (strncpy_s(g_hiviewConfig.logOutputModule + destStart, modSize - destStart, mod + sourceStart, copyLen) != 0) {
109        printf("Copy log domain fail : %s \n", mod);
110        return -1;
111    }
112
113    printf("Set log domain : %s \n", g_hiviewConfig.logOutputModule);
114    return 0;
115}
116
117int SetOutputLevel(char cmd)
118{
119    unsigned char level = LOG_DEBUG;
120    if (cmd == g_logLevelInfo[LOG_DEBUG]) {
121        level = LOG_DEBUG;
122    } else if (cmd == g_logLevelInfo[LOG_INFO]) {
123        level = LOG_INFO;
124    } else if (cmd == g_logLevelInfo[LOG_WARN]) {
125        level = LOG_WARN;
126    } else if (cmd == g_logLevelInfo[LOG_ERROR]) {
127        level = LOG_ERROR;
128    } else if (cmd == g_logLevelInfo[LOG_FATAL]) {
129        level = LOG_FATAL;
130    } else {
131        printf("Invalid level : %c\n", cmd);
132        return -1;
133    }
134
135    if (SetLogLevel(level)) {
136        printf("Set the log output level success.\n");
137        return 0;
138    }
139    printf("Set the log output level failure level=%d.\n", level);
140    return -1;
141}
142
143int ProcAutoSet(void)
144{
145#ifdef OHOS_RELEASE
146#if APPHILOGCAT_STATUS_RELEASE == APPHILOGCAT_OFF
147    return -1;
148#else
149    SetLogLevel(CONFIG_LOG_LEVEL_RELEASE);
150    printf("Default log level: %d \n", CONFIG_LOG_LEVEL_RELEASE);
151#endif
152#else  // OHOS_DEBUG
153#if APPHILOGCAT_STATUS_DEBUG == APPHILOGCAT_OFF
154    return -1;
155#else
156    SetLogLevel(CONFIG_LOG_LEVEL_DEBUG);
157    printf("Default log level: %d \n", CONFIG_LOG_LEVEL_DEBUG);
158#endif
159#endif
160    return 0;
161}
162
163int HilogLevelProc(const char* arg)
164{
165    if (arg == NULL) {
166        printf("Invalid command.\n");
167        return -1;
168    }
169    if (strncmp(arg, PARA_AUTO, PARA_AUTO_LEN) == 0) {
170        return ProcAutoSet();
171    }
172    char level = arg[0];
173    return SetOutputLevel(level);
174}
175
176int HilogDomainProc(const char* arg)
177{
178    return SetOutputDomain(arg);
179}
180
181int HilogSilenceProc()
182{
183    g_hiviewConfig.silenceMod = SILENT_MODE_ON;
184    return 0;
185}
186
187int HilogCmdProc(const char *tag, int argc, char *argv[])
188{
189    int ret = -1;
190    int optionIndex = 0;
191    int opt = 0;
192
193    struct option longOptions[] = {
194        {"help", no_argument, NULL, OPTION_HELP},
195        {"level", required_argument, NULL, OPTION_LEVEL},
196        {"domain", required_argument, NULL, OPTION_DOMAIN},
197        {"silence", no_argument, NULL, OPTION_SILENCE},
198        {0, 0, 0, 0}
199    };
200    const char *shortOptions = "hL:D:";
201
202    while ((opt = getopt_long(argc, argv, shortOptions, longOptions, &optionIndex)) != -1) {
203        switch (opt) {
204            case OPTION_HELP:
205                ret = HilogHelpProc(tag);
206                break;
207            case OPTION_LEVEL:
208                ret = HilogLevelProc(optarg);
209                break;
210            case OPTION_DOMAIN:
211                ret = HilogDomainProc(optarg);
212                break;
213            case OPTION_SILENCE:
214                ret = HilogSilenceProc();
215                break;
216            default:
217                ret = -1;
218                printf("Invalid command.\n");
219                break;
220        }
221        if (ret == -1) {
222            return -1;
223        }
224    }
225    return ret;
226}
227
228bool FilterLevelLog(unsigned char setLevel, unsigned char logLevel)
229{
230    int logMinLevel;
231
232    for (logMinLevel = LOG_DEBUG; logMinLevel < HILOG_LEVEL_MAX; logMinLevel++) {
233        if (logLevel == g_logLevelInfo[logMinLevel]) {
234            break;
235        }
236    }
237    // Loglevel >= set level, may print log
238    if (logMinLevel >= setLevel) {
239        return true;
240    }
241    return false;
242}
243
244bool FilterModuleLog(const char *setModule, const char *logModule)
245{
246    if (strncmp(setModule, HILOG_MODULE_MAX, DOMAIN_ID_LENGTH) == 0) {
247        return true;
248    }
249    return strncmp(logModule, g_hiviewConfig.logOutputModule, DOMAIN_ID_LENGTH) == 0;
250}