1 /*
2 * Copyright (c) 2021-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
16 #include "common_utils.h"
17
18 #include <cstdint>
19 #include <cstdio>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <sstream>
23 #include <string>
24 #include <sys/wait.h>
25 #include <sys/syscall.h>
26 #include <unistd.h>
27 #include <vector>
28
29 #include "securec.h"
30 #include "time_util.h"
31
32 using namespace std;
33 namespace OHOS {
34 namespace HiviewDFX {
35 namespace CommonUtils {
ExecCommand(const std::string & cmd,const std::vector<std::string> & args)36 int ExecCommand(const std::string &cmd, const std::vector<std::string> &args)
37 {
38 pid_t pid = fork();
39 if (pid < 0) {
40 return -1;
41 } else if (pid == 0) {
42 // Redirect the stdout to /dev/null
43 int fd = open("/dev/null", O_WRONLY);
44 // follow standard, although dup2 may handle the case of invalid oldfd
45 if (fd >= 0) {
46 dup2(fd, STDOUT_FILENO);
47 close(fd);
48 }
49
50 std::vector<char *> argv;
51 argv.push_back(const_cast<char *>(cmd.c_str()));
52 for (const auto &arg : args) {
53 argv.push_back(const_cast<char *>(arg.c_str()));
54 }
55 argv.push_back(0);
56 execv(argv[0], &argv[0]);
57 }
58 constexpr uint64_t maxWaitingTime = 60; // 60 seconds
59 uint64_t remainedTime = maxWaitingTime * NS_PER_SECOND;
60 while (remainedTime > 0) {
61 uint64_t startTime = TimeUtil::GetNanoTime();
62 int status = 0;
63 waitpid(pid, &status, WNOHANG);
64 if (WIFEXITED(status)) {
65 return 0;
66 }
67 sleep(1);
68 uint64_t duration = TimeUtil::GetNanoTime() - startTime;
69 remainedTime = (remainedTime > duration) ? (remainedTime - duration) : 0;
70 }
71
72 return -1;
73 }
74
GetProcNameByPid(pid_t pid)75 std::string GetProcNameByPid(pid_t pid)
76 {
77 std::string result;
78 char buf[BUF_SIZE_256] = {0};
79 (void)snprintf_s(buf, BUF_SIZE_256, BUF_SIZE_256 - 1, "/proc/%d/comm", pid);
80 FileUtil::LoadStringFromFile(std::string(buf, strlen(buf)), result);
81 auto pos = result.find_last_not_of(" \n\r\t");
82 if (pos == std::string::npos) {
83 return result;
84 }
85 result.erase(pos + 1);
86 return result;
87 }
88
GetPidByName(const std::string & processName)89 pid_t GetPidByName(const std::string& processName)
90 {
91 pid_t pid = -1;
92 std::string cmd = "pidof " + processName;
93
94 FILE* fp = popen(cmd.c_str(), "r");
95 if (fp != nullptr) {
96 char buffer[BUF_SIZE_256] = {'\0'};
97 while (fgets(buffer, sizeof(buffer) - 1, fp) != nullptr) {}
98 std::istringstream istr(buffer);
99 istr >> pid;
100 pclose(fp);
101 }
102 return pid;
103 }
104
IsTheProcessExist(pid_t pid)105 bool IsTheProcessExist(pid_t pid)
106 {
107 int ret = syscall(SYS_tgkill, pid, pid, 0);
108 if (ret != 0 && errno == ESRCH) {
109 return false;
110 }
111 return true;
112 }
113
IsSpecificCmdExist(const std::string & fullPath)114 bool IsSpecificCmdExist(const std::string& fullPath)
115 {
116 return access(fullPath.c_str(), X_OK) == 0;
117 }
118
WriteCommandResultToFile(int fd,const std::string & cmd)119 bool WriteCommandResultToFile(int fd, const std::string& cmd)
120 {
121 if (cmd.empty()) {
122 return false;
123 }
124
125 FILE* fp = popen(cmd.c_str(), "r");
126 if (fp != nullptr) {
127 char buffer[BUF_SIZE_256] = {0};
128 while (fgets(buffer, sizeof(buffer), fp) != nullptr) {
129 FileUtil::SaveStringToFd(fd, buffer);
130 }
131 pclose(fp);
132 return true;
133 }
134 return false;
135 }
136
WriteCommandResultToFile(int fd,const std::string & cmd,const std::vector<std::string> & args)137 int WriteCommandResultToFile(int fd, const std::string &cmd, const std::vector<std::string> &args)
138 {
139 if (cmd.empty()) {
140 return -1;
141 }
142
143 pid_t pid = fork();
144 if (pid < 0) {
145 return -1;
146 } else if (pid == 0) {
147 // follow standard, although dup2 may handle the case of invalid oldfd
148 if (fd >= 0) {
149 dup2(fd, STDOUT_FILENO);
150 dup2(fd, STDIN_FILENO);
151 dup2(fd, STDERR_FILENO);
152 }
153
154 std::vector<char *> argv;
155 for (const auto &arg : args) {
156 argv.push_back(const_cast<char *>(arg.c_str()));
157 }
158 argv.push_back(0);
159 execv(cmd.c_str(), &argv[0]);
160 }
161
162 constexpr uint64_t maxWaitingTime = 120; // 120 seconds
163 uint64_t endTime = TimeUtil::GetMilliseconds() + maxWaitingTime * TimeUtil::SEC_TO_MILLISEC;
164 while (endTime > TimeUtil::GetMilliseconds()) {
165 int status = 0;
166 pid_t p = waitpid(pid, &status, WNOHANG);
167 if (p < 0) {
168 return -1;
169 }
170
171 if (p == pid) {
172 return WEXITSTATUS(status);
173 }
174 }
175
176 return -1;
177 }
178 }
179 } // namespace HiviewDFX
180 } // namespace OHOS
181