• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-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 #include "init_service_manager.h"
16 
17 #include <limits.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/socket.h>
21 #include <sys/wait.h>
22 #include <unistd.h>
23 
24 #include "cJSON.h"
25 #include "init.h"
26 #include "init_group_manager.h"
27 #include "init_jobs_internal.h"
28 #include "init_log.h"
29 #include "init_service_file.h"
30 #include "init_service_socket.h"
31 #include "init_utils.h"
32 #include "securec.h"
33 #include "service_control.h"
34 
35 #ifdef WITH_SELINUX
36 #   include "init_selinux_param.h"
37 #endif // WITH_SELINUX
38 
39 // All serivce processes that init will fork+exec.
40 static ServiceSpace g_serviceSpace = { 0 };
41 static const int CRITICAL_DEFAULT_CRASH_TIME = 20;
42 // maximum number of crashes within time CRITICAL_DEFAULT_CRASH_TIME for one service
43 static const int CRITICAL_DEFAULT_CRASH_COUNT =  4;
44 static const int CRITICAL_CONFIG_ARRAY_LEN = 3;
45 
46 #ifdef OHOS_SERVICE_DUMP
DumpServiceArgs(const char * info,const ServiceArgs * args)47 static void DumpServiceArgs(const char *info, const ServiceArgs *args)
48 {
49     INIT_LOGI("\tservice %s count %d", info, args->count);
50     for (int j = 0; j < args->count; j++) {
51         if (args->argv[j] != NULL) {
52             INIT_LOGI("\t\tinfo [%d] %s", j, args->argv[j]);
53         }
54     }
55 }
56 
DumpServiceJobs(const Service * service)57 static void DumpServiceJobs(const Service *service)
58 {
59     INIT_LOGI("\tservice job info");
60     if (service->serviceJobs.jobsName[JOB_ON_BOOT] != NULL) {
61         INIT_LOGI("\t\tservice boot job %s", service->serviceJobs.jobsName[JOB_ON_BOOT]);
62     }
63     if (service->serviceJobs.jobsName[JOB_ON_START] != NULL) {
64         INIT_LOGI("\t\tservice start job %s", service->serviceJobs.jobsName[JOB_ON_START]);
65     }
66     if (service->serviceJobs.jobsName[JOB_ON_STOP] != NULL) {
67         INIT_LOGI("\t\tservice stop job %s", service->serviceJobs.jobsName[JOB_ON_STOP]);
68     }
69     if (service->serviceJobs.jobsName[JOB_ON_RESTART] != NULL) {
70         INIT_LOGI("\t\tservice restart job %s", service->serviceJobs.jobsName[JOB_ON_RESTART]);
71     }
72 }
73 
DumpServiceSocket(const Service * service)74 static void DumpServiceSocket(const Service *service)
75 {
76     INIT_LOGI("\tservice socket info");
77     ServiceSocket *sockopt = service->socketCfg;
78     while (sockopt != NULL) {
79         INIT_LOGI("\t\tsocket name: %s", sockopt->name);
80         INIT_LOGI("\t\tsocket type: %d", sockopt->type);
81         INIT_LOGI("\t\tsocket uid: %d", sockopt->uid);
82         INIT_LOGI("\t\tsocket gid: %d", sockopt->gid);
83         sockopt = sockopt->next;
84     }
85 }
86 
DumpAllServices()87 void DumpAllServices()
88 {
89     const InitArgInfo startModeMap[] = {
90         {"condition", START_MODE_CONDITION},
91         {"boot", START_MODE_BOOT},
92         {"normal", START_MODE_NARMAL}
93     };
94     int size = 0;
95     const InitArgInfo *statusMap = GetServieStatusMap(&size);
96     INIT_LOGI("Ready to dump all services:");
97     INIT_LOGI("total service number: %d", g_serviceSpace.serviceCount);
98     InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
99     while (node != NULL) {
100         if (node->data.service == NULL) {
101             node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
102             continue;
103         }
104         Service *service = node->data.service;
105         INIT_LOGI("\tservice name: [%s]", service->name);
106         INIT_LOGI("\tservice pid: [%d]", service->pid);
107         INIT_LOGI("\tservice crashCnt: [%d]", service->crashCnt);
108         INIT_LOGI("\tservice attribute: [%d]", service->attribute);
109         INIT_LOGI("\tservice importance: [%d]", service->importance);
110         INIT_LOGI("\tservice startMode: [%s]", startModeMap[service->status].name);
111         INIT_LOGI("\tservice status: [%s]", statusMap[service->status].name);
112         INIT_LOGI("\tservice perms uID [%d]", service->servPerm.uID);
113         DumpServiceArgs("path arg", &service->pathArgs);
114         DumpServiceArgs("writepid file", &service->writePidArgs);
115         DumpServiceJobs(service);
116         DumpServiceSocket(service);
117 
118         INIT_LOGI("\tservice perms groupId %d", service->servPerm.gIDCnt);
119         for (int i = 0; i < service->servPerm.gIDCnt; i++) {
120             INIT_LOGI("\t\tservice perms groupId %d", service->servPerm.gIDArray[i]);
121         }
122         INIT_LOGI("\tservice perms capability %d", service->servPerm.capsCnt);
123         for (int i = 0; i < (int)service->servPerm.capsCnt; i++) {
124             INIT_LOGI("\t\tservice perms capability %d", service->servPerm.caps[i]);
125         }
126         node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
127     }
128     INIT_LOGI("Dump all services finished");
129 }
130 #endif
131 
FreeServiceArg(ServiceArgs * arg)132 static void FreeServiceArg(ServiceArgs *arg)
133 {
134     if (arg == NULL) {
135         return;
136     }
137     for (int i = 0; i < arg->count; ++i) {
138         if (arg->argv[i] != NULL) {
139             free(arg->argv[i]);
140             arg->argv[i] = NULL;
141         }
142     }
143     free(arg->argv);
144     arg->argv = NULL;
145     arg->count = 0;
146 }
147 
FreeServiceSocket(ServiceSocket * sockopt)148 static void FreeServiceSocket(ServiceSocket *sockopt)
149 {
150     while (sockopt != NULL) {
151         ServiceSocket *tmp = sockopt;
152         if (tmp->sockFd >= 0) {
153             close(tmp->sockFd);
154             tmp->sockFd = -1;
155         }
156         sockopt = sockopt->next;
157         free(tmp);
158     }
159     return;
160 }
161 
AddService(const char * name)162 Service *AddService(const char *name)
163 {
164     // check service in group
165     if (CheckNodeValid(NODE_TYPE_SERVICES, name) != 0) {
166         INIT_LOGI("Service %s not exist in group ", name);
167         return NULL;
168     }
169     InitGroupNode *node = AddGroupNode(NODE_TYPE_SERVICES, name);
170     if (node == NULL) {
171         INIT_LOGE("Failed to create service name %s", name);
172         return NULL;
173     }
174     Service *service = (Service *)calloc(1, sizeof(Service));
175     INIT_ERROR_CHECK(service != NULL, return NULL, "Failed to malloc for service");
176     node->data.service = service;
177     service->name = node->name;
178     service->status = SERVICE_IDLE;
179     CPU_ZERO(&service->cpuSet);
180     g_serviceSpace.serviceCount++;
181     INIT_LOGV("AddService %s", node->name);
182     return service;
183 }
184 
FreeServiceFile(ServiceFile * fileOpt)185 static void FreeServiceFile(ServiceFile *fileOpt)
186 {
187     while (fileOpt != NULL) {
188         ServiceFile *tmp = fileOpt;
189         if (tmp->fd >= 0) {
190             close(tmp->fd);
191             tmp->fd = -1;
192         }
193         fileOpt = fileOpt->next;
194         free(tmp);
195     }
196     return;
197 }
198 
ReleaseService(Service * service)199 void ReleaseService(Service *service)
200 {
201     if (service == NULL) {
202         return;
203     }
204     FreeServiceArg(&service->pathArgs);
205     FreeServiceArg(&service->writePidArgs);
206     FreeServiceArg(&service->capsArgs);
207 
208     if (service->servPerm.caps != NULL) {
209         free(service->servPerm.caps);
210         service->servPerm.caps = NULL;
211     }
212     service->servPerm.capsCnt = 0;
213     if (service->servPerm.gIDArray != NULL) {
214         free(service->servPerm.gIDArray);
215         service->servPerm.gIDArray = NULL;
216     }
217     service->servPerm.gIDCnt = 0;
218     FreeServiceSocket(service->socketCfg);
219     FreeServiceFile(service->fileCfg);
220 
221     g_serviceSpace.serviceCount--;
222     InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_SERVICES, service->name);
223     if (groupNode != NULL) {
224         groupNode->data.service = NULL;
225     }
226     free(service);
227 }
228 
GetStringValue(const cJSON * json,const char * name,size_t * strLen)229 static char *GetStringValue(const cJSON *json, const char *name, size_t *strLen)
230 {
231     char *fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(json, name));
232     INIT_CHECK(fieldStr != NULL, return NULL);
233     *strLen = strlen(fieldStr);
234     return fieldStr;
235 }
236 
GetStringItem(const cJSON * json,const char * name,char * buffer,int buffLen)237 static int GetStringItem(const cJSON *json, const char *name, char *buffer, int buffLen)
238 {
239     INIT_ERROR_CHECK(json != NULL, return SERVICE_FAILURE, "Invalid json for %s", name);
240     size_t strLen = 0;
241     char *fieldStr = GetStringValue(json, name, &strLen);
242     INIT_CHECK((fieldStr != NULL) && (strLen != 0) && (strLen <= (size_t)buffLen),
243         return SERVICE_FAILURE);
244     return strcpy_s(buffer, buffLen, fieldStr);
245 }
246 
GetArrayItem(const cJSON * fileRoot,int * arrSize,const char * arrName)247 cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName)
248 {
249     cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName);
250     if (!cJSON_IsArray(arrItem)) {
251         return NULL;
252     }
253     *arrSize = cJSON_GetArraySize(arrItem);
254     INIT_CHECK_RETURN_VALUE(*arrSize > 0, NULL);
255     return arrItem;
256 }
257 
GetServiceArgs(const cJSON * argJson,const char * name,int maxCount,ServiceArgs * args)258 static int GetServiceArgs(const cJSON *argJson, const char *name, int maxCount, ServiceArgs *args)
259 {
260     INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson");
261     cJSON *obj = cJSON_GetObjectItem(argJson, name);
262     INIT_CHECK(obj != NULL, return SERVICE_FAILURE);
263 
264     int ret = cJSON_IsArray(obj);
265     INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type");
266     int count = cJSON_GetArraySize(obj);
267     INIT_ERROR_CHECK((count > 0) && (count < maxCount), return SERVICE_FAILURE, "Array size = %d is wrong", count);
268 
269     args->argv = (char **)malloc((count + 1) * sizeof(char *));
270     INIT_ERROR_CHECK(args->argv != NULL, return SERVICE_FAILURE, "Failed to malloc for argv");
271     for (int i = 0; i < count + 1; ++i) {
272         args->argv[i] = NULL;
273     }
274     // ServiceArgs have a variety of uses, some requiring a NULL ending, some not
275     if (strcmp(name, D_CAPS_STR_IN_CFG) != 0) {
276         args->count = count + 1;
277     } else {
278         args->count = count;
279     }
280     for (int i = 0; i < count; ++i) {
281         char *curParam = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i));
282         INIT_ERROR_CHECK(curParam != NULL, return SERVICE_FAILURE, "Invalid arg %d", i);
283         INIT_ERROR_CHECK(strlen(curParam) <= MAX_ONE_ARG_LEN, return SERVICE_FAILURE, "Arg %s is tool long", curParam);
284         args->argv[i] = strdup(curParam);
285         INIT_ERROR_CHECK(args->argv[i] != NULL, return SERVICE_FAILURE, "Failed to dupstring %s", curParam);
286     }
287     return SERVICE_SUCCESS;
288 }
289 
GetUid(cJSON * json,uid_t * uid)290 static int GetUid(cJSON *json, uid_t *uid)
291 {
292     INIT_CHECK_RETURN_VALUE(json != NULL, SERVICE_SUCCESS);
293     if (cJSON_IsString(json)) {
294         char *str = cJSON_GetStringValue(json);
295         INIT_ERROR_CHECK(str != NULL, return SERVICE_FAILURE, "Invalid str");
296         *uid = DecodeUid(str);
297     } else if (cJSON_IsNumber(json)) {
298         *uid = (uid_t)cJSON_GetNumberValue(json);
299     }
300     INIT_CHECK_RETURN_VALUE(*uid != (uid_t)(-1), SERVICE_FAILURE);
301     return SERVICE_SUCCESS;
302 }
303 
GetServiceGids(const cJSON * curArrItem,Service * curServ)304 static int GetServiceGids(const cJSON *curArrItem, Service *curServ)
305 {
306     int gidCount;
307     cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(curArrItem, GID_STR_IN_CFG);
308     if (!arrItem) {
309         curServ->servPerm.gIDCnt = 0;
310         return SERVICE_SUCCESS;
311     } else if (!cJSON_IsArray(arrItem)) {
312         gidCount = 1;
313     } else {
314         gidCount = cJSON_GetArraySize(arrItem);
315     }
316     INIT_ERROR_CHECK((gidCount != 0) && (gidCount <= NGROUPS_MAX + 1), return SERVICE_FAILURE,
317         "Invalid gid count %d", gidCount);
318     curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t) * gidCount);
319     INIT_ERROR_CHECK(curServ->servPerm.gIDArray != NULL, return SERVICE_FAILURE, "Failed to malloc");
320     curServ->servPerm.gIDCnt = gidCount;
321 
322     gid_t gid;
323     if (!cJSON_IsArray(arrItem)) {
324         int ret = GetUid(arrItem, &gid);
325         INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to uid");
326         curServ->servPerm.gIDArray[0] = gid;
327         return SERVICE_SUCCESS;
328     }
329 
330     for (int i = 0; i < gidCount; ++i) {
331         cJSON *item = cJSON_GetArrayItem(arrItem, i);
332         int ret = GetUid(item, &gid);
333         if (ret != 0) {
334             curServ->servPerm.gIDArray[i] = 0;
335             continue;
336         }
337         curServ->servPerm.gIDArray[i] = gid;
338     }
339     return SERVICE_SUCCESS;
340 }
341 
GetServiceAttr(const cJSON * curArrItem,Service * curServ,const char * attrName,int flag,int (* processAttr)(Service * curServ,const char * attrName,int value,int flag))342 static int GetServiceAttr(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag,
343     int (*processAttr)(Service *curServ, const char *attrName, int value, int flag))
344 {
345     cJSON *filedJ = cJSON_GetObjectItem(curArrItem, attrName);
346     if (filedJ == NULL) {
347         return SERVICE_SUCCESS;
348     }
349     INIT_ERROR_CHECK(cJSON_IsNumber(filedJ), return SERVICE_FAILURE,
350         "%s is null or is not a number, service name is %s", attrName, curServ->name);
351 
352     int value = (int)cJSON_GetNumberValue(filedJ);
353     if (processAttr == NULL) {
354         curServ->attribute &= ~flag;
355         if (value == 1) {
356             curServ->attribute |= flag;
357         }
358         return 0;
359     }
360     return processAttr(curServ, attrName, value, flag);
361 }
362 
ParseSocketFamily(cJSON * json,ServiceSocket * sockopt)363 static int ParseSocketFamily(cJSON *json, ServiceSocket *sockopt)
364 {
365     sockopt->family = AF_UNIX;
366     size_t strLen = 0;
367     char *stringValue = GetStringValue(json, "family", &strLen);
368     INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), return SERVICE_FAILURE,
369         "Failed to get string for family");
370     if (strncmp(stringValue, "AF_UNIX", strLen) == 0) {
371         sockopt->family = AF_UNIX;
372     } else if (strncmp(stringValue, "AF_NETLINK", strLen) == 0) {
373         sockopt->family = AF_NETLINK;
374     }
375     return 0;
376 }
377 
ParseSocketType(cJSON * json,ServiceSocket * sockopt)378 static int ParseSocketType(cJSON *json, ServiceSocket *sockopt)
379 {
380     sockopt->type = SOCK_SEQPACKET;
381     size_t strLen = 0;
382     char *stringValue = GetStringValue(json, "type", &strLen);
383     INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), return SERVICE_FAILURE,
384         "Failed to get string for type");
385     if (strncmp(stringValue, "SOCK_SEQPACKET", strLen) == 0) {
386         sockopt->type = SOCK_SEQPACKET;
387     } else if (strncmp(stringValue, "SOCK_STREAM", strLen) == 0) {
388         sockopt->type = SOCK_STREAM;
389     } else if (strncmp(stringValue, "SOCK_DGRAM", strLen) == 0) {
390         sockopt->type = SOCK_DGRAM;
391     }
392     return 0;
393 }
394 
ParseSocketProtocol(cJSON * json,ServiceSocket * sockopt)395 static int ParseSocketProtocol(cJSON *json, ServiceSocket *sockopt)
396 {
397     sockopt->protocol = 0;
398     size_t strLen = 0;
399     char *stringValue = GetStringValue(json, "protocol", &strLen);
400     INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), return SERVICE_FAILURE,
401         "Failed to get string for protocol");
402     if (strncmp(stringValue, "default", strLen) == 0) {
403         sockopt->protocol = 0;
404     } else if (strncmp(stringValue, "NETLINK_KOBJECT_UEVENT", strLen) == 0) {
405 #ifndef __LITEOS__
406         sockopt->protocol = NETLINK_KOBJECT_UEVENT;
407 #else
408         return -1;
409 #endif
410     }
411     return 0;
412 }
413 
ParseSocketOption(cJSON * json,ServiceSocket * sockopt)414 static int ParseSocketOption(cJSON *json, ServiceSocket *sockopt)
415 {
416     sockopt->option = 0;
417     unsigned int tempType = 0;
418     int typeCnt = 0;
419     char *stringValue = NULL;
420     cJSON *typeItem = NULL;
421     cJSON *typeArray = GetArrayItem(json, &typeCnt, "option");
422     INIT_CHECK((typeArray != NULL) && (typeCnt > 0), return 0);
423     for (int i = 0; i < typeCnt; ++i) {
424         typeItem = cJSON_GetArrayItem(typeArray, i);
425         INIT_CHECK_RETURN_VALUE(cJSON_IsString(typeItem), SERVICE_FAILURE);
426         stringValue = cJSON_GetStringValue(typeItem);
427         INIT_ERROR_CHECK(stringValue != NULL, return SERVICE_FAILURE, "Failed to get string for type");
428         if (strncmp(stringValue, "SOCKET_OPTION_PASSCRED", strlen(stringValue)) == 0) {
429             sockopt->option |= SOCKET_OPTION_PASSCRED;
430         } else if (strncmp(stringValue, "SOCKET_OPTION_RCVBUFFORCE", strlen(stringValue)) == 0) {
431             sockopt->option |= SOCKET_OPTION_RCVBUFFORCE;
432         } else if (strncmp(stringValue, "SOCK_CLOEXEC", strlen(stringValue)) == 0) {
433             tempType |= SOCK_CLOEXEC;
434         } else if (strncmp(stringValue, "SOCK_NONBLOCK", strlen(stringValue)) == 0) {
435             tempType |= SOCK_NONBLOCK;
436         }
437     }
438     if (tempType != 0) {
439         sockopt->type |= tempType;
440     }
441     return 0;
442 }
443 
AddServiceSocket(cJSON * json,Service * service)444 static int AddServiceSocket(cJSON *json, Service *service)
445 {
446     size_t strLen = 0;
447     char* fieldStr = GetStringValue(json, "name", &strLen);
448     INIT_ERROR_CHECK(fieldStr != NULL, return SERVICE_FAILURE, "Failed to get socket name");
449     INIT_ERROR_CHECK(strLen <= MAX_SERVICE_NAME, return SERVICE_FAILURE, "socket name exceeds length limit");
450     ServiceSocket *sockopt = (ServiceSocket *)calloc(1, sizeof(ServiceSocket) + strLen + 1);
451     INIT_INFO_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Failed to malloc for service %s", service->name);
452 
453     int ret = strcpy_s(sockopt->name, strLen + 1, fieldStr);
454     INIT_INFO_CHECK(ret == 0, free(sockopt); sockopt = NULL; return SERVICE_FAILURE,
455         "Failed to copy socket name %s", fieldStr);
456     sockopt->sockFd = -1;
457     sockopt->watcher = NULL;
458 
459     ret = ParseSocketFamily(json, sockopt);
460     INIT_ERROR_CHECK(ret == 0, free(sockopt); sockopt = NULL; return SERVICE_FAILURE,
461         "Failed to parse socket family");
462     ret = ParseSocketType(json, sockopt);
463     INIT_ERROR_CHECK(ret == 0, free(sockopt); sockopt = NULL; return SERVICE_FAILURE,
464         "Failed to parse socket type");
465     ret = ParseSocketProtocol(json, sockopt);
466     INIT_ERROR_CHECK(ret == 0, free(sockopt); sockopt = NULL; return SERVICE_FAILURE,
467         "Failed to parse socket protocol");
468 
469     char *stringValue = GetStringValue(json, "permissions", &strLen);
470     INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), free(sockopt); sockopt = NULL; return SERVICE_FAILURE,
471         "Failed to get string for permissions");
472     sockopt->perm = strtoul(stringValue, 0, OCTAL_BASE);
473     stringValue = GetStringValue(json, "uid", &strLen);
474     INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), free(sockopt); sockopt = NULL; return SERVICE_FAILURE,
475         "Failed to get string for uid");
476     sockopt->uid = DecodeUid(stringValue);
477     stringValue = GetStringValue(json, "gid", &strLen);
478     INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), free(sockopt); sockopt = NULL; return SERVICE_FAILURE,
479         "Failed to get string for gid");
480     sockopt->gid = DecodeUid(stringValue);
481     INIT_ERROR_CHECK((sockopt->uid != (uid_t)-1) && (sockopt->gid != (uid_t)-1),
482         free(sockopt); sockopt = NULL; return SERVICE_FAILURE, "Invalid uid or gid");
483     ret = ParseSocketOption(json, sockopt);
484     INIT_ERROR_CHECK(ret == 0, free(sockopt); sockopt = NULL; return SERVICE_FAILURE,
485         "Failed to parse socket option");
486 
487     sockopt->next = NULL;
488     if (service->socketCfg == NULL) {
489         service->socketCfg = sockopt;
490     } else {
491         sockopt->next = service->socketCfg->next;
492         service->socketCfg->next = sockopt;
493     }
494     return SERVICE_SUCCESS;
495 }
496 
ParseServiceSocket(const cJSON * curArrItem,Service * curServ)497 static int ParseServiceSocket(const cJSON *curArrItem, Service *curServ)
498 {
499     int sockCnt = 0;
500     cJSON *filedJ = GetArrayItem(curArrItem, &sockCnt, "socket");
501     INIT_CHECK(filedJ != NULL && sockCnt > 0, return SERVICE_FAILURE);
502     int ret = 0;
503     curServ->socketCfg = NULL;
504     for (int i = 0; i < sockCnt; ++i) {
505         cJSON *sockJ = cJSON_GetArrayItem(filedJ, i);
506         ret = AddServiceSocket(sockJ, curServ);
507         if (ret != 0) {
508             return ret;
509         }
510     }
511     if (IsOnDemandService(curServ)) {
512         ret = CreateServiceSocket(curServ);
513     }
514     return ret;
515 }
516 
AddServiceFile(cJSON * json,Service * service)517 static int AddServiceFile(cJSON *json, Service *service)
518 {
519     if (!cJSON_IsString(json) || !cJSON_GetStringValue(json)) {
520         return SERVICE_FAILURE;
521     }
522     char *fileStr = cJSON_GetStringValue(json);
523     char *opt[FILE_OPT_NUMS] = {
524         NULL,
525     };
526     int num = SplitString(fileStr, " ", opt, FILE_OPT_NUMS);
527     if (num != FILE_OPT_NUMS) {
528         return SERVICE_FAILURE;
529     }
530     if (opt[SERVICE_FILE_NAME] == NULL || opt[SERVICE_FILE_FLAGS] == NULL || opt[SERVICE_FILE_PERM] == NULL ||
531         opt[SERVICE_FILE_UID] == NULL || opt[SERVICE_FILE_GID] == NULL) {
532         INIT_LOGE("Invalid file opt");
533         return SERVICE_FAILURE;
534     }
535     ServiceFile *fileOpt = (ServiceFile *)calloc(1, sizeof(ServiceFile) + strlen(opt[SERVICE_FILE_NAME]) + 1);
536     INIT_INFO_CHECK(fileOpt != NULL, return SERVICE_FAILURE, "Failed to calloc for file %s", opt[SERVICE_FILE_NAME]);
537     int ret = strcpy_s(fileOpt->fileName, strlen(opt[SERVICE_FILE_NAME]) + 1, opt[SERVICE_FILE_NAME]);
538     INIT_INFO_CHECK(ret == 0, free(fileOpt);
539         return SERVICE_FAILURE, "Failed to copy file name %s", opt[SERVICE_FILE_NAME]);
540     if (strcmp(opt[SERVICE_FILE_FLAGS], "rd") == 0) {
541         fileOpt->flags = O_RDONLY;
542     } else if (strcmp(opt[SERVICE_FILE_FLAGS], "wd") == 0) {
543         fileOpt->flags = O_WRONLY;
544     } else if (strcmp(opt[SERVICE_FILE_FLAGS], "rw") == 0) {
545         fileOpt->flags = O_RDWR;
546     } else {
547         INIT_LOGE("Failed file flags %s", opt[SERVICE_FILE_FLAGS]);
548         return SERVICE_FAILURE;
549     }
550     fileOpt->perm = strtoul(opt[SERVICE_FILE_PERM], 0, OCTAL_BASE);
551     fileOpt->uid = DecodeUid(opt[SERVICE_FILE_UID]);
552     fileOpt->gid = DecodeUid(opt[SERVICE_FILE_GID]);
553     if (fileOpt->uid == (uid_t)-1 || fileOpt->gid == (gid_t)-1) {
554         free(fileOpt);
555         fileOpt = NULL;
556         INIT_LOGE("Invalid uid or gid");
557         return SERVICE_FAILURE;
558     }
559     fileOpt->fd = -1;
560     fileOpt->next = NULL;
561     if (service->fileCfg == NULL) {
562         service->fileCfg = fileOpt;
563     } else {
564         fileOpt->next = service->fileCfg->next;
565         service->fileCfg->next = fileOpt;
566     }
567     return SERVICE_SUCCESS;
568 }
569 
ParseServiceFile(const cJSON * curArrItem,Service * curServ)570 static int ParseServiceFile(const cJSON *curArrItem, Service *curServ)
571 {
572     int fileCnt = 0;
573     cJSON *filedJ = GetArrayItem(curArrItem, &fileCnt, "file");
574     INIT_CHECK(filedJ != NULL && fileCnt > 0, return SERVICE_FAILURE);
575     int ret = 0;
576     curServ->fileCfg = NULL;
577     for (int i = 0; i < fileCnt; ++i) {
578         cJSON *fileJ = cJSON_GetArrayItem(filedJ, i);
579         ret = AddServiceFile(fileJ, curServ);
580         if (ret != 0) {
581             break;
582         }
583     }
584     return ret;
585 }
586 
IsServiceInMainStrap(Service * curServ)587 static bool IsServiceInMainStrap(Service *curServ)
588 {
589     char *mainServiceList[] = {
590         "appspawn", "udevd",  "samgr",      "multimodalinput", "weston",         "installs",
591         "hiview",   "hilogd", "hdf_devmgr", "distributedsche", "softbus_server", "foundation"
592     };
593     unsigned int length = ARRAY_LENGTH(mainServiceList);
594     for (unsigned int i = 0; i < length; ++i) {
595         INIT_INFO_CHECK(strncmp(curServ->name, mainServiceList[i], strlen(mainServiceList[i])) != 0, return true,
596             "%s must be main service", curServ->name);
597     }
598     return false;
599 }
600 
GetDynamicService(const cJSON * curArrItem,Service * curServ)601 static int GetDynamicService(const cJSON *curArrItem, Service *curServ)
602 {
603     cJSON *item = cJSON_GetObjectItem(curArrItem, "dynamic");
604     if (item == NULL) {
605         return SERVICE_SUCCESS;
606     }
607 
608     INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE,
609         "Service : %s dynamic value only support bool.", curServ->name);
610     bool isDynamic = (bool)cJSON_GetNumberValue(item);
611     INIT_INFO_CHECK(isDynamic, return SERVICE_SUCCESS,
612         "Service : %s dynamic value is false, it will be started with init.", curServ->name);
613     INIT_CHECK_RETURN_VALUE(!IsServiceInMainStrap(curServ), SERVICE_SUCCESS);
614     INIT_LOGI("%s is dynamic service", curServ->name);
615 
616     curServ->attribute |= SERVICE_ATTR_DYNAMIC;
617     curServ->attribute |= SERVICE_ATTR_ONCE;
618     return SERVICE_SUCCESS;
619 }
620 
GetServiceOnDemand(const cJSON * curArrItem,Service * curServ)621 static int GetServiceOnDemand(const cJSON *curArrItem, Service *curServ)
622 {
623     cJSON *item = cJSON_GetObjectItem(curArrItem, "ondemand");
624     if (item == NULL) {
625         return SERVICE_SUCCESS;
626     }
627 
628     INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE,
629         "Service : %s ondemand value only support bool.", curServ->name);
630     bool isOnDemand = (bool)cJSON_GetNumberValue(item);
631     INIT_INFO_CHECK(isOnDemand, return SERVICE_SUCCESS,
632         "Service : %s ondemand value is false, it will be manage socket by itself", curServ->name);
633     if (curServ->attribute & SERVICE_ATTR_CRITICAL) {
634         INIT_LOGE("Service : %s is invalid which has both critical and ondemand attribute", curServ->name);
635         return SERVICE_FAILURE;
636     }
637 
638     curServ->attribute |= SERVICE_ATTR_ONDEMAND;
639     return SERVICE_SUCCESS;
640 }
641 
CheckServiceKeyName(const cJSON * curService)642 static int CheckServiceKeyName(const cJSON *curService)
643 {
644     char *cfgServiceKeyList[] = {
645         "name", "path", "uid", "gid", "once", "importance", "caps", "disabled",
646         "writepid", "critical", "socket", "console", "dynamic", "file", "ondemand",
647         "d-caps", "apl", "jobs", "start-mode", "end-mode", "cpucore", "secon"
648     };
649     INIT_CHECK_RETURN_VALUE(curService != NULL, SERVICE_FAILURE);
650     cJSON *child = curService->child;
651     INIT_CHECK_RETURN_VALUE(child != NULL, SERVICE_FAILURE);
652     while (child != NULL) {
653         int i = 0;
654         int keyListSize = ARRAY_LENGTH(cfgServiceKeyList);
655         for (; i < keyListSize; i++) {
656             if (strcmp(child->string, cfgServiceKeyList[i]) == 0) {
657                 break;
658             }
659         }
660         if (i < keyListSize) {
661             child = child->next;
662         } else {
663             INIT_LOGE("CheckServiceKeyName, key name %s is not found. error.", child->string);
664             return SERVICE_FAILURE;
665         }
666     }
667     return SERVICE_SUCCESS;
668 }
669 
GetServiceMode(Service * service,const cJSON * json)670 static int GetServiceMode(Service *service, const cJSON *json)
671 {
672     const InitArgInfo startModeMap[] = {
673         {"condition", START_MODE_CONDITION},
674         {"boot", START_MODE_BOOT},
675         {"normal", START_MODE_NARMAL}
676     };
677     const InitArgInfo endModeMap[] = {
678         {"pre-fork", END_PRE_FORK},
679         {"after-fork", END_AFTER_FORK},
680         {"after-exec", END_AFTER_EXEC},
681         {"ready", END_RECV_READY}
682     };
683     service->startMode = START_MODE_NARMAL;
684     service->endMode = END_AFTER_EXEC;
685     char *value = cJSON_GetStringValue(cJSON_GetObjectItem(json, "start-mode"));
686     if (value != NULL) {
687         service->startMode = GetMapValue(value,
688             (InitArgInfo *)startModeMap, (int)ARRAY_LENGTH(startModeMap), START_MODE_NARMAL);
689     }
690     value = cJSON_GetStringValue(cJSON_GetObjectItem(json, "end-mode"));
691     if (value != NULL) {
692         service->endMode = GetMapValue(value,
693             (InitArgInfo *)endModeMap, (int)ARRAY_LENGTH(endModeMap), END_AFTER_EXEC);
694     }
695     return 0;
696 }
697 
GetServiceJobs(Service * service,cJSON * json)698 static int GetServiceJobs(Service *service, cJSON *json)
699 {
700     const char *jobTypes[] = {
701         "on-boot", "on-start", "on-stop", "on-restart"
702     };
703     for (int i = 0; i < (int)ARRAY_LENGTH(jobTypes); i++) {
704         char *jobName = cJSON_GetStringValue(cJSON_GetObjectItem(json, jobTypes[i]));
705         if (jobName != NULL) {
706             service->serviceJobs.jobsName[i] = strdup(jobName);
707             // save job name for group job check
708             AddGroupNode(NODE_TYPE_JOBS, jobName);
709         }
710     }
711     return SERVICE_SUCCESS;
712 }
713 
GetCritical(const cJSON * curArrItem,Service * curServ,const char * attrName,int flag)714 int  GetCritical(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag)
715 {
716     int criticalSize = 0;
717     curServ->crashCount = CRITICAL_DEFAULT_CRASH_COUNT;
718     curServ->crashTime = CRITICAL_DEFAULT_CRASH_TIME;
719     cJSON *arrItem = cJSON_GetObjectItem(curArrItem, attrName);
720     if (arrItem == NULL) {
721         return SERVICE_SUCCESS;
722     }
723 
724     if (cJSON_IsNumber(arrItem)) {
725         return GetServiceAttr(curArrItem, curServ, attrName, flag, NULL);
726     } else if (cJSON_IsArray(arrItem)) {
727         criticalSize = cJSON_GetArraySize(arrItem);
728         cJSON *attrItem = cJSON_GetArrayItem(arrItem, 0); // 0 : critical attribute index
729         if (attrItem == NULL || !cJSON_IsNumber(attrItem)) {
730             INIT_LOGE("%s critical invalid", curServ->name);
731             return SERVICE_FAILURE;
732         }
733         int attrValue = (int)cJSON_GetNumberValue(attrItem);
734         curServ->attribute &= ~flag;
735         if (criticalSize == 1) {
736             if (attrValue == 1) {
737                 curServ->attribute |= flag;
738             }
739         } else if (criticalSize == CRITICAL_CONFIG_ARRAY_LEN) {
740             cJSON *crashCountItem = cJSON_GetArrayItem(arrItem, 1); // 1 : critical crash count index
741             INIT_ERROR_CHECK(crashCountItem != NULL, return SERVICE_FAILURE, "%s critical invalid", curServ->name);
742             int value = (int)cJSON_GetNumberValue(crashCountItem);
743             INIT_ERROR_CHECK(value > 0, return SERVICE_FAILURE, "%s critical crashc ount invalid", curServ->name);
744             curServ->crashCount = value;
745 
746             cJSON *crashTimeItem = cJSON_GetArrayItem(arrItem, 2); // 2 : critical crash time index
747             INIT_ERROR_CHECK(crashTimeItem != NULL, return SERVICE_FAILURE, "%s critical invalid", curServ->name);
748             value = (int)cJSON_GetNumberValue(crashTimeItem);
749             INIT_ERROR_CHECK(value > 0, return SERVICE_FAILURE, "%s critical crash time invalid", curServ->name);
750             curServ->crashTime = value;
751 
752             if (attrValue == 1) {
753                 curServ->attribute |= flag;
754             }
755         } else {
756             curServ->attribute &= ~flag;
757             INIT_LOGE("%s critical param invalid", curServ->name);
758             return SERVICE_FAILURE;
759         }
760     } else {
761         INIT_LOGE("%s critical type error", curServ->name);
762         return SERVICE_FAILURE;
763     }
764     return SERVICE_SUCCESS;
765 }
766 
GetCpuArgs(const cJSON * argJson,const char * name,Service * service)767 static int GetCpuArgs(const cJSON *argJson, const char *name, Service *service)
768 {
769     INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson");
770     cJSON *obj = cJSON_GetObjectItem(argJson, name);
771     INIT_CHECK(obj != NULL, return SERVICE_FAILURE);
772 
773     int ret = cJSON_IsArray(obj);
774     INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type");
775     int count = cJSON_GetArraySize(obj);
776     int cpus = -1;
777     int cpuNumMax = sysconf(_SC_NPROCESSORS_CONF);
778     for (int i = 0; i < count; ++i) {
779         cJSON *item = cJSON_GetArrayItem(obj, i);
780         INIT_ERROR_CHECK(item != NULL, return SERVICE_FAILURE, "prase invalid");
781         cpus = (int)cJSON_GetNumberValue(item);
782         if (cpuNumMax <= cpus) {
783             INIT_LOGW("%s core number %d of CPU cores does not exist", service->name, cpus);
784             continue;
785         }
786         if (CPU_ISSET(cpus, &service->cpuSet)) {
787             continue;
788         }
789         CPU_SET(cpus, &service->cpuSet);
790     }
791     return SERVICE_SUCCESS;
792 }
793 
ParseOneService(const cJSON * curItem,Service * service)794 int ParseOneService(const cJSON *curItem, Service *service)
795 {
796     INIT_CHECK_RETURN_VALUE(curItem != NULL && service != NULL, SERVICE_FAILURE);
797     int ret = 0;
798 #ifdef WITH_SELINUX
799     ret = GetStringItem(curItem, SECON_STR_IN_CFG, service->secon, MAX_SECON_LEN);
800     INIT_CHECK_ONLY_ELOG(ret == 0, "GetServiceSecon %s section not found, skip", SECON_STR_IN_CFG);
801 #endif // WITH_SELINUX
802     ret = GetServiceArgs(curItem, "path", MAX_PATH_ARGS_CNT, &service->pathArgs);
803     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get path for service %s", service->name);
804     if ((service->pathArgs.count > 0) && IsForbidden(service->pathArgs.argv[0])) {
805         INIT_LOGE("Service %s is forbidden.", service->name);
806         return SERVICE_FAILURE;
807     }
808     ret = GetUid(cJSON_GetObjectItem(curItem, UID_STR_IN_CFG), &service->servPerm.uID);
809     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get uid for service %s", service->name);
810     ret = GetServiceGids(curItem, service);
811     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get gid for service %s", service->name);
812 
813     ret = GetServiceAttr(curItem, service, ONCE_STR_IN_CFG, SERVICE_ATTR_ONCE, NULL);
814     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get once flag for service %s", service->name);
815     ret = GetServiceAttr(curItem, service, IMPORTANT_STR_IN_CFG, SERVICE_ATTR_IMPORTANT, SetImportantValue);
816     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get import flag for service %s", service->name);
817     ret = GetCritical(curItem, service, CRITICAL_STR_IN_CFG, SERVICE_ATTR_CRITICAL);
818     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get critical flag for service %s", service->name);
819     ret = GetServiceAttr(curItem, service, DISABLED_STR_IN_CFG, SERVICE_ATTR_DISABLED, NULL);
820     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get disabled flag for service %s", service->name);
821     ret = GetServiceAttr(curItem, service, CONSOLE_STR_IN_CFG, SERVICE_ATTR_CONSOLE, NULL);
822     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get console for service %s", service->name);
823 
824     (void)GetServiceArgs(curItem, "writepid", MAX_WRITEPID_FILES, &service->writePidArgs);
825     (void)GetServiceArgs(curItem, D_CAPS_STR_IN_CFG, MAX_WRITEPID_FILES, &service->capsArgs);
826     (void)GetStringItem(curItem, APL_STR_IN_CFG, service->apl, MAX_APL_NAME);
827     (void)GetCpuArgs(curItem, CPU_CORE_STR_IN_CFG, service);
828     ret = GetServiceCaps(curItem, service);
829     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get caps for service %s", service->name);
830     ret = GetDynamicService(curItem, service);
831     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get dynamic flag for service %s", service->name);
832     ret = GetServiceOnDemand(curItem, service);
833     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get ondemand flag for service %s", service->name);
834     ret = GetServiceMode(service, curItem);
835     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get start/end mode for service %s", service->name);
836     ret = GetServiceJobs(service, cJSON_GetObjectItem(curItem, "jobs"));
837     INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get jobs for service %s", service->name);
838     return ret;
839 }
840 
ParseAllServices(const cJSON * fileRoot)841 void ParseAllServices(const cJSON *fileRoot)
842 {
843     int servArrSize = 0;
844     cJSON *serviceArr = GetArrayItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON);
845     INIT_CHECK(serviceArr != NULL, return);
846 
847     INIT_ERROR_CHECK(servArrSize <= MAX_SERVICES_CNT_IN_FILE, return,
848         "Too many services[cnt %d] detected, should not exceed %d.",
849         servArrSize, MAX_SERVICES_CNT_IN_FILE);
850 
851     char serviceName[MAX_SERVICE_NAME] = {};
852     for (int i = 0; i < servArrSize; ++i) {
853         cJSON *curItem = cJSON_GetArrayItem(serviceArr, i);
854         int ret = GetStringItem(curItem, "name", serviceName, MAX_SERVICE_NAME);
855         if (ret != 0) {
856             INIT_LOGE("Failed to get service name %s", serviceName);
857             continue;
858         }
859         if (CheckServiceKeyName(curItem) != SERVICE_SUCCESS) { // invalid service
860             INIT_LOGE("Invalid service name %s", serviceName);
861             continue;
862         }
863         Service *service = GetServiceByName(serviceName);
864         if (service != NULL) {
865             INIT_LOGE("Service name %s has been exist", serviceName);
866             continue;
867         }
868         service = AddService(serviceName);
869         if (service == NULL) {
870             INIT_LOGE("Failed to create service name %s", serviceName);
871             continue;
872         }
873 
874         ret = ParseOneService(curItem, service);
875         if (ret != SERVICE_SUCCESS) {
876             ReleaseService(service);
877             service = NULL;
878             continue;
879         }
880         if (ParseServiceSocket(curItem, service) != SERVICE_SUCCESS) {
881             FreeServiceSocket(service->socketCfg);
882             service->socketCfg = NULL;
883         }
884         if (ParseServiceFile(curItem, service) != SERVICE_SUCCESS) {
885             FreeServiceFile(service->fileCfg);
886             service->fileCfg = NULL;
887         }
888         ret = GetCmdLinesFromJson(cJSON_GetObjectItem(curItem, "onrestart"), &service->restartArg);
889         INIT_CHECK(ret == SERVICE_SUCCESS, service->restartArg = NULL);
890     }
891 }
892 
GetServiceByExtServName(const char * fullServName)893 static Service *GetServiceByExtServName(const char *fullServName)
894 {
895     INIT_ERROR_CHECK(fullServName != NULL, return NULL, "Failed get parameters");
896     char *tmpServName = strdup(fullServName);
897     char *dstPtr[MAX_PATH_ARGS_CNT] = {NULL};
898     int returnCount = SplitString(tmpServName, "|", dstPtr, MAX_PATH_ARGS_CNT);
899     if (returnCount == 0) {
900         free(tmpServName);
901         return NULL;
902     }
903     Service *service = GetServiceByName(dstPtr[0]);
904     if (service == NULL) {
905         free(tmpServName);
906         return NULL;
907     }
908     service->extraArgs.count = service->pathArgs.count + returnCount - 1;
909     service->extraArgs.argv = (char **)calloc(service->extraArgs.count + 1, sizeof(char *));
910     INIT_ERROR_CHECK(service->extraArgs.argv != NULL, free(tmpServName);
911         return NULL, "Failed calloc err=%d", errno);
912     int argc;
913     for (argc = 0; argc < (service->pathArgs.count - 1); argc++) {
914         service->extraArgs.argv[argc] = strdup(service->pathArgs.argv[argc]);
915     }
916     int extArgc;
917     for (extArgc = 0; extArgc < (returnCount - 1); extArgc++) {
918         service->extraArgs.argv[extArgc + argc] = strdup(dstPtr[extArgc + 1]);
919     }
920     for (int i = 0; i < service->extraArgs.count - 1; i++) {
921         INIT_LOGI("service->extraArgs.argv[%d] is %s", i, service->extraArgs.argv[i]);
922     }
923     service->extraArgs.argv[service->extraArgs.count] = NULL;
924     free(tmpServName);
925     return service;
926 }
927 
StartServiceByName(const char * servName,bool checkDynamic)928 void StartServiceByName(const char *servName, bool checkDynamic)
929 {
930     INIT_LOGE("StartServiceByName Service %s", servName);
931     Service *service = GetServiceByName(servName);
932     if (service == NULL) {
933         service = GetServiceByExtServName(servName);
934     }
935     INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName);
936 
937     if (checkDynamic && (service->attribute & SERVICE_ATTR_DYNAMIC)) {
938         INIT_LOGI("%s is dynamic service.", servName);
939         NotifyServiceChange(service, SERVICE_STOPPED);
940         return;
941     }
942     if (ServiceStart(service) != SERVICE_SUCCESS) {
943         INIT_LOGE("Service %s start failed!", servName);
944     }
945     // After starting, clear the extra parameters.
946     FreeStringVector(service->extraArgs.argv, service->extraArgs.count);
947     service->extraArgs.argv = NULL;
948     service->extraArgs.count = 0;
949     return;
950 }
951 
StopServiceByName(const char * servName)952 void StopServiceByName(const char *servName)
953 {
954     Service *service = GetServiceByName(servName);
955     INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName);
956 
957     if (ServiceStop(service) != SERVICE_SUCCESS) {
958         INIT_LOGE("Service %s start failed!", servName);
959     }
960     return;
961 }
962 
StopAllServices(int flags,const char ** exclude,int size,int (* filter)(const Service * service,const char ** exclude,int size))963 void StopAllServices(int flags, const char **exclude, int size,
964     int (*filter)(const Service *service, const char **exclude, int size))
965 {
966     Service *service = GetServiceByName("appspawn");
967     if (((SERVICE_ATTR_NEEDWAIT & flags) == SERVICE_ATTR_NEEDWAIT) && service != NULL && service->pid != 0) {
968         waitpid(service->pid, 0, 0);
969     }
970 
971     InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
972     while (node != NULL) {
973         Service *service = node->data.service;
974         if (service == NULL) {
975             node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
976             continue;
977         }
978         INIT_LOGI("StopAllServices stop service %s ", service->name);
979         if (filter != NULL && filter(service, exclude, size) != 0) {
980             node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
981             continue;
982         }
983         service->attribute |= (flags & SERVICE_ATTR_INVALID);
984         int ret = ServiceStop(service);
985         if (ret != SERVICE_SUCCESS) {
986             INIT_LOGE("Service %s stop failed!", service->name);
987         }
988         node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
989     }
990 }
991 
GetServiceByPid(pid_t pid)992 Service *GetServiceByPid(pid_t pid)
993 {
994     InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
995     while (node != NULL) {
996         Service *service = node->data.service;
997         if (service != NULL && service->pid == pid) {
998             return service;
999         }
1000         node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
1001     }
1002     return NULL;
1003 }
1004 
GetServiceByName(const char * servName)1005 Service *GetServiceByName(const char *servName)
1006 {
1007     INIT_ERROR_CHECK(servName != NULL, return NULL, "Failed get servName");
1008     InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_SERVICES, servName);
1009     if (groupNode != NULL) {
1010         return groupNode->data.service;
1011     }
1012     return NULL;
1013 }
1014 
StartAllServices(int startMode)1015 void StartAllServices(int startMode)
1016 {
1017     INIT_LOGI("StartAllServices %d", startMode);
1018     InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
1019     while (node != NULL) {
1020         Service *service = node->data.service;
1021         if (service == NULL || service->startMode != startMode) {
1022             node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
1023             continue;
1024         }
1025         if (IsOnDemandService(service)) {
1026             if (CreateServiceSocket(service) != 0) {
1027                 INIT_LOGE("service %s exit! create socket failed!", service->name);
1028             }
1029             node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
1030             continue;
1031         }
1032         if (service->attribute & SERVICE_ATTR_DYNAMIC) {
1033             INIT_LOGI("%s is dynamic service.", service->name);
1034             NotifyServiceChange(service, SERVICE_STOPPED);
1035             node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
1036             continue;
1037         }
1038         if (ServiceStart(service) != SERVICE_SUCCESS) {
1039             INIT_LOGE("Service %s start failed!", service->name);
1040         }
1041         node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
1042     }
1043     INIT_LOGI("StartAllServices %d finsh", startMode);
1044 }
1045 
LoadAccessTokenId(void)1046 void LoadAccessTokenId(void)
1047 {
1048     GetAccessToken();
1049 }
1050