param_cmd.c 16.5 KB
Newer Older
H
handyohos 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
X
xionglei6 已提交
15 16 17 18
#include <grp.h>
#include <pwd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
H
handyohos 已提交
19 20
#include <stdio.h>
#include <string.h>
X
xionglei6 已提交
21 22 23
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
H
handyohos 已提交
24

X
xionglei6 已提交
25 26 27
#include "begetctl.h"
#include "init_utils.h"
#include "param_security.h"
H
handyohos 已提交
28
#include "param_utils.h"
X
xionglei6 已提交
29
#include "shell_utils.h"
H
handyohos 已提交
30
#include "sys_param.h"
31 32 33 34
#ifdef WITH_SELINUX
#include <policycoreutils.h>
#include <selinux/selinux.h>
#endif // WITH_SELINUX
H
handyohos 已提交
35

X
xionglei6 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
#define MASK_LENGTH_MAX 4
pid_t g_shellPid = 0;
static struct termios g_terminalState;
char g_isSetTerminal = 0;

void demoExit(void)
{
    BShellEnvDestory(GetShellHandle());
    if (g_shellPid != 0) {
        kill(g_shellPid, SIGKILL);
    }
    if (g_isSetTerminal != 0) {
        tcsetattr(0, TCSAFLUSH, &g_terminalState);
    }
}

#define CMD_PATH "/system/bin/paramshell"
#define SHELL_NAME "paramshell"
#ifndef TIOCSCTTY
#define TIOCSCTTY 0x540E
#endif
static char *GetLocalBuffer(uint32_t *buffSize)
{
    static char buffer[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX] = {0};
    if (buffSize != NULL) {
        *buffSize = sizeof(buffer);
    }
    return buffer;
}

static char *GetRealParameter(BShellHandle shell, const char *name, char *buffer, uint32_t buffSize)
{
    BSH_CHECK(buffer != NULL && name != NULL, return NULL, "Invalid parameter");
    const BShellParam *param = BShellEnvGetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER);
    const char *current = (param == NULL) ? "" : param->value.string;
    int32_t realLen = 0;
    int ret = 0;
    if (name[0] == '.') { // relatively
        if (strcmp(name, "..") == 0) {
            char *tmp = strrchr(current, '.');
            if (tmp != NULL) {
                realLen = tmp - current;
                ret = memcpy_s(buffer, buffSize, current, realLen);
            } else {
                ret = memcpy_s(buffer, buffSize, "#", 1);
                realLen = 1;
            }
            BSH_CHECK(ret == 0, return NULL, "Failed to memcpy");
        } else if (strcmp(name, ".") == 0) {
            realLen = sprintf_s(buffer, buffSize, "%s", current);
H
handyohos 已提交
86
        } else {
X
xionglei6 已提交
87
            realLen = sprintf_s(buffer, buffSize, "%s%s", current, name);
H
handyohos 已提交
88
        }
X
xionglei6 已提交
89 90 91 92
    } else if (strlen(name) == 0) {
        realLen = sprintf_s(buffer, buffSize, "%s", current);
    } else {
        realLen = sprintf_s(buffer, buffSize, "%s", name);
H
handyohos 已提交
93
    }
X
xionglei6 已提交
94 95 96
    buffer[realLen] = '\0';
    BSH_LOGV("GetRealParameter current %s input %s real %s", current, name, buffer);
    return buffer;
H
handyohos 已提交
97 98
}

X
xionglei6 已提交
99
int SetParamShellPrompt(BShellHandle shell, const char *param)
H
handyohos 已提交
100
{
X
xionglei6 已提交
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    uint32_t buffSize = 0;
    char *buffer = GetLocalBuffer(&buffSize);
    char *realParameter = GetRealParameter(shell, param, buffer, buffSize);
    BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
    if (strlen(realParameter) == 0) {
        BShellEnvOutputPrompt(shell, PARAM_SHELL_DEFAULT_PROMPT);
        return -1;
    }
    // check parameter
    int ret = SysCheckParamExist(realParameter);
    if (ret != 0) {
        BShellEnvOutput(shell, "Error: parameter \'%s\' not found\r\n", realParameter);
        return -1;
    }
    if (strcmp(realParameter, "#") == 0) {
        ret = BShellEnvSetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER,
            "", PARAM_STRING, (void *)"");
        BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to set param value");
        BShellEnvOutputPrompt(shell, PARAM_SHELL_DEFAULT_PROMPT);
        return 0;
    }
    ret = BShellEnvSetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER,
        "", PARAM_STRING, (void *)realParameter);
    BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to set param value");
    if (strcat_s(realParameter, buffSize, "#") != 0) {
        BSH_CHECK(ret != 0, return BSH_SYSTEM_ERR, "Failed to cat prompt %s", realParameter);
H
handyohos 已提交
127
    }
