• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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