init_cmds.c 35.5 KB
Newer Older
W
wenjun 已提交
1
/*
Z
zhong_ning 已提交
2
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
W
wenjun 已提交
3 4 5 6 7 8 9 10 11 12 13 14
 * 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.
 */
15

W
wenjun 已提交
16
#include "init_cmds.h"
Z
zhong_ning 已提交
17

W
wenjun 已提交
18 19
#include <ctype.h>
#include <errno.h>
20
#include <stdbool.h>
W
wenjun 已提交
21 22 23 24
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
Z
zhong_ning 已提交
25
#include <sys/resource.h>
W
wenjun 已提交
26
#include <sys/stat.h>
Z
zhong_ning 已提交
27 28
#include <sys/sysmacros.h>
#include <sys/wait.h>
W
wenjun 已提交
29
#include <unistd.h>
Z
zhong_ning 已提交
30
#include <fcntl.h>
Z
zhong_ning 已提交
31
#ifndef OHOS_LITE
Z
zhong_ning 已提交
32 33
#include <linux/module.h>
#endif
Z
zhong_ning 已提交
34 35 36
#include <sys/syscall.h>
#include "init_jobs.h"
#include "init_log.h"
Z
zhong_ning 已提交
37 38 39
#ifndef OHOS_LITE
#include "init_param.h"
#endif
Z
zhong_ning 已提交
40
#include "init_reboot.h"
W
wenjun 已提交
41
#include "init_service_manager.h"
Z
zhong_ning 已提交
42
#include "init_utils.h"
W
wenjun 已提交
43 44 45 46 47 48
#include "securec.h"

#define DEFAULT_DIR_MODE 0755  // mkdir, default mode
#define SPACES_CNT_IN_CMD_MAX 10   // mount, max number of spaces in cmdline
#define SPACES_CNT_IN_CMD_MIN 2    // mount, min number of spaces in cmdline

M
mamingshuai 已提交
49 50 51
#define LOADCFG_BUF_SIZE  128  // loadcfg, max buffer for one cmdline
#define LOADCFG_MAX_FILE_LEN 51200  // loadcfg, max file size is 50K
#define LOADCFG_MAX_LOOP 20  // loadcfg, to prevent to be trapped in infite loop
L
leon 已提交
52
#define OCTAL_TYPE 8  // 8 means octal to decimal
S
sun_fan 已提交
53
#define MAX_BUFFER 256UL
Z
zhong_ning 已提交
54
#define AUTHORITY_MAX_SIZE 128
Z
zhong_ning 已提交
55
#define WAIT_MAX_COUNT 10
Z
zhong_ning 已提交
56
#define MAX_EACH_CMD_LENGTH 30
Z
zhong_ning 已提交
57

M
mamingshuai 已提交
58
static const char *g_supportCfg[] = {
J
jason_gitee 已提交
59
    "/etc/patch.cfg",
M
mamingshuai 已提交
60 61 62
    "/patch/fstab.cfg",
};

W
wenjun 已提交
63 64 65 66 67 68
static const char* g_supportedCmds[] = {
    "start ",
    "mkdir ",
    "chmod ",
    "chown ",
    "mount ",
Z
zhong_ning 已提交
69
    "export ",
M
mamingshuai 已提交
70
    "loadcfg ",
Z
zhong_ning 已提交
71
    "insmod ",
Z
zhong_ning 已提交
72 73 74 75 76 77 78 79 80 81 82
    "rm ",
    "rmdir ",
    "write ",
    "exec ",
    "mknode ",
    "makedev ",
    "symlink ",
    "stop ",
    "trigger ",
    "reset ",
    "copy ",
Z
zhong_ning 已提交
83
    "setparam ",
Z
zhong_ning 已提交
84 85 86
    "load_persist_params ",
    "load_param ",
    "reboot ",
Z
zhong_ning 已提交
87
    "setrlimit ",
W
wenjun 已提交
88 89
};

Z
zhong_ning 已提交
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
#ifndef OHOS_LITE
int GetParamValue(char *symValue, char *paramValue, unsigned int paramLen)
{
    if ((symValue == NULL) || (paramValue == NULL) || (paramLen == 0)) {
        return -1;
    }
    char tmpName[MAX_PARAM_NAME_LEN] = {0};
    char tmpValue[MAX_PARAM_VALUE_LEN] = {0};
    unsigned int tmpLen = 0;
    char *p = NULL;
    char *tmpptr = NULL;
    p = strchr(symValue, '$');
    if (p == NULL) { // not has '$' copy the original string
        INIT_CHECK_ONLY_RETURN(strncpy_s(paramValue, paramLen, symValue,
        paramLen - 1) == EOK, return -1);
        return 0;
    }
    tmpLen = p - symValue;
    if (tmpLen > 0) { // copy '$' front string
        INIT_CHECK_ONLY_RETURN(strncpy_s(paramValue, paramLen, symValue, tmpLen) == EOK, return -1);
    }
    p++;
    if (*p == '{') {
        p++;
        char *right = strchr(p, '}');
        if (right == NULL) {
Z
zhong_ning 已提交
116
            INIT_LOGE("Invalid cfg file name, miss '}'.");
Z
zhong_ning 已提交
117 118 119 120
            return -1;
        }
        tmpLen = right - p;
        if (tmpLen > MAX_PARAM_NAME_LEN) {
Z
zhong_ning 已提交
121
            INIT_LOGE("Parameter name longer than %d", MAX_PARAM_NAME_LEN);
Z
zhong_ning 已提交
122 123 124 125 126
            return -1;
        }
        INIT_CHECK_ONLY_RETURN(strncpy_s(tmpName, MAX_PARAM_NAME_LEN, p, tmpLen) == EOK, return -1);
        int ret = SystemReadParam(tmpName, tmpValue, &tmpLen); // get param
        if (ret != 0) {
Z
zhong_ning 已提交
127
            INIT_LOGE("Failed to read parameter \" %s \"", tmpName);
Z
zhong_ning 已提交
128 129 130 131 132 133 134 135 136
            return -1;
        }
        // change param to new string
        INIT_CHECK_ONLY_RETURN(strncat_s(paramValue, paramLen, tmpValue, MAX_PARAM_VALUE_LEN) == EOK, return -1);
        tmpptr = right + 1;
        tmpLen = paramLen - (tmpptr - symValue);
        if (*tmpptr != '\0') { // copy last string
            INIT_CHECK_ONLY_RETURN(strncat_s(paramValue, paramLen, tmpptr, tmpLen) == EOK, return -1);
        }
Z
zhong_ning 已提交
137
        INIT_LOGI("paramValue is %s ", paramValue);
Z
zhong_ning 已提交
138 139
        return 0;
    } else {
Z
zhong_ning 已提交
140
        INIT_LOGE("Invalid cfg file name, miss '{'.");
Z
zhong_ning 已提交
141 142 143
        return -1;
    }
}
S
sun_fan 已提交
144 145 146 147
#else
// For ite ohos, do not support parameter operation. just do string copy
inline int GetParamValue(char *symValue, char *paramValue, unsigned int paramLen)
{
Z
zhong_ning 已提交
148
    return (strncpy_s(paramValue, paramLen, symValue, strlen(symValue)) == EOK) ? 0 : -1;
S
sun_fan 已提交
149
}
Z
zhong_ning 已提交
150 151
#endif