X
xionglei6 已提交
128 129
    BShellEnvOutputPrompt(shell, realParameter);
    return 0;
H
handyohos 已提交
130 131
}

X
xionglei6 已提交
132
static char *GetPermissionString(uint32_t mode, int shift, char *str, int size)
H
handyohos 已提交
133
{
X
xionglei6 已提交
134 135 136 137 138 139 140 141 142 143 144 145
    if (size < MASK_LENGTH_MAX) {
        return str;
    }
    str[0] = '-';
    str[1] = '-';
    str[2] = '-'; // 2 watcher
    str[3] = '\0'; // 3 end
    if (mode & (DAC_READ >> shift)) {
        str[0] = 'r';
    }
    if (mode & (DAC_WRITE >> shift)) {
        str[1] = 'w';
H
handyohos 已提交
146
    }
X
xionglei6 已提交
147 148 149 150
    if (mode & (DAC_WATCH >> shift)) {
        str[2] = 'w'; // 2 watcher
    }
    return str;
H
handyohos 已提交
151 152
}

X
xionglei6 已提交
153
static void ShowParam(BShellHandle shell, const char *name, const char *value)
H
handyohos 已提交
154
{
X
xionglei6 已提交
155 156 157
    ParamAuditData auditData = {};
    int ret = GetParamSecurityAuditData(name, 0, &auditData);
    if (ret != 0) {
X
xionglei6 已提交
158
        BSH_LOGE("Failed to get param security for %s", name);
X
xionglei6 已提交
159
        return;
H
handyohos 已提交
160
    }
X
xionglei6 已提交
161 162 163
    char permissionStr[MASK_LENGTH_MAX] = {'-', '-', '-', 0};
    struct passwd *user = getpwuid(auditData.dacData.uid);
    struct group *group = getgrgid(auditData.dacData.gid);
X
xionglei6 已提交
164 165 166 167
    if (user == NULL || group == NULL) {
        BSH_LOGE("Failed to get group for user for %s", name);
        return;
    }
X
xionglei6 已提交
168 169 170 171 172 173 174 175
    BShellEnvOutput(shell, "Parameter infomation:\r\n");
    BShellEnvOutput(shell, "    dac  : %s(%s) %s(%s) (%s) \r\n",
        user->pw_name, GetPermissionString(auditData.dacData.mode, 0, permissionStr, MASK_LENGTH_MAX),
        group->gr_name, GetPermissionString(auditData.dacData.mode, DAC_GROUP_START, permissionStr, MASK_LENGTH_MAX),
        GetPermissionString(auditData.dacData.mode, DAC_OTHER_START, permissionStr, MASK_LENGTH_MAX));
    BShellEnvOutput(shell, "    name : %s\r\n", name);
    if (value != NULL) {
        BShellEnvOutput(shell, "    value: %s\r\n", value);
H
handyohos 已提交
176
    }
X
xionglei6 已提交
177 178 179 180 181 182 183 184
}

static void ShowParamForCmdLs(ParamHandle handle, void *cookie)
{
    uint32_t buffSize = 0;
    char *buffer = GetLocalBuffer(&buffSize);
    if (buffSize < (PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX)) {
        return;
H
handyohos 已提交
185
    }
X
xionglei6 已提交
186 187 188 189 190
    char *value = buffer + PARAM_NAME_LEN_MAX;
    (void)SystemGetParameterName(handle, buffer, PARAM_NAME_LEN_MAX);
    uint32_t valueLen = buffSize - PARAM_NAME_LEN_MAX;
    (void)SystemGetParameterValue(handle, value, &valueLen);
    ShowParam((BShellHandle)cookie, buffer, value);
H
handyohos 已提交
191 192
}

