1 // Copyright (C) 2022 The Android Open Source Project 2 // 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 #pragma once 15 16 #include <atomic> 17 #include <chrono> 18 #include <cstdio> 19 #include <functional> 20 #include <future> 21 #include <istream> 22 #include <memory> 23 #include <optional> 24 #include <string> 25 #include <string_view> 26 #include <unordered_map> 27 #include <utility> 28 #include <vector> 29 30 #include "aemu/base/streams/RingStreambuf.h" 31 #include "aemu/base/process/Process.h" 32 33 namespace android { 34 namespace base { 35 36 using android::base::streams::RingStreambuf; 37 using BufferDefinition = std::pair<size_t, std::chrono::milliseconds>; 38 using CommandArguments = std::vector<std::string>; 39 40 /** 41 * @brief A Command that you can execute and observe. 42 */ 43 class Command { 44 public: 45 /** 46 * @brief Alias for a function that creates ObservableProcess instances. 47 */ 48 using ProcessFactory = 49 std::function<std::unique_ptr<ObservableProcess>(CommandArguments, bool, bool)>; 50 51 /** 52 * @brief Sets the standard output buffer size and timeout. 53 * 54 * If the buffer is filled, the process will block for at most |w| 55 * milliseconds before timing out. Timeouts can result in data loss or 56 * stream closure. 57 * 58 * @param n The maximum number of bytes to buffer for standard output. 59 * @param w The maximum time to wait for buffer space, defaults to one year. 60 * @return A reference to this Command object for chaining. 61 */ 62 Command& withStdoutBuffer( 63 size_t n, 64 std::chrono::milliseconds w = std::chrono::hours(24 * 365)); 65 66 /** 67 * @brief Sets the standard error buffer size and timeout. 68 * 69 * If the buffer is filled, the process will block for at most |w| 70 * milliseconds before timing out. Timeouts can result in data loss or 71 * stream closure. 72 * 73 * @param n The maximum number of bytes to buffer for standard error. 74 * @param w The maximum time to wait for buffer space, defaults to one year. 75 * @return A reference to this Command object for chaining. 76 */ 77 Command& withStderrBuffer( 78 size_t n, 79 std::chrono::milliseconds w = std::chrono::hours(24 * 365)); 80 81 /** 82 * @brief Adds a single argument to the list of arguments. 83 * 84 * @param arg The argument to add. 85 * @return A reference to this Command object for chaining. 86 */ 87 Command& arg(const std::string& arg); 88 89 /** 90 * @brief Adds a list of arguments to the existing arguments. 91 * 92 * @param args The arguments to add. 93 * @return A reference to this Command object for chaining. 94 */ 95 Command& args(const CommandArguments& args); 96 97 /** 98 * @brief Launches the command as a daemon. 99 * 100 * You will not be able to read stderr/stdout, and the process will not be 101 * terminated when the created process goes out of scope. 102 * 103 * @return A reference to this Command object for chaining. 104 */ 105 Command& asDeamon(); 106 107 /** 108 * @brief Sets the command to inherit all file handles. 109 * 110 * @return A reference to this Command object for chaining. 111 */ 112 Command& inherit(); 113 114 /** 115 * @brief Sets the command to replace the current process. 116 * 117 * This behaves similarly to execv. 118 * 119 * @return A reference to this Command object for chaining. 120 */ 121 Command& replace(); 122 123 /** 124 * @brief Launches the process. 125 * 126 * @return A unique pointer to the ObservableProcess representing the 127 * launched process. 128 */ 129 std::unique_ptr<ObservableProcess> execute(); 130 131 /** 132 * @brief Creates a new Command object. 133 * 134 * @param programWithArgs The program to execute, along with its arguments. 135 * @return A Command object representing the command to execute. 136 */ 137 static Command create(CommandArguments programWithArgs); 138 139 /** 140 * @brief Sets a custom ProcessFactory for testing. 141 * 142 * You likely only want to use this for testing. Implement your own factory 143 * that produces an implemented process. Make sure to set to nullptr when 144 * you want to revert to the default. 145 * 146 * @param factory The custom ProcessFactory to use. 147 */ 148 static void setTestProcessFactory(ProcessFactory factory); 149 150 protected: 151 Command() = default; 152 153 /** 154 * @brief Constructor with initial command arguments. 155 * 156 * @param args The initial command arguments. 157 */ Command(CommandArguments args)158 Command(CommandArguments args) : mArgs(args){}; 159 160 private: 161 static ProcessFactory sProcessFactory; 162 static ProcessFactory sTestFactory; 163 164 CommandArguments mArgs; 165 bool mDeamon{false}; 166 bool mCaptureOutput{false}; 167 bool mInherit{false}; 168 bool mReplace{false}; 169 BufferDefinition mStdout{0, 0}; 170 BufferDefinition mStderr{0, 0}; 171 }; 172 } // namespace base 173 } // namespace android 174