1104476Ssam/*
2104476Ssam * Copyright (c) 1988, 1993
3104476Ssam *	The Regents of the University of California.  All rights reserved.
4139825Simp *
5104476Ssam * Redistribution and use in source and binary forms, with or without
6104476Ssam * modification, are permitted provided that the following conditions
7104476Ssam * are met:
8104476Ssam * 1. Redistributions of source code must retain the above copyright
9104476Ssam *    notice, this list of conditions and the following disclaimer.
10104476Ssam * 2. Redistributions in binary form must reproduce the above copyright
11104476Ssam *    notice, this list of conditions and the following disclaimer in the
12275732Sjmg *    documentation and/or other materials provided with the distribution.
13275732Sjmg * 4. Neither the name of the University nor the names of its contributors
14104476Ssam *    may be used to endorse or promote products derived from this software
15275732Sjmg *    without specific prior written permission.
16275732Sjmg *
17275732Sjmg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18275732Sjmg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19104476Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20104476Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21104476Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22104476Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23104476Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24104476Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25104476Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26104476Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27104476Ssam * SUCH DAMAGE.
28104476Ssam */
29104476Ssam
30104476Ssam#if defined(LIBC_SCCS) && !defined(lint)
31292963Sallanjudestatic char sccsid[] = "@(#)ttyname.c	8.2 (Berkeley) 1/27/94";
32292963Sallanjude#endif /* LIBC_SCCS and not lint */
33104476Ssam#include <sys/cdefs.h>
34292963Sallanjude__FBSDID("$FreeBSD: stable/10/lib/libc/gen/ttyname.c 317392 2017-04-24 22:44:59Z brooks $");
35292963Sallanjude
36292963Sallanjude#include "namespace.h"
37292963Sallanjude#include <sys/types.h>
38292963Sallanjude#include <sys/ioctl.h>
39292963Sallanjude#include <sys/filio.h>
40292963Sallanjude#include <fcntl.h>
41292963Sallanjude#include <dirent.h>
42292963Sallanjude#include <stdlib.h>
43292963Sallanjude#include <termios.h>
44104476Ssam#include <unistd.h>
45292963Sallanjude#include <string.h>
46292963Sallanjude#include <paths.h>
47292963Sallanjude#include <errno.h>
48292963Sallanjude#include "reentrant.h"
49292963Sallanjude#include "un-namespace.h"
50104476Ssam
51104476Ssam#include "libc_private.h"
52104476Ssam
53104476Ssamstatic char ttyname_buf[sizeof(_PATH_DEV) + MAXNAMLEN];
54104476Ssam
55275732Sjmgstatic once_t		ttyname_init_once = ONCE_INITIALIZER;
56104476Ssamstatic thread_key_t	ttyname_key;
57104476Ssamstatic int		ttyname_keycreated = 0;
58104476Ssam
59104476Ssamint
60104476Ssamttyname_r(int fd, char *buf, size_t len)
61213068Spjd{
62104476Ssam	size_t used;
63104476Ssam
64104476Ssam	/* Don't write off the end of a zero-length buffer. */
65104476Ssam	if (len < 1)
66104476Ssam		return (ERANGE);
67104476Ssam
68104476Ssam	*buf = '\0';
69104476Ssam
70104476Ssam	/* Must be a terminal. */
71104476Ssam	if (!isatty(fd))
72275732Sjmg		return (errno);
73275732Sjmg	/* Must have enough room */
74275732Sjmg	if (len <= sizeof(_PATH_DEV))
75213068Spjd		return (ERANGE);
76104476Ssam
77169425Sgnn	strcpy(buf, _PATH_DEV);
78104476Ssam	used = strlen(buf);
79292963Sallanjude	if (fdevname_r(fd, buf + used, len - used) == NULL)
80292963Sallanjude		return (errno == EINVAL ? ERANGE : errno);
81292963Sallanjude	return (0);
82292963Sallanjude}
83292963Sallanjude
84292963Sallanjudestatic void
85104476Ssamttyname_keycreate(void)
86292963Sallanjude{
87292963Sallanjude	ttyname_keycreated = (thr_keycreate(&ttyname_key, free) == 0);
88292963Sallanjude}
89292963Sallanjude
90292963Sallanjudechar *
91104476Ssamttyname(int fd)
92292963Sallanjude{
93	char	*buf;
94
95	if (thr_main() != 0)
96		buf = ttyname_buf;
97	else {
98		if (thr_once(&ttyname_init_once, ttyname_keycreate) != 0 ||
99		    !ttyname_keycreated)
100			return (NULL);
101		if ((buf = thr_getspecific(ttyname_key)) == NULL) {
102			if ((buf = malloc(sizeof ttyname_buf)) == NULL)
103				return (NULL);
104			if (thr_setspecific(ttyname_key, buf) != 0) {
105				free(buf);
106				return (NULL);
107			}
108		}
109	}
110
111	if (ttyname_r(fd, buf, sizeof ttyname_buf) != 0)
112		return (NULL);
113	return (buf);
114}
115