11573Srgrimes/*
21573Srgrimes * Copyright (c) 1988, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes * 4. Neither the name of the University nor the names of its contributors
141573Srgrimes *    may be used to endorse or promote products derived from this software
151573Srgrimes *    without specific prior written permission.
161573Srgrimes *
171573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271573Srgrimes * SUCH DAMAGE.
281573Srgrimes */
291573Srgrimes
301573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
311573Srgrimesstatic char sccsid[] = "@(#)ttyname.c	8.2 (Berkeley) 1/27/94";
321573Srgrimes#endif /* LIBC_SCCS and not lint */
3390045Sobrien#include <sys/cdefs.h>
3490045Sobrien__FBSDID("$FreeBSD$");
351573Srgrimes
3671579Sdeischen#include "namespace.h"
371573Srgrimes#include <sys/types.h>
38143305Sphk#include <sys/ioctl.h>
39143305Sphk#include <sys/filio.h>
401573Srgrimes#include <fcntl.h>
411573Srgrimes#include <dirent.h>
4213545Sjulian#include <stdlib.h>
4310954Speter#include <termios.h>
4413545Sjulian#include <unistd.h>
451573Srgrimes#include <string.h>
461573Srgrimes#include <paths.h>
47146186Sdelphij#include <errno.h>
48146453Sume#include "reentrant.h"
4971579Sdeischen#include "un-namespace.h"
5013545Sjulian
5171579Sdeischen#include "libc_private.h"
5271579Sdeischen
53143305Sphkstatic char ttyname_buf[sizeof(_PATH_DEV) + MAXNAMLEN];
5471579Sdeischen
55146453Sumestatic once_t		ttyname_init_once = ONCE_INITIALIZER;
56146453Sumestatic thread_key_t	ttyname_key;
57146453Sumestatic int		ttyname_keycreated = 0;
5871579Sdeischen
59146186Sdelphijint
6071579Sdeischenttyname_r(int fd, char *buf, size_t len)
6113545Sjulian{
62146455Sume	size_t used;
6313545Sjulian
64143305Sphk	*buf = '\0';
6513545Sjulian
6613545Sjulian	/* Must be a terminal. */
6713545Sjulian	if (!isatty(fd))
68146186Sdelphij		return (ENOTTY);
6913545Sjulian	/* Must have enough room */
7013545Sjulian	if (len <= sizeof(_PATH_DEV))
71146186Sdelphij		return (ERANGE);
7213545Sjulian
73116651Sphk	strcpy(buf, _PATH_DEV);
74146455Sume	used = strlen(buf);
75188497Sed	if (fdevname_r(fd, buf + used, len - used) == NULL)
76188497Sed		return (ENOTTY);
77146186Sdelphij	return (0);
7813545Sjulian}
7913545Sjulian
80146453Sumestatic void
81146453Sumettyname_keycreate(void)
82146453Sume{
83146453Sume	ttyname_keycreated = (thr_keycreate(&ttyname_key, free) == 0);
84146453Sume}
85146453Sume
86143305Sphkchar *
87143305Sphkttyname(int fd)
8813545Sjulian{
8971579Sdeischen	char	*buf;
9013545Sjulian
91146453Sume	if (thr_main() != 0)
92146453Sume		buf = ttyname_buf;
93146453Sume	else {
94146453Sume		if (thr_once(&ttyname_init_once, ttyname_keycreate) != 0 ||
95146453Sume		    !ttyname_keycreated)
96146186Sdelphij			return (NULL);
97146453Sume		if ((buf = thr_getspecific(ttyname_key)) == NULL) {
98146453Sume			if ((buf = malloc(sizeof ttyname_buf)) == NULL)
9971579Sdeischen				return (NULL);
100146453Sume			if (thr_setspecific(ttyname_key, buf) != 0) {
10113545Sjulian				free(buf);
10213545Sjulian				return (NULL);
10313545Sjulian			}
10413545Sjulian		}
10513545Sjulian	}
106146453Sume
107146453Sume	if (ttyname_r(fd, buf, sizeof ttyname_buf) != 0)
108146451Sume		return (NULL);
109146186Sdelphij	return (buf);
11013545Sjulian}
111