scottmg | e5a1d49 | 2017-05-24 23:41:43 | [diff] [blame^] | 1 | // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "base/process/launch.h" |
| 6 | |
| 7 | #include <launchpad/launchpad.h> |
| 8 | #include <magenta/process.h> |
| 9 | |
| 10 | #include "base/command_line.h" |
| 11 | |
| 12 | namespace base { |
| 13 | |
| 14 | Process LaunchProcess(const CommandLine& cmdline, |
| 15 | const LaunchOptions& options) { |
| 16 | return LaunchProcess(cmdline.argv(), options); |
| 17 | } |
| 18 | |
| 19 | Process LaunchProcess(const std::vector<std::string>& argv, |
| 20 | const LaunchOptions& options) { |
| 21 | std::vector<const char*> argv_cstr; |
| 22 | argv_cstr.reserve(argv.size() + 1); |
| 23 | for (size_t i = 0; i < argv.size(); i++) { |
| 24 | argv_cstr.push_back(argv[i].c_str()); |
| 25 | } |
| 26 | argv_cstr.push_back(nullptr); |
| 27 | |
| 28 | // Note that per launchpad.h, the intention is that launchpad_ functions are |
| 29 | // used in a "builder" style. From launchpad_create() to launchpad_go() the |
| 30 | // status is tracked in the launchpad_t object, and launchpad_go() reports on |
| 31 | // the final status, and cleans up |lp| (assuming it was even created). |
| 32 | launchpad_t* lp; |
| 33 | launchpad_create(options.job_handle, argv_cstr[0], &lp); |
| 34 | launchpad_load_from_file(lp, argv_cstr[0]); |
| 35 | launchpad_set_args(lp, argv.size(), argv_cstr.data()); |
| 36 | |
| 37 | uint32_t to_clone = |
| 38 | LP_CLONE_MXIO_ROOT | LP_CLONE_MXIO_CWD | LP_CLONE_DEFAULT_JOB; |
| 39 | |
| 40 | std::unique_ptr<char* []> new_environ; |
| 41 | char* const empty_environ = nullptr; |
| 42 | char* const* old_environ = environ; |
| 43 | if (options.clear_environ) |
| 44 | old_environ = &empty_environ; |
| 45 | if (!options.environ.empty()) |
| 46 | new_environ = AlterEnvironment(old_environ, options.environ); |
| 47 | if (!options.environ.empty() || options.clear_environ) |
| 48 | launchpad_set_environ(lp, new_environ.get()); |
| 49 | else |
| 50 | to_clone |= LP_CLONE_ENVIRON; |
| 51 | |
| 52 | if (!options.fds_to_remap) |
| 53 | to_clone |= LP_CLONE_MXIO_STDIO; |
| 54 | launchpad_clone(lp, to_clone); |
| 55 | |
| 56 | if (options.fds_to_remap) { |
| 57 | for (const auto& src_target : *options.fds_to_remap) { |
| 58 | launchpad_clone_fd(lp, src_target.first, src_target.second); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | mx_handle_t proc; |
| 63 | const char* errmsg; |
| 64 | mx_status_t status = launchpad_go(lp, &proc, &errmsg); |
| 65 | if (status != NO_ERROR) { |
| 66 | LOG(ERROR) << "launchpad_go failed: " << errmsg << ", status=" << status; |
| 67 | return Process(); |
| 68 | } |
| 69 | |
| 70 | return Process(proc); |
| 71 | } |
| 72 | |
| 73 | } // namespace base |