diff options
Diffstat (limited to 'usr/src/lib/libc/port/sys/open.c')
-rw-r--r-- | usr/src/lib/libc/port/sys/open.c | 183 |
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; +} |