S
sun_fan 已提交
152
struct CmdArgs* GetCmd(const char *cmdContent, const char *delim, int argsCount)
Z
zhong_ning 已提交
153
{
S
sun_fan 已提交
154
    INIT_CHECK_ONLY_RETURN(cmdContent != NULL, return NULL);
Z
zhong_ning 已提交
155 156 157
    struct CmdArgs *ctx = (struct CmdArgs *)malloc(sizeof(struct CmdArgs));
    INIT_CHECK_ONLY_RETURN(ctx != NULL, return NULL);

S
sun_fan 已提交
158 159 160 161 162
    if (argsCount > SPACES_CNT_IN_CMD_MAX) {
        INIT_LOGW("Too much arguments for command, max number is %d", SPACES_CNT_IN_CMD_MAX);
        argsCount = SPACES_CNT_IN_CMD_MAX;
    }
    ctx->argv = (char**)malloc(sizeof(char*) * (size_t)argsCount + 1);
Z
zhong_ning 已提交
163 164 165
    INIT_CHECK_ONLY_RETURN(ctx->argv != NULL, FreeCmd(&ctx); return NULL);

    char tmpCmd[MAX_BUFFER];
S
sun_fan 已提交
166 167 168 169 170 171 172 173
    size_t cmdLength = strlen(cmdContent);
    if (cmdLength > MAX_BUFFER - 1) {
        INIT_LOGE("command line is too larget, should not bigger than %d. ignore...\n", MAX_BUFFER);
        FreeCmd(&ctx);
        return NULL;
    }

    INIT_CHECK_ONLY_RETURN(strncpy_s(tmpCmd, MAX_BUFFER - 1, cmdContent, cmdLength) == EOK,
Z
zhong_ning 已提交
174 175 176 177
        FreeCmd(&ctx);
        return NULL);
    tmpCmd[strlen(cmdContent)] = '\0';

S
sun_fan 已提交
178 179 180 181 182 183 184 185
    char *p = tmpCmd;
    char *token = NULL;
    size_t allocSize = 0;

    // Skip lead whitespaces
    while (isspace(*p)) {
        p++;
    }
Z
zhong_ning 已提交
186
    ctx->argc = 0;
S
sun_fan 已提交
187 188 189
    token = strstr(p, delim);
    if (token == NULL) { // No whitespaces
        // Make surce there is enough memory to store parameter value
S
sun_fan 已提交
190
        allocSize = (size_t)(cmdLength + MAX_PARAM_VALUE_LEN + 1);
S
sun_fan 已提交
191
        ctx->argv[ctx->argc] = calloc(sizeof(char), allocSize);
Z
zhong_ning 已提交
192
        INIT_CHECK_ONLY_RETURN(ctx->argv[ctx->argc] != NULL, FreeCmd(&ctx); return NULL);
S
sun_fan 已提交
193 194
        INIT_CHECK_ONLY_RETURN(GetParamValue(p, ctx->argv[ctx->argc], allocSize) == 0,
            FreeCmd(&ctx); return NULL);
Z
zhong_ning 已提交
195
        ctx->argc += 1;
S
sun_fan 已提交
196 197 198 199 200 201 202
        ctx->argv[ctx->argc] = NULL;
        return ctx;
    }

    int index = ctx->argc;
    while (token != NULL) {
        // Too more arguments, treat rest of data as one argument
Z
zhong_ning 已提交
203
        if (index == (argsCount - 1)) {
S
sun_fan 已提交
204 205 206
            break;
        }
        *token = '\0'; // replace it with '\0';
S
sun_fan 已提交
207
        allocSize = (size_t)((token - p) + MAX_PARAM_VALUE_LEN + 1);
S
sun_fan 已提交
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
        ctx->argv[index] = calloc(sizeof(char), allocSize);
        INIT_CHECK_ONLY_RETURN(ctx->argv[index] != NULL, FreeCmd(&ctx); return NULL);
        INIT_CHECK_ONLY_RETURN(GetParamValue(p, ctx->argv[index], allocSize) == 0,
            FreeCmd(&ctx); return NULL);
        p = token + 1; // skip '\0'
        // Skip lead whitespaces
        while (isspace(*p)) {
            p++;
        }
        index++;
        token = strstr(p, delim);
    }

    ctx->argc = index;
    if (p < tmpCmd + cmdLength) {
        // no more white space or encounter max argument count
        size_t restSize = tmpCmd + cmdLength - p;
S
sun_fan 已提交
225
        allocSize = restSize + MAX_PARAM_VALUE_LEN + 1;
S
sun_fan 已提交
226 227 228 229 230
        ctx->argv[index] = calloc(sizeof(char),  allocSize);
        INIT_CHECK_ONLY_RETURN(ctx->argv[index] != NULL, FreeCmd(&ctx); return NULL);
        INIT_CHECK_ONLY_RETURN(GetParamValue(p, ctx->argv[index], allocSize) == 0,
            FreeCmd(&ctx); return NULL);
        ctx->argc = index + 1;
Z
zhong_ning 已提交
231
    }
S
sun_fan 已提交
232

Z
zhong_ning 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
    ctx->argv[ctx->argc] = NULL;
    return ctx;
}

void FreeCmd(struct CmdArgs **cmd)
{
    struct CmdArgs *tmpCmd = *cmd;
    INIT_CHECK_ONLY_RETURN(tmpCmd != NULL, return);
    for (int i = 0; i < tmpCmd->argc; ++i) {
        INIT_CHECK_ONLY_RETURN(tmpCmd->argv[i] == NULL, free(tmpCmd->argv[i]));
    }
    INIT_CHECK_ONLY_RETURN(tmpCmd->argv == NULL, free(tmpCmd->argv));
    free(tmpCmd);
    return;
}

W
wenjun 已提交
249 250
void ParseCmdLine(const char* cmdStr, CmdLine* resCmd)
{
251 252
    size_t cmdLineLen = 0;
    if (cmdStr == NULL || resCmd == NULL || (cmdLineLen = strlen(cmdStr)) == 0) {
W
wenjun 已提交
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
        return;
    }

    size_t supportCmdCnt = sizeof(g_supportedCmds) / sizeof(g_supportedCmds[0]);
    int foundAndSucceed = 0;
    for (size_t i = 0; i < supportCmdCnt; ++i) {
        size_t curCmdNameLen = strlen(g_supportedCmds[i]);
        if (cmdLineLen > curCmdNameLen && cmdLineLen <= (curCmdNameLen + MAX_CMD_CONTENT_LEN) &&
            strncmp(g_supportedCmds[i], cmdStr, curCmdNameLen) == 0) {
            if (memcpy_s(resCmd->name, MAX_CMD_NAME_LEN, cmdStr, curCmdNameLen) != EOK) {
                break;
            }
            resCmd->name[curCmdNameLen] = '\0';

            const char* cmdContent = cmdStr + curCmdNameLen;
            size_t cmdContentLen = cmdLineLen - curCmdNameLen;
            if (memcpy_s(resCmd->cmdContent, MAX_CMD_CONTENT_LEN, cmdContent, cmdContentLen) != EOK) {
                break;
            }
            resCmd->cmdContent[cmdContentLen] = '\0';
            foundAndSucceed = 1;
            break;
        }
    }

    if (!foundAndSucceed) {
Z
zhong_ning 已提交
279
        INIT_LOGE("Cannot parse command: %s", cmdStr);
W
wenjun 已提交
280 281 282 283 284 285
        (void)memset_s(resCmd, sizeof(*resCmd), 0, sizeof(*resCmd));
    }
}

