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 
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <unistd.h>
20 
21 #include "control_fd.h"
22 #include "init_service.h"
23 #include "init_service_manager.h"
24 #include "init_modulemgr.h"
25 #include "init_utils.h"
26 #include "init_log.h"
27 #include "init_group_manager.h"
28 #include "init_param.h"
29 #include "hookmgr.h"
30 #include "bootstage.h"
31 #include "le_task.h"
32 #include "loop_event.h"
33 #include "init_hashmap.h"
34 #include "le_loop.h"
35 
DumpLoopNodeInfo(const HashNode * node,const void * context)36 static void DumpLoopNodeInfo(const HashNode *node, const void *context)
37 {
38     INIT_CHECK(node != NULL, return);
39     BaseTask *baseTask =  HASHMAP_ENTRY(node, BaseTask, hashNode);
40     INIT_CHECK(baseTask != NULL, return);
41     const TaskHandle task = (void*)baseTask;
42     if (baseTask->dumpTaskInfo != NULL) {
43         baseTask->dumpTaskInfo(task);
44     }
45 }
46 
DumpLoop()47 static void DumpLoop()
48 {
49     printf("  Dump Loop Info:\n");
50     OH_HashMapTraverse(((EventLoop *)LE_GetDefaultLoop())->taskMap, DumpLoopNodeInfo, NULL);
51 }
52 
DumpServiceArgs(const char * info,const ServiceArgs * args)53 static void DumpServiceArgs(const char *info, const ServiceArgs *args)
54 {
55     printf("\tservice %s count %d \n", info, args->count);
56     for (int j = 0; j < args->count; j++) {
57         if (args->argv[j] != NULL) {
58             printf("\t\tinfo [%d] %s \n", j, args->argv[j]);
59         }
60     }
61 }
62 
DumpServiceJobs(const Service * service)63 static void DumpServiceJobs(const Service *service)
64 {
65     printf("\tservice job info \n");
66     if (service->serviceJobs.jobsName[JOB_ON_BOOT] != NULL) {
67         printf("\t\tservice boot job %s \n", service->serviceJobs.jobsName[JOB_ON_BOOT]);
68     }
69     if (service->serviceJobs.jobsName[JOB_PRE_START]!= NULL) {
70         printf("\t\tservice pre-start job %s \n", service->serviceJobs.jobsName[JOB_PRE_START]);
71     }
72     if (service->serviceJobs.jobsName[JOB_ON_START] != NULL) {
73         printf("\t\tservice start job %s \n", service->serviceJobs.jobsName[JOB_ON_START]);
74     }
75     if (service->serviceJobs.jobsName[JOB_ON_STOP] != NULL) {
76         printf("\t\tservice stop job %s \n", service->serviceJobs.jobsName[JOB_ON_STOP]);
77     }
78     if (service->serviceJobs.jobsName[JOB_ON_RESTART] != NULL) {
79         printf("\t\tservice restart job %s \n", service->serviceJobs.jobsName[JOB_ON_RESTART]);
80     }
81 }
82 
DumpServiceSocket(const Service * service)83 static void DumpServiceSocket(const Service *service)
84 {
85     printf("\tservice socket info \n");
86     ServiceSocket *sockopt = service->socketCfg;
87     while (sockopt != NULL) {
88         printf("\t\tsocket fd: %d \n", sockopt->sockFd);
89         printf("\t\tsocket name: %s \n", sockopt->name);
90         printf("\t\tsocket type: %u \n", sockopt->type);
91         printf("\t\tsocket uid: %u \n", sockopt->uid);
92         printf("\t\tsocket gid: %u \n", sockopt->gid);
93         sockopt = sockopt->next;
94     }
95 }
96 
DumpServiceHookExecute(const char * name,const char * info)97 void DumpServiceHookExecute(const char *name, const char *info)
98 {
99     SERVICE_INFO_CTX context;
100     context.serviceName = name;
101     context.reserved = info;
102     (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&context), NULL);
103 }
104 
DumpOneService(const Service * service)105 static void DumpOneService(const Service *service)
106 {
107     static const struct InitErrMap initErrMaps[] = {
108         {INIT_OK, ""},
109 #define XX(code, info) {INIT_ ## code, info},
110         INIT_ERRNO_MAP(XX)
111 #undef XX
112         {INIT_OK, ""}
113     };
114 
115     const InitArgInfo startModeMap[] = {
116         {"condition", START_MODE_CONDITION},
117         {"boot", START_MODE_BOOT},
118         {"normal", START_MODE_NORMAL}
119     };
120 
121     const static char *serviceStatusMap[] = {
122         "created", "starting", "running", "ready",
123         "stopping", "stopped", "suspended", "freezed", "disabled", "critical"
124     };
125 
126     printf("\tservice name: [%s] \n", service->name);
127     printf("\tservice pid: [%d] \n", service->pid);
128     int tmpCount = sizeof(initErrMaps) / sizeof(initErrMaps[0]);
129     if ((int)service->lastErrno < tmpCount) {
130         printf("\tservice last error: %s(%d) \n", initErrMaps[service->lastErrno].info, service->lastErrno);
131     } else {
132         printf("\tservice last error: %d \n", service->lastErrno);
133     }
134     printf("\tservice context : [%s] \n", (service->context.type == INIT_CONTEXT_CHIPSET) ? "chipset" : "system");
135     printf("\tservice crashCnt: [%d] \n", service->crashCnt);
136     printf("\tservice attribute: [%u] \n", service->attribute);
137     printf("\tservice importance: [%d] \n", service->importance);
138     printf("\tservice startMode: [%s] \n", startModeMap[service->startMode].name);
139     printf("\tservice status: [%s] \n", serviceStatusMap[service->status]);
140     printf("\tservice perms uID [%u] \n", service->servPerm.uID);
141     printf("\tservice Timer ID [%d] \n", LE_GetSocketFd(service->timer));
142     DumpServiceArgs("path arg", &service->pathArgs);
143     DumpServiceArgs("writepid file", &service->writePidArgs);
144     DumpServiceJobs(service);
145     DumpServiceSocket(service);
146 
147     printf("\tservice perms groupId %d \n", service->servPerm.gIDCnt);
148     for (int i = 0; i < service->servPerm.gIDCnt; i++) {
149         printf("\t\tservice perms groupId %u \n", service->servPerm.gIDArray[i]);
150     }
151     printf("\tservice perms capability %u \n", service->servPerm.capsCnt);
152     for (int i = 0; i < (int)service->servPerm.capsCnt; i++) {
153         printf("\t\tservice perms capability %u \n", service->servPerm.caps[i]);
154     }
155 
156     DumpServiceHookExecute(service->name, NULL);
157 }
158 
PrintBootEventHead(const char * cmd)159 static void PrintBootEventHead(const char *cmd)
160 {
161     if (strcmp(cmd, "bootevent") == 0) {
162         printf("\t%-20.20s\t%-50s\t%-20.20s\t%-20.20s\n",
163             "service-name", "bootevent-name", "fork", "ready");
164     }
165     return;
166 }
167 
DumpAllExtData(const char * cmd)168 static void DumpAllExtData(const char *cmd)
169 {
170     PrintBootEventHead(cmd);
171     InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
172     while (node != NULL) {
173         if (node->data.service == NULL) {
174             node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
175             continue;
176         }
177         DumpServiceHookExecute(node->name, cmd);
178         node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
179     }
180 }
181 
DumpAllServices(void)182 static void DumpAllServices(void)
183 {
184     printf("Ready to dump all services: \n");
185     InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
186     while (node != NULL) {
187         if (node->data.service == NULL) {
188             node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
189             continue;
190         }
191         Service *service = node->data.service;
192         DumpOneService(service);
193         node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
194     }
195     printf("Dump all services finished \n");
196 }
197 
ProcessSandboxControlFd(uint16_t type,const char * serviceCmd)198 static void ProcessSandboxControlFd(uint16_t type, const char *serviceCmd)
199 {
200     if ((type != ACTION_SANDBOX) || (serviceCmd == NULL)) {
201         INIT_LOGE("Invalid parameter");
202         return;
203     }
204     Service *service  = GetServiceByName(serviceCmd);
205     if (service == NULL) {
206         INIT_LOGE("Failed get service %s", serviceCmd);
207         return;
208     }
209     EnterServiceSandbox(service);
210     return;
211 }
212 
ProcessDumpServiceControlFd(uint16_t type,const char * serviceCmd)213 static void ProcessDumpServiceControlFd(uint16_t type, const char *serviceCmd)
214 {
215     if ((type != ACTION_DUMP) || (serviceCmd == NULL)) {
216         return;
217     }
218     char *cmd = strrchr(serviceCmd, '#');
219     if (cmd != NULL) {
220         cmd[0] = '\0';
221         cmd++;
222     }
223 
224     if (strcmp(serviceCmd, "all") == 0) {
225         if (cmd != NULL) {
226             DumpAllExtData(cmd);
227         } else {
228             DumpAllServices();
229         }
230         return;
231     }
232     if (strcmp(serviceCmd, "parameter_service") == 0) {
233         if (cmd != NULL && strcmp(cmd, "trigger") == 0) {
234             SystemDumpTriggers(0, printf);
235         } else {
236             SystemDumpParameters(0, 0, printf);
237         }
238         return;
239     }
240     if (strcmp(serviceCmd, "loop") == 0) {
241         DumpLoop();
242         return;
243     }
244     Service *service  = GetServiceByName(serviceCmd);
245     if (service != NULL) {
246         if (cmd != NULL) {
247             PrintBootEventHead(cmd);
248             DumpServiceHookExecute(serviceCmd, cmd);
249         } else {
250             DumpOneService(service);
251         }
252     }
253     return;
254 }
255 
ProcessModuleMgrControlFd(uint16_t type,const char * serviceCmd)256 static void ProcessModuleMgrControlFd(uint16_t type, const char *serviceCmd)
257 {
258     if ((type != ACTION_MODULEMGR) || (serviceCmd == NULL)) {
259         return;
260     }
261     INIT_LOGE("ProcessModuleMgrControlFd argc [%s] \n", serviceCmd);
262     if (strcmp(serviceCmd, "list") == 0) {
263         InitModuleMgrDump();
264         return;
265     }
266 }
267 
ProcessControlFd(uint16_t type,const char * serviceCmd,const void * context)268 void ProcessControlFd(uint16_t type, const char *serviceCmd, const void *context)
269 {
270     if ((type >= ACTION_MAX) || (serviceCmd == NULL)) {
271         return;
272     }
273     switch (type) {
274         case ACTION_SANDBOX :
275             ProcessSandboxControlFd(type, serviceCmd);
276             break;
277         case ACTION_DUMP :
278             ProcessDumpServiceControlFd(type, serviceCmd);
279             break;
280         case ACTION_MODULEMGR :
281             ProcessModuleMgrControlFd(type, serviceCmd);
282             break;
283         default :
284             INIT_LOGW("Unknown control fd type.");
285             break;
286     }
287 }
288 
InitControlFd(void)289 void InitControlFd(void)
290 {
291     CmdServiceInit(INIT_CONTROL_FD_SOCKET_PATH, ProcessControlFd, LE_GetDefaultLoop());
292     return;
293 }
294