1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/process/launch.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <tuple>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <lib/fdio/limits.h>
10*6777b538SAndroid Build Coastguard Worker #include <lib/fdio/namespace.h>
11*6777b538SAndroid Build Coastguard Worker #include <lib/fdio/spawn.h>
12*6777b538SAndroid Build Coastguard Worker #include <lib/zx/job.h>
13*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
14*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
15*6777b538SAndroid Build Coastguard Worker #include <zircon/processargs.h>
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/default_job.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/file_utils.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/fuchsia_logging.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/process/environment_internal.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/scoped_generic.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker namespace base {
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker namespace {
32*6777b538SAndroid Build Coastguard Worker
GetAppOutputInternal(const CommandLine & cmd_line,bool include_stderr,std::string * output,int * exit_code)33*6777b538SAndroid Build Coastguard Worker bool GetAppOutputInternal(const CommandLine& cmd_line,
34*6777b538SAndroid Build Coastguard Worker bool include_stderr,
35*6777b538SAndroid Build Coastguard Worker std::string* output,
36*6777b538SAndroid Build Coastguard Worker int* exit_code) {
37*6777b538SAndroid Build Coastguard Worker DCHECK(exit_code);
38*6777b538SAndroid Build Coastguard Worker TRACE_EVENT0("base", "GetAppOutput");
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker LaunchOptions options;
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker // LaunchProcess will automatically clone any stdio fd we do not explicitly
43*6777b538SAndroid Build Coastguard Worker // map.
44*6777b538SAndroid Build Coastguard Worker int pipe_fd[2];
45*6777b538SAndroid Build Coastguard Worker if (pipe(pipe_fd) < 0)
46*6777b538SAndroid Build Coastguard Worker return false;
47*6777b538SAndroid Build Coastguard Worker options.fds_to_remap.emplace_back(pipe_fd[1], STDOUT_FILENO);
48*6777b538SAndroid Build Coastguard Worker if (include_stderr)
49*6777b538SAndroid Build Coastguard Worker options.fds_to_remap.emplace_back(pipe_fd[1], STDERR_FILENO);
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker Process process = LaunchProcess(cmd_line, options);
52*6777b538SAndroid Build Coastguard Worker close(pipe_fd[1]);
53*6777b538SAndroid Build Coastguard Worker if (!process.IsValid()) {
54*6777b538SAndroid Build Coastguard Worker close(pipe_fd[0]);
55*6777b538SAndroid Build Coastguard Worker return false;
56*6777b538SAndroid Build Coastguard Worker }
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker output->clear();
59*6777b538SAndroid Build Coastguard Worker for (;;) {
60*6777b538SAndroid Build Coastguard Worker char buffer[256];
61*6777b538SAndroid Build Coastguard Worker ssize_t bytes_read = read(pipe_fd[0], buffer, sizeof(buffer));
62*6777b538SAndroid Build Coastguard Worker if (bytes_read <= 0)
63*6777b538SAndroid Build Coastguard Worker break;
64*6777b538SAndroid Build Coastguard Worker output->append(buffer, static_cast<size_t>(bytes_read));
65*6777b538SAndroid Build Coastguard Worker }
66*6777b538SAndroid Build Coastguard Worker close(pipe_fd[0]);
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker // It is okay to allow this process to wait on the launched process as a
69*6777b538SAndroid Build Coastguard Worker // process launched with GetAppOutput*() shouldn't wait back on the process
70*6777b538SAndroid Build Coastguard Worker // that launched it.
71*6777b538SAndroid Build Coastguard Worker internal::GetAppOutputScopedAllowBaseSyncPrimitives allow_wait;
72*6777b538SAndroid Build Coastguard Worker return process.WaitForExit(exit_code);
73*6777b538SAndroid Build Coastguard Worker }
74*6777b538SAndroid Build Coastguard Worker
FdioSpawnAction(uint32_t action)75*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t FdioSpawnAction(uint32_t action) {
76*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t new_action = {};
77*6777b538SAndroid Build Coastguard Worker new_action.action = action;
78*6777b538SAndroid Build Coastguard Worker return new_action;
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker
FdioSpawnActionCloneFd(int local_fd,int target_fd)81*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t FdioSpawnActionCloneFd(int local_fd, int target_fd) {
82*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t action = FdioSpawnAction(FDIO_SPAWN_ACTION_CLONE_FD);
83*6777b538SAndroid Build Coastguard Worker action.fd.local_fd = local_fd;
84*6777b538SAndroid Build Coastguard Worker action.fd.target_fd = target_fd;
85*6777b538SAndroid Build Coastguard Worker return action;
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker
FdioSpawnActionAddNamespaceEntry(const char * prefix,zx_handle_t handle)88*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t FdioSpawnActionAddNamespaceEntry(const char* prefix,
89*6777b538SAndroid Build Coastguard Worker zx_handle_t handle) {
90*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t action = FdioSpawnAction(FDIO_SPAWN_ACTION_ADD_NS_ENTRY);
91*6777b538SAndroid Build Coastguard Worker action.ns.prefix = prefix;
92*6777b538SAndroid Build Coastguard Worker action.ns.handle = handle;
93*6777b538SAndroid Build Coastguard Worker return action;
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker
FdioSpawnActionAddHandle(uint32_t id,zx_handle_t handle)96*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t FdioSpawnActionAddHandle(uint32_t id, zx_handle_t handle) {
97*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t action = FdioSpawnAction(FDIO_SPAWN_ACTION_ADD_HANDLE);
98*6777b538SAndroid Build Coastguard Worker action.h.id = id;
99*6777b538SAndroid Build Coastguard Worker action.h.handle = handle;
100*6777b538SAndroid Build Coastguard Worker return action;
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker
FdioSpawnActionSetName(const char * name)103*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t FdioSpawnActionSetName(const char* name) {
104*6777b538SAndroid Build Coastguard Worker fdio_spawn_action_t action = FdioSpawnAction(FDIO_SPAWN_ACTION_SET_NAME);
105*6777b538SAndroid Build Coastguard Worker action.name.data = name;
106*6777b538SAndroid Build Coastguard Worker return action;
107*6777b538SAndroid Build Coastguard Worker }
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker } // namespace
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Worker // static
AddHandleToTransfer(HandlesToTransferVector * handles_to_transfer,zx_handle_t handle)112*6777b538SAndroid Build Coastguard Worker uint32_t LaunchOptions::AddHandleToTransfer(
113*6777b538SAndroid Build Coastguard Worker HandlesToTransferVector* handles_to_transfer,
114*6777b538SAndroid Build Coastguard Worker zx_handle_t handle) {
115*6777b538SAndroid Build Coastguard Worker CHECK_LE(handles_to_transfer->size(), std::numeric_limits<uint16_t>::max())
116*6777b538SAndroid Build Coastguard Worker << "Number of handles to transfer exceeds total allowed";
117*6777b538SAndroid Build Coastguard Worker auto handle_id =
118*6777b538SAndroid Build Coastguard Worker static_cast<uint32_t>(PA_HND(PA_USER1, handles_to_transfer->size()));
119*6777b538SAndroid Build Coastguard Worker handles_to_transfer->push_back({handle_id, handle});
120*6777b538SAndroid Build Coastguard Worker return handle_id;
121*6777b538SAndroid Build Coastguard Worker }
122*6777b538SAndroid Build Coastguard Worker
LaunchProcess(const CommandLine & cmdline,const LaunchOptions & options)123*6777b538SAndroid Build Coastguard Worker Process LaunchProcess(const CommandLine& cmdline,
124*6777b538SAndroid Build Coastguard Worker const LaunchOptions& options) {
125*6777b538SAndroid Build Coastguard Worker return LaunchProcess(cmdline.argv(), options);
126*6777b538SAndroid Build Coastguard Worker }
127*6777b538SAndroid Build Coastguard Worker
LaunchProcess(const std::vector<std::string> & argv,const LaunchOptions & options)128*6777b538SAndroid Build Coastguard Worker Process LaunchProcess(const std::vector<std::string>& argv,
129*6777b538SAndroid Build Coastguard Worker const LaunchOptions& options) {
130*6777b538SAndroid Build Coastguard Worker // fdio_spawn_etc() accepts an array of |fdio_spawn_action_t|, describing
131*6777b538SAndroid Build Coastguard Worker // namespace entries, descriptors and handles to launch the child process
132*6777b538SAndroid Build Coastguard Worker // with. |fdio_spawn_action_t| does not own any values assigned to its
133*6777b538SAndroid Build Coastguard Worker // members, so strings assigned to members must be valid through the
134*6777b538SAndroid Build Coastguard Worker // fdio_spawn_etc() call.
135*6777b538SAndroid Build Coastguard Worker std::vector<fdio_spawn_action_t> spawn_actions;
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker // Handles to be transferred to the child are owned by this vector, so that
138*6777b538SAndroid Build Coastguard Worker // they they are closed on early-exit, and can be release()d otherwise.
139*6777b538SAndroid Build Coastguard Worker std::vector<zx::handle> transferred_handles;
140*6777b538SAndroid Build Coastguard Worker
141*6777b538SAndroid Build Coastguard Worker // Add caller-supplied handles for transfer. We must do this first to ensure
142*6777b538SAndroid Build Coastguard Worker // that the handles are consumed even if some later step fails.
143*6777b538SAndroid Build Coastguard Worker for (const auto& id_and_handle : options.handles_to_transfer) {
144*6777b538SAndroid Build Coastguard Worker spawn_actions.push_back(
145*6777b538SAndroid Build Coastguard Worker FdioSpawnActionAddHandle(id_and_handle.id, id_and_handle.handle));
146*6777b538SAndroid Build Coastguard Worker transferred_handles.emplace_back(id_and_handle.handle);
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker // Determine the job under which to launch the new process.
150*6777b538SAndroid Build Coastguard Worker zx::unowned_job job = options.job_handle != ZX_HANDLE_INVALID
151*6777b538SAndroid Build Coastguard Worker ? zx::unowned_job(options.job_handle)
152*6777b538SAndroid Build Coastguard Worker : GetDefaultJob();
153*6777b538SAndroid Build Coastguard Worker DCHECK(job->is_valid());
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker // Construct an |argv| array of C-strings from the supplied std::strings.
156*6777b538SAndroid Build Coastguard Worker std::vector<const char*> argv_cstr;
157*6777b538SAndroid Build Coastguard Worker argv_cstr.reserve(argv.size() + 1);
158*6777b538SAndroid Build Coastguard Worker for (const auto& arg : argv)
159*6777b538SAndroid Build Coastguard Worker argv_cstr.push_back(arg.c_str());
160*6777b538SAndroid Build Coastguard Worker argv_cstr.push_back(nullptr);
161*6777b538SAndroid Build Coastguard Worker
162*6777b538SAndroid Build Coastguard Worker // If |environment| is set then it contains values to set/replace to create
163*6777b538SAndroid Build Coastguard Worker // the new process' environment.
164*6777b538SAndroid Build Coastguard Worker EnvironmentMap environ_modifications = options.environment;
165*6777b538SAndroid Build Coastguard Worker
166*6777b538SAndroid Build Coastguard Worker // "PWD" is set in the new process' environment, to one of:
167*6777b538SAndroid Build Coastguard Worker // 1. The value of |current_directory|, if set.
168*6777b538SAndroid Build Coastguard Worker // 2. The value specified in |environment|, if any.
169*6777b538SAndroid Build Coastguard Worker // 3. The current process' current working directory, if known.
170*6777b538SAndroid Build Coastguard Worker if (!options.current_directory.empty()) {
171*6777b538SAndroid Build Coastguard Worker environ_modifications["PWD"] = options.current_directory.value();
172*6777b538SAndroid Build Coastguard Worker } else if (environ_modifications.find("PWD") == environ_modifications.end()) {
173*6777b538SAndroid Build Coastguard Worker FilePath cwd;
174*6777b538SAndroid Build Coastguard Worker if (GetCurrentDirectory(&cwd)) {
175*6777b538SAndroid Build Coastguard Worker environ_modifications["PWD"] = cwd.value();
176*6777b538SAndroid Build Coastguard Worker }
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker
179*6777b538SAndroid Build Coastguard Worker // By default the calling process' environment is copied, and the collated
180*6777b538SAndroid Build Coastguard Worker // modifications applied, to create the new process' environment. If
181*6777b538SAndroid Build Coastguard Worker // |clear_environment| is set then only the collated modifications are used.
182*6777b538SAndroid Build Coastguard Worker char* const kEmptyEnviron = nullptr;
183*6777b538SAndroid Build Coastguard Worker char* const* old_environ =
184*6777b538SAndroid Build Coastguard Worker options.clear_environment ? &kEmptyEnviron : environ;
185*6777b538SAndroid Build Coastguard Worker std::unique_ptr<char*[]> new_environ =
186*6777b538SAndroid Build Coastguard Worker internal::AlterEnvironment(old_environ, environ_modifications);
187*6777b538SAndroid Build Coastguard Worker
188*6777b538SAndroid Build Coastguard Worker // Always clone the library loader service and UTC clock to new processes,
189*6777b538SAndroid Build Coastguard Worker // in addition to any flags specified by the caller.
190*6777b538SAndroid Build Coastguard Worker uint32_t spawn_flags = FDIO_SPAWN_DEFAULT_LDSVC | FDIO_SPAWN_CLONE_UTC_CLOCK |
191*6777b538SAndroid Build Coastguard Worker options.spawn_flags;
192*6777b538SAndroid Build Coastguard Worker
193*6777b538SAndroid Build Coastguard Worker // Add actions to clone handles for any specified paths into the new process'
194*6777b538SAndroid Build Coastguard Worker // namespace.
195*6777b538SAndroid Build Coastguard Worker if (!options.paths_to_clone.empty() || !options.paths_to_transfer.empty()) {
196*6777b538SAndroid Build Coastguard Worker DCHECK((options.spawn_flags & FDIO_SPAWN_CLONE_NAMESPACE) == 0);
197*6777b538SAndroid Build Coastguard Worker transferred_handles.reserve(transferred_handles.size() +
198*6777b538SAndroid Build Coastguard Worker options.paths_to_clone.size() +
199*6777b538SAndroid Build Coastguard Worker options.paths_to_transfer.size());
200*6777b538SAndroid Build Coastguard Worker
201*6777b538SAndroid Build Coastguard Worker for (const auto& path_to_transfer : options.paths_to_transfer) {
202*6777b538SAndroid Build Coastguard Worker zx::handle handle(path_to_transfer.handle);
203*6777b538SAndroid Build Coastguard Worker spawn_actions.push_back(FdioSpawnActionAddNamespaceEntry(
204*6777b538SAndroid Build Coastguard Worker path_to_transfer.path.value().c_str(), handle.get()));
205*6777b538SAndroid Build Coastguard Worker transferred_handles.push_back(std::move(handle));
206*6777b538SAndroid Build Coastguard Worker }
207*6777b538SAndroid Build Coastguard Worker
208*6777b538SAndroid Build Coastguard Worker for (const auto& path_to_clone : options.paths_to_clone) {
209*6777b538SAndroid Build Coastguard Worker fidl::InterfaceHandle<::fuchsia::io::Directory> directory =
210*6777b538SAndroid Build Coastguard Worker base::OpenDirectoryHandle(path_to_clone);
211*6777b538SAndroid Build Coastguard Worker if (!directory) {
212*6777b538SAndroid Build Coastguard Worker LOG(WARNING) << "Could not open handle for path: " << path_to_clone;
213*6777b538SAndroid Build Coastguard Worker return base::Process();
214*6777b538SAndroid Build Coastguard Worker }
215*6777b538SAndroid Build Coastguard Worker
216*6777b538SAndroid Build Coastguard Worker zx::handle handle = directory.TakeChannel();
217*6777b538SAndroid Build Coastguard Worker
218*6777b538SAndroid Build Coastguard Worker spawn_actions.push_back(FdioSpawnActionAddNamespaceEntry(
219*6777b538SAndroid Build Coastguard Worker path_to_clone.value().c_str(), handle.get()));
220*6777b538SAndroid Build Coastguard Worker transferred_handles.push_back(std::move(handle));
221*6777b538SAndroid Build Coastguard Worker }
222*6777b538SAndroid Build Coastguard Worker }
223*6777b538SAndroid Build Coastguard Worker
224*6777b538SAndroid Build Coastguard Worker // Add any file-descriptors to be cloned into the new process.
225*6777b538SAndroid Build Coastguard Worker // Note that if FDIO_SPAWN_CLONE_STDIO is set, then any stdio entries in
226*6777b538SAndroid Build Coastguard Worker // |fds_to_remap| will be used in place of the parent process' descriptors.
227*6777b538SAndroid Build Coastguard Worker for (const auto& src_target : options.fds_to_remap) {
228*6777b538SAndroid Build Coastguard Worker spawn_actions.push_back(
229*6777b538SAndroid Build Coastguard Worker FdioSpawnActionCloneFd(src_target.first, src_target.second));
230*6777b538SAndroid Build Coastguard Worker }
231*6777b538SAndroid Build Coastguard Worker
232*6777b538SAndroid Build Coastguard Worker // If |process_name_suffix| is specified then set process name as
233*6777b538SAndroid Build Coastguard Worker // "<file_name><suffix>", otherwise leave the default value.
234*6777b538SAndroid Build Coastguard Worker std::string process_name; // Must outlive the fdio_spawn_etc() call.
235*6777b538SAndroid Build Coastguard Worker if (!options.process_name_suffix.empty()) {
236*6777b538SAndroid Build Coastguard Worker process_name = base::FilePath(argv[0]).BaseName().value() +
237*6777b538SAndroid Build Coastguard Worker options.process_name_suffix;
238*6777b538SAndroid Build Coastguard Worker spawn_actions.push_back(FdioSpawnActionSetName(process_name.c_str()));
239*6777b538SAndroid Build Coastguard Worker }
240*6777b538SAndroid Build Coastguard Worker
241*6777b538SAndroid Build Coastguard Worker zx::process process_handle;
242*6777b538SAndroid Build Coastguard Worker // fdio_spawn_etc() will write a null-terminated scring to |error_message| in
243*6777b538SAndroid Build Coastguard Worker // case of failure, so we avoid unnecessarily initializing it here.
244*6777b538SAndroid Build Coastguard Worker char error_message[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
245*6777b538SAndroid Build Coastguard Worker zx_status_t status = fdio_spawn_etc(
246*6777b538SAndroid Build Coastguard Worker job->get(), spawn_flags, argv_cstr[0], argv_cstr.data(),
247*6777b538SAndroid Build Coastguard Worker new_environ.get(), spawn_actions.size(), spawn_actions.data(),
248*6777b538SAndroid Build Coastguard Worker process_handle.reset_and_get_address(), error_message);
249*6777b538SAndroid Build Coastguard Worker
250*6777b538SAndroid Build Coastguard Worker // fdio_spawn_etc() will close all handles specified in add-handle actions,
251*6777b538SAndroid Build Coastguard Worker // regardless of whether it succeeds or fails, so release our copies.
252*6777b538SAndroid Build Coastguard Worker for (auto& transferred_handle : transferred_handles)
253*6777b538SAndroid Build Coastguard Worker std::ignore = transferred_handle.release();
254*6777b538SAndroid Build Coastguard Worker
255*6777b538SAndroid Build Coastguard Worker if (status != ZX_OK) {
256*6777b538SAndroid Build Coastguard Worker ZX_LOG(ERROR, status) << "fdio_spawn: " << error_message;
257*6777b538SAndroid Build Coastguard Worker return Process();
258*6777b538SAndroid Build Coastguard Worker }
259*6777b538SAndroid Build Coastguard Worker
260*6777b538SAndroid Build Coastguard Worker // Wrap the handle into a Process, and wait for it to terminate, if requested.
261*6777b538SAndroid Build Coastguard Worker Process process(process_handle.release());
262*6777b538SAndroid Build Coastguard Worker if (options.wait) {
263*6777b538SAndroid Build Coastguard Worker status = zx_object_wait_one(process.Handle(), ZX_TASK_TERMINATED,
264*6777b538SAndroid Build Coastguard Worker ZX_TIME_INFINITE, nullptr);
265*6777b538SAndroid Build Coastguard Worker ZX_DCHECK(status == ZX_OK, status) << "zx_object_wait_one";
266*6777b538SAndroid Build Coastguard Worker }
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Worker return process;
269*6777b538SAndroid Build Coastguard Worker }
270*6777b538SAndroid Build Coastguard Worker
GetAppOutput(const CommandLine & cl,std::string * output)271*6777b538SAndroid Build Coastguard Worker bool GetAppOutput(const CommandLine& cl, std::string* output) {
272*6777b538SAndroid Build Coastguard Worker int exit_code;
273*6777b538SAndroid Build Coastguard Worker bool result = GetAppOutputInternal(cl, false, output, &exit_code);
274*6777b538SAndroid Build Coastguard Worker return result && exit_code == EXIT_SUCCESS;
275*6777b538SAndroid Build Coastguard Worker }
276*6777b538SAndroid Build Coastguard Worker
GetAppOutput(const std::vector<std::string> & argv,std::string * output)277*6777b538SAndroid Build Coastguard Worker bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) {
278*6777b538SAndroid Build Coastguard Worker return GetAppOutput(CommandLine(argv), output);
279*6777b538SAndroid Build Coastguard Worker }
280*6777b538SAndroid Build Coastguard Worker
GetAppOutputAndError(const CommandLine & cl,std::string * output)281*6777b538SAndroid Build Coastguard Worker bool GetAppOutputAndError(const CommandLine& cl, std::string* output) {
282*6777b538SAndroid Build Coastguard Worker int exit_code;
283*6777b538SAndroid Build Coastguard Worker bool result = GetAppOutputInternal(cl, true, output, &exit_code);
284*6777b538SAndroid Build Coastguard Worker return result && exit_code == EXIT_SUCCESS;
285*6777b538SAndroid Build Coastguard Worker }
286*6777b538SAndroid Build Coastguard Worker
GetAppOutputAndError(const std::vector<std::string> & argv,std::string * output)287*6777b538SAndroid Build Coastguard Worker bool GetAppOutputAndError(const std::vector<std::string>& argv,
288*6777b538SAndroid Build Coastguard Worker std::string* output) {
289*6777b538SAndroid Build Coastguard Worker return GetAppOutputAndError(CommandLine(argv), output);
290*6777b538SAndroid Build Coastguard Worker }
291*6777b538SAndroid Build Coastguard Worker
GetAppOutputWithExitCode(const CommandLine & cl,std::string * output,int * exit_code)292*6777b538SAndroid Build Coastguard Worker bool GetAppOutputWithExitCode(const CommandLine& cl,
293*6777b538SAndroid Build Coastguard Worker std::string* output,
294*6777b538SAndroid Build Coastguard Worker int* exit_code) {
295*6777b538SAndroid Build Coastguard Worker // Contrary to GetAppOutput(), |true| return here means that the process was
296*6777b538SAndroid Build Coastguard Worker // launched and the exit code was waited upon successfully, but not
297*6777b538SAndroid Build Coastguard Worker // necessarily that the exit code was EXIT_SUCCESS.
298*6777b538SAndroid Build Coastguard Worker return GetAppOutputInternal(cl, false, output, exit_code);
299*6777b538SAndroid Build Coastguard Worker }
300*6777b538SAndroid Build Coastguard Worker
RaiseProcessToHighPriority()301*6777b538SAndroid Build Coastguard Worker void RaiseProcessToHighPriority() {
302*6777b538SAndroid Build Coastguard Worker // Fuchsia doesn't provide an API to change process priority.
303*6777b538SAndroid Build Coastguard Worker }
304*6777b538SAndroid Build Coastguard Worker
305*6777b538SAndroid Build Coastguard Worker } // namespace base
306