static void DoStart(const char* cmdContent)
{
Z
zhong_ning 已提交
286
    INIT_LOGD("DoStart %s ", cmdContent);
W
wenjun 已提交
287 288 289
    StartServiceByName(cmdContent);
}

Z
zhong_ning 已提交
290
static void DoStop(const char* cmdContent)
W
wenjun 已提交
291
{
Z
zhong_ning 已提交
292
    INIT_LOGD("DoStop %s ", cmdContent);
Z
zhong_ning 已提交
293
    StopServiceByName(cmdContent);
W
wenjun 已提交
294 295
}

Z
zhong_ning 已提交
296
static void DoReset(const char* cmdContent)
W
wenjun 已提交
297
{
Z
zhong_ning 已提交
298
    INIT_LOGD("DoReset %s ", cmdContent);
Z
zhong_ning 已提交
299 300 301
    DoStop(cmdContent);
    DoStart(cmdContent);
}
W
wenjun 已提交
302

Z
zhong_ning 已提交
303 304 305 306 307 308
static void DoCopy(const char* cmdContent)
{
    int srcFd = -1;
    int dstFd = -1;
    int rdLen = 0;
    int rtLen = 0;
S
sun_fan 已提交
309
    int argsCount = 2;
Z
zhong_ning 已提交
310
    char buf[MAX_COPY_BUF_SIZE] = {0};
S
sun_fan 已提交
311 312
    char *realPath1 = NULL;
    char *realPath2 = NULL;
Z
zhong_ning 已提交
313 314
    mode_t mode = 0;
    struct stat fileStat = {0};
S
sun_fan 已提交
315
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
S
sun_fan 已提交
316 317
    if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL || ctx->argv[1] == NULL ||
        ctx->argc != DEFAULT_COPY_ARGS_CNT) {
Z
zhong_ning 已提交
318
        INIT_LOGE("DoCopy failed.");
Z
zhong_ning 已提交
319 320
        goto out;
    }
S
sun_fan 已提交
321 322 323 324 325 326 327 328 329
    realPath1 = realpath(ctx->argv[0], NULL);
    if (realPath1 == NULL) {
        goto out;
    }
    realPath2 = realpath(ctx->argv[1], NULL);
    if (realPath2 == NULL) {
        goto out;
    }
    srcFd = open(realPath1, O_RDONLY);
Z
zhong_ning 已提交
330 331
    INIT_ERROR_CHECK(srcFd >= 0, goto out, "copy open %s fail %d! ", ctx->argv[0], errno);
    INIT_ERROR_CHECK(stat(ctx->argv[0], &fileStat) == 0, goto out, "stat fail ");
Z
zhong_ning 已提交
332
    mode = fileStat.st_mode;
S
sun_fan 已提交
333
    dstFd = open(realPath2, O_WRONLY | O_TRUNC | O_CREAT, mode);
Z
zhong_ning 已提交
334
    INIT_ERROR_CHECK(dstFd >= 0, goto out, "copy open %s fail %d! ", ctx->argv[1], errno);
Z
zhong_ning 已提交
335 336
    while ((rdLen = read(srcFd, buf, sizeof(buf) - 1)) > 0) {
        rtLen = write(dstFd, buf, rdLen);
Z
zhong_ning 已提交
337
        INIT_ERROR_CHECK(rtLen == rdLen, goto out, "write %s file fail %d! ", ctx->argv[1], errno);
Z
zhong_ning 已提交
338 339 340 341 342
    }
    fsync(dstFd);
out:
    FreeCmd(&ctx);
    ctx = NULL;
Z
zhong_ning 已提交
343 344 345 346 347 348 349 350
    if (srcFd >= 0) {
        close(srcFd);
        srcFd = -1;
    }
    if (dstFd >= 0) {
        close(dstFd);
        dstFd = -1;
    }
S
sun_fan 已提交
351 352 353 354 355 356 357 358
    if (realPath1) {
        free(realPath1);
        realPath1 = NULL;
    }
    if (realPath2) {
        free(realPath2);
        realPath2 = NULL;
    }
Z
zhong_ning 已提交
359 360 361 362 363 364
    return;
}

static void DoChown(const char* cmdContent)
{
    // format: chown owner group /xxx/xxx/xxx
S
sun_fan 已提交
365 366 367
    const int argsCount = 3;
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != argsCount) {
Z
zhong_ning 已提交
368
        INIT_LOGE("DoChown failed.");
Z
zhong_ning 已提交
369 370 371 372 373 374 375
        goto out;
    }

    uid_t owner = (uid_t)-1;
    gid_t group = (gid_t)-1;
    if (isalpha(ctx->argv[0][0])) {
        owner = DecodeUid(ctx->argv[0]);
Z
zhong_ning 已提交
376
        INIT_ERROR_CHECK(owner != (uid_t)-1, goto out, "DoChown decode owner failed.");
Z
zhong_ning 已提交
377 378
    } else {
        owner = strtoul(ctx->argv[0], NULL, 0);
W
wenjun 已提交
379 380
    }

Z
zhong_ning 已提交
381 382
    if (isalpha(ctx->argv[1][0])) {
        group = DecodeUid(ctx->argv[1]);
Z
zhong_ning 已提交
383
        INIT_ERROR_CHECK(group != (gid_t)-1, goto out, "DoChown decode group failed.");
Z
zhong_ning 已提交
384 385
    } else {
        group = strtoul(ctx->argv[1], NULL, 0);
W
wenjun 已提交
386 387
    }

Z
zhong_ning 已提交
388 389
    int pathPos = 2;
    if (chown(ctx->argv[pathPos], owner, group) != 0) {
Z
zhong_ning 已提交
390
        INIT_LOGE("DoChown, failed for %s, err %d.", cmdContent, errno);
W
wenjun 已提交
391
    }
Z
zhong_ning 已提交
392 393 394
out:
    FreeCmd(&ctx);
    return;
W
wenjun 已提交
395 396
}

