1 /*
2  * Copyright (c) 2024 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 <stdio.h>
16 #include <stdlib.h>
17 #include <signal.h>
18 
19 #include "appspawn.h"
20 #include "appspawn_utils.h"
21 
22 #include "devicedebug_base.h"
23 #include "devicedebug_kill.h"
24 #include "cJSON.h"
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 #define DEVICEDEBUG_KILL_CMD_NUM 4
31 #define DEVICEDEBUG_KILL_CMD_SIGNAL_INDEX 2
32 #define DEVICEDEBUG_KILL_CMD_PID_INDEX 3
33 
DeviceDebugShowKillHelp(void)34 APPSPAWN_STATIC void DeviceDebugShowKillHelp(void)
35 {
36     printf("\r\nusage: devicedebug kill [options] <pid>"
37         "\r\noptions list:"
38         "\r\n         -h, --help                list available commands"
39         "\r\n         kill -<signal> <pid>      send a signal(1-64) to a process\r\n");
40 }
41 
DeviceDebugJsonStringGeneral(int pid,const char * op,cJSON * args)42 APPSPAWN_STATIC char* DeviceDebugJsonStringGeneral(int pid, const char *op, cJSON *args)
43 {
44     cJSON *root = cJSON_CreateObject();
45     if (root == NULL) {
46         cJSON_Delete(args);
47         DEVICEDEBUG_LOGE("devicedebug json write create root object unsuccess");
48         return NULL;
49     }
50 
51     cJSON_AddNumberToObject(root, "app", pid);
52     cJSON_AddStringToObject(root, "op", op);
53     cJSON_AddItemToObject(root, "args", args);
54 
55     char *jsonString = cJSON_Print(root);
56     cJSON_Delete(root);
57     return jsonString;
58 }
59 
DevicedebugKillRetDeal(int result,int pid)60 APPSPAWN_STATIC void DevicedebugKillRetDeal(int result, int pid)
61 {
62     switch (result) {
63         case APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_EXIST:
64             printf("devicedebug: kill: %d: No such app process\r\n", pid);
65             break;
66         case APPSPAWN_DEVICEDEBUG_ERROR_APP_NOT_DEBUGGABLE:
67             printf("devicedebug: kill: process: %d is not debuggable app\r\n", pid);
68             break;
69         default:
70             printf("devicedebug: process: %d kill unsuccess ret=%d, please check the hilog for the cause\r\n",
71                 pid, result);
72             break;
73     }
74 }
75 
DeviceDebugKill(int pid,int signal)76 APPSPAWN_STATIC int DeviceDebugKill(int pid, int signal)
77 {
78     cJSON *args = cJSON_CreateObject();
79     if (args == NULL) {
80         DEVICEDEBUG_LOGE("devicedebug json write create args object unsuccess");
81         return DEVICEDEBUG_ERRNO_JSON_CREATED_FAILED;
82     }
83     cJSON_AddNumberToObject(args, "signal", signal);
84     char *jsonString = DeviceDebugJsonStringGeneral(pid, "kill", args);
85     if (jsonString == NULL) {
86         return DEVICEDEBUG_ERRNO_JSON_CREATED_FAILED;
87     }
88 
89     AppSpawnReqMsgHandle reqHandle;
90     int ret = AppSpawnReqMsgCreate(MSG_DEVICE_DEBUG, "devicedebug", &reqHandle);
91     if (ret != 0) {
92         free(jsonString);
93         DEVICEDEBUG_LOGE("devicedebug appspawn message create unsuccess, ret=%{public}d", ret);
94         return ret;
95     }
96 
97     ret = AppSpawnReqMsgAddExtInfo(reqHandle, "devicedebug", (uint8_t *)jsonString, strlen(jsonString) + 1);
98     if (ret != 0) {
99         DEVICEDEBUG_LOGE("devicedebug appspawn message add devicedebug[%{public}s] unsuccess, ret=%{public}d",
100             jsonString, ret);
101         free(jsonString);
102         AppSpawnReqMsgFree(reqHandle);
103         return ret;
104     }
105 
106     AppSpawnClientHandle clientHandle;
107     ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle);
108     if (ret != 0) {
109         free(jsonString);
110         AppSpawnReqMsgFree(reqHandle);
111         DEVICEDEBUG_LOGE("devicedebug appspawn client init unsuccess, ret=%{public}d", ret);
112         return ret;
113     }
114 
115     AppSpawnResult result = {0};
116     ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
117     AppSpawnClientDestroy(clientHandle);
118     free(jsonString);
119     if (ret != 0) {
120         DEVICEDEBUG_LOGE("devicedebug appspawn send msg unsuccess, ret=%{public}d", ret);
121         return ret;
122     }
123 
124     if (result.result != 0) {
125         return result.result;
126     }
127 
128     return 0;
129 }
130 
DeviceDebugCmdKill(int argc,char * argv[])131 int DeviceDebugCmdKill(int argc, char *argv[])
132 {
133     if (!IsDeveloperModeOpen()) {
134         return DEVICEDEBUG_ERRNO_NOT_IN_DEVELOPER_MODE;
135     }
136 
137     if (argc <= DEVICEDEBUG_NUM_2 || strcmp(argv[DEVICEDEBUG_NUM_2], "-h") == 0 ||
138         strcmp(argv[DEVICEDEBUG_NUM_2], "help") == 0) {
139         DeviceDebugShowKillHelp();
140         return 0;
141     }
142 
143     if (argc < DEVICEDEBUG_KILL_CMD_NUM) {
144         DEVICEDEBUG_LOGE("devicedebug cmd operator num is %{public}d < %{public}d", argc, DEVICEDEBUG_KILL_CMD_NUM);
145         DeviceDebugShowKillHelp();
146         return DEVICEDEBUG_ERRNO_OPERATOR_ARGV_MISS;
147     }
148 
149     int signal = atoi(argv[DEVICEDEBUG_KILL_CMD_SIGNAL_INDEX] + 1);
150     if (signal > SIGRTMAX || signal <= 0) {
151         DEVICEDEBUG_LOGE("signal is %{public}d not in [1, %{public}d]", signal, SIGRTMAX);
152         DeviceDebugShowKillHelp();
153         return DEVICEDEBUG_ERRNO_PARAM_INVALID;
154     }
155 
156     int pid = atoi(argv[DEVICEDEBUG_KILL_CMD_PID_INDEX]);
157     DEVICEDEBUG_LOGI("devicedebug cmd kill start signal[%{public}d], pid[%{public}d]", signal, pid);
158 
159     int ret = DeviceDebugKill(pid, signal);
160     if (ret != 0) {
161         DevicedebugKillRetDeal(ret, pid);
162     }
163 
164     return ret;
165 }
166 
167 #ifdef __cplusplus
168 }
169 #endif
170