1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27/* Copyright (c) 1988 AT&T */ 28/* All Rights Reserved */ 29 30#include "lint.h" 31#include <sys/mkdev.h> 32#include <limits.h> 33#include <stdarg.h> 34#include <unistd.h> 35#include <strings.h> 36#include <errno.h> 37#include <sys/stat.h> 38#include <sys/fcntl.h> 39#include <sys/stropts.h> 40#include <sys/stream.h> 41#include <sys/ptms.h> 42#include <sys/syscall.h> 43#include "libc.h" 44 45static int xpg4_fixup(int fd); 46static void push_module(int fd); 47static int isptsfd(int fd); 48static void itoa(int i, char *ptr); 49 50int 51__openat(int dfd, const char *path, int oflag, mode_t mode) 52{ 53 int fd = syscall(SYS_openat, dfd, path, oflag, mode); 54 return (xpg4_fixup(fd)); 55} 56 57int 58__open(const char *path, int oflag, mode_t mode) 59{ 60#if defined(_RETAIN_OLD_SYSCALLS) 61 int fd = syscall(SYS_open, path, oflag, mode); 62 return (xpg4_fixup(fd)); 63#else 64 return (__openat(AT_FDCWD, path, oflag, mode)); 65#endif 66} 67 68#if !defined(_LP64) 69 70int 71__openat64(int dfd, const char *path, int oflag, mode_t mode) 72{ 73 int fd = syscall(SYS_openat64, dfd, path, oflag, mode); 74 return (xpg4_fixup(fd)); 75} 76 77int 78__open64(const char *path, int oflag, mode_t mode) 79{ 80#if defined(_RETAIN_OLD_SYSCALLS) 81 int fd = syscall(SYS_open64, path, oflag, mode); 82 return (xpg4_fixup(fd)); 83#else 84 return (__openat64(AT_FDCWD, path, oflag, mode)); 85#endif 86} 87 88#endif /* !_LP64 */ 89 90/* 91 * XPG4v2 requires that open of a slave pseudo terminal device 92 * provides the process with an interface that is identical to 93 * the terminal interface. For a more detailed discussion, 94 * see bugid 4025044. 95 */ 96static int 97xpg4_fixup(int fd) 98{ 99 if (libc__xpg4 != 0 && fd >= 0 && isptsfd(fd)) 100 push_module(fd); 101 return (fd); 102} 103 104/* 105 * Check if the file matches an entry in the /dev/pts directory. 106 * Be careful to preserve errno. 107 */ 108static int 109isptsfd(int fd) 110{ 111 char buf[TTYNAME_MAX]; 112 char *str1 = buf; 113 const char *str2 = "/dev/pts/"; 114 struct stat64 fsb, stb; 115 int oerrno = errno; 116 int rval = 0; 117 118 if (fstat64(fd, &fsb) == 0 && S_ISCHR(fsb.st_mode)) { 119 /* 120 * Do this without strcpy() or strlen(), 121 * to avoid invoking the dynamic linker. 122 */ 123 while (*str2 != '\0') 124 *str1++ = *str2++; 125 /* 126 * Inline version of minor(dev), to avoid the dynamic linker. 127 */ 128 itoa(fsb.st_rdev & MAXMIN, str1); 129 if (stat64(buf, &stb) == 0) 130 rval = (stb.st_rdev == fsb.st_rdev); 131 } 132 errno = oerrno; 133 return (rval); 134} 135 136/* 137 * Converts a number to a string (null terminated). 138 */ 139static void 140itoa(int i, char *ptr) 141{ 142 int dig = 0; 143 int tempi; 144 145 tempi = i; 146 do { 147 dig++; 148 tempi /= 10; 149 } while (tempi); 150 151 ptr += dig; 152 *ptr = '\0'; 153 while (--dig >= 0) { 154 *(--ptr) = i % 10 + '0'; 155 i /= 10; 156 } 157} 158 159/* 160 * Push modules to provide tty semantics 161 */ 162static void 163push_module(int fd) 164{ 165 struct strioctl istr; 166 int oerrno = errno; 167 168 istr.ic_cmd = PTSSTTY; 169 istr.ic_len = 0; 170 istr.ic_timout = 0; 171 istr.ic_dp = NULL; 172 if (ioctl(fd, I_STR, &istr) != -1) { 173 (void) ioctl(fd, __I_PUSH_NOCTTY, "ptem"); 174 (void) ioctl(fd, __I_PUSH_NOCTTY, "ldterm"); 175 (void) ioctl(fd, __I_PUSH_NOCTTY, "ttcompat"); 176 istr.ic_cmd = PTSSTTY; 177 istr.ic_len = 0; 178 istr.ic_timout = 0; 179 istr.ic_dp = NULL; 180 (void) ioctl(fd, I_STR, &istr); 181 } 182 errno = oerrno; 183} 184