Z
zhong_ning 已提交
397
static void DoMkDir(const char* cmdContent)
W
wenjun 已提交
398
{
Z
zhong_ning 已提交
399
    // format: mkdir /xxx/xxx/xxx or mkdir /xxx/xxx/xxx mode owner group
S
sun_fan 已提交
400 401
    const int argsCount = 4;
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
Z
zhong_ning 已提交
402
    if (ctx == NULL || ctx->argv == NULL || ctx->argc < 1) {
Z
zhong_ning 已提交
403
        INIT_LOGE("DoMkDir failed.");
Z
zhong_ning 已提交
404 405 406 407
        goto out;
    }

    mode_t mode = DEFAULT_DIR_MODE;
Z
zhong_ning 已提交
408
    if (mkdir(ctx->argv[0], mode) != 0 && errno != EEXIST) {
Z
zhong_ning 已提交
409
        INIT_LOGE("DoMkDir, failed for %s, err %d.", cmdContent, errno);
Z
zhong_ning 已提交
410
        goto out;
W
wenjun 已提交
411 412
    }

Z
zhong_ning 已提交
413 414 415
    if (ctx->argc > 1) {
        mode = strtoul(ctx->argv[1], NULL, OCTAL_TYPE);
        if (chmod(ctx->argv[0], mode) != 0) {
Z
zhong_ning 已提交
416
            INIT_LOGE("DoMkDir failed for %s, err %d.", cmdContent, errno);
Z
zhong_ning 已提交
417
        }
S
sun_fan 已提交
418 419
        const int ownerPos = 2;
        const int groupPos = 3;
Z
zhong_ning 已提交
420 421 422
        char chownCmdContent[AUTHORITY_MAX_SIZE] = { 0 };
        if (snprintf_s(chownCmdContent, AUTHORITY_MAX_SIZE, AUTHORITY_MAX_SIZE - 1, "%s %s %s",
            ctx->argv[ownerPos], ctx->argv[groupPos], ctx->argv[0]) == -1) {
Z
zhong_ning 已提交
423
            INIT_LOGE("DoMkDir snprintf failed.");
Z
zhong_ning 已提交
424
            goto out;
W
wenjun 已提交
425
        }
Z
zhong_ning 已提交
426 427 428 429 430 431 432 433 434 435
        DoChown(chownCmdContent);
    }
out:
    FreeCmd(&ctx);
    return;
}

static void DoChmod(const char* cmdContent)
{
    // format: chmod xxxx /xxx/xxx/xxx
S
sun_fan 已提交
436 437 438
    int argsCount = 2;
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != argsCount) {
Z
zhong_ning 已提交
439
        INIT_LOGE("DoChmod failed.");
Z
zhong_ning 已提交
440
        goto out;
W
wenjun 已提交
441 442
    }

Z
zhong_ning 已提交
443 444
    mode_t mode = strtoul(ctx->argv[0], NULL, OCTAL_TYPE);
    if (mode == 0) {
Z
zhong_ning 已提交
445
        INIT_LOGE("DoChmod, strtoul failed for %s, er %d.", cmdContent, errno);
Z
zhong_ning 已提交
446 447 448 449
        goto out;
    }

    if (chmod(ctx->argv[1], mode) != 0) {
Z
zhong_ning 已提交
450
        INIT_LOGE("DoChmod, failed for %s, err %d.", cmdContent, errno);
W
wenjun 已提交
451
    }
Z
zhong_ning 已提交
452 453 454
out:
    FreeCmd(&ctx);
    return;
W
wenjun 已提交
455 456 457 458 459
}

static char* CopySubStr(const char* srcStr, size_t startPos, size_t endPos)
{
    if (endPos <= startPos) {
Z
zhong_ning 已提交
460
        INIT_LOGE("DoMount, invalid params<%zu, %zu> for %s.", endPos, startPos, srcStr);
W
wenjun 已提交
461 462 463 464 465 466
        return NULL;
    }

    size_t mallocLen = endPos - startPos + 1;
    char* retStr = (char*)malloc(mallocLen);
    if (retStr == NULL) {
Z
zhong_ning 已提交
467
        INIT_LOGE("DoMount, malloc failed! malloc size %zu, for %s.", mallocLen, srcStr);
W
wenjun 已提交
468 469 470 471 472
        return NULL;
    }

    const char* copyStart = srcStr + startPos;
    if (memcpy_s(retStr, mallocLen, copyStart, endPos - startPos) != EOK) {
Z
zhong_ning 已提交
473
        INIT_LOGE("DoMount, memcpy_s failed for %s.", srcStr);
W
wenjun 已提交
474 475 476 477 478 479 480 481 482 483 484 485
        free(retStr);
        return NULL;
    }
    retStr[mallocLen - 1] = '\0';

    // for example, source may be none
    if (strncmp(retStr, "none", strlen("none")) == 0) {
        retStr[0] = '\0';
    }
    return retStr;
}

Z
zhong_ning 已提交
486
static int GetMountFlag(unsigned long* mountflags, const char* targetStr, const char *source)
W
wenjun 已提交
487 488 489 490 491 492 493
{
    if (targetStr == NULL) {
        return 0;
    }

    if (strncmp(targetStr, "nodev", strlen("nodev")) == 0) {
        (*mountflags) |= MS_NODEV;
G
Gymee 已提交
494
    } else if (strncmp(targetStr, "noexec", strlen("noexec")) == 0) {
W
wenjun 已提交
495
        (*mountflags) |= MS_NOEXEC;
G
Gymee 已提交
496
    } else if (strncmp(targetStr, "nosuid", strlen("nosuid")) == 0) {
W
wenjun 已提交
497
        (*mountflags) |= MS_NOSUID;
G
Gymee 已提交
498
    } else if (strncmp(targetStr, "rdonly", strlen("rdonly")) == 0) {
W
wenjun 已提交
499
        (*mountflags) |= MS_RDONLY;
Z
zhong_ning 已提交
500 501 502
    } else if (strncmp(targetStr, "noatime", strlen("noatime")) == 0) {
        (*mountflags) |= MS_NOATIME;
    } else if (strncmp(targetStr, "wait", strlen("wait")) == 0) {
Z
zhong_ning 已提交
503
        WaitForFile(source, WAIT_MAX_COUNT);
G
Gymee 已提交
504 505
    } else {
        return 0;
W
wenjun 已提交
506
    }
G
Gymee 已提交
507
    return 1;
W
wenjun 已提交
508 509 510 511
}

static int CountSpaces(const char* cmdContent, size_t* spaceCnt, size_t* spacePosArr, size_t spacePosArrLen)
{
M
mamingshuai 已提交
512 513
    *spaceCnt = 0;
    size_t strLen = strlen(cmdContent);
W
wenjun 已提交
514
    for (size_t i = 0; i < strLen; ++i) {
M
mamingshuai 已提交
515 516 517
        if (cmdContent[i] == ' ') {
            ++(*spaceCnt);
            if ((*spaceCnt) > spacePosArrLen) {
Z
zhong_ning 已提交
518
                INIT_LOGE("DoMount, too many spaces, bad format for %s.", cmdContent);
M
mamingshuai 已提交
519 520 521
                return 0;
            }
            spacePosArr[(*spaceCnt) - 1] = i;
W
wenjun 已提交
522 523 524
        }
    }

M
mamingshuai 已提交
525 526 527
    if ((*spaceCnt) < SPACES_CNT_IN_CMD_MIN ||           // spaces count should not less than 2(at least 3 items)
        spacePosArr[0] == 0 ||                           // should not start with space
        spacePosArr[(*spaceCnt) - 1] == strLen - 1) {    // should not end with space
Z
zhong_ning 已提交
528
        INIT_LOGE("DoMount, bad format for %s.", cmdContent);
W
wenjun 已提交
529 530 531 532
        return 0;
    }

    // spaces should not be adjacent
M
mamingshuai 已提交
533 534
    for (size_t i = 1; i < (*spaceCnt); ++i) {
        if (spacePosArr[i] == spacePosArr[i - 1] + 1) {
Z
zhong_ning 已提交
535
            INIT_LOGE("DoMount, bad format for %s.", cmdContent);
W
wenjun 已提交
536 537 538 539 540 541 542 543 544 545 546 547 548 549
            return 0;
        }
    }
    return 1;
}

