1 /* $NetBSD: pty.c,v 1.31 2009/02/20 16:44:06 christos Exp $ */
4 * Copyright (c) 1990, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 #if defined(LIBC_SCCS) && !defined(lint)
35 static char sccsid
[] = "@(#)pty.c 8.3 (Berkeley) 5/16/94";
37 __RCSID("$NetBSD: pty.c,v 1.31 2009/02/20 16:44:06 christos Exp $");
39 #endif /* LIBC_SCCS and not lint */
41 #include <sys/types.h>
42 #include <sys/ioctl.h>
47 #endif /* defined(__minix) */
59 * XXX: `v' removed until no ports are using console devices which use ttyv0
61 #define TTY_LETTERS "pqrstuwxyzPQRST"
62 #define TTY_OLD_SUFFIX "0123456789abcdef"
63 #define TTY_NEW_SUFFIX "ghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
66 openpty(int *amaster
, int *aslave
, char *name
, struct termios
*term
,
69 char line
[] = "/dev/XtyXX";
70 const char *cp1
, *cp2
, *cp
, *linep
;
74 struct group grs
, *grp
;
77 _DIAGASSERT(amaster
!= NULL
);
78 _DIAGASSERT(aslave
!= NULL
);
79 /* name may be NULL */
80 /* term may be NULL */
81 /* winp may be NULL */
84 if ((master
= open("/dev/ptm", O_RDWR
)) != -1) {
86 if (ioctl(master
, TIOCPTMGET
, &pt
) != -1) {
97 * On MINIX3, we implement non-root openpty(3) using Unix98 PTYs.
98 * If this fails, the fallback code below works for root only.
100 if ((master
= posix_openpt(O_RDWR
| O_NOCTTY
)) != -1) {
101 if (grantpt(master
) != -1 && unlockpt(master
) != -1 &&
102 (linep
= ptsname(master
)) != NULL
&&
103 (slave
= open(linep
, O_RDWR
| O_NOCTTY
)) != -1)
107 #endif /* !defined(__minix) */
109 (void)getgrnam_r("tty", &grs
, grbuf
, sizeof(grbuf
), &grp
);
111 ttygid
= grp
->gr_gid
;
112 mode
= S_IRUSR
|S_IWUSR
|S_IWGRP
;
115 mode
= S_IRUSR
|S_IWUSR
;
118 for (cp1
= TTY_LETTERS
; *cp1
; cp1
++) {
120 for (cp
= cp2
= TTY_OLD_SUFFIX TTY_NEW_SUFFIX
; *cp2
; cp2
++) {
124 if ((master
= open(line
, O_RDWR
| O_NOCTTY
, 0)) == -1) {
126 if ((master
= open(line
, O_RDWR
, 0)) == -1) {
127 #endif /* defined(__minix) */
130 if ((size_t)(cp2
- cp
+ 1) < sizeof(TTY_OLD_SUFFIX
))
131 return -1; /* out of ptys */
133 break; /* out of ptys in this group */
137 if (chown(line
, getuid(), ttygid
) == 0 &&
138 chmod(line
, mode
) == 0 &&
139 #if !defined(__minix)
141 #endif /* !defined(__minix) */
143 (slave
= open(line
, O_RDWR
| O_NOCTTY
, 0)) != -1) {
145 (slave
= open(line
, O_RDWR
, 0)) != -1) {
146 #endif /* defined(__minix) */
151 (void)strcpy(name
, linep
);
153 (void)tcsetattr(slave
, TCSAFLUSH
, term
);
155 (void)ioctl(slave
, TIOCSWINSZ
, winp
);
161 errno
= ENOENT
; /* out of ptys */
166 forkpty(int *amaster
, char *name
, struct termios
*term
, struct winsize
*winp
)
171 _DIAGASSERT(amaster
!= NULL
);
172 /* name may be NULL */
173 /* term may be NULL */
174 /* winp may be NULL */
176 if (openpty(&master
, &slave
, name
, term
, winp
) == -1)
178 switch (pid
= fork()) {