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 45 static int xpg4_fixup(int fd); 46 static void push_module(int fd); 47 static int isptsfd(int fd); 48 static void itoa(int i, char *ptr); 49 50 int 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 57 int 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 70 int 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 77 int 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 */ 96 static int 97 xpg4_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 */ 108 static int 109 isptsfd(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 */ 139 static void 140 itoa(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 */ 162 static void 163 push_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