static void DoMount(const char* cmdContent)
{
    size_t spaceCnt = 0;
    size_t spacePosArr[SPACES_CNT_IN_CMD_MAX] = {0};
    if (!CountSpaces(cmdContent, &spaceCnt, spacePosArr, SPACES_CNT_IN_CMD_MAX)) {
        return;
    }

550 551 552
    // format: fileSystemType source target mountFlag1 mountFlag2... data
    unsigned long mountflags = 0;
    size_t strLen = strlen(cmdContent);
W
wenjun 已提交
553 554
    size_t indexOffset = 0;
    char* fileSysType = CopySubStr(cmdContent, 0, spacePosArr[indexOffset]);
M
mamingshuai 已提交
555 556 557 558
    if (fileSysType == NULL) {
        return;
    }

W
wenjun 已提交
559
    char* source = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, spacePosArr[indexOffset + 1]);
M
mamingshuai 已提交
560 561 562 563
    if (source == NULL) {
        free(fileSysType);
        return;
    }
W
wenjun 已提交
564 565 566 567 568
    ++indexOffset;

    // maybe only has "filesystype source target", 2 spaces
    size_t targetEndPos = (indexOffset == spaceCnt - 1) ? strLen : spacePosArr[indexOffset + 1];
    char* target = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, targetEndPos);
M
mamingshuai 已提交
569 570 571 572 573
    if (target == NULL) {
        free(fileSysType);
        free(source);
        return;
    }
W
wenjun 已提交
574 575 576 577 578 579
    ++indexOffset;

    // get mountflags, if fail, the rest part of string will be data
    while (indexOffset < spaceCnt) {
        size_t tmpStrEndPos = (indexOffset == spaceCnt - 1) ? strLen : spacePosArr[indexOffset + 1];
        char* tmpStr = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, tmpStrEndPos);
Z
zhong_ning 已提交
580
        int ret = GetMountFlag(&mountflags, tmpStr, source);
W
wenjun 已提交
581 582 583 584 585 586 587 588 589 590
        free(tmpStr);
        tmpStr = NULL;

        // get flag failed, the rest part of string will be data
        if (ret == 0) {
            break;
        }
        ++indexOffset;
    }

M
mamingshuai 已提交
591 592 593
    int mountRet;
    if (indexOffset >= spaceCnt) {    // no data
        mountRet = mount(source, target, fileSysType, mountflags, NULL);
W
wenjun 已提交
594
    } else {
M
mamingshuai 已提交
595 596 597 598 599
        const char* dataStr = cmdContent + spacePosArr[indexOffset] + 1;
        mountRet = mount(source, target, fileSysType, mountflags, dataStr);
    }

    if (mountRet != 0) {
Z
zhong_ning 已提交
600
        INIT_LOGE("DoMount, failed for %s, err %d.", cmdContent, errno);
W
wenjun 已提交
601 602 603 604 605 606 607
    }

    free(fileSysType);
    free(source);
    free(target);
}

Z
zhong_ning 已提交
608
#ifndef OHOS_LITE
L
leon 已提交
609
#define OPTIONS_SIZE 128u
L
leon 已提交
610 611 612 613 614 615
static void DoInsmodInternal(const char *fileName, char *secondPtr, char *restPtr, int flags)
{
    char options[OPTIONS_SIZE] = {0};
    if (flags == 0) { //  '-f' option
        if (restPtr != NULL && secondPtr != NULL) { // Reset arugments, combine then all.
            if (snprintf_s(options, sizeof(options), OPTIONS_SIZE -1, "%s %s", secondPtr, restPtr) == -1) {
Z
zhong_ning 已提交
616
                return;
L
leon 已提交
617
            }
L
leon 已提交
618
        } else if (secondPtr != NULL) {
L
leon 已提交
619
            if (strncpy_s(options, OPTIONS_SIZE - 1, secondPtr, strlen(secondPtr)) != 0) {
Z
zhong_ning 已提交
620
                return;
L
leon 已提交
621 622 623 624
            }
        }
    } else { // Only restPtr is option
        if (restPtr != NULL) {
Z
zhong_ning 已提交
625
            if (strncpy_s(options, OPTIONS_SIZE - 1, restPtr, strlen(restPtr)) != 0) {
Z
zhong_ning 已提交
626
                return;
Z
zhong_ning 已提交
627
            }
L
leon 已提交
628 629
        }
    }
S
sun_fan 已提交
630
    if (fileName == NULL) {
Z
zhong_ning 已提交
631
        return;
Z
zhong_ning 已提交
632
    }
S
sun_fan 已提交
633
    char *realPath = realpath(fileName, NULL);
Z
zhong_ning 已提交
634 635 636 637
    if (realPath == NULL) {
        return;
    }
    int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
L
leon 已提交
638
    if (fd < 0) {
Z
zhong_ning 已提交
639
        INIT_LOGE("failed to open %s: %d", realPath, errno);
Z
zhong_ning 已提交
640
        free(realPath);
S
sun_fan 已提交
641
        realPath = NULL;
Z
zhong_ning 已提交
642
        return;
L
leon 已提交
643 644 645
    }
    int rc = syscall(__NR_finit_module, fd, options, flags);
    if (rc == -1) {
Z
zhong_ning 已提交
646
        INIT_LOGE("finit_module for %s failed: %d", realPath, errno);
L
leon 已提交
647
    }
Z
zhong_ning 已提交
648
    if (fd >= 0) {
L
leon 已提交
649 650
        close(fd);
    }
Z
zhong_ning 已提交
651
    free(realPath);
S
sun_fan 已提交
652
    realPath = NULL;
L
leon 已提交
653 654 655
    return;
}

