1 /*
2 * Copyright (C) 2023 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 "shell_catcher.h"
16 #include <unistd.h>
17 #include <sys/wait.h>
18 #include "logger.h"
19 #include "common_utils.h"
20 #include "log_catcher_utils.h"
21 #include "securec.h"
22 #include "time_util.h"
23 namespace OHOS {
24 namespace HiviewDFX {
25 DEFINE_LOG_LABEL(0xD002D01, "EventLogger-ShellCatcher");
ShellCatcher()26 ShellCatcher::ShellCatcher() : EventLogCatcher()
27 {
28 name_ = "ShellCatcher";
29 }
30
Initialize(const std::string & cmd,int type,int catcherPid)31 bool ShellCatcher::Initialize(const std::string& cmd, int type, int catcherPid)
32 {
33 catcherCmd_ = cmd;
34 catcherType_ = CATCHER_TYPE(type);
35 pid_ = catcherPid;
36 description_ = "catcher cmd: " + catcherCmd_ + " ";
37 return true;
38 }
39
CaDoInChildProcesscatcher(int writeFd)40 int ShellCatcher::CaDoInChildProcesscatcher(int writeFd)
41 {
42 int ret = -1;
43 switch (catcherType_) {
44 case CATCHER_HILOG:
45 ret = execl("/system/bin/hilog", "hilog", "-x", nullptr);
46 break;
47 case CATCHER_LIGHT_HILOG:
48 ret = execl("/system/bin/hilog", "hilog", "-z", "100", "-P", std::to_string(pid_).c_str(),
49 nullptr);
50 break;
51 case CATCHER_SNAPSHOT:
52 {
53 std::string path = "/data/log/eventlog/snapshot_display_";
54 path += TimeUtil::TimestampFormatToDate(TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC,
55 "%Y%m%d%H%M%S");
56 path += ".jpeg";
57 ret = execl("/system/bin/snapshot_display", "snapshot_display", "-f", path.c_str(), nullptr);
58 }
59 break;
60 case CATCHER_SCBSESSION:
61 ret = execl("/system/bin/scb_debug", "scb_debug", "SCBScenePanel", "getContainerSession", nullptr);
62 break;
63 case CATCHER_SCBVIEWPARAM:
64 ret = execl("/system/bin/scb_debug", "scb_debug", "SCBScenePanel", "getViewParam", nullptr);
65 default:
66 break;
67 }
68 return ret;
69 }
70
DoChildProcess(int writeFd)71 void ShellCatcher::DoChildProcess(int writeFd)
72 {
73 if (writeFd < 0 || dup2(writeFd, STDOUT_FILENO) == -1 ||
74 dup2(writeFd, STDIN_FILENO) == -1 || dup2(writeFd, STDERR_FILENO) == -1) {
75 HIVIEW_LOGE("dup2 writeFd fail");
76 _exit(-1);
77 }
78
79 int ret = -1;
80 switch (catcherType_) {
81 case CATCHER_AMS:
82 ret = execl("/system/bin/hidumper", "hidumper", "-s", "AbilityManagerService", "-a", "-a", nullptr);
83 break;
84 case CATCHER_WMS:
85 ret = execl("/system/bin/hidumper", "hidumper", "-s", "WindowManagerService", "-a", "-a", nullptr);
86 break;
87 case CATCHER_CPU:
88 ret = execl("/system/bin/hidumper", "hidumper", "--cpuusage", nullptr);
89 break;
90 case CATCHER_MEM:
91 ret = execl("/system/bin/hidumper", "hidumper", "--mem", std::to_string(pid_).c_str(), nullptr);
92 break;
93 case CATCHER_PMS:
94 ret = execl("/system/bin/hidumper", "hidumper", "-s", "PowerManagerService", "-a", "-s", nullptr);
95 break;
96 case CATCHER_DPMS:
97 ret = execl("/system/bin/hidumper", "hidumper", "-s", "DisplayPowerManagerService", nullptr);
98 break;
99 case CATCHER_RS:
100 ret = execl("/system/bin/hidumper", "hidumper", "-s", "RenderService", "-a", "allInfo", nullptr);
101 break;
102 default:
103 ret = CaDoInChildProcesscatcher(writeFd);
104 break;
105 }
106 if (ret < 0) {
107 HIVIEW_LOGE("execl %{public}d, errno: %{public}d", ret, errno);
108 _exit(-1);
109 }
110 }
111
ReadShellToFile(int writeFd,const std::string & cmd)112 bool ShellCatcher::ReadShellToFile(int writeFd, const std::string& cmd)
113 {
114 int childPid = fork();
115 if (childPid < 0) {
116 HIVIEW_LOGE("fork fail");
117 return false;
118 } else if (childPid == 0) {
119 DoChildProcess(writeFd);
120 } else {
121 if (waitpid(childPid, nullptr, 0) != childPid) {
122 HIVIEW_LOGE("waitpid fail, pid: %{public}d, errno: %{public}d", childPid, errno);
123 return false;
124 }
125 HIVIEW_LOGI("waitpid %{public}d success", childPid);
126 }
127 return true;
128 }
129
Catch(int fd,int jsonFd)130 int ShellCatcher::Catch(int fd, int jsonFd)
131 {
132 auto originSize = GetFdSize(fd);
133 if (catcherCmd_.empty()) {
134 HIVIEW_LOGE("catcherCmd empty");
135 return -1;
136 }
137
138 ReadShellToFile(fd, catcherCmd_);
139 logSize_ = GetFdSize(fd) - originSize;
140 return logSize_;
141 }
142 } // namespace HiviewDFX
143 } // namespace OHOS
144