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 2008 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 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include "lint.h" 33 #include <sys/mkdev.h> 34 #include <limits.h> 35 #include <stdarg.h> 36 #include <unistd.h> 37 #include <strings.h> 38 #include <errno.h> 39 #include <sys/stat.h> 40 #include <sys/stropts.h> 41 #include <sys/stream.h> 42 #include <sys/ptms.h> 43 #include "libc.h" 44 45 #if !defined(_LP64) 46 extern int __open64_syscall(const char *fname, int oflag, mode_t mode); 47 #endif 48 49 extern int __open_syscall(const char *fname, int oflag, mode_t mode); 50 51 static void push_module(int fd); 52 static int isptsfd(int fd); 53 static void itoa(int i, char *ptr); 54 55 int 56 __open(const char *fname, int oflag, ...) 57 { 58 mode_t mode; 59 int fd; 60 va_list ap; 61 62 va_start(ap, oflag); 63 mode = va_arg(ap, mode_t); 64 va_end(ap); 65 66 /* 67 * XPG4v2 requires that open of a slave pseudo terminal device 68 * provides the process with an interface that is identical to 69 * the terminal interface. For a more detailed discussion, 70 * see bugid 4025044. 71 */ 72 fd = __open_syscall(fname, oflag, mode); 73 if (libc__xpg4 != 0 && fd >= 0 && isptsfd(fd)) 74 push_module(fd); 75 return (fd); 76 } 77 78 #if !defined(_LP64) 79 /* 80 * The 32-bit APIs to large files require this interposition. 81 * The 64-bit APIs just fall back to __open() above. 82 */ 83 int 84 __open64(const char *fname, int oflag, ...) 85 { 86 mode_t mode; 87 int fd; 88 va_list ap; 89 90 va_start(ap, oflag); 91 mode = va_arg(ap, mode_t); 92 va_end(ap); 93 94 /* 95 * XPG4v2 requires that open of a slave pseudo terminal device 96 * provides the process with an interface that is identical to 97 * the terminal interface. For a more detailed discussion, 98 * see bugid 4025044. 99 */ 100 fd = __open64_syscall(fname, oflag, mode); 101 if (libc__xpg4 != 0 && fd >= 0 && isptsfd(fd)) 102 push_module(fd); 103 return (fd); 104 } 105 #endif /* !_LP64 */ 106 107 /* 108 * Check if the file matches an entry in the /dev/pts directory. 109 * Be careful to preserve errno. 110 */ 111 static int 112 isptsfd(int fd) 113 { 114 char buf[TTYNAME_MAX]; 115 char *str1 = buf; 116 const char *str2 = "/dev/pts/"; 117 struct stat64 fsb, stb; 118 int oerrno = errno; 119 int rval = 0; 120 121 if (fstat64(fd, &fsb) == 0 && S_ISCHR(fsb.st_mode)) { 122 /* 123 * Do this without strcpy() or strlen(), 124 * to avoid invoking the dynamic linker. 125 */ 126 while (*str2 != '\0') 127 *str1++ = *str2++; 128 /* 129 * Inline version of minor(dev), to avoid the dynamic linker. 130 */ 131 itoa(fsb.st_rdev & MAXMIN, str1); 132 if (stat64(buf, &stb) == 0) 133 rval = (stb.st_rdev == fsb.st_rdev); 134 } 135 errno = oerrno; 136 return (rval); 137 } 138 139 /* 140 * Converts a number to a string (null terminated). 141 */ 142 static void 143 itoa(int i, char *ptr) 144 { 145 int dig = 0; 146 int tempi; 147 148 tempi = i; 149 do { 150 dig++; 151 tempi /= 10; 152 } while (tempi); 153 154 ptr += dig; 155 *ptr = '\0'; 156 while (--dig >= 0) { 157 *(--ptr) = i % 10 + '0'; 158 i /= 10; 159 } 160 } 161 162 /* 163 * Push modules to provide tty semantics 164 */ 165 static void 166 push_module(int fd) 167 { 168 struct strioctl istr; 169 int oerrno = errno; 170 171 istr.ic_cmd = PTSSTTY; 172 istr.ic_len = 0; 173 istr.ic_timout = 0; 174 istr.ic_dp = NULL; 175 if (ioctl(fd, I_STR, &istr) != -1) { 176 (void) ioctl(fd, __I_PUSH_NOCTTY, "ptem"); 177 (void) ioctl(fd, __I_PUSH_NOCTTY, "ldterm"); 178 (void) ioctl(fd, __I_PUSH_NOCTTY, "ttcompat"); 179 istr.ic_cmd = PTSSTTY; 180 istr.ic_len = 0; 181 istr.ic_timout = 0; 182 istr.ic_dp = NULL; 183 (void) ioctl(fd, I_STR, &istr); 184 } 185 errno = oerrno; 186 } 187