Z
zhong_ning 已提交
656 657 658 659 660 661
// format insmod <ko name> [-f] [options]
static void DoInsmod(const char *cmdContent)
{
    char *p = NULL;
    char *restPtr = NULL;
    char *fileName = NULL;
L
leon 已提交
662
    char *line = NULL;
Z
zhong_ning 已提交
663 664 665 666
    int flags = 0;

    size_t count = strlen(cmdContent);
    if (count > OPTIONS_SIZE) {
Z
zhong_ning 已提交
667
        INIT_LOGE("DoInsmod options too long, maybe lost some of options");
Z
zhong_ning 已提交
668 669 670
    }
    line = (char *)malloc(count + 1);
    if (line == NULL) {
Z
zhong_ning 已提交
671
        INIT_LOGE("DoInsmod allocate memory failed.");
Z
zhong_ning 已提交
672 673
        return;
    }
L
leon 已提交
674

S
sun_fan 已提交
675
    if (memcpy_s(line, count + 1, cmdContent, count) != EOK) {
Z
zhong_ning 已提交
676
        INIT_LOGE("DoInsmod memcpy failed");
Z
zhong_ning 已提交
677
        free(line);
L
leon 已提交
678
        return;
Z
zhong_ning 已提交
679 680 681 682
    }
    line[count] = '\0';
    do {
        if ((p = strtok_r(line, " ", &restPtr)) == NULL) {
Z
zhong_ning 已提交
683
            INIT_LOGE("DoInsmod cannot get filename.");
Z
zhong_ning 已提交
684
            free(line);
Z
zhong_ning 已提交
685 686 687
            return;
        }
        fileName = p;
Z
zhong_ning 已提交
688
        INIT_LOGI("DoInsmod fileName is [%s].", fileName);
Z
zhong_ning 已提交
689 690 691 692 693 694 695
        if ((p = strtok_r(NULL, " ", &restPtr)) == NULL) {
            break;
        }
        if (!strcmp(p, "-f")) {
            flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS;
        }
    } while (0);
L
leon 已提交
696
    DoInsmodInternal(fileName, p, restPtr, flags);
Z
zhong_ning 已提交
697 698 699
    if (line != NULL) {
        free(line);
    }
L
leon 已提交
700
    return;
Z
zhong_ning 已提交
701
}
Z
zhong_ning 已提交
702 703 704

static void DoSetParam(const char* cmdContent)
{
S
sun_fan 已提交
705 706 707
    int argsCount = 2;
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != argsCount) {
Z
zhong_ning 已提交
708
        INIT_LOGE("DoSetParam failed.");
Z
zhong_ning 已提交
709 710
        goto out;
    }
Z
zhong_ning 已提交
711
    INIT_LOGE("param name: %s, value %s ", ctx->argv[0], ctx->argv[1]);
Z
zhong_ning 已提交
712
    SystemWriteParam(ctx->argv[0], ctx->argv[1]);
Z
zhong_ning 已提交
713 714 715 716 717
out:
    FreeCmd(&ctx);
    return;
}

L
leon 已提交
718
#endif // OHOS_LITE
Z
zhong_ning 已提交
719

M
mamingshuai 已提交
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
static bool CheckValidCfg(const char *path)
{
    size_t cfgCnt = sizeof(g_supportCfg) / sizeof(g_supportCfg[0]);
    struct stat fileStat = {0};

    if (stat(path, &fileStat) != 0 || fileStat.st_size <= 0 || fileStat.st_size > LOADCFG_MAX_FILE_LEN) {
        return false;
    }

    for (size_t i = 0; i < cfgCnt; ++i) {
        if (strcmp(path, g_supportCfg[i]) == 0) {
            return true;
        }
    }

    return false;
}

static void DoLoadCfg(const char *path)
{
    char buf[LOADCFG_BUF_SIZE] = {0};
    FILE *fp = NULL;
    size_t maxLoop = 0;
    CmdLine *cmdLine = NULL;
    int len;

    if (path == NULL) {
        return;
    }

Z
zhong_ning 已提交
750
    INIT_LOGI("DoLoadCfg cfg file %s", path);
M
mamingshuai 已提交
751
    if (!CheckValidCfg(path)) {
Z
zhong_ning 已提交
752
        INIT_LOGE("CheckCfg file %s Failed", path);
M
mamingshuai 已提交
753 754
        return;
    }
S
sun_fan 已提交
755 756 757 758
    if (path == NULL) {
        INIT_LOGE("CheckCfg path is NULL.");
        return;
    }
S
sun_fan 已提交
759 760 761 762 763
    char *realPath = realpath(path, NULL);
    if (realPath == NULL) {
        return;
    }
    fp = fopen(realPath, "r");
M
mamingshuai 已提交
764
    if (fp == NULL) {
Z
zhong_ning 已提交
765
        INIT_LOGE("open cfg error = %d", errno);
S
sun_fan 已提交
766 767
        free(realPath);
        realPath = NULL;
M
mamingshuai 已提交
768 769 770 771 772
        return;
    }

    cmdLine = (CmdLine *)malloc(sizeof(CmdLine));
    if (cmdLine == NULL) {
Z
zhong_ning 已提交
773
        INIT_LOGE("malloc cmdline error");
M
mamingshuai 已提交
774
        fclose(fp);
S
sun_fan 已提交
775 776
        free(realPath);
        realPath = NULL;
M
mamingshuai 已提交
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
        return;
    }

    while (fgets(buf, LOADCFG_BUF_SIZE, fp) != NULL && maxLoop < LOADCFG_MAX_LOOP) {
        maxLoop++;
        len = strlen(buf);
        if (len < 1) {
            continue;
        }
        if (buf[len - 1] == '\n') {
            buf[len - 1] = '\0'; // we replace '\n' with '\0'
        }
        (void)memset_s(cmdLine, sizeof(CmdLine), 0, sizeof(CmdLine));
        ParseCmdLine(buf, cmdLine);
        DoCmd(cmdLine);
        (void)memset_s(buf, sizeof(char) * LOADCFG_BUF_SIZE, 0, sizeof(char) * LOADCFG_BUF_SIZE);
    }
S
sun_fan 已提交
794 795
    free(realPath);
    realPath = NULL;
M
mamingshuai 已提交
796 797 798 799
    free(cmdLine);
    fclose(fp);
}

Z
zhong_ning 已提交
800 801 802
static void DoWrite(const char *cmdContent)
{
    // format: write path content
S
sun_fan 已提交
803 804 805
    const int argsCount = 2;
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
    if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL || ctx->argc != argsCount) {
Z
zhong_ning 已提交
806
        INIT_LOGE("DoWrite: invalid arguments");
Z
zhong_ning 已提交
807 808
        goto out;
    }
S
sun_fan 已提交
809 810 811 812 813
    char *realPath = realpath(ctx->argv[0], NULL);
    if (realPath == NULL) {
        goto out;
    }
    int fd = open(realPath, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRWXU | S_IRGRP | S_IROTH);
Z
zhong_ning 已提交
814
    if (fd == -1) {
Z
zhong_ning 已提交
815
        INIT_LOGE("DoWrite: open %s failed: %d", ctx->argv[0], errno);
S
sun_fan 已提交
816 817
        free(realPath);
        realPath = NULL;
Z
zhong_ning 已提交
818 819 820 821 822
        goto out;
    }

    size_t ret = write(fd, ctx->argv[1], strlen(ctx->argv[1]));
    if (ret < 0) {
Z
zhong_ning 已提交
823
        INIT_LOGE("DoWrite: write to file %s failed: %d", ctx->argv[0], errno);
S
sun_fan 已提交
824 825
        free(realPath);
        realPath = NULL;
Z
zhong_ning 已提交
826 827 828
        close(fd);
        goto out;
    }
S
sun_fan 已提交
829 830
    free(realPath);
    realPath = NULL;
Z
zhong_ning 已提交
831 832 833 834 835 836 837 838 839
    close(fd);
