Gazebo Utils

API Reference

3.1.0
Subprocess.hh
Go to the documentation of this file.
1/*
2 * Copyright (C) 2023 Open Source Robotics Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18#ifndef GZ_UTILS__SUBPROCESS_HH_
19#define GZ_UTILS__SUBPROCESS_HH_
20
21#include "detail/subprocess.h"
23
24#include <iostream>
25#include <string>
26#include <vector>
27#include <utility>
28
29#include <gz/utils/detail/subprocess.h>
30
31// This header contains a wrapper to the cross-platform subprocess library.
32// It can be used to spawn processes to interact with, primarily for testing.
33
34namespace gz
35{
36namespace utils
37{
38
41{
49 public: explicit Subprocess(const std::vector<std::string> &_commandLine):
50 commandLine(_commandLine),
51 environment({}),
53 {
54 this->Create();
55 }
56
66 public: Subprocess(const std::vector<std::string> &_commandLine,
67 gz::utils::EnvironmentMap _environment):
68 commandLine(_commandLine),
69 environment(std::move(_environment)),
71 {
72 this->Create();
73 }
74
84 public: Subprocess(const std::vector<std::string> &_commandLine,
85 const gz::utils::EnvironmentStrings &_environment):
86 Subprocess(_commandLine, gz::utils::envStringsToMap(_environment))
87 {
88 }
89
90
91 private: void Create()
92 {
93 if (this->process != nullptr)
94 return;
95
96 this->process = new subprocess_s;
97
98 auto environmentStr = gz::utils::envMapToStrings(this->environment);
99 std::vector<const char*> environmentCstr;
100 std::vector<const char*> commandLineCstr;
101
102 for (const auto &val : this->commandLine)
103 {
104 commandLineCstr.push_back(val.c_str());
105 }
106 commandLineCstr.push_back(nullptr);
107
108 if (!this->inheritEnvironment)
109 {
110 for (const auto &val : environmentStr)
111 {
112 environmentCstr.push_back(val.c_str());
113 }
114 environmentCstr.push_back(nullptr);
115 }
116
117 int ret = -1;
118 if (!this->inheritEnvironment)
119 {
120 ret = subprocess_create_ex(commandLineCstr.data(),
121 0, environmentCstr.data(), this->process);
122 }
123 else
124 {
125 ret = subprocess_create(commandLineCstr.data(),
126 subprocess_option_inherit_environment,
127 this->process);
128 }
129
130 if (0 != ret)
131 {
132 std::cerr << "failed to create subprocess" << std::endl;
133 delete this->process;
134 this->process = nullptr;
135 }
136 }
137
138 public: ~Subprocess()
139 {
140 if (this->process != nullptr)
141 subprocess_destroy(this->process);
142 delete this->process;
143 }
144
146 {
147 std::string result;
148 if (this->process != nullptr)
149 {
150 auto *p_stdout = subprocess_stdout(this->process);
151 char buffer[128];
152 while (!feof(p_stdout))
153 {
154 if (fgets(buffer, 128, p_stdout) != nullptr)
155 result += buffer;
156 }
157 }
158 return result;
159 }
160
162 {
163 std::string result;
164 if (this->process != nullptr)
165 {
166 auto *p_stdout = subprocess_stderr(this->process);
167 char buffer[128];
168 while (!feof(p_stdout))
169 {
170 if (fgets(buffer, 128, p_stdout) != nullptr)
171 result += buffer;
172 }
173 }
174 return result;
175
176 }
177
178 public: bool Alive()
179 {
180 if (this->process != nullptr)
181 return subprocess_alive(this->process);
182 else
183 return false;
184 }
185
186 public: bool Terminate()
187 {
188 if (this->process != nullptr)
189 return subprocess_terminate(this->process) != 0;
190 else
191 return false;
192 }
193
194 public: int Join()
195 {
196 int return_code = -1;
197 if (this->process != nullptr)
198 {
199 auto ret = subprocess_join(this->process, &return_code);
200 if (ret != 0)
201 {
202 std::cerr << "Failed to join subprocess" << std::endl;
203 }
204 }
205
206 return return_code;
207 }
208
210
212
213 protected: bool inheritEnvironment;
214
215 protected: subprocess_s * process {nullptr};
216};
217} // namespace utils
218} // namespace gz
219
220#endif // GZ_UTILS__SUBPROCESS_HH_