Android-cuttlefish cvd tool
command.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2018 The Android Open Source Project
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#pragma once
17
18#include <map>
19#include <ostream>
20#include <sstream>
21#include <string>
22#include <string_view>
23#include <utility>
24#include <vector>
25
26#include "absl/log/check.h"
27
32
33namespace cuttlefish {
34
35// An executable command. Multiple subprocesses can be started from the same
36// command object. This class owns any file descriptors that the subprocess
37// should inherit.
38class Command {
39 private:
40 template <typename T>
41 // For every type other than SharedFD (for which there is a specialisation)
42 void BuildParameter(std::stringstream* stream, T t) {
43 *stream << t;
44 }
45 // Special treatment for SharedFD
46 void BuildParameter(std::stringstream* stream, SharedFD shared_fd);
47 void BuildParameter(std::stringstream* stream, Fd fd);
48 // Special treatment for bool so it uses true/false instead of 1/0
49 void BuildParameter(std::stringstream* stream, bool arg);
50 template <typename T, typename... Args>
51 void BuildParameter(std::stringstream* stream, T&& t, Args&&... args) {
52 BuildParameter(stream, std::forward<T>(t));
53 BuildParameter(stream, std::forward<Args>(args)...);
54 }
55
56 public:
57 enum class StdIoChannel {
58 kStdIn = 0,
59 kStdOut = 1,
60 kStdErr = 2,
61 };
62
63 // Constructs a command object from the path to an executable binary and an
64 // optional subprocess stopper. When not provided, stopper defaults to sending
65 // SIGKILL to the subprocess.
66 Command(std::string executable, SubprocessStopper stopper = KillSubprocess);
67 Command(Command&&) = default;
68 // The default copy constructor is unsafe because it would mean multiple
69 // closing of the inherited file descriptors. If needed it can be implemented
70 // using dup(2)
71 Command(const Command&) = delete;
72 Command& operator=(const Command&) = delete;
73 ~Command();
74
75 const std::string& Executable() const {
76 return executable_ ? *executable_ : command_[0];
77 }
78
79 Command& SetExecutable(std::string executable) & {
80 executable_ = std::move(executable);
81 return *this;
82 }
83 Command SetExecutable(std::string executable) && {
84 return std::move(SetExecutable(executable));
85 }
86
87 Command& SetName(std::string name) & {
88 command_[0] = std::move(name);
89 return *this;
90 }
91 Command SetName(std::string name) && {
92 return std::move(SetName(std::move(name)));
93 }
94
96 return SetExecutable(name).SetName(std::move(name));
97 }
98
100 return std::move(SetExecutableAndName(std::move(name)));
101 }
102
104 subprocess_stopper_ = std::move(stopper);
105 return *this;
106 }
108 return std::move(SetStopper(std::move(stopper)));
109 }
110
111 // Specify the environment for the subprocesses to be started. By default
112 // subprocesses inherit the parent's environment.
113 Command& SetEnvironment(std::vector<std::string> env) & {
114 env_ = std::move(env);
115 return *this;
116 }
117 Command SetEnvironment(std::vector<std::string> env) && {
118 return std::move(SetEnvironment(std::move(env)));
119 }
120
121 Command& AddEnvironmentVariable(std::string_view env_var,
122 std::string_view value) &;
123 Command AddEnvironmentVariable(std::string_view env_var,
124 std::string_view value) &&;
125
126 // Specify an environment variable to be unset from the parent's
127 // environment for the subprocesses to be started.
128 Command& UnsetFromEnvironment(std::string_view env_var) &;
129 Command UnsetFromEnvironment(std::string_view env_var) &&;
130
131 // Adds a single parameter to the command. All arguments are concatenated into
132 // a single string to form a parameter. If one of those arguments is a
133 // SharedFD a duplicate of it will be used and won't be closed until the
134 // object is destroyed. To add multiple parameters to the command the function
135 // must be called multiple times, one per parameter.
136 template <typename... Args>
137 Command& AddParameter(Args&&... args) & {
138 std::stringstream ss;
139 BuildParameter(&ss, std::forward<Args>(args)...);
140 command_.push_back(ss.str());
141 return *this;
142 }
143 template <typename... Args>
144 Command AddParameter(Args&&... args) && {
145 return std::move(AddParameter(std::forward<Args>(args)...));
146 }
147 Command& AddParameter(std::string arg) &;
148 Command AddParameter(std::string arg) &&;
149
150 // Similar to AddParameter, except the args are appended to the last (most
151 // recently-added) parameter in the command.
152 template <typename... Args>
154 CHECK(!command_.empty()) << "There is no parameter to append to.";
155 std::stringstream ss;
156 BuildParameter(&ss, args...);
157 command_[command_.size() - 1] += ss.str();
158 return *this;
159 }
160 template <typename... Args>
162 return std::move(AppendToLastParameter(std::forward<Args>(args)...));
163 }
164
165 // Redirects the standard IO of the command.
166 Command& RedirectStdIO(StdIoChannel channel, SharedFD shared_fd) &;
167 Command RedirectStdIO(StdIoChannel channel, SharedFD shared_fd) &&;
168 Command& RedirectStdIO(StdIoChannel subprocess_channel,
169 StdIoChannel parent_channel) &;
170 Command RedirectStdIO(StdIoChannel subprocess_channel,
171 StdIoChannel parent_channel) &&;
172
173 Command& SetWorkingDirectory(const std::string& path) &;
174 Command SetWorkingDirectory(const std::string& path) &&;
177
178 Command& AddPrerequisite(const std::function<Result<void>()>& prerequisite) &;
179 Command AddPrerequisite(const std::function<Result<void>()>& prerequisite) &&;
180
181 // Starts execution of the command. This method can be called multiple times,
182 // effectively staring multiple (possibly concurrent) instances.
184
185 std::string GetShortName() const {
186 // This is safe because the constructor guarantees the name of the binary to
187 // be at index 0 on the vector
188 return command_[0];
189 }
190
191 std::string ToString() const;
192
193 // Generates the contents for a bash script that can be used to run this
194 // command. Note that this command must not require any file descriptors
195 // or stdio redirects as those would not be available when the bash script
196 // is run.
197 std::string AsBashScript(const std::string& redirected_stdio_path = "") const;
198
199 private:
200 friend std::ostream& operator<<(std::ostream& out, const Command& command);
201 std::optional<std::string> executable_; // When unset, use command_[0]
202 std::vector<std::string> command_;
203 std::vector<std::function<Result<void>()>> prerequisites_;
204 std::map<SharedFD, int> inherited_fds_{};
205 std::map<StdIoChannel, int> redirects_{};
206 std::vector<std::string> env_{};
209};
210std::ostream& operator<<(std::ostream& out, const Command& command);
211
212} // namespace cuttlefish
Definition: command.h:38
~Command()
Definition: command.cc:113
std::vector< std::string > command_
Definition: command.h:202
std::map< SharedFD, int > inherited_fds_
Definition: command.h:204
Command & AddEnvironmentVariable(std::string_view env_var, std::string_view value) &
Definition: command.cc:145
Command SetExecutable(std::string executable) &&
Definition: command.h:83
Command & RedirectStdIO(StdIoChannel channel, SharedFD shared_fd) &
Definition: command.cc:183
friend std::ostream & operator<<(std::ostream &out, const Command &command)
Definition: command.cc:336
Command(std::string executable, SubprocessStopper stopper=KillSubprocess)
Definition: command.cc:105
Command & SetExecutable(std::string executable) &
Definition: command.h:79
Command & UnsetFromEnvironment(std::string_view env_var) &
Definition: command.cc:157
void BuildParameter(std::stringstream *stream, T t)
Definition: command.h:42
std::string GetShortName() const
Definition: command.h:185
Command & AddPrerequisite(const std::function< Result< void >()> &prerequisite) &
Definition: command.cc:234
SharedFD working_directory_
Definition: command.h:208
std::string AsBashScript(const std::string &redirected_stdio_path="") const
Definition: command.cc:361
void BuildParameter(std::stringstream *stream, T &&t, Args &&... args)
Definition: command.h:51
std::vector< std::string > env_
Definition: command.h:206
Command(const Command &)=delete
const std::string & Executable() const
Definition: command.h:75
std::map< StdIoChannel, int > redirects_
Definition: command.h:205
Subprocess Start(SubprocessOptions options=SubprocessOptions()) const
Definition: command.cc:246
std::string ToString() const
Definition: command.cc:353
Command & SetEnvironment(std::vector< std::string > env) &
Definition: command.h:113
Command & operator=(const Command &)=delete
Command SetExecutableAndName(std::string name) &&
Definition: command.h:99
std::vector< std::function< Result< void >()> > prerequisites_
Definition: command.h:203
Command AppendToLastParameter(Args... args) &&
Definition: command.h:161
Command SetEnvironment(std::vector< std::string > env) &&
Definition: command.h:117
Command & SetName(std::string name) &
Definition: command.h:87
Command SetStopper(SubprocessStopper stopper) &&
Definition: command.h:107
Command & SetExecutableAndName(std::string name) &
Definition: command.h:95
Command & AddParameter(Args &&... args) &
Definition: command.h:137
Command(Command &&)=default
Command SetName(std::string name) &&
Definition: command.h:91
Command & AppendToLastParameter(Args... args) &
Definition: command.h:153
StdIoChannel
Definition: command.h:57
Command & SetWorkingDirectory(const std::string &path) &
Definition: command.cc:210
std::optional< std::string > executable_
Definition: command.h:201
SubprocessStopper subprocess_stopper_
Definition: command.h:207
Command & SetStopper(SubprocessStopper stopper) &
Definition: command.h:103
Command AddParameter(Args &&... args) &&
Definition: command.h:144
Definition: fd.h:88
Definition: shared_fd.h:124
Definition: subprocess_options.h:22
Definition: subprocess.h:45
int options
Definition: f2fscrypt.c:124
#define CHECK(x)
Definition: logging.h:251
char * name
Definition: libf2fs.c:1403
Definition: alloc_driver.h:20
StopperResult KillSubprocess(Subprocess *subprocess)
Definition: subprocess.cc:137
std::function< StopperResult(Subprocess *)> SubprocessStopper
Definition: subprocess.h:35
tl::expected< T, StackTraceError > Result
Definition: result_type.h:30
std::ostream & operator<<(std::ostream &out, DeviceType device_type)
Definition: device_type.cpp:72
std::vector< std::string_view > Args
Definition: incremental.h:28