out:
    FreeCmd(&ctx);
    return;
}

static void DoRmdir(const char *cmdContent)
{
    // format: rmdir path
S
sun_fan 已提交
840
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", 1);
Z
zhong_ning 已提交
841
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != 1) {
Z
zhong_ning 已提交
842
        INIT_LOGE("DoRmdir: invalid arguments");
Z
zhong_ning 已提交
843 844 845 846 847
        goto out;
    }

    int ret = rmdir(ctx->argv[0]);
    if (ret == -1) {
Z
zhong_ning 已提交
848
        INIT_LOGE("DoRmdir: remove %s failed: %d.", ctx->argv[0], errno);
Z
zhong_ning 已提交
849 850 851 852 853 854 855
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

Z
zhong_ning 已提交
856 857 858 859 860 861 862 863
static void DoSetrlimit(const char *cmdContent)
{
    char *resource[] = {
        "RLIMIT_CPU", "RLIMIT_FSIZE", "RLIMIT_DATA", "RLIMIT_STACK", "RLIMIT_CORE", "RLIMIT_RSS",
        "RLIMIT_NPROC", "RLIMIT_NOFILE", "RLIMIT_MEMLOCK", "RLIMIT_AS", "RLIMIT_LOCKS", "RLIMIT_SIGPENDING",
        "RLIMIT_MSGQUEUE", "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIM_NLIMITS"
    };
    // format: setrlimit resource curValue maxValue
S
sun_fan 已提交
864 865 866 867
    const int argsCount = 3;
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
    const int rlimMaxPos = 2;
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != argsCount) {
Z
zhong_ning 已提交
868
        INIT_LOGE("DoSetrlimit: invalid arguments");
Z
zhong_ning 已提交
869 870 871 872
        goto out;
    }

    struct rlimit limit;
S
sun_fan 已提交
873
    limit.rlim_cur = (rlim_t)atoi(ctx->argv[1]);
Z
zhong_ning 已提交
874
    limit.rlim_max = (rlim_t)atoi(ctx->argv[rlimMaxPos]);
Z
zhong_ning 已提交
875 876 877 878 879 880 881
    int rcs = -1;
    for (unsigned int i = 0 ; i < sizeof(resource) / sizeof(char*); ++i) {
        if (strcmp(ctx->argv[0], resource[i]) == 0) {
            rcs = (int)i;
        }
    }
    if (rcs == -1) {
Z
zhong_ning 已提交
882
        INIT_LOGE("DoSetrlimit failed, resouces :%s not support.", ctx->argv[0]);
Z
zhong_ning 已提交
883 884 885 886
        goto out;
    }
    int ret = setrlimit(rcs, &limit);
    if (ret) {
Z
zhong_ning 已提交
887
        INIT_LOGE("DoSetrlimit failed : %d", errno);
Z
zhong_ning 已提交
888 889 890 891 892 893 894
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

Z
zhong_ning 已提交
895 896 897
static void DoRm(const char *cmdContent)
{
    // format: rm /xxx/xxx/xxx
S
sun_fan 已提交
898
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", 1);
Z
zhong_ning 已提交
899
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != 1) {
Z
zhong_ning 已提交
900
        INIT_LOGE("DoRm: invalid arguments");
Z
zhong_ning 已提交
901 902 903 904
        goto out;
    }
    int ret = unlink(ctx->argv[0]);
    if (ret == -1) {
Z
zhong_ning 已提交
905
        INIT_LOGE("DoRm: unlink %s failed: %d.", ctx->argv[0], errno);
Z
zhong_ning 已提交
906 907 908 909 910 911 912 913 914 915
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

static void DoExport(const char *cmdContent)
{
    // format: export xxx /xxx/xxx/xxx
S
sun_fan 已提交
916 917 918
    const int argsCount = 2;
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != argsCount) {
Z
zhong_ning 已提交
919
        INIT_LOGE("DoExport: invalid arguments");
Z
zhong_ning 已提交
920 921 922 923
        goto out;
    }
    int ret = setenv(ctx->argv[0], ctx->argv[1], 1);
    if (ret != 0) {
Z
zhong_ning 已提交
924
        INIT_LOGE("DoExport: set %s with %s failed: %d", ctx->argv[0], ctx->argv[1], errno);
Z
zhong_ning 已提交
925 926 927 928 929 930 931 932 933 934 935
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

static void DoExec(const char *cmdContent)
{
    // format: exec /xxx/xxx/xxx xxx
    pid_t pid = fork();
Z
zhong_ning 已提交
936
    if (pid < 0) {
Z
zhong_ning 已提交
937
        INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent);
Z
zhong_ning 已提交
938 939
        return;
    }
Z
zhong_ning 已提交
940
    if (pid == 0) {
S
sun_fan 已提交
941 942 943
        int argsCount = 10;
        struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
        if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL) {
Z
zhong_ning 已提交
944
            INIT_LOGE("DoExec: invalid arguments");
Z
zhong_ning 已提交
945 946
            _exit(0x7f);
        }
Z
zhong_ning 已提交
947 948 949 950 951 952
#ifdef OHOS_LITE
        int ret = execve(ctx->argv[0], ctx->argv, NULL);
#else
        int ret = execv(ctx->argv[0], ctx->argv);
#endif
        if (ret == -1) {
Z
zhong_ning 已提交
953
            INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno);
Z
zhong_ning 已提交
954
        }
Z
zhong_ning 已提交
955 956
        FreeCmd(&ctx);
        _exit(0x7f);
Z
zhong_ning 已提交
957 958 959 960 961 962 963 964
    }
    return;
}

#ifndef __LITEOS__
static void DoSymlink(const char *cmdContent)
{
    // format: symlink /xxx/xxx/xxx /xxx/xxx/xxx
S
sun_fan 已提交
965 966 967
    const int argsCount = 2;
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != argsCount) {
Z
zhong_ning 已提交
968
        INIT_LOGE("DoSymlink: invalid arguments.");
Z
zhong_ning 已提交
969 970 971 972 973
        goto out;
    }

    int ret = symlink(ctx->argv[0], ctx->argv[1]);
    if (ret != 0) {
Z
zhong_ning 已提交
974
        INIT_LOGE("DoSymlink: link %s to %s failed: %d", ctx->argv[0], ctx->argv[1], errno);
Z
zhong_ning 已提交
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

static mode_t GetDeviceMode(const char *deviceStr)
{
    switch (*deviceStr) {
        case 'b':
        case 'B':
            return S_IFBLK;
        case 'c':
        case 'C':
            return S_IFCHR;
        case 'f':
        case 'F':
            return S_IFIFO;
        default:
            return -1;
    }
}

static void DoMakeNode(const char *cmdContent)
{
    // format: mknod path b 0644 1 9
S
sun_fan 已提交
1002 1003 1004 1005 1006 1007 1008 1009 1010
    const int argsCount = 5;
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
    const int deviceTypePos = 1;
    const int authorityPos = 2;
    const int majorDevicePos = 3;
    const int minorDevicePos = 4;
    const int decimal = 10;
    const int octal = 8;
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != argsCount) {
Z
zhong_ning 已提交
1011
        INIT_LOGE("DoMakeNode: invalid arguments");
Z
zhong_ning 已提交
1012 1013 1014 1015
        goto out;
    }

    if (!access(ctx->argv[1], F_OK)) {
Z
zhong_ning 已提交
1016
        INIT_LOGE("DoMakeNode failed, path has not sexisted");
Z
zhong_ning 已提交
1017 1018 1019 1020 1021 1022 1023 1024 1025
        goto out;
    }
    mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]);
    unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, decimal);
    unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, decimal);
    mode_t authority = strtoul(ctx->argv[authorityPos], NULL, octal);

    int ret = mknod(ctx->argv[0], deviceMode | authority, makedev(major, minor));
    if (ret != 0) {
Z
zhong_ning 已提交
1026
        INIT_LOGE("DoMakeNode: path: %s failed: %d", ctx->argv[0], errno);
Z
zhong_ning 已提交
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}