X
xionglei6 已提交
193
static int32_t BShellParamCmdLs(BShellHandle shell, int32_t argc, char *argv[])
H
handyohos 已提交
194
{
X
xionglei6 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207 208
    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
    int all = 0;
    char *input = NULL;
    for (int32_t i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-r") == 0) {
            all = 1;
        } else if (input == NULL) {
            input = argv[i];
        }
    }
    uint32_t buffSize = 0;
    char *buffer = GetLocalBuffer(&buffSize);
    char *realParameter = GetRealParameter(shell, (input == NULL) ? "" : input, buffer, buffSize);
    BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
X
xionglei6 已提交
209
    char *prefix = strdup((strlen(realParameter) == 0) ? "#" : realParameter);
X
xionglei6 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
    BSH_LOGV("BShellParamCmdLs prefix %s", prefix);
    int ret = 0;
    if (all != 0) {
        ret = SystemTraversalParameter(prefix, ShowParamForCmdLs, (void *)shell);
        if (ret != 0) {
            BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n");
        }
    } else {
        ParamHandle handle;
        ret = SystemFindParameter(prefix, &handle);
        if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
            BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n");
        } else if (ret == 0) {
            ShowParamForCmdLs(handle, (void *)shell);
        } else if (ret == PARAM_CODE_NODE_EXIST) {
            ShowParam(shell, prefix, NULL);
H
handyohos 已提交
226
        } else {
X
xionglei6 已提交
227
            BShellEnvOutput(shell, "Parameter %s not found\r\n", prefix);
H
handyohos 已提交
228 229
        }
    }
X
xionglei6 已提交
230 231
    free(prefix);
    return 0;
H
handyohos 已提交
232 233
}

X
xionglei6 已提交
234
static int32_t BShellParamCmdCat(BShellHandle shell, int32_t argc, char *argv[])
H
handyohos 已提交
235
{
X
xionglei6 已提交
236 237 238 239 240 241 242 243 244
    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
    BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env");
    uint32_t buffSize = 0;
    char *buffer = GetLocalBuffer(&buffSize);
    char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize);
    BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
    int ret = SystemGetParameter(realParameter, buffer, &buffSize);
    if (ret == 0) {
        BShellEnvOutput(shell, "    %s\r\n", buffer);
H
handyohos 已提交
245
    }
X
xionglei6 已提交
246 247 248 249 250 251 252 253 254
    return 0;
}

static int32_t BShellParamCmdCd(BShellHandle shell, int32_t argc, char *argv[])
{
    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
    BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env");
    SetParamShellPrompt(shell, argv[1]);
    return 0;
H
handyohos 已提交
255 256
}

X
xionglei6 已提交
257
static void ShowParamForCmdGet(ParamHandle handle, void *cookie)
H
handyohos 已提交
258
{
X
xionglei6 已提交
259 260 261
    uint32_t buffSize = 0;
    char *buffer = GetLocalBuffer(&buffSize);
    if (buffSize < (PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX)) {
H
handyohos 已提交
262 263
        return;
    }
X
xionglei6 已提交
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
    char *value = buffer + PARAM_NAME_LEN_MAX;
    (void)SystemGetParameterName(handle, buffer, PARAM_NAME_LEN_MAX);
    uint32_t valueLen = buffSize - PARAM_NAME_LEN_MAX;
    (void)SystemGetParameterValue(handle, value, &valueLen);
    BShellEnvOutput((BShellHandle)cookie, "    %s = %s\r\n", buffer, value);
}

