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 29static 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 72static 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 78static 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 91static 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 BEGET_LOGE("Process service %s status: %d ", serviceName, status); 100 if (status == SERVICE_STARTED || status == SERVICE_READY) { 101 if (StopProcess(serviceName) != 0) { 102 BEGET_LOGE("Stop service %s failed", serviceName); 103 return -1; 104 } 105 if (ServiceWaitForStatus(serviceName, SERVICE_STOPPED, DEFAULT_PARAM_WAIT_TIMEOUT) != 0) { 106 BEGET_LOGE("Failed wait service %s stopped", serviceName); 107 return -1; 108 } 109 if (StartProcess(serviceName, extArgv, extArgc) != 0) { 110 BEGET_LOGE("Start service %s failed", serviceName); 111 return -1; 112 } 113 } else if (status != SERVICE_STARTING) { 114 if (StartProcess(serviceName, extArgv, extArgc) != 0) { 115 BEGET_LOGE("Start service %s failed", serviceName); 116 return -1; 117 } 118 } 119 return 0; 120} 121 122int ServiceControlWithExtra(const char *serviceName, int action, const char *extArgv[], int extArgc) 123{ 124 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); 125 int ret = 0; 126 switch (action) { 127 case START: 128 ret = StartProcess(serviceName, extArgv, extArgc); 129 break; 130 case STOP: 131 ret = StopProcess(serviceName); 132 break; 133 case RESTART: 134 ret = RestartProcess(serviceName, extArgv, extArgc); 135 break; 136 default: 137 BEGET_LOGE("Set service %s action %d error", serviceName, action); 138 ret = -1; 139 break; 140 } 141 return ret; 142} 143 144int ServiceControl(const char *serviceName, int action) 145{ 146 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); 147 int ret = ServiceControlWithExtra(serviceName, action, NULL, 0); 148 return ret; 149} 150 151static int GetProcessInfo(const char *serviceName, char *nameBuffer, char *valueBuffer, ServiceStatus status) 152{ 153 if (snprintf_s(nameBuffer, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s.%s", 154 STARTUP_SERVICE_CTL, serviceName) == -1) { 155 BEGET_LOGE("Failed snprintf_s err=%d", errno); 156 return -1; 157 } 158 if (snprintf_s(valueBuffer, MAX_INT_LEN, MAX_INT_LEN - 1, "%d", (int)status) == -1) { 159 BEGET_LOGE("Failed snprintf_s err=%d", errno); 160 return -1; 161 } 162 return 0; 163} 164 165int ServiceWaitForStatus(const char *serviceName, ServiceStatus status, int waitTimeout) 166{ 167 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); 168 BEGET_ERROR_CHECK(waitTimeout >= 0, return -1, "Invalid timeout."); 169 char paramName[PARAM_NAME_LEN_MAX] = {0}; 170 char value[MAX_INT_LEN] = {0}; 171 int ret = GetProcessInfo(serviceName, paramName, value, status); 172 BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get param info."); 173 return (SystemWaitParameter(paramName, value, waitTimeout) != 0) ? -1 : 0; 174} 175 176int ServiceSetReady(const char *serviceName) 177{ 178 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); 179 char paramName[PARAM_NAME_LEN_MAX] = {0}; 180 char value[MAX_INT_LEN] = {0}; 181 int ret = GetProcessInfo(serviceName, paramName, value, SERVICE_READY); 182 BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get param info."); 183 return SystemSetParameter(paramName, value); 184} 185 186int StartServiceByTimer(const char *serviceName, uint64_t timeout) 187{ 188 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); 189 if (timeout == 0) { 190 // start service immediately. 191 return ServiceControl(serviceName, START); 192 } 193 // restrict timeout value, not too long. 194 char value[PARAM_VALUE_LEN_MAX] = {}; 195 if (snprintf_s(value, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s|%lld", serviceName, timeout) == -1) { 196 BEGET_LOGE("Failed to build parameter value"); 197 return -1; 198 } 199 return SystemSetParameter("ohos.servicectrl.timer_start", value); 200} 201 202int StopServiceTimer(const char *serviceName) 203{ 204 BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); 205 return SystemSetParameter("ohos.servicectrl.timer_stop", serviceName); 206} 207