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)29 int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd)
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 OH_ListInit(&cmd->cmdExecutor);
47 }
48 if (execCmd == NULL) {
49 return 0;
50 }
51 PluginCmdExecutor *cmdExec = (PluginCmdExecutor *)calloc(1, sizeof(PluginCmdExecutor));
52 INIT_ERROR_CHECK(cmdExec != NULL, return -1, "Failed to create cmd listener");
53 OH_ListInit(&cmdExec->node);
54 cmdExec->id = ++g_cmdExecutorId;
55 cmdExec->execCmd = execCmd;
56 OH_ListAddTail(&cmd->cmdExecutor, &cmdExec->node);
57 return cmdExec->id;
58 }
59
RemoveCmdExecutor(const char * cmdName,int id)60 void RemoveCmdExecutor(const char *cmdName, int id)
61 {
62 INIT_ERROR_CHECK(cmdName != NULL, return, "Invalid input param");
63 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName);
64 INIT_ERROR_CHECK(groupNode != NULL && groupNode->data.cmd != NULL,
65 return, "Can not find cmd %s", cmdName);
66
67 PluginCmd *cmd = groupNode->data.cmd;
68 ListNode *node = cmd->cmdExecutor.next;
69 while (node != &cmd->cmdExecutor) {
70 PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node);
71 if (cmdExec->id == id) {
72 OH_ListRemove(&cmdExec->node);
73 free(cmdExec);
74 break;
75 }
76 node = node->next;
77 }
78 if (cmd->cmdExecutor.next != &cmd->cmdExecutor) {
79 return;
80 }
81 DelGroupNode(NODE_TYPE_CMDS, cmdName);
82 free(cmd);
83 }
84
PluginExecCmd_(PluginCmd * cmd,const char * cmdContent)85 void PluginExecCmd_(PluginCmd *cmd, const char *cmdContent)
86 {
87 const struct CmdArgs *ctx = GetCmdArg(cmdContent, " ", MAX_CMD_ARGC);
88 if (ctx == NULL) {
89 INIT_LOGE("Invalid arguments cmd: %s content: %s", cmd->name, cmdContent);
90 return;
91 } else if (ctx->argc > MAX_CMD_ARGC) {
92 INIT_LOGE("Invalid arguments cmd: %s content: %s argc: %d ",
93 cmd->name, cmdContent, ctx->argc);
94 FreeCmdArg((struct CmdArgs *)ctx);
95 return;
96 }
97 INIT_LOGV("PluginExecCmd_ index %s content: %s", cmd->name, cmdContent);
98 ListNode *node = cmd->cmdExecutor.next;
99 while (node != &cmd->cmdExecutor) {
100 PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node);
101 cmdExec->execCmd(cmdExec->id, cmd->name, ctx->argc, (const char **)ctx->argv);
102 node = node->next;
103 }
104 FreeCmdArg((struct CmdArgs *)ctx);
105 }
106
PluginExecCmdByName(const char * name,const char * cmdContent)107 void PluginExecCmdByName(const char *name, const char *cmdContent)
108 {
109 INIT_ERROR_CHECK(name != NULL, return, "Invalid cmd for %s", cmdContent);
110 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, name);
111 if (groupNode == NULL || groupNode->data.cmd == NULL) {
112 return;
113 }
114 PluginCmd *cmd = groupNode->data.cmd;
115 PluginExecCmd_(cmd, cmdContent);
116 }
117
PluginExecCmd(const char * name,int argc,const char ** argv)118 int PluginExecCmd(const char *name, int argc, const char **argv)
119 {
120 INIT_ERROR_CHECK(name != NULL, return -1, "Invalid cmd ");
121 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, name);
122 if (groupNode == NULL || groupNode->data.cmd == NULL) {
123 return -1;
124 }
125 PluginCmd *cmd = groupNode->data.cmd;
126 INIT_LOGV("PluginExecCmd index %s", cmd->name);
127 int ret = 0;
128 ListNode *node = cmd->cmdExecutor.next;
129 while (node != &cmd->cmdExecutor) {
130 PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node);
131 ret = cmdExec->execCmd(cmdExec->id, cmd->name, argc, argv);
132 node = node->next;
133 }
134 return ret;
135 }
136
CompareCmdId(const HashNode * node,const void * key)137 static int CompareCmdId(const HashNode *node, const void *key)
138 {
139 InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode);
140 if (groupNode == NULL || groupNode->data.cmd == NULL) {
141 return 1;
142 }
143 PluginCmd *cmd = groupNode->data.cmd;
144 return cmd->cmdId - *(int *)key;
145 }
146
GetPluginCmdByIndex(int index)147 static PluginCmd *GetPluginCmdByIndex(int index)
148 {
149 int hashCode = (((unsigned int)index >> 16) & 0x0000ffff) - 1; // 16 left shift
150 int cmdId = ((unsigned int)index & 0x0000ffff);
151 HashNode *node = OH_HashMapFind(GetGroupHashMap(NODE_TYPE_CMDS),
152 hashCode, (const void *)&cmdId, CompareCmdId);
153 if (node == NULL) {
154 return NULL;
155 }
156 InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode);
157 if (groupNode == NULL || groupNode->data.cmd == NULL) {
158 return NULL;
159 }
160 return groupNode->data.cmd;
161 }
162
GetPluginCmdNameByIndex(int index)163 const char *GetPluginCmdNameByIndex(int index)
164 {
165 PluginCmd *cmd = GetPluginCmdByIndex(index);
166 if (cmd == NULL) {
167 return NULL;
168 }
169 return cmd->name;
170 }
171
PluginExecCmdByCmdIndex(int index,const char * cmdContent)172 void PluginExecCmdByCmdIndex(int index, const char *cmdContent)
173 {
174 PluginCmd *cmd = GetPluginCmdByIndex(index);
175 if (cmd == NULL) {
176 INIT_LOGW("Cannot find plugin command with index %d", index);
177 return;
178 }
179 INIT_LOGV("Command: %s cmdContent: %s", cmd->name, cmdContent);
180 PluginExecCmd_(cmd, cmdContent);
181 }
182
PluginGetCmdIndex(const char * cmdStr,int * index)183 const char *PluginGetCmdIndex(const char *cmdStr, int *index)
184 {
185 char cmdName[MAX_CMD_NAME_LEN] = {};
186 int i = 0;
187 while ((i < MAX_CMD_NAME_LEN) && (*(cmdStr + i) != '\0') && (*(cmdStr + i) != ' ')) {
188 cmdName[i] = *(cmdStr + i);
189 i++;
190 }
191 if (i >= MAX_CMD_NAME_LEN) {
192 return NULL;
193 }
194 cmdName[i] = '\0';
195 InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName);
196 if (groupNode == NULL || groupNode->data.cmd == NULL) {
197 AddCmdExecutor(cmdName, NULL);
198 }
199 groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName);
200 INIT_ERROR_CHECK(groupNode != NULL && groupNode->data.cmd != NULL,
201 return NULL, "Failed to create pluginCmd %s", cmdName);
202
203 PluginCmd *cmd = groupNode->data.cmd;
204 int hashCode = GenerateHashCode(cmdName);
205 hashCode = (hashCode < 0) ? -hashCode : hashCode;
206 hashCode = hashCode % GROUP_HASHMAP_BUCKET;
207 *index = ((hashCode + 1) << 16) | cmd->cmdId; // 16 left shift
208 return cmd->name;
209 }
210