Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 1 | // 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> |
| 9 | #include <vector> |
| 10 | |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 11 | #include <base/files/scoped_file.h> |
Ben Chan | 3b832b9 | 2014-09-02 19:39:57 -0700 | [diff] [blame] | 12 | #include <base/macros.h> |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 13 | |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 14 | #include <gtest/gtest_prod.h> |
| 15 | |
| 16 | namespace cros_disks { |
| 17 | |
| 18 | // A base class for executing a process. |
| 19 | // |
François Degros | c0b33b1 | 2019-09-12 14:50:43 +1000 | [diff] [blame] | 20 | // TODO(crbug.com/1003654) This base class is not feature complete yet. |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 21 | class Process { |
| 22 | public: |
Ben Chan | acac395 | 2012-04-24 22:50:01 -0700 | [diff] [blame] | 23 | // Invalid process ID assigned to a process that has not started. |
| 24 | static const pid_t kInvalidProcessId; |
| 25 | |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 26 | static const int kInvalidFD; |
| 27 | |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 28 | virtual ~Process(); |
| 29 | |
| 30 | // Adds an argument to the end of the argument list. Any argument added by |
| 31 | // this method does not affect the process that has been started by Start(). |
| 32 | void AddArgument(const std::string& argument); |
| 33 | |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 34 | // Starts the process without waiting for it to terminate. |
| 35 | bool Start(); |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 36 | |
Sergei Datsenko | 9246e9c | 2019-03-22 10:26:47 +1100 | [diff] [blame] | 37 | // Waits for the process to finish and returns its exit status. |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 38 | int Wait(); |
| 39 | |
| 40 | // Checks if the process finished. |
| 41 | bool IsFinished(); |
Sergei Datsenko | 9246e9c | 2019-03-22 10:26:47 +1100 | [diff] [blame] | 42 | |
François Degros | edaefc5 | 2019-10-03 12:00:20 +1000 | [diff] [blame^] | 43 | // Starts a process, captures its output and waits for it to finish. Returns |
| 44 | // the same exit status as Wait(). |
| 45 | // |
| 46 | // Precondition: output is non-null |
| 47 | int Run(std::vector<std::string>* output); |
Sergei Datsenko | 9246e9c | 2019-03-22 10:26:47 +1100 | [diff] [blame] | 48 | |
Ben Chan | acac395 | 2012-04-24 22:50:01 -0700 | [diff] [blame] | 49 | pid_t pid() const { return pid_; } |
| 50 | |
Sergei Datsenko | 9246e9c | 2019-03-22 10:26:47 +1100 | [diff] [blame] | 51 | const std::vector<std::string>& arguments() const { return arguments_; } |
| 52 | |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 53 | protected: |
| 54 | Process(); |
| 55 | |
| 56 | // Returns the array of arguments used to start the process, or NULL if |
| 57 | // no arguments is added using AddArgument(). This method calls |
| 58 | // BuildArgumentsArray() to build |arguments_array_| only once (i.e. |
| 59 | // when |arguments_array_| is null). Once |arguments_array_| is built, |
| 60 | // subsequent calls to AddArgument() do not change the return value of |
| 61 | // this method. The returned array of arguments is managed by the base |
| 62 | // class. |
François Degros | 5593b8c | 2019-07-25 12:27:42 +1000 | [diff] [blame] | 63 | char* const* GetArguments(); |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 64 | |
François Degros | 5593b8c | 2019-07-25 12:27:42 +1000 | [diff] [blame] | 65 | virtual pid_t StartImpl(base::ScopedFD* in_fd, |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 66 | base::ScopedFD* out_fd, |
| 67 | base::ScopedFD* err_fd) = 0; |
François Degros | 92bbea4 | 2019-09-13 10:42:52 +1000 | [diff] [blame] | 68 | |
| 69 | // Once either WaitImpl() or WaitNonBlockingImpl() has returned a nonnegative |
| 70 | // exit status, none of these methods is called again. |
| 71 | |
François Degros | 0156464 | 2019-09-13 14:10:17 +1000 | [diff] [blame] | 72 | // Waits for the process to finish and returns its nonnegative exit status. |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 73 | virtual int WaitImpl() = 0; |
François Degros | 92bbea4 | 2019-09-13 10:42:52 +1000 | [diff] [blame] | 74 | |
François Degros | 0156464 | 2019-09-13 14:10:17 +1000 | [diff] [blame] | 75 | // Checks if the process has finished and returns its nonnegative exit status, |
| 76 | // or -1 if the process is still running. |
François Degros | 92bbea4 | 2019-09-13 10:42:52 +1000 | [diff] [blame] | 77 | virtual int WaitNonBlockingImpl() = 0; |
Ben Chan | acac395 | 2012-04-24 22:50:01 -0700 | [diff] [blame] | 78 | |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 79 | private: |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 80 | // Waits for process to finish collecting process' stdout and stderr |
| 81 | // output and fills interleaved version of it. |
| 82 | void Communicate(std::vector<std::string>* output); |
| 83 | |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 84 | // Builds |arguments_array_| and |arguments_buffer_| from |arguments_|. |
| 85 | // Existing values of |arguments_array_| and |arguments_buffer_| are |
| 86 | // overridden. Return false if |arguments_| is empty. |
| 87 | bool BuildArgumentsArray(); |
| 88 | |
François Degros | 0156464 | 2019-09-13 14:10:17 +1000 | [diff] [blame] | 89 | bool finished() const { return status_ >= 0; } |
| 90 | |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 91 | // Process arguments. |
| 92 | std::vector<std::string> arguments_; |
Ben Chan | 5e3ca67 | 2014-08-25 15:53:58 -0700 | [diff] [blame] | 93 | std::vector<char*> arguments_array_; |
| 94 | std::vector<char> arguments_buffer_; |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 95 | |
Ben Chan | acac395 | 2012-04-24 22:50:01 -0700 | [diff] [blame] | 96 | // Process ID (default to kInvalidProcessId when the process has not started). |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 97 | pid_t pid_ = kInvalidProcessId; |
| 98 | |
| 99 | base::ScopedFD in_fd_; |
| 100 | base::ScopedFD out_fd_; |
| 101 | base::ScopedFD err_fd_; |
| 102 | |
François Degros | 0156464 | 2019-09-13 14:10:17 +1000 | [diff] [blame] | 103 | // Exit status. A nonnegative value indicates that the process has finished. |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 104 | int status_ = -1; |
Ben Chan | acac395 | 2012-04-24 22:50:01 -0700 | [diff] [blame] | 105 | |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 106 | FRIEND_TEST(ProcessTest, GetArguments); |
| 107 | FRIEND_TEST(ProcessTest, GetArgumentsWithNoArgumentsAdded); |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 108 | |
| 109 | DISALLOW_COPY_AND_ASSIGN(Process); |
| 110 | }; |
| 111 | |
| 112 | } // namespace cros_disks |
| 113 | |
| 114 | #endif // CROS_DISKS_PROCESS_H_ |