blob: 351151340dfbbd306338170f9faaba4b8bc2b2e5 [file] [log] [blame]
Ben Chan6f391cb2012-03-21 17:38:21 -07001// Copyright (c) 2012 The Chromium OS 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#ifndef CROS_DISKS_PROCESS_H_
6#define CROS_DISKS_PROCESS_H_
7
8#include <string>
François Degros597bcf42020-08-28 19:34:19 +10009#include <utility>
Ben Chan6f391cb2012-03-21 17:38:21 -070010#include <vector>
11
Sergei Datsenkocd676b72019-05-10 11:42:05 +100012#include <base/files/scoped_file.h>
François Degrosee318212020-07-14 14:11:42 +100013#include <base/strings/string_piece.h>
Sergei Datsenkocd676b72019-05-10 11:42:05 +100014
Ben Chan6f391cb2012-03-21 17:38:21 -070015#include <gtest/gtest_prod.h>
16
17namespace cros_disks {
18
19// A base class for executing a process.
20//
François Degrosc0b33b12019-09-12 14:50:43 +100021// TODO(crbug.com/1003654) This base class is not feature complete yet.
Ben Chan6f391cb2012-03-21 17:38:21 -070022class Process {
23 public:
Ben Chanacac3952012-04-24 22:50:01 -070024 // Invalid process ID assigned to a process that has not started.
25 static const pid_t kInvalidProcessId;
26
Sergei Datsenkocd676b72019-05-10 11:42:05 +100027 static const int kInvalidFD;
28
Sergei Datsenko50c204d2020-11-14 21:18:40 +110029 Process(const Process&) = delete;
30 Process& operator=(const Process&) = delete;
31
Ben Chan6f391cb2012-03-21 17:38:21 -070032 virtual ~Process();
33
François Degrosee318212020-07-14 14:11:42 +100034 // Adds an argument to the end of the argument list.
35 // Precondition: Start() has not been called yet.
36 void AddArgument(std::string argument);
37
38 // Adds a variable to the environment that will be passed to the process.
39 // Precondition: Start() has not been called yet.
40 // Precondition: `name` is not empty and doesn't contain '='.
41 void AddEnvironmentVariable(base::StringPiece name, base::StringPiece value);
Ben Chan6f391cb2012-03-21 17:38:21 -070042
François Degros597bcf42020-08-28 19:34:19 +100043 // Sets the string to pass to the process stdin.
44 // Might be silently truncated if it doesn't fit in a pipe's buffer.
45 // Precondition: Start() has not been called yet.
46 void SetStdIn(std::string input) { input_ = std::move(input); }
47
François Degros1ef69942019-10-01 15:31:17 +100048 // Starts the process. The started process has its stdin, stdout and stderr
49 // connected to /dev/null. Returns true in case of success. Once started, the
50 // process can be waiting for to finish using Wait().
Sergei Datsenkocd676b72019-05-10 11:42:05 +100051 bool Start();
Ben Chan6f391cb2012-03-21 17:38:21 -070052
Sergei Datsenko9246e9c2019-03-22 10:26:47 +110053 // Waits for the process to finish and returns its exit status.
Sergei Datsenkocd676b72019-05-10 11:42:05 +100054 int Wait();
55
56 // Checks if the process finished.
57 bool IsFinished();
Sergei Datsenko9246e9c2019-03-22 10:26:47 +110058
François Degrosedaefc52019-10-03 12:00:20 +100059 // Starts a process, captures its output and waits for it to finish. Returns
60 // the same exit status as Wait().
61 //
62 // Precondition: output is non-null
63 int Run(std::vector<std::string>* output);
Sergei Datsenko9246e9c2019-03-22 10:26:47 +110064
Ben Chanacac3952012-04-24 22:50:01 -070065 pid_t pid() const { return pid_; }
66
Sergei Datsenko9246e9c2019-03-22 10:26:47 +110067 const std::vector<std::string>& arguments() const { return arguments_; }
François Degrosee318212020-07-14 14:11:42 +100068 const std::vector<std::string>& environment() const { return environment_; }
François Degros597bcf42020-08-28 19:34:19 +100069 const std::string& input() const { return input_; }
Sergei Datsenko9246e9c2019-03-22 10:26:47 +110070
Ben Chan6f391cb2012-03-21 17:38:21 -070071 protected:
72 Process();
73
François Degros2a4ec242019-10-15 16:28:54 +110074 // Gets the arguments used to start the process. This method calls
75 // BuildArgumentsArray() to build |arguments_array_| only once (i.e. when
76 // |arguments_array_| is empty). Once |arguments_array_| is built, subsequent
77 // calls to AddArgument() are not allowed. The returned array of arguments is
78 // owned by this Process object.
François Degros5593b8c2019-07-25 12:27:42 +100079 char* const* GetArguments();
Ben Chan6f391cb2012-03-21 17:38:21 -070080
François Degrosee318212020-07-14 14:11:42 +100081 // Gets the environment to pass to the subprocess. The returned array of
82 // environment variables is owned by this Process object.
83 char* const* GetEnvironment();
84
François Degros1ef69942019-10-01 15:31:17 +100085 // Starts a process, and connects to its stdin, stdout and stderr the given
86 // file descriptors.
87 //
88 // Returns the PID of the started process, or -1 in case of error.
89 virtual pid_t StartImpl(base::ScopedFD in_fd,
90 base::ScopedFD out_fd,
91 base::ScopedFD err_fd) = 0;
François Degros92bbea42019-09-13 10:42:52 +100092
93 // Once either WaitImpl() or WaitNonBlockingImpl() has returned a nonnegative
94 // exit status, none of these methods is called again.
95
François Degros01564642019-09-13 14:10:17 +100096 // Waits for the process to finish and returns its nonnegative exit status.
Sergei Datsenkocd676b72019-05-10 11:42:05 +100097 virtual int WaitImpl() = 0;
François Degros92bbea42019-09-13 10:42:52 +100098
François Degros01564642019-09-13 14:10:17 +100099 // Checks if the process has finished and returns its nonnegative exit status,
100 // or -1 if the process is still running.
François Degros92bbea42019-09-13 10:42:52 +1000101 virtual int WaitNonBlockingImpl() = 0;
Ben Chanacac3952012-04-24 22:50:01 -0700102
Ben Chan6f391cb2012-03-21 17:38:21 -0700103 private:
François Degros1ef69942019-10-01 15:31:17 +1000104 // Starts the process. The started process has its stdin, stdout and stderr
105 // redirected to the given file descriptors. Returns true in case of success.
106 bool Start(base::ScopedFD in_fd,
107 base::ScopedFD out_fd,
108 base::ScopedFD err_fd);
109
Sergei Datsenkocd676b72019-05-10 11:42:05 +1000110 // Waits for process to finish collecting process' stdout and stderr
111 // output and fills interleaved version of it.
François Degros1ef69942019-10-01 15:31:17 +1000112 void Communicate(std::vector<std::string>* output,
113 base::ScopedFD out_fd,
114 base::ScopedFD err_fd);
Sergei Datsenkocd676b72019-05-10 11:42:05 +1000115
François Degros2a4ec242019-10-15 16:28:54 +1100116 // Builds |arguments_array_| from |arguments_|. Existing values of
117 // |arguments_array_| are overridden.
118 void BuildArgumentsArray();
Ben Chan6f391cb2012-03-21 17:38:21 -0700119
François Degros01564642019-09-13 14:10:17 +1000120 bool finished() const { return status_ >= 0; }
121
Ben Chan6f391cb2012-03-21 17:38:21 -0700122 // Process arguments.
123 std::vector<std::string> arguments_;
Ben Chan5e3ca672014-08-25 15:53:58 -0700124 std::vector<char*> arguments_array_;
Ben Chan6f391cb2012-03-21 17:38:21 -0700125
François Degrosee318212020-07-14 14:11:42 +1000126 // Extra environment variables.
127 std::vector<std::string> environment_;
128
129 // Full environment for the subprocess.
130 std::vector<char*> environment_array_;
131
François Degros597bcf42020-08-28 19:34:19 +1000132 // String to pass to the process stdin.
133 std::string input_;
134
Ben Chanacac3952012-04-24 22:50:01 -0700135 // Process ID (default to kInvalidProcessId when the process has not started).
Sergei Datsenkocd676b72019-05-10 11:42:05 +1000136 pid_t pid_ = kInvalidProcessId;
137
François Degros01564642019-09-13 14:10:17 +1000138 // Exit status. A nonnegative value indicates that the process has finished.
Sergei Datsenkocd676b72019-05-10 11:42:05 +1000139 int status_ = -1;
Ben Chanacac3952012-04-24 22:50:01 -0700140
Ben Chan6f391cb2012-03-21 17:38:21 -0700141 FRIEND_TEST(ProcessTest, GetArguments);
142 FRIEND_TEST(ProcessTest, GetArgumentsWithNoArgumentsAdded);
Ben Chan6f391cb2012-03-21 17:38:21 -0700143};
144
145} // namespace cros_disks
146
147#endif // CROS_DISKS_PROCESS_H_