1 /*
2 * Copyright (c) 2021 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
16 #include "cJSON.h"
17 #include "init_param.h"
18 #include "init_utils.h"
19 #include "init_log.h"
20 #include "init_group_manager.h"
21 #include "init_service_manager.h"
22 #include "securec.h"
23 #include "modulemgr.h"
24 #include "init_module_engine.h"
25
26 #define MAX_CMD_ARGC 10
27 static int g_cmdExecutorId = 0;
28 static int g_cmdId = 0;
AddCmdExecutor_(const char * cmdName,CmdExecutor execCmd,int careContext)29 int AddCmdExecutor_(const char *cmdName, CmdExecutor execCmd, int careContext)
30 {
31 INIT_ERROR_CHECK(cmdName != NULL, return -1, "Invalid input param");
32 INIT_LOGV("Add command '%s' executor.", cmdName);
33 PluginCmd *cmd = NULL;
34 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName);
35 if (groupNode == NULL) {
36 groupNode = AddGroupNode(NODE_TYPE_CMDS, cmdName);
37 INIT_ERROR_CHECK(groupNode != NULL, return -1, "Failed to create group node");
38 }
39 cmd = groupNode->data.cmd;
40 if (cmd == NULL) {
41 cmd = (PluginCmd *)calloc(1, sizeof(PluginCmd));
42 INIT_ERROR_CHECK(cmd != NULL, return -1, "Failed to create cmd condition");
43 groupNode->data.cmd = cmd;
44 cmd->cmdId = g_cmdId++;
45 cmd->name = groupNode->name;
46 cmd->careContext = careContext;
47 OH_ListInit(&cmd->cmdExecutor);
48 }
49 if (execCmd == NULL) {
50 return 0;
51 }
52 PluginCmdExecutor *cmdExec = (PluginCmdExecutor *)calloc(1, sizeof(PluginCmdExecutor));
53 INIT_ERROR_CHECK(cmdExec != NULL, return -1, "Failed to create cmd listener");
54 OH_ListInit(&cmdExec->node);
55 cmdExec->id = ++g_cmdExecutorId;
56 cmdExec->execCmd = execCmd;
57 OH_ListAddTail(&cmd->cmdExecutor, &cmdExec->node);
58 return cmdExec->id;
59 }
60
AddCareContextCmdExecutor(const char * cmdName,CmdExecutor execCmd)61 int AddCareContextCmdExecutor(const char *cmdName, CmdExecutor execCmd)
62 {
63 return AddCmdExecutor_(cmdName, execCmd, 1);
64 }
65
AddCmdExecutor(const char * cmdName,CmdExecutor execCmd)66 int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd)
67 {
68 return AddCmdExecutor_(cmdName, execCmd, 0);
69 }
70
RemoveCmdExecutor(const char * cmdName,int id)71 void RemoveCmdExecutor(const char *cmdName, int id)
72 {
73 INIT_ERROR_CHECK(cmdName != NULL, return, "Invalid input param");
74 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName);
75 INIT_ERROR_CHECK(groupNode != NULL && groupNode->data.cmd != NULL,
76 return, "Can not find cmd %s", cmdName);
77
78 PluginCmd *cmd = groupNode->data.cmd;
79 ListNode *node = cmd->cmdExecutor.next;
80 while (node != &cmd->cmdExecutor) {
81 PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node);
82 if (cmdExec->id == id) {
83 OH_ListRemove(&cmdExec->node);
84 free(cmdExec);
85 break;
86 }
87 node = node->next;
88 }
89 if (cmd->cmdExecutor.next != &cmd->cmdExecutor) {
90 return;
91 }
92 DelGroupNode(NODE_TYPE_CMDS, cmdName);
93 free(cmd);
94 }
95
PluginExecCmd_(PluginCmd * cmd,const char * cmdContent)96 static void PluginExecCmd_(PluginCmd *cmd, const char *cmdContent)
97 {
98 const struct CmdArgs *ctx = GetCmdArg(cmdContent, " ", MAX_CMD_ARGC);
99 if (ctx == NULL) {
100 INIT_LOGE("Invalid arguments cmd: %s content: %s", cmd->name, cmdContent);
101 return;
102 } else if (ctx->argc > MAX_CMD_ARGC) {
103 INIT_LOGE("Invalid arguments cmd: %s content: %s argc: %d ",
104 cmd->name, cmdContent, ctx->argc);
105 FreeCmdArg((struct CmdArgs *)ctx);
106 return;
107 }
108 INIT_LOGV("PluginExecCmd_ index %s content: %s", cmd->name, cmdContent);
109 ListNode *node = cmd->cmdExecutor.next;
110 while (node != &cmd->cmdExecutor) {
111 PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node);
112 cmdExec->execCmd(cmdExec->id, cmd->name, ctx->argc, (const char **)ctx->argv);
113 node = node->next;
114 }
115 FreeCmdArg((struct CmdArgs *)ctx);
116 }
117
PluginExecCmdByName(const char * name,const char * cmdContent)118 void PluginExecCmdByName(const char *name, const char *cmdContent)
119 {
120 INIT_ERROR_CHECK(name != NULL, return, "Invalid cmd for %s", cmdContent);
121 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, name);
122 if (groupNode == NULL || groupNode->data.cmd == NULL) {
123 return;
124 }
125 PluginCmd *cmd = groupNode->data.cmd;
126 PluginExecCmd_(cmd, cmdContent);
127 }
128
PluginExecCmd(const char * name,int argc,const char ** argv)129 int PluginExecCmd(const char *name, int argc, const char **argv)
130 {
131 INIT_ERROR_CHECK(name != NULL, return -1, "Invalid cmd ");
132 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, name);
133 if (groupNode == NULL || groupNode->data.cmd == NULL) {
134 return -1;
135 }
136 PluginCmd *cmd = groupNode->data.cmd;
137 INIT_LOGV("PluginExecCmd index %s", cmd->name);
138 int ret = 0;
139 ListNode *node = cmd->cmdExecutor.next;
140 while (node != &cmd->cmdExecutor) {
141 PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node);
142 ret = cmdExec->execCmd(cmdExec->id, cmd->name, argc, argv);
143 node = node->next;
144 }
145 return ret;
146 }
147
CompareCmdId(const HashNode * node,const void * key)148 static int CompareCmdId(const HashNode *node, const void *key)
149 {
150 InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode);
151 if (groupNode == NULL || groupNode->data.cmd == NULL) {
152 return 1;
153 }
154 PluginCmd *cmd = groupNode->data.cmd;
155 return cmd->cmdId - *(int *)key;
156 }
157
GetPluginCmdByIndex(int index)158 static PluginCmd *GetPluginCmdByIndex(int index)
159 {
160 int hashCode = (((unsigned int)index >> 16) & 0x0000ffff) - 1; // 16 left shift
161 int cmdId = ((unsigned int)index & 0x0000ffff);
162 HashNode *node = OH_HashMapFind(GetGroupHashMap(NODE_TYPE_CMDS),
163 hashCode, (const void *)&cmdId, CompareCmdId);
164 if (node == NULL) {
165 return NULL;
166 }
167 InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode);
168 if (groupNode == NULL || groupNode->data.cmd == NULL) {
169 return NULL;
170 }
171 return groupNode->data.cmd;
172 }
173
GetPluginCmdNameByIndex(int index)174 const char *GetPluginCmdNameByIndex(int index)
175 {
176 PluginCmd *cmd = GetPluginCmdByIndex(index);
177 if (cmd == NULL) {
178 return NULL;
179 }
180 return cmd->name;
181 }
182
PluginExecCmdByCmdIndex(int index,const char * cmdContent,const ConfigContext * context)183 void PluginExecCmdByCmdIndex(int index, const char *cmdContent, const ConfigContext *context)
184 {
185 PluginCmd *cmd = GetPluginCmdByIndex(index);
186 if (cmd == NULL) {
187 INIT_LOGW("Cannot find plugin command with index %d", index);
188 return;
189 }
190 INIT_LOGV("Command: %s cmdContent: %s %d", cmd->name, cmdContent, cmd->careContext);
191 if (!cmd->careContext || !CheckExecuteInSubInit(context)) {
192 PluginExecCmd_(cmd, cmdContent);
193 } else {
194 ExecuteCmdInSubInit(context, cmd->name, cmdContent);
195 }
196 }
197
PluginGetCmdIndex(const char * cmdStr,int * index)198 const char *PluginGetCmdIndex(const char *cmdStr, int *index)
199 {
200 char cmdName[MAX_CMD_NAME_LEN] = {};
201 int i = 0;
202 while ((i < MAX_CMD_NAME_LEN) && (*(cmdStr + i) != '\0') && (*(cmdStr + i) != ' ')) {
203 cmdName[i] = *(cmdStr + i);
204 i++;
205 }
206 if (i >= MAX_CMD_NAME_LEN) {
207 return NULL;
208 }
209 cmdName[i] = '\0';
210 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName);
211 if (groupNode == NULL || groupNode->data.cmd == NULL) {
212 AddCmdExecutor(cmdName, NULL);
213 }
214 groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName);
215 INIT_ERROR_CHECK(groupNode != NULL && groupNode->data.cmd != NULL,
216 return NULL, "Failed to create pluginCmd %s", cmdName);
217
218 PluginCmd *cmd = groupNode->data.cmd;
219 int hashCode = GenerateHashCode(cmdName);
220 hashCode = (hashCode < 0) ? -hashCode : hashCode;
221 hashCode = hashCode % GROUP_HASHMAP_BUCKET;
222 *index = ((hashCode + 1) << 16) | cmd->cmdId; // 16 left shift
223 return cmd->name;
224 }
225