blob: 0a4450f33ab4a008dd95dc8fcc7b8e70c7cc3fc0 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/native_support/make_pty_pair.h"
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
namespace native_support {
bool MakePtyPair(base::ScopedFD* master_fd,
base::ScopedFD* slave_fd,
int* errno_value) {
DCHECK(master_fd);
DCHECK(!master_fd->is_valid()); // Not very wrong, but unlikely.
DCHECK(slave_fd);
DCHECK(!slave_fd->is_valid()); // Not very wrong, but unlikely.
DCHECK(errno_value);
#if defined(FNL_MUSL)
base::ScopedFD master(posix_openpt(O_RDWR | O_NOCTTY));
#else
// Android doesn't yet have posix_openpt
base::ScopedFD master(getpt());
#endif
if (!master.is_valid()) {
*errno_value = errno;
PLOG(ERROR) << "posix_openpt/getpt";
return false;
}
if (grantpt(master.get()) < 0) {
*errno_value = errno;
PLOG(ERROR) << "grantpt()";
return false;
}
if (unlockpt(master.get()) < 0) {
*errno_value = errno;
PLOG(ERROR) << "unlockpt()";
return false;
}
const char* name = ptsname(master.get());
if (!name) {
*errno_value = errno;
PLOG(ERROR) << "ptsname()";
return false;
}
base::ScopedFD slave(HANDLE_EINTR(open(name, O_RDWR)));
if (!slave.is_valid()) {
*errno_value = errno;
PLOG(ERROR) << "open()";
return false;
}
*master_fd = master.Pass();
*slave_fd = slave.Pass();
return true;
}
} // namespace native_support