static void DoMakeDevice(const char *cmdContent)
{
    // format: makedev major minor
S
sun_fan 已提交
1037 1038 1039 1040
    const int argsCount = 2;
    struct CmdArgs *ctx = GetCmd(cmdContent, " ", argsCount);
    const int decimal = 10;
    if (ctx == NULL || ctx->argv == NULL || ctx->argc != argsCount) {
Z
zhong_ning 已提交
1041
        INIT_LOGE("DoMakedevice: invalid arugments");
Z
zhong_ning 已提交
1042 1043 1044 1045 1046 1047
        goto out;
    }
    unsigned int major = strtoul(ctx->argv[0], NULL, decimal);
    unsigned int minor = strtoul(ctx->argv[1], NULL, decimal);
    dev_t deviceId = makedev(major, minor);
    if (deviceId < 0) {
Z
zhong_ning 已提交
1048
        INIT_LOGE("DoMakedevice \" %s \" failed :%d ", cmdContent, errno);
Z
zhong_ning 已提交
1049 1050 1051 1052 1053 1054 1055 1056
        goto out;
    }
out:
    FreeCmd(&ctx);
    return;
}
#endif // __LITEOS__

W
wenjun 已提交
1057 1058
void DoCmd(const CmdLine* curCmd)
{
Z
zhong_ning 已提交
1059 1060
    // null curCmd or empty command, just quit.
    if (curCmd == NULL || curCmd->name[0] == '\0') {
W
wenjun 已提交
1061 1062
        return;
    }
Z
zhong_ning 已提交
1063 1064
    DoCmdByName(curCmd->name, curCmd->cmdContent);
}
W
wenjun 已提交
1065

Z
zhong_ning 已提交
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
void DoCmdByName(const char *name, const char *cmdContent)
{
    if (name == NULL || cmdContent == NULL) {
        return;
    }
    if (strncmp(name, "start ", strlen("start ")) == 0) {
        DoStart(cmdContent);
    } else if (strncmp(name, "mkdir ", strlen("mkdir ")) == 0) {
        DoMkDir(cmdContent);
    } else if (strncmp(name, "stop ", strlen("stop ")) == 0) {
        DoStop(cmdContent);
    } else if (strncmp(name, "reset ", strlen("reset ")) == 0) {
        DoReset(cmdContent);
    } else if (strncmp(name, "copy ", strlen("copy ")) == 0) {
        DoCopy(cmdContent);
    } else if (strncmp(name, "chmod ", strlen("chmod ")) == 0) {
        DoChmod(cmdContent);
    } else if (strncmp(name, "chown ", strlen("chown ")) == 0) {
        DoChown(cmdContent);
    } else if (strncmp(name, "mount ", strlen("mount ")) == 0) {
        DoMount(cmdContent);
    } else if (strncmp(name, "write ", strlen("write ")) == 0) {
        DoWrite(cmdContent);
    } else if (strncmp(name, "rmdir ", strlen("rmdir ")) == 0) {
        DoRmdir(cmdContent);
    } else if (strncmp(name, "rm ", strlen("rm ")) == 0) {
        DoRm(cmdContent);
    } else if (strncmp(name, "export ", strlen("export ")) == 0) {
        DoExport(cmdContent);
Z
zhong_ning 已提交
1095 1096
    } else if (strncmp(name, "setrlimit ", strlen("setrlimit ")) == 0) {
        DoSetrlimit(cmdContent);
Z
zhong_ning 已提交
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
    } else if (strncmp(name, "exec ", strlen("exec ")) == 0) {
        DoExec(cmdContent);
#ifndef __LITEOS__
    } else if (strncmp(name, "symlink ", strlen("symlink ")) == 0) {
        DoSymlink(cmdContent);
    } else if (strncmp(name, "makedev ", strlen("makedev ")) == 0) {
        DoMakeDevice(cmdContent);
    } else if (strncmp(name, "mknode ", strlen("mknode ")) == 0) {
        DoMakeNode(cmdContent);
#endif
    } else if (strncmp(name, "loadcfg ", strlen("loadcfg ")) == 0) {
        DoLoadCfg(cmdContent);
Z
zhong_ning 已提交
1109
#ifndef OHOS_LITE
Z
zhong_ning 已提交
1110 1111 1112
    } else if (strncmp(name, "insmod ", strlen("insmod ")) == 0) {
        DoInsmod(cmdContent);
    } else if (strncmp(name, "trigger ", strlen("trigger ")) == 0) {
Z
zhong_ning 已提交
1113
        INIT_LOGD("ready to trigger job: %s", name);
Z
zhong_ning 已提交
1114
        DoTriggerExec(cmdContent);
Z
zhong_ning 已提交
1115 1116
    } else if (strncmp(name, "load_persist_params ", strlen("load_persist_params ")) == 0) {
        LoadPersistParams();
Z
zhong_ning 已提交
1117 1118
    } else if (strncmp(name, "setparam ", strlen("setparam ")) == 0) {
        DoSetParam(cmdContent);
Z
zhong_ning 已提交
1119 1120
    } else if (strncmp(name, "load_param ", strlen("load_param ")) == 0) {
        LoadDefaultParams(cmdContent);
Z
zhong_ning 已提交
1121
#endif
Z
zhong_ning 已提交
1122 1123 1124
    } else if (strncmp(name, "reboot ", strlen("reboot ")) == 0) {
        DoReboot(cmdContent);
    }  else {
Z
zhong_ning 已提交
1125
        INIT_LOGE("DoCmd, unknown cmd name %s.", name);
W
wenjun 已提交
1126 1127
    }
}
M
mamingshuai 已提交
1128

Z
zhong_ning 已提交
1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
const char *GetMatchCmd(const char *cmdStr)
{
    if (cmdStr == NULL) {
        return NULL;
    }
    size_t supportCmdCnt = sizeof(g_supportedCmds) / sizeof(g_supportedCmds[0]);
    for (size_t i = 0; i < supportCmdCnt; ++i) {
        size_t curCmdNameLen = strlen(g_supportedCmds[i]);
        if (strncmp(g_supportedCmds[i], cmdStr, curCmdNameLen) == 0) {
            return g_supportedCmds[i];
        }
    }
    return NULL;
}