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 #include "executor/cmd_dumper.h"
16 #include "securec.h"
17
18 namespace OHOS {
19 namespace HiviewDFX {
CMDDumper()20 CMDDumper::CMDDumper() : fp_(nullptr)
21 {
22 }
23
~CMDDumper()24 CMDDumper::~CMDDumper()
25 {
26 if (fp_ != nullptr) {
27 pclose(fp_);
28 fp_ = nullptr;
29 }
30 }
31
PreExecute(const std::shared_ptr<DumperParameter> & parameter,StringMatrix dumpDatas)32 DumpStatus CMDDumper::PreExecute(const std::shared_ptr<DumperParameter>& parameter,
33 StringMatrix dumpDatas)
34 {
35 if (dumpDatas.get() == nullptr) {
36 return DumpStatus::DUMP_FAIL;
37 }
38 std::string cmd = ptrDumpCfg_->target_;
39 if (ptrDumpCfg_->args_ != nullptr) {
40 if (ptrDumpCfg_->args_->HasPid()) {
41 int pid = ptrDumpCfg_->args_->GetPid();
42 ReplacePidInCmd(cmd, pid);
43 }
44 if (ptrDumpCfg_->args_->HasCpuId()) {
45 int cpuId = ptrDumpCfg_->args_->GetCpuId();
46 ReplaceCpuIdInCmd(cmd, cpuId);
47 }
48 }
49 cmd_ = cmd;
50 needLoop_ = (ptrDumpCfg_->loop_ == DumperConstant::LOOP);
51 if (fp_ == nullptr) {
52 if ((fp_ = popen(cmd_.c_str(), "r")) == nullptr) {
53 return DumpStatus::DUMP_FAIL;
54 }
55 }
56 dumpDatas_ = dumpDatas;
57
58 // Add only once!
59 if (lineData_.size() <= 0) {
60 std::string lineStr = "\ncmd is: ";
61 lineStr = lineStr + cmd_ + "\n\n";
62 lineData_.push_back(lineStr);
63 dumpDatas_->push_back(lineData_);
64 }
65 return DumpStatus::DUMP_OK;
66 }
67
Execute()68 DumpStatus CMDDumper::Execute()
69 {
70 DumpStatus ret = DumpStatus::DUMP_OK;
71 if (needLoop_) {
72 // dump one line
73 return ReadLine();
74 } else {
75 // dump all line
76 do {
77 if (IsCanceled()) {
78 break;
79 }
80 ret = ReadLine();
81 } while (ret == DumpStatus::DUMP_MORE_DATA);
82 }
83 return ret;
84 }
85
AfterExecute()86 DumpStatus CMDDumper::AfterExecute()
87 {
88 if (moreData_ && IsTimeout()) {
89 DUMPER_HILOGE(MODULE_COMMON, "error|cmd timeout");
90 std::vector<std::string> line_vector_timeout;
91 line_vector_timeout.push_back(GetTimeoutStr());
92 dumpDatas_->push_back(line_vector_timeout);
93 moreData_ = false;
94 }
95
96 if (!moreData_) {
97 if (fp_ != nullptr) {
98 pclose(fp_);
99 fp_ = nullptr;
100 }
101 return DumpStatus::DUMP_OK;
102 }
103 return DumpStatus::DUMP_MORE_DATA;
104 }
105
106 // provide interface to others
GetCmdInterface(const std::string & cmd,StringMatrix dumpDatas)107 DumpStatus CMDDumper::GetCmdInterface(const std::string& cmd, StringMatrix dumpDatas)
108 {
109 DumpStatus ret = DumpStatus::DUMP_MORE_DATA;
110 FILE* fp = popen(cmd.c_str(), "r");
111 if (fp == nullptr) {
112 return DumpStatus::DUMP_FAIL;
113 }
114 do {
115 ret = GetLineData(fp, dumpDatas);
116 } while (ret == DumpStatus::DUMP_MORE_DATA);
117 pclose(fp);
118 return ret;
119 }
120
GetLineData(FILE * fp,StringMatrix dumpDatas)121 DumpStatus CMDDumper::GetLineData(FILE* fp, StringMatrix dumpDatas)
122 {
123 DumpStatus ret = DumpStatus::DUMP_MORE_DATA;
124 char* line_buffer = nullptr;
125 size_t len = 0;
126 ssize_t read = 0;
127 read = getline(&line_buffer, &len, fp);
128 if (read != -1) {
129 if (line_buffer[read - 1] == '\n') {
130 line_buffer[read - 1] = '\0'; // replease \n
131 }
132 std::string line = line_buffer;
133 std::vector<std::string> line_vector;
134 line_vector.push_back(line);
135 dumpDatas->push_back(line_vector);
136 } else {
137 if (feof(fp) == 0) { // ferror()
138 ret = DumpStatus::DUMP_FAIL;
139 } else {
140 ret = DumpStatus::DUMP_OK;
141 }
142 }
143 if (line_buffer != nullptr) {
144 free(line_buffer);
145 line_buffer = nullptr;
146 }
147 return ret;
148 }
149
150 // read one line
ReadLine()151 DumpStatus CMDDumper::ReadLine()
152 {
153 if (fp_ == nullptr) {
154 return DumpStatus::DUMP_FAIL;
155 }
156 DumpStatus ret = GetLineData(fp_, dumpDatas_);
157 moreData_ = (ret == DumpStatus::DUMP_MORE_DATA);
158 return ret;
159 }
160
ReplacePidInCmd(std::string & cmd,int pid)161 void CMDDumper::ReplacePidInCmd(std::string &cmd, int pid)
162 {
163 size_t pos = cmd.find("%pid");
164 if (pos != std::string::npos) {
165 cmd = cmd.replace(pos, strlen("%pid"), std::to_string(pid));
166 cmd_ = cmd;
167 }
168 }
169
ReplaceCpuIdInCmd(std::string & cmd,int cpuId)170 void CMDDumper::ReplaceCpuIdInCmd(std::string &cmd, int cpuId)
171 {
172 size_t pos = cmd.find("%cpuid");
173 if (pos != std::string::npos) {
174 cmd = cmd.replace(pos, strlen("%cpuid"), std::to_string(cpuId));
175 cmd_ = cmd;
176 }
177 }
178 } // namespace HiviewDFX
179 } // namespace OHOS
180