1/*
2* Copyright (c) 2022 Huawei Device Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7*     http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15#include <errno.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <grp.h>
19#include <pwd.h>
20#include <dirent.h>
21
22#include "begetctl.h"
23#include "init_utils.h"
24#include "init_param.h"
25#include "securec.h"
26#include "shell_utils.h"
27#include "parameter.h"
28
29#define BEGETCTRL_INIT_CMD "ohos.servicectrl.cmd"
30
31/**
32 * @brief 通用的命令通道,注册函数完成参数校验,调用HandleCmd进行处理
33 * init进程使用 initCmd 按命令字进行处理
34 */
35static int HandleCmd(BShellHandle shell, const char *cmdName, int argc, char **argv)
36{
37    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
38    BSH_LOGI("initCmd %s argc %d", cmdName, argc);
39    // format args
40    if (argc == 0) {
41        return SystemSetParameter(BEGETCTRL_INIT_CMD, cmdName);
42    }
43    char value[PARAM_VALUE_LEN_MAX] = { 0 };
44    int ret = sprintf_s(value, sizeof(value) - 1, "%s ", cmdName);
45    BSH_CHECK(ret > 0, return BSH_INVALID_PARAM, "Failed to format cmdName");
46    for (int i = 0; i < argc; i++) {
47        ret = strcat_s(value, sizeof(value), argv[i]);
48        BSH_CHECK(ret == 0, return BSH_INVALID_PARAM, "Failed to format name");
49        ret = strcat_s(value, sizeof(value), " ");
50        BSH_CHECK(ret == 0, return BSH_INVALID_PARAM, "Failed to format name");
51    }
52    return SystemSetParameter(BEGETCTRL_INIT_CMD, value);
53}
54
55static int SetInitLogLevelFromParam(BShellHandle shell, int argc, char **argv)
56{
57    if (argc != 2) { // 2 is set log level parameter number
58        char *helpArgs[] = {"set", NULL};
59        BShellCmdHelp(shell, 1, helpArgs);
60        return 0;
61    }
62    errno = 0;
63    unsigned int level = strtoul(argv[1], 0, 10); // 10 is decimal
64    if (errno != 0) {
65        printf("Failed to transform %s to unsigned int. \n", argv[1]);
66        return -1;
67    }
68    if ((level >= INIT_DEBUG) && (level <= INIT_FATAL)) {
69        const char *logLevelStr[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" };
70        int ret = HandleCmd(shell, "setloglevel", argc - 1, &argv[1]);
71        if (ret != 0) {
72            printf("Failed to set log level %s. \n", logLevelStr[level]);
73        } else {
74            printf("Success to set log level %s. \n", logLevelStr[level]);
75        }
76    } else {
77        printf("%s is invalid. \n", argv[1]);
78    }
79    return 0;
80}
81
82static int32_t GetInitLogLevelFromParam(BShellHandle shell, int argc, char **argv)
83{
84    int level = GetIntParameter(INIT_DEBUG_LEVEL, (int)INIT_ERROR);
85    if ((level >= INIT_DEBUG) && (level <= INIT_FATAL)) {
86        const char *logLevelStr[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" };
87        printf("Init log level: %s \n", logLevelStr[level]);
88    }
89    return 0;
90}
91
92static int32_t GetUidByName(BShellHandle shell, int argc, char **argv)
93{
94    if (argc != 2) { // 2 is dac get uid parameter number
95        char *helpArgs[] = {"dac", NULL};
96        BShellCmdHelp(shell, 1, helpArgs);
97        return 0;
98    }
99    struct passwd *data = getpwnam(argv[1]);
100    if (data == NULL) {
101        printf("getpwnam uid failed\n");
102    } else {
103        printf("getpwnam uid %s : %u\n", argv[1], data->pw_uid);
104    }
105
106    data = NULL;
107    while ((data = getpwent()) != NULL) {
108        if ((data->pw_name != NULL) && (strcmp(data->pw_name, argv[1]) == 0)) {
109            printf("getpwent uid %s : %u\n", argv[1], data->pw_uid);
110            break;
111        }
112    }
113    endpwent();
114    return 0;
115}
116
117static void ShowUserInGroup(struct group *data)
118{
119    int index = 0;
120    printf("users in this group:");
121    while (data->gr_mem[index]) { // user in this group
122        printf(" %s", data->gr_mem[index]);
123        index++;
124    }
125    printf("\n");
126    return;
127}
128
129static int32_t GetGidByName(BShellHandle shell, int argc, char **argv)
130{
131    if (argc != 2) { // 2 is dac get gid parameter number
132        char *helpArgs[] = {"dac", NULL};
133        BShellCmdHelp(shell, 1, helpArgs);
134        return 0;
135    }
136    struct group *data = getgrnam(argv[1]);
137    if (data == NULL) {
138        printf("getgrnam gid failed\n");
139    } else {
140        printf("getgrnam gid %s : %u\n", argv[1], data->gr_gid);
141        ShowUserInGroup(data);
142    }
143
144    data = NULL;
145    while ((data = getgrent()) != NULL) {
146        if ((data->gr_name != NULL) && (strcmp(data->gr_name, argv[1]) == 0)) {
147            printf("getgrent gid %s : %u\n", argv[1], data->gr_gid);
148            ShowUserInGroup(data);
149            break;
150        }
151    }
152    endgrent();
153    return 0;
154}
155
156MODULE_CONSTRUCTOR(void)
157{
158    const CmdInfo infos[] = {
159        {"set", SetInitLogLevelFromParam,
160            "set init log level 0:debug, 1:info, 2:warning, 3:err, 4:fatal", "set log level", "set log level"},
161        {"get", GetInitLogLevelFromParam, "get init log level", "get log level", "get log level"},
162        {"dac", GetGidByName, "get dac gid by group name", "dac gid groupname", "dac gid"},
163        {"dac", GetUidByName, "get dac uid by user name", "dac uid username", "dac uid"},
164    };
165    for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) {
166        BShellEnvRegisterCmd(GetShellHandle(), &infos[i]);
167    }
168}