blob: 11277492c0b498120b8bac1e3f41cd1cf1110ecc [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CROS_DISKS_PROCESS_H_
#define CROS_DISKS_PROCESS_H_
#include <string>
#include <vector>
#include <base/files/scoped_file.h>
#include <base/macros.h>
#include <gtest/gtest_prod.h>
namespace cros_disks {
// A base class for executing a process.
//
// TODO(benchan): This base class is not feature complete yet.
class Process {
public:
// Invalid process ID assigned to a process that has not started.
static const pid_t kInvalidProcessId;
static const int kInvalidFD;
virtual ~Process();
// Adds an argument to the end of the argument list. Any argument added by
// this method does not affect the process that has been started by Start().
void AddArgument(const std::string& argument);
// Starts the process without waiting for it to terminate.
bool Start();
// Waits for the process to finish and returns its exit status.
int Wait();
// Checks if the process finished.
bool IsFinished();
// Starts and waits for the process to finish. Returns the same exit status
// as Wait() does.
int Run(std::vector<std::string>* output = nullptr);
pid_t pid() const { return pid_; }
const std::vector<std::string>& arguments() const { return arguments_; }
protected:
Process();
// Returns the array of arguments used to start the process, or NULL if
// no arguments is added using AddArgument(). This method calls
// BuildArgumentsArray() to build |arguments_array_| only once (i.e.
// when |arguments_array_| is null). Once |arguments_array_| is built,
// subsequent calls to AddArgument() do not change the return value of
// this method. The returned array of arguments is managed by the base
// class.
char** GetArguments();
virtual pid_t StartImpl(std::vector<char*>& args,
base::ScopedFD* in_fd,
base::ScopedFD* out_fd,
base::ScopedFD* err_fd) = 0;
virtual int WaitImpl() = 0;
virtual bool WaitNonBlockingImpl(int* status) = 0;
private:
// Waits for process to finish collecting process' stdout and stderr
// output and fills interleaved version of it.
void Communicate(std::vector<std::string>* output);
// Builds |arguments_array_| and |arguments_buffer_| from |arguments_|.
// Existing values of |arguments_array_| and |arguments_buffer_| are
// overridden. Return false if |arguments_| is empty.
bool BuildArgumentsArray();
// Process arguments.
std::vector<std::string> arguments_;
std::vector<char*> arguments_array_;
std::vector<char> arguments_buffer_;
// Process ID (default to kInvalidProcessId when the process has not started).
pid_t pid_ = kInvalidProcessId;
base::ScopedFD in_fd_;
base::ScopedFD out_fd_;
base::ScopedFD err_fd_;
int status_ = -1;
bool finished_ = false;
FRIEND_TEST(ProcessTest, GetArguments);
FRIEND_TEST(ProcessTest, GetArgumentsWithNoArgumentsAdded);
FRIEND_TEST(ProcessTest, ReadStdout);
FRIEND_TEST(ProcessTest, ReadStderr);
FRIEND_TEST(ProcessTest, Communicate);
DISALLOW_COPY_AND_ASSIGN(Process);
};
} // namespace cros_disks
#endif // CROS_DISKS_PROCESS_H_