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 "service_control.h"
17
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "beget_ext.h"
24 #include "init_utils.h"
25 #include "securec.h"
26 #include "sys_param.h"
27
StartProcess(const char * name,const char * extArgv[],int extArgc)28 static int StartProcess(const char *name, const char *extArgv[], int extArgc)
29 {
30 if (name == NULL) {
31 BEGET_LOGE("Start dynamic service failed, service name is null.");
32 return -1;
33 }
34 int extraArg = 0;
35 if ((extArgv != NULL) && (extArgc > 0)) {
36 BEGET_LOGI("Start service by extra args");
37 extraArg = 1;
38 }
39 if (extraArg == 1) {
40 unsigned int len = 0;
41 for (int i = 0; i < extArgc; i++) {
42 len += strlen(extArgv[i]);
43 }
44 len += strlen(name) + extArgc + 1;
45 char *nameValue = (char *)calloc(len, sizeof(char));
46 if (nameValue == NULL) {
47 BEGET_LOGE("Failed calloc err=%d", errno);
48 return -1;
49 }
50 if (strncat_s(nameValue, len, name, strlen(name)) != 0) {
51 BEGET_LOGE("Failed strncat_s name err=%d", errno);
52 return -1;
53 }
54 for (int j = 0; j < extArgc; j++) {
55 if (strncat_s(nameValue, len, "|", 1) != 0) {
56 BEGET_LOGE("Failed strncat_s \"|\"err=%d", errno);
57 return -1;
58 }
59 if (strncat_s(nameValue, len, extArgv[j], strlen(extArgv[j])) != 0) {
60 BEGET_LOGE("Failed strncat_s err=%d", errno);
61 return -1;
62 }
63 }
64 if (SystemSetParameter("ohos.ctl.start", nameValue) != 0) {
65 BEGET_LOGE("Set param for %s failed.\n", nameValue);
66 free(nameValue);
67 return -1;
68 }
69 free(nameValue);
70 } else {
71 if (SystemSetParameter("ohos.ctl.start", name) != 0) {
72 BEGET_LOGE("Set param for %s failed.\n", name);
73 return -1;
74 }
75 }
76 return 0;
77 }
78
StopProcess(const char * serviceName)79 static int StopProcess(const char *serviceName)
80 {
81 if (serviceName == NULL) {
82 BEGET_LOGE("Stop dynamic service failed, service is null.\n");
83 return -1;
84 }
85 if (SystemSetParameter("ohos.ctl.stop", serviceName) != 0) {
86 BEGET_LOGE("Set param for %s failed.\n", serviceName);
87 return -1;
88 }
89 return 0;
90 }
91
GetCurrentServiceStatus(const char * serviceName,ServiceStatus * status)92 static int GetCurrentServiceStatus(const char *serviceName, ServiceStatus *status)
93 {
94 char paramName[PARAM_NAME_LEN_MAX] = {0};
95 if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1,
96 "%s.%s", STARTUP_SERVICE_CTL, serviceName) == -1) {
97 BEGET_LOGE("Failed snprintf_s err=%d", errno);
98 return -1;
99 }
100 char paramValue[PARAM_VALUE_LEN_MAX] = {0};
101 unsigned int valueLen = PARAM_VALUE_LEN_MAX;
102 if (SystemGetParameter(paramName, paramValue, &valueLen) != 0) {
103 BEGET_LOGE("Failed get paramName.");
104 return -1;
105 }
106 int size = 0;
107 const InitArgInfo *statusMap = GetServieStatusMap(&size);
108 *status = GetMapValue(paramValue, statusMap, size, SERVICE_IDLE);
109 return 0;
110 }
111
RestartProcess(const char * serviceName,const char * extArgv[],int extArgc)112 static int RestartProcess(const char *serviceName, const char *extArgv[], int extArgc)
113 {
114 if (serviceName == NULL) {
115 BEGET_LOGE("Restart dynamic service failed, service is null.\n");
116 return -1;
117 }
118 ServiceStatus status = SERVICE_IDLE;
119 if (GetCurrentServiceStatus(serviceName, &status) != 0) {
120 BEGET_LOGE("Get service status failed.\n");
121 return -1;
122 }
123 if (status == SERVICE_STARTED || status == SERVICE_READY) {
124 if (StopProcess(serviceName) != 0) {
125 BEGET_LOGE("Stop service %s failed", serviceName);
126 return -1;
127 }
128 if (ServiceWaitForStatus(serviceName, SERVICE_STOPPED, DEFAULT_PARAM_WAIT_TIMEOUT) != 0) {
129 BEGET_LOGE("Failed wait service %s stopped", serviceName);
130 return -1;
131 }
132 if (StartProcess(serviceName, extArgv, extArgc) != 0) {
133 BEGET_LOGE("Start service %s failed", serviceName);
134 return -1;
135 }
136 } else if (status != SERVICE_STARTING) {
137 if (StartProcess(serviceName, extArgv, extArgc) != 0) {
138 BEGET_LOGE("Start service %s failed", serviceName);
139 return -1;
140 }
141 } else {
142 BEGET_LOGE("Current service status: %d is not support.", status);
143 }
144 return 0;
145 }
146
ServiceControlWithExtra(const char * serviceName,int action,const char * extArgv[],int extArgc)147 int ServiceControlWithExtra(const char *serviceName, int action, const char *extArgv[], int extArgc)
148 {
149 if (serviceName == NULL) {
150 BEGET_LOGE("Service wait failed, service is null.\n");
151 return -1;
152 }
153 int ret = 0;
154 switch (action) {
155 case START:
156 ret = StartProcess(serviceName, extArgv, extArgc);
157 break;
158 case STOP:
159 ret = StopProcess(serviceName);
160 break;
161 case RESTART:
162 ret = RestartProcess(serviceName, extArgv, extArgc);
163 break;
164 default:
165 BEGET_LOGE("Set service %s action %d error", serviceName, action);
166 ret = -1;
167 break;
168 }
169 return ret;
170 }
171
ServiceControl(const char * serviceName,int action)172 int ServiceControl(const char *serviceName, int action)
173 {
174 if (serviceName == NULL) {
175 BEGET_LOGE("Service getctl failed, service is null.");
176 return -1;
177 }
178 int ret = ServiceControlWithExtra(serviceName, action, NULL, 0);
179 return ret;
180 }
181
ServiceWaitForStatus(const char * serviceName,ServiceStatus status,int waitTimeout)182 int ServiceWaitForStatus(const char *serviceName, ServiceStatus status, int waitTimeout)
183 {
184 char *state = NULL;
185 int size = 0;
186 const InitArgInfo *statusMap = GetServieStatusMap(&size);
187 if (((int)status < size) && (statusMap[status].value == (int)status)) {
188 state = statusMap[status].name;
189 }
190 if (serviceName == NULL || state == NULL || waitTimeout <= 0) {
191 BEGET_LOGE("Service wait failed, service name is null or status invalid %d", status);
192 return -1;
193 }
194 char paramName[PARAM_NAME_LEN_MAX] = {0};
195 if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s.%s",
196 STARTUP_SERVICE_CTL, serviceName) == -1) {
197 BEGET_LOGE("Failed snprintf_s err=%d", errno);
198 return -1;
199 }
200 if (SystemWaitParameter(paramName, state, waitTimeout) != 0) {
201 BEGET_LOGE("Wait param for %s failed.", paramName);
202 return -1;
203 }
204 BEGET_LOGI("Success wait");
205 return 0;
206 }
207
ServiceSetReady(const char * serviceName)208 int ServiceSetReady(const char *serviceName)
209 {
210 if (serviceName == NULL) {
211 BEGET_LOGE("Service wait failed, service is null.");
212 return -1;
213 }
214 char paramName[PARAM_NAME_LEN_MAX] = {0};
215 if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s.%s",
216 STARTUP_SERVICE_CTL, serviceName) == -1) {
217 BEGET_LOGE("Failed snprintf_s err=%d", errno);
218 return -1;
219 }
220 if (SystemSetParameter(paramName, "ready") != 0) {
221 BEGET_LOGE("Set param for %s failed.", paramName);
222 return -1;
223 }
224 BEGET_LOGI("Success set %d read", serviceName);
225 return 0;
226 }
227
StartServiceByTimer(const char * serviceName,uint64_t timeout)228 int StartServiceByTimer(const char *serviceName, uint64_t timeout)
229 {
230 if (serviceName == NULL) {
231 BEGET_LOGE("Request start serivce by timer with invalid service name");
232 return -1;
233 }
234
235 if (timeout == 0) {
236 // start service immediately.
237 return ServiceControl(serviceName, START);
238 }
239 // restrict timeout value, not too long.
240 char value[PARAM_VALUE_LEN_MAX] = {};
241 if (snprintf_s(value, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s|%lld", serviceName, timeout) == -1) {
242 BEGET_LOGE("Failed to build parameter value");
243 return -1;
244 }
245
246 if (SystemSetParameter("ohos.servicectrl.timer_start", value) != 0) {
247 BEGET_LOGE("Failed to set parameter \' ohos.servicectrl.timer_start \' with value \' %s \'", value);
248 return -1;
249 }
250 return 0;
251 }
252
StopServiceTimer(const char * serviceName)253 int StopServiceTimer(const char *serviceName)
254 {
255 if (serviceName == NULL) {
256 BEGET_LOGE("Request stop serivce timer with invalid service name");
257 return -1;
258 }
259
260 char value[PARAM_VALUE_LEN_MAX] = {};
261 int ret = strncpy_s(value, PARAM_VALUE_LEN_MAX - 1, serviceName, strlen(serviceName));
262 if (ret < 0) {
263 BEGET_LOGE("Failed to copy service name to parameter");
264 return -1;
265 }
266
267 if (SystemSetParameter("ohos.servicectrl", value) != 0) {
268 BEGET_LOGE("Failed to set parameter \' ohos.servicectrl.timer_stop \' with value \' %s \'", value);
269 return -1;
270 }
271 return 0;
272 }
273