libc.src.unistd.getpid
libc.src.unistd.getppid
libc.src.unistd.getuid
+ libc.src.unistd.isatty
libc.src.unistd.link
libc.src.unistd.linkat
libc.src.unistd.lseek
libc.include.stdio
libc.include.stdlib
libc.include.string
+ libc.include.sys_ioctl
libc.include.sys_mman
libc.include.sys_random
libc.include.sys_syscall
file(MAKE_DIRECTORY "sys")
add_gen_header(
+ sys_ioctl
+ DEF_FILE sys/ioctl.h.def
+ GEN_HDR sys/ioctl.h
+ DEPENDS
+ .llvm_libc_common_h
+ .llvm-libc-macros.sys_ioctl_macros
+)
+
+add_gen_header(
sys_mman
DEF_FILE sys/mman.h.def
GEN_HDR sys/mman.h
)
add_header(
+ sys_ioctl_macros
+ HDR
+ sys-ioctl-macros.h
+ DEPENDS
+ .linux.sys_ioctl_macros
+)
+
+
+add_header(
sys_stat_macros
HDR
sys-stat-macros.h
)
add_header(
+ sys_ioctl_macros
+ HDR
+ sys-ioctl-macros.h
+)
+
+add_header(
sys_mman_macros
HDR
sys-mman-macros.h
--- /dev/null
+//===-- Definition of macros from sys/ioctl.h -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_MACROS_LINUX_SYS_IOCTL_MACROS_H
+#define __LLVM_LIBC_MACROS_LINUX_SYS_IOCTL_MACROS_H
+
+// TODO (michaelrj): Finish defining these macros.
+// Just defining this macro for the moment since it's all that we need right
+// now. The other macros are mostly just constants, but there's some complexity
+// around the definitions of macros like _IO, _IOR, _IOW, and _IOWR that I don't
+// think is worth digging into right now.
+#define TIOCGETD 0x5424
+
+#endif // __LLVM_LIBC_MACROS_LINUX_SYS_IOCTL_MACROS_H
--- /dev/null
+//===-- Macros defined in sys/ioctl.h header file -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_MACROS_SYS_IOCTL_MACROS_H
+#define __LLVM_LIBC_MACROS_SYS_IOCTL_MACROS_H
+
+#ifdef __unix__
+#include "linux/sys-ioctl-macros.h"
+#endif
+
+#endif // __LLVM_LIBC_MACROS_SYS_IOCTL_MACROS_H
--- /dev/null
+//===-- POSIX header ioctl.h ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SYS_IOCTL_H
+#define LLVM_LIBC_SYS_IOCTL_H
+
+#include <__llvm-libc-common.h>
+
+#include <llvm-libc-macros/sys-ioctl-macros.h>
+
+%%public_api()
+
+#endif // LLVM_LIBC_SYS_IOCTL_H
[ArgSpec<VoidType>]
>,
FunctionSpec<
+ "isatty",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
"link",
RetValSpec<IntType>,
[ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>]
]
>;
+ HeaderSpec SysIOctl = HeaderSpec<
+ "sys/ioctl.h",
+ [
+ Macro<"TIOCGETD">,
+ ], // Macros
+ [], // Types
+ [], // Enumerations
+ [] // Functions
+ >;
+
let Headers = [
CType,
Dirent,
Signal,
StdIO,
StdLib,
+ SysIOctl,
SysMMan,
SysResource,
SysStat,
)
add_entrypoint_object(
+ isatty
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.isatty
+)
+
+add_entrypoint_object(
link
ALIAS
DEPENDS
--- /dev/null
+//===-- Implementation header for isatty ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_UNISTD_ISATTY_H
+#define LLVM_LIBC_SRC_UNISTD_ISATTY_H
+
+#include <unistd.h>
+
+namespace __llvm_libc {
+
+int isatty(int fd);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_UNISTD_ISATTY_H
)
add_entrypoint_object(
+ isatty
+ SRCS
+ isatty.cpp
+ HDRS
+ ../isatty.h
+ DEPENDS
+ libc.include.unistd
+ libc.include.errno
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
link
SRCS
link.cpp
--- /dev/null
+//===-- Linux implementation of isatty ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/isatty.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <sys/ioctl.h> // For ioctl numbers.
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, isatty, (int fd)) {
+ constexpr int INIT_VAL = 0x1234abcd;
+ int line_d_val = INIT_VAL;
+ // This gets the line dicipline of the terminal. When called on something that
+ // isn't a terminal it doesn't change line_d_val and returns -1.
+ int result = __llvm_libc::syscall_impl(SYS_ioctl, fd, TIOCGETD, &line_d_val);
+ if (result == 0)
+ return 1;
+
+ errno = -result;
+ return 0;
+}
+
+} // namespace __llvm_libc
)
add_libc_unittest(
+ isatty_test
+ SUITE
+ libc_unistd_unittests
+ SRCS
+ isatty_test.cpp
+ DEPENDS
+ libc.src.unistd.isatty
+ libc.src.fcntl.open
+ libc.src.unistd.close
+ libc.include.errno
+ libc.src.errno.errno
+)
+
+add_libc_unittest(
geteuid_test
SUITE
libc_unistd_unittests
--- /dev/null
+//===-- Unittests for isatty ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/fcntl/open.h"
+#include "src/unistd/close.h"
+#include "src/unistd/isatty.h"
+#include "test/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+
+#include <errno.h>
+
+using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+
+TEST(LlvmLibcIsATTYTest, StdInOutTests) {
+ // If stdin is connected to a terminal, assume that all of the standard i/o
+ // fds are.
+ if (__llvm_libc::isatty(0)) {
+ EXPECT_THAT(__llvm_libc::isatty(0), Succeeds(1)); // stdin
+ EXPECT_THAT(__llvm_libc::isatty(1), Succeeds(1)); // stdout
+ EXPECT_THAT(__llvm_libc::isatty(2), Succeeds(1)); // stderr
+ } else {
+ EXPECT_THAT(__llvm_libc::isatty(0), Fails(ENOTTY, 0)); // stdin
+ EXPECT_THAT(__llvm_libc::isatty(1), Fails(ENOTTY, 0)); // stdout
+ EXPECT_THAT(__llvm_libc::isatty(2), Fails(ENOTTY, 0)); // stderr
+ }
+}
+
+TEST(LlvmLibcIsATTYTest, BadFdTest) {
+ EXPECT_THAT(__llvm_libc::isatty(-1), Fails(EBADF, 0)); // invalid fd
+}
+
+TEST(LlvmLibcIsATTYTest, DevTTYTest) {
+ constexpr const char *TTY_FILE = "/dev/tty";
+ int fd = __llvm_libc::open(TTY_FILE, O_RDONLY);
+ ASSERT_EQ(errno, 0);
+ ASSERT_GT(fd, 0);
+ EXPECT_THAT(__llvm_libc::isatty(fd), Succeeds(1));
+ ASSERT_THAT(__llvm_libc::close(fd), Succeeds(0));
+}
+
+TEST(LlvmLibcIsATTYTest, FileTest) {
+ constexpr const char *TEST_FILE = "testdata/isatty.test";
+ int fd = __llvm_libc::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
+ ASSERT_EQ(errno, 0);
+ ASSERT_GT(fd, 0);
+ EXPECT_THAT(__llvm_libc::isatty(fd), Fails(ENOTTY, 0));
+ ASSERT_THAT(__llvm_libc::close(fd), Succeeds(0));
+}