static int32_t BShellParamCmdGet(BShellHandle shell, int32_t argc, char *argv[])
{
    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
    BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env");
    int ret = 0;
    uint32_t buffSize = 0;
    char *buffer = GetLocalBuffer(&buffSize);
    char *realParameter = GetRealParameter(shell, (argc == 1) ? "" : argv[1], buffer, buffSize);
    if ((argc == 1) || (realParameter == NULL) ||
        (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) {
        ret = SystemTraversalParameter(realParameter, ShowParamForCmdGet, (void *)shell);
        if (ret != 0) {
            BShellEnvOutput(shell, "Error: Forbid to get all parameters\r\n");
        }
        return 0;
H
handyohos 已提交
286
    }
X
xionglei6 已提交
287 288 289 290 291 292
    char *key = strdup(realParameter);
    ret = SystemGetParameter(key, buffer, &buffSize);
    if (ret == 0) {
        BShellEnvOutput(shell, "%s \n", buffer);
    } else {
        BShellEnvOutput(shell, "Get parameter \"%s\" fail\n", key);
H
handyohos 已提交
293
    }
X
xionglei6 已提交
294 295
    free(key);
    return 0;
H
handyohos 已提交
296
}
X
xionglei6 已提交
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342

static int32_t BShellParamCmdSet(BShellHandle shell, int32_t argc, char *argv[])
{
    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
    if (argc < 3) { // 3 min param
        char *helpArgs[] = {"param", NULL};
        BShellCmdHelp(shell, 1, helpArgs);
        return 0;
    }
    uint32_t buffSize = 0;
    char *buffer = GetLocalBuffer(&buffSize);
    char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize);
    if ((realParameter == NULL) || (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) {
        BShellEnvOutput(shell, "Set parameter %s %s fail\n", argv[1], argv[2]); // 2 value param
        return 0;
    }
    int ret = SystemSetParameter(realParameter, argv[2]); // 2 value param
    if (ret == 0) {
        BShellEnvOutput(shell, "Set parameter %s %s success\n", realParameter, argv[2]); // 2 value param
    } else {
        BShellEnvOutput(shell, "Set parameter %s %s fail\n", realParameter, argv[2]); // 2 value param
    }
    return 0;
}

static int32_t BShellParamCmdWait(BShellHandle shell, int32_t argc, char *argv[])
{
    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
    if (argc < 2) { // 2 min param
        char *helpArgs[] = {"param", NULL};
        BShellCmdHelp(shell, 1, helpArgs);
        return 0;
    }
    int32_t timeout = 30; // 30s
    char *value = "*";
    if (argc > 2) { // 2 value param
        value = argv[2]; // 2 value param
    }
    if (argc > 3) { // 3 timeout param
        timeout = atoi(argv[3]); // 3 timeout param
    }
    uint32_t buffSize = 0;
    char *buffer = GetLocalBuffer(&buffSize);
    char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize);
    if ((realParameter == NULL) || (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) {
        BShellEnvOutput(shell, "Wait parameter %s fail\n", argv[1]);
H
handyohos 已提交
343 344 345
        return 0;
    }

X
xionglei6 已提交
346 347 348 349 350 351 352 353 354 355 356 357
    int ret = SystemWaitParameter(realParameter, value, timeout);
    if (ret == 0) {
        BShellEnvOutput(shell, "Wait parameter %s success\n", argv[1]);
    } else {
        BShellEnvOutput(shell, "Wait parameter %s fail\n", argv[1]);
    }
    return 0;
}

static int32_t BShellParamCmdDump(BShellHandle shell, int32_t argc, char *argv[])
{
    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
X
xionglei6 已提交
358
    if (argc >= 2 && strcmp(argv[1], "verbose") == 0) { // 2 min arg
X
xionglei6 已提交
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
        SystemSetParameter("ohos.servicectrl.display", "system");
        SystemDumpParameters(1);
    } else {
        SystemDumpParameters(0);
    }
    return 0;
}

static int32_t BShellParamCmdPwd(BShellHandle shell, int32_t argc, char *argv[])
{
    uint32_t buffSize = 0;
    char *buffer = GetLocalBuffer(&buffSize);
    char *realParameter = GetRealParameter(shell, "", buffer, buffSize);
    BShellEnvOutput(shell, "%s\r\n", realParameter);
    return 0;
}

static int32_t BShellParamCmdShell(BShellHandle shell, int32_t argc, char *argv[])
{
    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
    BSH_LOGV("BShellParamCmdShell %d %s", argc, argv[1]);
    int ret = 0;
    if (argc > 1) {
        ret = SysCheckParamExist(argv[1]);
        if (ret != 0) {
            BShellEnvOutput(shell, "Error: parameter \'%s\' not found\r\n", argv[1]);
            return -1;
        }
    }
    if (tcgetattr(0, &g_terminalState)) {
        return BSH_SYSTEM_ERR;
    }
    g_isSetTerminal = 1;
    pid_t pid = fork();
    if (pid == 0) {
X
xionglei6 已提交
394 395
        setuid(2000); // 2000 shell group
        setgid(2000); // 2000 shell group
396 397 398
#ifdef WITH_SELINUX
        setcon("u:r:normal_hap_domain:s0");
#endif
X
xionglei6 已提交
399 400 401 402 403 404 405 406 407 408
        if (argc >= 2) { // 2 min argc
            char *args[] = {SHELL_NAME, argv[1], NULL};
            ret = execv(CMD_PATH, args);
        } else {
            char *args[] = {SHELL_NAME, NULL};
            ret = execv(CMD_PATH, args);
        }
        if (ret < 0) {
            printf("error on exec %d \n", errno);
            exit(0);
H
handyohos 已提交
409
        }
X
xionglei6 已提交
410 411 412 413 414 415 416
        exit(0);
    } else if (pid > 0) {
        g_shellPid = pid;
        int status = 0;
        wait(&status);
        tcsetattr(0, TCSAFLUSH, &g_terminalState);
        g_isSetTerminal = 0;
H
handyohos 已提交
417
    }
X
xionglei6 已提交
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
    return 0;
}

static int32_t BShellParamCmdRegForShell(BShellHandle shell)
{
    CmdInfo infos[] = {
        {"ls", BShellParamCmdLs, "display system parameter", "ls [-r] [name]", NULL},
        {"get", BShellParamCmdGet, "get system parameter", "get [name]", NULL},
        {"set", BShellParamCmdSet, "set system parameter", "set name value", NULL},
        {"wait", BShellParamCmdWait, "wait system parameter", "wait name [value] [timeout]", NULL},
        {"dump", BShellParamCmdDump, "dump system parameter", "dump [verbose]", ""},
        {"cd", BShellParamCmdCd, "change path of parameter", "cd name", NULL},
        {"cat", BShellParamCmdCat, "display value of parameter", "cat name", NULL},
        {"pwd", BShellParamCmdPwd, "display current parameter", "pwd", NULL},
    };
    for (size_t i = sizeof(infos) / sizeof(infos[0]); i > 0; i--) {
        BShellEnvRegitsterCmd(shell, &infos[i - 1]);
H
handyohos 已提交
435 436 437 438
    }
    return 0;
}

X
xionglei6 已提交
439
static int32_t BShellParamCmdRegForIndepent(BShellHandle shell)
H
handyohos 已提交
440
{
X
xionglei6 已提交
441 442 443 444 445 446 447 448 449 450 451 452
    CmdInfo infos[] = {
        {"param", BShellParamCmdLs, "display system parameter", "param ls [-r] [name]", "param ls"},
        {"param", BShellParamCmdGet, "get system parameter", "param get [name]", "param get"},
        {"param", BShellParamCmdSet, "set system parameter", "param set name value", "param set"},
        {"param", BShellParamCmdWait, "wait system parameter", "param wait name [value] [timeout]", "param wait"},
        {"param", BShellParamCmdDump, "dump system parameter", "param dump [verbose]", "param dump"},
        {"param", BShellParamCmdShell, "shell system parameter", "param shell [name]", "param shell"},
    };
    for (size_t i = sizeof(infos) / sizeof(infos[0]); i > 0; i--) {
        BShellEnvRegitsterCmd(shell, &infos[i - 1]);
    }
    return 0;
H
handyohos 已提交
453 454
}

X
xionglei6 已提交
455
int32_t BShellParamCmdRegister(BShellHandle shell, int execMode)
H
handyohos 已提交
456
{
X
xionglei6 已提交
457 458 459 460 461 462
    if (execMode) {
        BShellParamCmdRegForShell(shell);
    } else {
        BShellParamCmdRegForIndepent(shell);
    }
    return 0;
H
handyohos 已提交
463
}