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