1/*
2 * Copyright (c) 2021-2022 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#include <grp.h>
16#include <pwd.h>
17#include <sys/ioctl.h>
18#include <stdio.h>
19#include <string.h>
20#include <sys/wait.h>
21#include <termios.h>
22#include <unistd.h>
23#include <signal.h>
24#undef _GNU_SOURCE
25#define _GNU_SOURCE
26#include <sched.h>
27
28#include "begetctl.h"
29#include "param_manager.h"
30#include "param_security.h"
31#include "init_param.h"
32#include "shell_utils.h"
33#include "param_init.h"
34#include "beget_ext.h"
35#ifdef PARAM_SUPPORT_SELINUX
36#include <policycoreutils.h>
37#include <selinux/selinux.h>
38#include "selinux_parameter.h"
39#endif // PARAM_SUPPORT_SELINUX
40
41typedef struct {
42    uid_t uid;
43    gid_t gid;
44    int cloneFlg;
45    char *parameter;
46} ParamShellExecArgs;
47
48#define STACK_SIZE (1024 * 1024 * 8)
49#define MASK_LENGTH_MAX 4
50pid_t g_shellPid = 0;
51static struct termios g_terminalState;
52char g_isSetTerminal = 0;
53
54void demoExit(void)
55{
56    if (g_shellPid != 0) {
57#ifndef STARTUP_INIT_TEST
58        kill(g_shellPid, SIGKILL);
59#endif
60    }
61}
62
63#define CMD_PATH "/system/bin/paramshell"
64#define SHELL_NAME "paramshell"
65#ifndef TIOCSCTTY
66#define TIOCSCTTY 0x540E
67#endif
68static char *GetLocalBuffer(uint32_t *buffSize)
69{
70    static char buffer[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX] = {0};
71    BEGET_CHECK(buffSize == NULL, *buffSize = sizeof(buffer));
72    return buffer;
73}
74
75static char *GetRealParameter(BShellHandle shell, const char *name, char *buffer, uint32_t buffSize)
76{
77    BSH_CHECK(buffer != NULL && name != NULL, return NULL, "Invalid parameter");
78    const BShellParam *param = BShellEnvGetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER);
79    const char *current = (param == NULL) ? "" : param->value.string;
80    int32_t realLen = 0;
81    int ret = 0;
82    if (name[0] == '.') { // relatively
83        if (strcmp(name, "..") == 0) {
84            char *tmp = strrchr(current, '.');
85            if (tmp != NULL) {
86                realLen = tmp - current;
87                ret = memcpy_s(buffer, buffSize, current, realLen);
88            } else {
89                ret = memcpy_s(buffer, buffSize, "#", 1);
90                realLen = 1;
91            }
92            BSH_CHECK(ret == 0, return NULL, "Failed to memcpy");
93        } else if (strcmp(name, ".") == 0) {
94            realLen = sprintf_s(buffer, buffSize, "%s", current);
95        } else {
96            realLen = sprintf_s(buffer, buffSize, "%s%s", current, name);
97        }
98    } else if (strlen(name) == 0) {
99        realLen = sprintf_s(buffer, buffSize, "%s", current);
100    } else {
101        realLen = sprintf_s(buffer, buffSize, "%s", name);
102    }
103    BSH_CHECK(realLen >= 0, return NULL, "Failed to format buffer");
104    buffer[realLen] = '\0';
105    BSH_LOGV("GetRealParameter current %s input %s real %s", current, name, buffer);
106    return buffer;
107}
108
109int SetParamShellPrompt(BShellHandle shell, const char *param)
110{
111    uint32_t buffSize = 0;
112    char *buffer = GetLocalBuffer(&buffSize);
113    char *realParameter = GetRealParameter(shell, param, buffer, buffSize);
114    BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
115    if (strlen(realParameter) == 0) {
116        BShellEnvOutputPrompt(shell, PARAM_SHELL_DEFAULT_PROMPT);
117        return -1;
118    }
119    // check parameter
120    int ret = SystemCheckParamExist(realParameter);
121    if (ret == PARAM_CODE_NOT_FOUND) {
122        BShellEnvOutput(shell, "Error: parameter \'%s\' not found\r\n", realParameter);
123        return -1;
124    } else if (ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
125        BShellEnvOutput(shell, "Error: Forbid to enter parameters \'%s\'\r\n", realParameter);
126        return -1;
127    }
128    if (strcmp(realParameter, "#") == 0) {
129        ret = BShellEnvSetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER,
130            "", PARAM_STRING, (void *)"");
131        BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to set param value");
132        BShellEnvOutputPrompt(shell, PARAM_SHELL_DEFAULT_PROMPT);
133        return 0;
134    }
135    ret = BShellEnvSetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER,
136        "", PARAM_STRING, (void *)realParameter);
137    BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to set param value");
138    if (strcat_s(realParameter, buffSize, "#") != 0) {
139        BSH_CHECK(ret != 0, return BSH_SYSTEM_ERR, "Failed to cat prompt %s", realParameter);
140    }
141    BShellEnvOutputPrompt(shell, realParameter);
142    return 0;
143}
144
145static char *GetPermissionString(uint32_t mode, int shift, char *str, int size)
146{
147    BEGET_CHECK(!(size < MASK_LENGTH_MAX), return str);
148    str[0] = '-';
149    str[1] = '-';
150    str[2] = '-'; // 2 watcher
151    str[3] = '\0'; // 3 end
152    if (mode & (DAC_READ >> shift)) {
153        str[0] = 'r';
154    }
155    if (mode & (DAC_WRITE >> shift)) {
156        str[1] = 'w';
157    }
158    if (mode & (DAC_WATCH >> shift)) {
159        str[2] = 'w'; // 2 watcher
160    }
161    return str;
162}
163
164static void ShowParam(BShellHandle shell, const char *name, const char *value)
165{
166    ParamAuditData auditData = {};
167    int ret = GetParamSecurityAuditData(name, 0, &auditData);
168    BSH_CHECK(ret == 0, return, "Failed to get param security for %s", name);
169    BShellEnvOutput(shell, "Parameter information:\r\n");
170#ifdef PARAM_SUPPORT_SELINUX
171    BShellEnvOutput(shell, "selinux  : %s \r\n", auditData.label);
172#endif
173    char permissionStr[3][MASK_LENGTH_MAX] = {}; // 3 permission
174    struct passwd *user = getpwuid(auditData.dacData.uid);
175    struct group *group = getgrgid(auditData.dacData.gid);
176    if (user != NULL && group != NULL) {
177        BShellEnvOutput(shell, "    dac  : %s(%s) %s(%s) (%s) \r\n",
178            user->pw_name,
179            GetPermissionString(auditData.dacData.mode, 0, permissionStr[0], MASK_LENGTH_MAX),
180            group->gr_name,
181            GetPermissionString(auditData.dacData.mode, DAC_GROUP_START, permissionStr[1], MASK_LENGTH_MAX),
182             // 2 other
183            GetPermissionString(auditData.dacData.mode, DAC_OTHER_START, permissionStr[2], MASK_LENGTH_MAX));
184    }
185    if (strcmp("#", name) != 0) {
186        BShellEnvOutput(shell, "    name : %s\r\n", name);
187    }
188    if (value != NULL) {
189        BShellEnvOutput(shell, "    value: %s\r\n", value);
190    }
191}
192
193static void ShowParamForCmdLs(ParamHandle handle, void *cookie)
194{
195    uint32_t buffSize = 0;
196    char *buffer = GetLocalBuffer(&buffSize);
197    if (buffSize < (PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX)) {
198        return;
199    }
200    char *value = buffer + PARAM_NAME_LEN_MAX;
201    (void)SystemGetParameterName(handle, buffer, PARAM_NAME_LEN_MAX);
202    uint32_t valueLen = buffSize - PARAM_NAME_LEN_MAX;
203    (void)SystemGetParameterValue(handle, value, &valueLen);
204    ShowParam((BShellHandle)cookie, buffer, value);
205}
206
207static int32_t BShellParamCmdLs(BShellHandle shell, int32_t argc, char *argv[])
208{
209    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
210    int all = 0;
211    char *input = NULL;
212    for (int32_t i = 1; i < argc; i++) {
213        if (strcmp(argv[i], "-r") == 0) {
214            all = 1;
215        } else if (input == NULL) {
216            input = argv[i];
217        }
218    }
219    uint32_t buffSize = 0;
220    char *buffer = GetLocalBuffer(&buffSize);
221    char *realParameter = GetRealParameter(shell, (input == NULL) ? "" : input, buffer, buffSize);
222    BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
223    char *prefix = strdup((strlen(realParameter) == 0) ? "#" : realParameter);
224    BSH_CHECK(prefix != NULL, return BSH_SYSTEM_ERR, "failed dup perfix");
225    BSH_LOGV("BShellParamCmdLs prefix %s", prefix);
226    int ret = 0;
227    if (all != 0) {
228        ret = SystemTraversalParameter(prefix, ShowParamForCmdLs, (void *)shell);
229        if (ret != 0) {
230            BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n");
231        }
232    } else {
233        ret = SystemCheckParamExist(prefix);
234        if (ret == 0) {
235            ParamHandle handle;
236            ret = SystemFindParameter(prefix, &handle);
237            if (ret != 0) {
238                BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n");
239            } else {
240                ShowParamForCmdLs(handle, (void *)shell);
241            }
242        } else if (ret == PARAM_CODE_NODE_EXIST) {
243            ShowParam(shell, prefix, NULL);
244        } else if (ret != PARAM_CODE_NOT_FOUND) {
245            BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n");
246        } else {
247            BShellEnvOutput(shell, "Parameter %s not found\r\n", prefix);
248        }
249    }
250    free(prefix);
251    return 0;
252}
253
254static int32_t BShellParamCmdCat(BShellHandle shell, int32_t argc, char *argv[])
255{
256    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
257    BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env");
258    uint32_t buffSize = 0;
259    char *buffer = GetLocalBuffer(&buffSize);
260    char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize);
261    BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
262    int ret = SystemGetParameter(realParameter, buffer, &buffSize);
263    BSH_CHECK(ret != 0, BShellEnvOutput(shell, "    %s\r\n", buffer));
264    return 0;
265}
266
267static int32_t BShellParamCmdCd(BShellHandle shell, int32_t argc, char *argv[])
268{
269    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
270    BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env");
271    SetParamShellPrompt(shell, argv[1]);
272    return 0;
273}
274
275static void ShowParamForCmdGet(ParamHandle handle, void *cookie)
276{
277    uint32_t buffSize = 0;
278    char *buffer = GetLocalBuffer(&buffSize);
279    BSH_CHECK(!(buffSize < (PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX)), return);
280    char *value = buffer + PARAM_NAME_LEN_MAX;
281    (void)SystemGetParameterName(handle, buffer, PARAM_NAME_LEN_MAX);
282    uint32_t valueLen = buffSize - PARAM_NAME_LEN_MAX;
283    (void)SystemGetParameterValue(handle, value, &valueLen);
284    BShellEnvOutput((BShellHandle)cookie, "    %s = %s\r\n", buffer, value);
285}
286
287static int32_t BShellParamCmdGet(BShellHandle shell, int32_t argc, char *argv[])
288{
289    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
290    BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env");
291    int ret = 0;
292    uint32_t buffSize = 0;
293    char *buffer = GetLocalBuffer(&buffSize);
294    char *realParameter = GetRealParameter(shell, (argc == 1) ? "" : argv[1], buffer, buffSize);
295    if ((argc == 1) || (realParameter == NULL) ||
296        (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) {
297        ret = SystemTraversalParameter(realParameter, ShowParamForCmdGet, (void *)shell);
298        if (ret != 0) {
299            BShellEnvOutput(shell, "Error: Forbid to get all parameters\r\n");
300        }
301        return 0;
302    }
303    char *key = strdup(realParameter);
304    BSH_CHECK(key != NULL, return BSH_SYSTEM_ERR, "failed to fup key");
305    ret = SystemGetParameter(key, buffer, &buffSize);
306    if (ret == 0) {
307        BShellEnvOutput(shell, "%s \n", buffer);
308    } else {
309        BShellEnvOutput(shell, "Get parameter \"%s\" fail! errNum is:%d!\n", key, ret);
310    }
311    free(key);
312    return 0;
313}
314
315static int32_t BShellParamCmdSet(BShellHandle shell, int32_t argc, char *argv[])
316{
317    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
318    if (argc < 3) { // 3 min param
319        char *helpArgs[] = {"param", NULL};
320        BShellCmdHelp(shell, 1, helpArgs);
321        return 0;
322    }
323    uint32_t buffSize = 0;
324    char *buffer = GetLocalBuffer(&buffSize);
325    char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize);
326    if ((realParameter == NULL) || (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) {
327        BShellEnvOutput(shell, "Set parameter %s %s fail\n", argv[1], argv[2]); // 2 value param
328        return 0;
329    }
330    int ret = SystemSetParameter(realParameter, argv[2]); // 2 value param
331    if (ret == 0) {
332        BShellEnvOutput(shell, "Set parameter %s %s success\n", realParameter, argv[2]); // 2 value param
333    } else {
334        BShellEnvOutput(shell, "Set parameter %s %s fail! errNum is:%d!\n", realParameter, argv[2], ret); // 2 param
335    }
336    return 0;
337}
338
339static int32_t BShellParamCmdSave(BShellHandle shell, int32_t argc, char *argv[])
340{
341    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
342    BSH_CHECK(argc == 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env");
343
344    int ret = SystemSaveParameters();
345    if (ret == 0) {
346        BShellEnvOutput(shell, "Save persist parameters success\n");
347    } else {
348        BShellEnvOutput(shell, "Save persist parameters fail! errNum is:%d!\n", ret);
349    }
350    return 0;
351}
352
353static int32_t BShellParamCmdWait(BShellHandle shell, int32_t argc, char *argv[])
354{
355    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
356    if (argc < 2) { // 2 min param
357        char *helpArgs[] = {"param", NULL};
358        BShellCmdHelp(shell, 1, helpArgs);
359        return 0;
360    }
361    int32_t timeout = 30; // 30s
362    char *value = "*";
363    if (argc > 2) { // 2 value param
364        value = argv[2]; // 2 value param
365    }
366    if (argc > 3) { // 3 timeout param
367        timeout = atoi(argv[3]); // 3 timeout param
368    }
369    uint32_t buffSize = 0;
370    char *buffer = GetLocalBuffer(&buffSize);
371    char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize);
372    if ((realParameter == NULL) || (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) {
373        BShellEnvOutput(shell, "Wait parameter %s fail\n", argv[1]);
374        return 0;
375    }
376
377    int ret = SystemWaitParameter(realParameter, value, timeout);
378    if (ret == 0) {
379        BShellEnvOutput(shell, "Wait parameter %s success\n", argv[1]);
380    } else {
381        BShellEnvOutput(shell, "Wait parameter %s fail! errNum is:%d!\n", argv[1], ret);
382    }
383    return 0;
384}
385
386static int32_t BShellParamCmdDump(BShellHandle shell, int32_t argc, char *argv[])
387{
388    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
389    if (argc >= 2) { // 2 min parameter
390        if (strcmp(argv[1], "verbose") == 0) {
391            SystemDumpParameters(1, -1, printf);
392            return 0;
393        }
394        int index = StringToInt(argv[1], 0);
395        SystemDumpParameters(1, index, printf);
396        return 0;
397    }
398    SystemDumpParameters(0, -1, printf);
399    return 0;
400}
401
402static int32_t BShellParamCmdPwd(BShellHandle shell, int32_t argc, char *argv[])
403{
404    uint32_t buffSize = 0;
405    char *buffer = GetLocalBuffer(&buffSize);
406    char *realParameter = GetRealParameter(shell, "", buffer, buffSize);
407    BShellEnvOutput(shell, "%s\r\n", realParameter);
408    return 0;
409}
410
411static void GetUserInfo(ParamShellExecArgs *execArg, int32_t argc, char *argv[])
412{
413    int32_t i = 0;
414    execArg->parameter = NULL;
415    while (i < argc) {
416        if (strcmp(argv[i], "-p") == 0 && ((i + 1) < argc)) {
417            execArg->parameter = argv[i + 1];
418            ++i;
419        } else if (strcmp(argv[i], "-u") == 0 && ((i + 1) < argc)) {
420            execArg->uid = DecodeUid(argv[i + 1]);
421            execArg->uid = (execArg->uid == -1) ? 0 : execArg->uid;
422            ++i;
423        } else if (strcmp(argv[i], "-g") == 0 && ((i + 1) < argc)) {
424            execArg->gid = DecodeGid(argv[i + 1]);
425            execArg->gid = (execArg->gid == -1) ? 0 : execArg->gid;
426            ++i;
427        } else if (strcmp(argv[i], "-c") == 0) {
428            execArg->cloneFlg = 1;
429        }
430        ++i;
431    }
432}
433
434static int ExecFunc(void *arg)
435{
436    ParamShellExecArgs *execArg = (ParamShellExecArgs *)arg;
437    int ret = 0;
438    setuid(execArg->uid);
439    setgid(execArg->gid);
440    BSH_LOGI("Exec shell %s \n", SHELL_NAME);
441    if (execArg->parameter != NULL) { // 2 min argc
442        char *args[] = {SHELL_NAME, execArg->parameter, NULL};
443        ret = execv(CMD_PATH, args);
444    } else {
445        char *args[] = {SHELL_NAME, NULL};
446        ret = execv(CMD_PATH, args);
447    }
448    if (ret != 0) {
449        printf("error on exec %d \n", errno);
450        exit(0);
451    }
452    return ret;
453}
454
455static pid_t ForkChild(int (*childFunc)(void *arg), void *args)
456{
457    pid_t pid = fork();
458    if (pid == 0) {
459        childFunc(args);
460        exit(0);
461    }
462    return pid;
463}
464
465static int32_t BShellParamCmdShell(BShellHandle shell, int32_t argc, char *argv[])
466{
467#ifndef STARTUP_INIT_TEST
468    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
469    int ret = 0;
470    if (tcgetattr(0, &g_terminalState)) {
471        return BSH_SYSTEM_ERR;
472    }
473    g_isSetTerminal = 1;
474    ParamShellExecArgs args = {0, 0, 0, NULL};
475    GetUserInfo(&args, argc, argv);
476    BSH_LOGV("BShellParamCmdShell %s %d %d argc %d", args.parameter, args.uid, args.gid, argc);
477    if (args.parameter != NULL) {
478        ret = SystemCheckParamExist(args.parameter);
479        if (ret != 0) {
480            BShellEnvOutput(shell, "Error: parameter \'%s\' not found\r\n", args.parameter);
481            return -1;
482        }
483    }
484    SetInitLogLevel(INIT_INFO);
485    pid_t pid = 0;
486    if (args.cloneFlg) {
487        char *childStack = (char *)calloc(1, STACK_SIZE);
488        BSH_CHECK(childStack != NULL, return -1, "calloc failed");
489        pid = clone(ExecFunc, childStack + STACK_SIZE, CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, (void *)&args);
490        free(childStack);
491    } else {
492        pid = ForkChild(ExecFunc, (void *)&args);
493    }
494    if (pid > 0) {
495        g_shellPid = pid;
496        int status = 0;
497        wait(&status);
498        tcsetattr(0, TCSAFLUSH, &g_terminalState);
499        g_isSetTerminal = 0;
500    }
501#endif
502    return 0;
503}
504
505static int32_t BShellParamCmdRegForShell(BShellHandle shell)
506{
507    const CmdInfo infos[] = {
508        {"ls", BShellParamCmdLs, "display system parameter", "ls [-r] [name]", NULL},
509        {"get", BShellParamCmdGet, "get system parameter", "get [name]", NULL},
510        {"set", BShellParamCmdSet, "set system parameter", "set name value", NULL},
511        {"wait", BShellParamCmdWait, "wait system parameter", "wait name [value] [timeout]", NULL},
512        {"dump", BShellParamCmdDump, "dump system parameter", "dump [verbose]", ""},
513        {"cd", BShellParamCmdCd, "change path of parameter", "cd name", NULL},
514        {"cat", BShellParamCmdCat, "display value of parameter", "cat name", NULL},
515        {"pwd", BShellParamCmdPwd, "display current parameter", "pwd", NULL},
516        {"save", BShellParamCmdSave, "save all persist parameters in workspace", "save", NULL},
517    };
518    for (size_t i = sizeof(infos) / sizeof(infos[0]); i > 0; i--) {
519        BShellEnvRegisterCmd(shell, &infos[i - 1]);
520    }
521    return 0;
522}
523
524static bool IsUserMode()
525{
526    bool isUser = true;
527    char value[2] = {0};
528    uint32_t length = sizeof(value);
529    int ret = SystemGetParameter("const.debuggable", value, &length);
530    if (ret != 0) {
531        BSH_LOGI("Failed to get param");
532        return isUser;
533    }
534    if (strcmp(value, "1") == 0) {
535        isUser = false;
536    }
537    return isUser;
538}
539
540static bool IsDebugCmd(const CmdInfo *cmdInfo)
541{
542    if (strcmp(cmdInfo->multikey, "param dump") == 0 || strcmp(cmdInfo->multikey, "param shell") == 0) {
543        return true;
544    }
545    return false;
546}
547
548static int32_t BShellParamCmdRegForIndepent(BShellHandle shell)
549{
550    const CmdInfo infos[] = {
551        {"param", BShellParamCmdLs, "display system parameter", "param ls [-r] [name]", "param ls"},
552        {"param", BShellParamCmdGet, "get system parameter", "param get [name]", "param get"},
553        {"param", BShellParamCmdSet, "set system parameter", "param set name value", "param set"},
554        {"param", BShellParamCmdWait, "wait system parameter", "param wait name [value] [timeout]", "param wait"},
555        {"param", BShellParamCmdDump, "dump system parameter", "param dump [verbose]", "param dump"},
556        {"param", BShellParamCmdShell, "shell system parameter",
557            "param shell [-p] [name] [-u] [username] [-g] [groupname]", "param shell"},
558        {"param", BShellParamCmdSave, "save all persist parameters in workspace", "param save", "param save"},
559    };
560    for (size_t i = sizeof(infos) / sizeof(infos[0]); i > 0; i--) {
561        if (IsUserMode() && IsDebugCmd(&infos[i - 1])) {
562            continue;
563        }
564        BShellEnvRegisterCmd(shell, &infos[i - 1]);
565    }
566    return 0;
567}
568
569static void UpdateInitLogLevel(void)
570{
571    char level[2] = {0}; // 2 max length
572    uint32_t length = sizeof(level);
573    int ret = SystemGetParameter(INIT_DEBUG_LEVEL, level, &length);
574    if (ret == 0) {
575        errno = 0;
576        InitLogLevel value = (InitLogLevel)strtoul(level, NULL, DECIMAL_BASE);
577        SetInitLogLevel((errno != 0) ? INIT_WARN : value);
578    }
579}
580
581int32_t BShellParamCmdRegister(BShellHandle shell, int execMode)
582{
583    UpdateInitLogLevel();
584    if (execMode) {
585        BShellParamCmdRegForShell(shell);
586    } else {
587        BShellParamCmdRegForIndepent(shell);
588    }
589    return 0;
590}
591