blob: c497a03daab8f42d5e060644cfc2e163ed2c0cdb [file] [log] [blame]
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string>
#include <glog/logging.h>
#include <process/future.hpp>
#include <process/reap.hpp>
#include <process/subprocess.hpp>
#include <stout/error.hpp>
#include <stout/foreach.hpp>
#include <stout/lambda.hpp>
#include <stout/option.hpp>
#include <stout/os.hpp>
#include <stout/strings.hpp>
#include <stout/try.hpp>
#include <stout/windows.hpp>
#include <stout/os/int_fd.hpp>
#include <stout/os/open.hpp>
#include <stout/os/pipe.hpp>
#include <stout/os/strerror.hpp>
using std::array;
using std::string;
namespace process {
using InputFileDescriptors = Subprocess::IO::InputFileDescriptors;
using OutputFileDescriptors = Subprocess::IO::OutputFileDescriptors;
// Opens a pair of file handles. On success, the first handle returned receives
// the 'read' handle of the pipe, while the second receives the 'write' handle.
// The pipe handles can then be passed to a child process, as shown in [1].
//
// [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
Subprocess::IO Subprocess::PIPE()
{
return Subprocess::IO(
[]() -> Try<InputFileDescriptors> {
// Create STDIN pipe and set the 'read' component to be not overlapped,
// because we're sending it to the child process.
const Try<array<int_fd, 2>> pipefd = os::pipe(false, true);
if (pipefd.isError()) {
return Error(pipefd.error());
}
return InputFileDescriptors{pipefd.get()[0], pipefd.get()[1]};
},
[]() -> Try<OutputFileDescriptors> {
// Create STDOUT pipe and set the 'write' component to be not
// overlapped, because we're sending it to the child process.
const Try<array<int_fd, 2>> pipefd = os::pipe(true, false);
if (pipefd.isError()) {
return Error(pipefd.error());
}
return OutputFileDescriptors{pipefd.get()[0], pipefd.get()[1]};
});
}
Subprocess::IO Subprocess::PATH(const string& path)
{
return Subprocess::IO(
[path]() -> Try<InputFileDescriptors> {
const Try<int_fd> open = os::open(path, O_RDONLY);
if (open.isError()) {
return Error(open.error());
}
return InputFileDescriptors{open.get(), None()};
},
[path]() -> Try<OutputFileDescriptors> {
const Try<int_fd> open = os::open(path, O_WRONLY | O_CREAT | O_APPEND);
if (open.isError()) {
return Error(open.error());
}
return OutputFileDescriptors{None(), open.get()};
});
}
} // namespace process {