summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc/port/sys/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libc/port/sys/open.c')
-rw-r--r--usr/src/lib/libc/port/sys/open.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/usr/src/lib/libc/port/sys/open.c b/usr/src/lib/libc/port/sys/open.c
new file mode 100644
index 0000000000..067bb72d69
--- /dev/null
+++ b/usr/src/lib/libc/port/sys/open.c
@@ -0,0 +1,183 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+#include "lint.h"
+#include <sys/mkdev.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <strings.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#include <sys/ptms.h>
+#include <sys/syscall.h>
+#include "libc.h"
+
+static int xpg4_fixup(int fd);
+static void push_module(int fd);
+static int isptsfd(int fd);
+static void itoa(int i, char *ptr);
+
+int
+__openat(int dfd, const char *path, int oflag, mode_t mode)
+{
+ int fd = syscall(SYS_openat, dfd, path, oflag, mode);
+ return (xpg4_fixup(fd));
+}
+
+int
+__open(const char *path, int oflag, mode_t mode)
+{
+#if defined(_RETAIN_OLD_SYSCALLS)
+ int fd = syscall(SYS_open, path, oflag, mode);
+ return (xpg4_fixup(fd));
+#else
+ return (__openat(AT_FDCWD, path, oflag, mode));
+#endif
+}
+
+#if !defined(_LP64)
+
+int
+__openat64(int dfd, const char *path, int oflag, mode_t mode)
+{
+ int fd = syscall(SYS_openat64, dfd, path, oflag, mode);
+ return (xpg4_fixup(fd));
+}
+
+int
+__open64(const char *path, int oflag, mode_t mode)
+{
+#if defined(_RETAIN_OLD_SYSCALLS)
+ int fd = syscall(SYS_open64, path, oflag, mode);
+ return (xpg4_fixup(fd));
+#else
+ return (__openat64(AT_FDCWD, path, oflag, mode));
+#endif
+}
+
+#endif /* !_LP64 */
+
+/*
+ * XPG4v2 requires that open of a slave pseudo terminal device
+ * provides the process with an interface that is identical to
+ * the terminal interface. For a more detailed discussion,
+ * see bugid 4025044.
+ */
+static int
+xpg4_fixup(int fd)
+{
+ if (libc__xpg4 != 0 && fd >= 0 && isptsfd(fd))
+ push_module(fd);
+ return (fd);
+}
+
+/*
+ * Check if the file matches an entry in the /dev/pts directory.
+ * Be careful to preserve errno.
+ */
+static int
+isptsfd(int fd)
+{
+ char buf[TTYNAME_MAX];
+ char *str1 = buf;
+ const char *str2 = "/dev/pts/";
+ struct stat64 fsb, stb;
+ int oerrno = errno;
+ int rval = 0;
+
+ if (fstat64(fd, &fsb) == 0 && S_ISCHR(fsb.st_mode)) {
+ /*
+ * Do this without strcpy() or strlen(),
+ * to avoid invoking the dynamic linker.
+ */
+ while (*str2 != '\0')
+ *str1++ = *str2++;
+ /*
+ * Inline version of minor(dev), to avoid the dynamic linker.
+ */
+ itoa(fsb.st_rdev & MAXMIN, str1);
+ if (stat64(buf, &stb) == 0)
+ rval = (stb.st_rdev == fsb.st_rdev);
+ }
+ errno = oerrno;
+ return (rval);
+}
+
+/*
+ * Converts a number to a string (null terminated).
+ */
+static void
+itoa(int i, char *ptr)
+{
+ int dig = 0;
+ int tempi;
+
+ tempi = i;
+ do {
+ dig++;
+ tempi /= 10;
+ } while (tempi);
+
+ ptr += dig;
+ *ptr = '\0';
+ while (--dig >= 0) {
+ *(--ptr) = i % 10 + '0';
+ i /= 10;
+ }
+}
+
+/*
+ * Push modules to provide tty semantics
+ */
+static void
+push_module(int fd)
+{
+ struct strioctl istr;
+ int oerrno = errno;
+
+ istr.ic_cmd = PTSSTTY;
+ istr.ic_len = 0;
+ istr.ic_timout = 0;
+ istr.ic_dp = NULL;
+ if (ioctl(fd, I_STR, &istr) != -1) {
+ (void) ioctl(fd, __I_PUSH_NOCTTY, "ptem");
+ (void) ioctl(fd, __I_PUSH_NOCTTY, "ldterm");
+ (void) ioctl(fd, __I_PUSH_NOCTTY, "ttcompat");
+ istr.ic_cmd = PTSSTTY;
+ istr.ic_len = 0;
+ istr.ic_timout = 0;
+ istr.ic_dp = NULL;
+ (void) ioctl(fd, I_STR, &istr);
+ }
+ errno = oerrno;
+}