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 "init_param.h"
26 #include "parameter.h"
27 #include "securec.h"
28
StartProcess(const char * name,const char * extArgv[],int extArgc)29 static int StartProcess(const char *name, const char *extArgv[], int extArgc)
30 {
31 BEGET_ERROR_CHECK(name != NULL, return -1, "Service name is null.");
32 int extraArg = 0;
33 if ((extArgv != NULL) && (extArgc > 0)) {
34 BEGET_LOGI("Start service by extra args");
35 extraArg = 1;
36 }
37 int ret = 0;
38 if (extraArg == 1) {
39 unsigned int len = 0;
40 for (int i = 0; i < extArgc; i++) {
41 len += strlen(extArgv[i]);
42 }
43 len += strlen(name) + extArgc + 1;
44 char *nameValue = (char *)calloc(len, sizeof(char));
45 BEGET_ERROR_CHECK(nameValue != NULL, return -1, "Failed calloc err=%d", errno);
46
47 ret = strncat_s(nameValue, len, name, strlen(name));
48 if (ret != 0) {
49 free(nameValue);
50 BEGET_LOGE("Failed to cat name");
51 return -1;
52 }
53 for (int j = 0; j < extArgc; j++) {
54 ret = strncat_s(nameValue, len, "|", 1);
55 if (ret == 0) {
56 ret = strncat_s(nameValue, len, extArgv[j], strlen(extArgv[j]));
57 }
58 if (ret != 0) {
59 free(nameValue);
60 BEGET_LOGE("Failed to cat name");
61 return -1;
62 }
63 }
64 ret = SystemSetParameter("ohos.ctl.start", nameValue);
65 free(nameValue);
66 } else {
67 ret = SystemSetParameter("ohos.ctl.start", name);
68 }
69 return ret;
70 }
71
StopProcess(const char * serviceName)72 static int StopProcess(const char *serviceName)
73 {
74 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null.");
75 return SystemSetParameter("ohos.ctl.stop", serviceName);
76 }
77
GetCurrentServiceStatus(const char * serviceName,ServiceStatus * status)78 static int GetCurrentServiceStatus(const char *serviceName, ServiceStatus *status)
79 {
80 char paramName[PARAM_NAME_LEN_MAX] = {0};
81 if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1,
82 "%s.%s", STARTUP_SERVICE_CTL, serviceName) == -1) {
83 BEGET_LOGE("Failed snprintf_s err=%d", errno);
84 return -1;
85 }
86 uint32_t value = GetUintParameter(paramName, SERVICE_IDLE);
87 *status = (ServiceStatus)value;
88 return 0;
89 }
90
RestartProcess(const char * serviceName,const char * extArgv[],int extArgc)91 static int RestartProcess(const char *serviceName, const char *extArgv[], int extArgc)
92 {
93 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null.");
94 ServiceStatus status = SERVICE_IDLE;
95 if (GetCurrentServiceStatus(serviceName, &status) != 0) {
96 BEGET_LOGE("Get service status failed.\n");
97 return -1;
98 }
99 if (status == SERVICE_STARTED || status == SERVICE_READY) {
100 if (StopProcess(serviceName) != 0) {
101 BEGET_LOGE("Stop service %s failed", serviceName);
102 return -1;
103 }
104 if (ServiceWaitForStatus(serviceName, SERVICE_STOPPED, DEFAULT_PARAM_WAIT_TIMEOUT) != 0) {
105 BEGET_LOGE("Failed wait service %s stopped", serviceName);
106 return -1;
107 }
108 if (StartProcess(serviceName, extArgv, extArgc) != 0) {
109 BEGET_LOGE("Start service %s failed", serviceName);
110 return -1;
111 }
112 } else if (status != SERVICE_STARTING) {
113 if (StartProcess(serviceName, extArgv, extArgc) != 0) {
114 BEGET_LOGE("Start service %s failed", serviceName);
115 return -1;
116 }
117 } else {
118 BEGET_LOGE("Current service status: %d is not support.", status);
119 }
120 return 0;
121 }
122
ServiceControlWithExtra(const char * serviceName,int action,const char * extArgv[],int extArgc)123 int ServiceControlWithExtra(const char *serviceName, int action, const char *extArgv[], int extArgc)
124 {
125 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null.");
126 int ret = 0;
127 switch (action) {
128 case START:
129 ret = StartProcess(serviceName, extArgv, extArgc);
130 break;
131 case STOP:
132 ret = StopProcess(serviceName);
133 break;
134 case RESTART:
135 ret = RestartProcess(serviceName, extArgv, extArgc);
136 break;
137 default:
138 BEGET_LOGE("Set service %s action %d error", serviceName, action);
139 ret = -1;
140 break;
141 }
142 return ret;
143 }
144
ServiceControl(const char * serviceName,int action)145 int ServiceControl(const char *serviceName, int action)
146 {
147 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null.");
148 int ret = ServiceControlWithExtra(serviceName, action, NULL, 0);
149 return ret;
150 }
151
GetProcessInfo(const char * serviceName,char * nameBuffer,char * valueBuffer,ServiceStatus status)152 static int GetProcessInfo(const char *serviceName, char *nameBuffer, char *valueBuffer, ServiceStatus status)
153 {
154 if (snprintf_s(nameBuffer, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s.%s",
155 STARTUP_SERVICE_CTL, serviceName) == -1) {
156 BEGET_LOGE("Failed snprintf_s err=%d", errno);
157 return -1;
158 }
159 if (snprintf_s(valueBuffer, MAX_INT_LEN, MAX_INT_LEN - 1, "%d", (int)status) == -1) {
160 BEGET_LOGE("Failed snprintf_s err=%d", errno);
161 return -1;
162 }
163 return 0;
164 }
165
ServiceWaitForStatus(const char * serviceName,ServiceStatus status,int waitTimeout)166 int ServiceWaitForStatus(const char *serviceName, ServiceStatus status, int waitTimeout)
167 {
168 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null.");
169 BEGET_ERROR_CHECK(waitTimeout >= 0, return -1, "Invalid timeout.");
170 char paramName[PARAM_NAME_LEN_MAX] = {0};
171 char value[MAX_INT_LEN] = {0};
172 int ret = GetProcessInfo(serviceName, paramName, value, status);
173 BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get param info.");
174 return (SystemWaitParameter(paramName, value, waitTimeout) != 0) ? -1 : 0;
175 }
176
ServiceSetReady(const char * serviceName)177 int ServiceSetReady(const char *serviceName)
178 {
179 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null.");
180 char paramName[PARAM_NAME_LEN_MAX] = {0};
181 char value[MAX_INT_LEN] = {0};
182 int ret = GetProcessInfo(serviceName, paramName, value, SERVICE_READY);
183 BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get param info.");
184 return SystemSetParameter(paramName, value);
185 }
186
StartServiceByTimer(const char * serviceName,uint64_t timeout)187 int StartServiceByTimer(const char *serviceName, uint64_t timeout)
188 {
189 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null.");
190 if (timeout == 0) {
191 // start service immediately.
192 return ServiceControl(serviceName, START);
193 }
194 // restrict timeout value, not too long.
195 char value[PARAM_VALUE_LEN_MAX] = {};
196 if (snprintf_s(value, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s|%lld", serviceName, timeout) == -1) {
197 BEGET_LOGE("Failed to build parameter value");
198 return -1;
199 }
200 return SystemSetParameter("ohos.servicectrl.timer_start", value);
201 }
202
StopServiceTimer(const char * serviceName)203 int StopServiceTimer(const char *serviceName)
204 {
205 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null.");
206 return SystemSetParameter("ohos.servicectrl.timer_stop", serviceName);
207 }
208