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 #pragma weak _ptsname = ptsname 33 #pragma weak _grantpt = grantpt 34 #pragma weak _unlockpt = unlockpt 35 36 #include "lint.h" 37 #include "libc.h" 38 #include "mtlib.h" 39 #include <sys/types.h> 40 #include <signal.h> 41 #include <sys/param.h> 42 #include <sys/mkdev.h> 43 #include <sys/stream.h> 44 #include <sys/stropts.h> 45 #include <sys/wait.h> 46 #include <sys/signal.h> 47 #include <errno.h> 48 #include <fcntl.h> 49 #include <sys/stat.h> 50 #include <sys/ptms.h> 51 #include <string.h> 52 #include <stdlib.h> 53 #include <unistd.h> 54 #include <wait.h> 55 #include <spawn.h> 56 #include <grp.h> 57 #include "tsd.h" 58 59 #define PTSNAME "/dev/pts/" /* slave name */ 60 #define PTLEN 32 /* slave name length */ 61 #define DEFAULT_TTY_GROUP "tty" /* slave device group owner */ 62 63 static void itoa(int, char *); 64 65 /* 66 * Check that fd argument is a file descriptor of an opened master. 67 * Do this by sending an ISPTM ioctl message down stream. Ioctl() 68 * will fail if:(1) fd is not a valid file descriptor.(2) the file 69 * represented by fd does not understand ISPTM(not a master device). 70 * If we have a valid master, get its minor number via fstat(). 71 * Concatenate it to PTSNAME and return it as the name of the slave 72 * device. 73 */ 74 static dev_t 75 ptsdev(int fd) 76 { 77 struct stat64 status; 78 struct strioctl istr; 79 80 istr.ic_cmd = ISPTM; 81 istr.ic_len = 0; 82 istr.ic_timout = 0; 83 istr.ic_dp = NULL; 84 85 if (ioctl(fd, I_STR, &istr) < 0 || fstat64(fd, &status) < 0) 86 return (NODEV); 87 88 return (minor(status.st_rdev)); 89 } 90 91 char * 92 ptsname(int fd) 93 { 94 dev_t dev; 95 char *sname; 96 97 if ((dev = ptsdev(fd)) == NODEV) 98 return (NULL); 99 100 sname = tsdalloc(_T_PTSNAME, PTLEN, NULL); 101 if (sname == NULL) 102 return (NULL); 103 (void) strcpy(sname, PTSNAME); 104 itoa(dev, sname + strlen(PTSNAME)); 105 106 /* 107 * This lookup will create the /dev/pts node (if the corresponding 108 * pty exists. 109 */ 110 if (access(sname, F_OK) == 0) 111 return (sname); 112 113 return (NULL); 114 } 115 116 /* 117 * Send an ioctl down to the master device requesting the 118 * master/slave pair be unlocked. 119 */ 120 int 121 unlockpt(int fd) 122 { 123 struct strioctl istr; 124 125 istr.ic_cmd = UNLKPT; 126 istr.ic_len = 0; 127 istr.ic_timout = 0; 128 istr.ic_dp = NULL; 129 130 if (ioctl(fd, I_STR, &istr) < 0) 131 return (-1); 132 133 return (0); 134 } 135 136 int 137 grantpt(int fd) 138 { 139 struct strioctl istr; 140 pt_own_t pto; 141 struct group *gr_name; 142 143 /* validate the file descriptor before proceeding */ 144 if (ptsdev(fd) == NODEV) 145 return (-1); 146 147 pto.pto_ruid = getuid(); 148 149 gr_name = getgrnam(DEFAULT_TTY_GROUP); 150 if (gr_name) 151 pto.pto_rgid = gr_name->gr_gid; 152 else 153 pto.pto_rgid = getgid(); 154 155 istr.ic_cmd = OWNERPT; 156 istr.ic_len = sizeof (pt_own_t); 157 istr.ic_timout = 0; 158 istr.ic_dp = (char *)&pto; 159 160 if (ioctl(fd, I_STR, &istr) != 0) { 161 errno = EACCES; 162 return (-1); 163 } 164 165 return (0); 166 } 167 168 /* 169 * Send an ioctl down to the master device requesting the master/slave pair 170 * be assigned to the given zone. 171 */ 172 int 173 zonept(int fd, zoneid_t zoneid) 174 { 175 struct strioctl istr; 176 177 istr.ic_cmd = ZONEPT; 178 istr.ic_len = sizeof (zoneid); 179 istr.ic_timout = 0; 180 istr.ic_dp = (char *)&zoneid; 181 182 if (ioctl(fd, I_STR, &istr) != 0) { 183 return (-1); 184 } 185 return (0); 186 } 187 188 189 static void 190 itoa(int i, char *ptr) 191 { 192 int dig = 0; 193 int tempi; 194 195 tempi = i; 196 do { 197 dig++; 198 tempi /= 10; 199 } while (tempi); 200 201 ptr += dig; 202 *ptr = '\0'; 203 while (--dig >= 0) { 204 *(--ptr) = i % 10 + '0'; 205 i /= 10; 206 } 207 } 208 209 210 /* 211 * added for SUSv3 standard 212 * 213 * Open a pseudo-terminal device. External interface. 214 */ 215 216 int 217 posix_openpt(int oflag) 218 { 219 return (open("/dev/ptmx", oflag)); 220 } 221