]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/ptsname.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / ptsname.c
CommitLineData
b168057a 1/* Copyright (C) 1998-2015 Free Software Foundation, Inc.
6591c335
UD
2 This file is part of the GNU C Library.
3 Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
6591c335
UD
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
6591c335 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
6591c335 18
9b3c7c3c
UD
19#include <errno.h>
20#include <paths.h>
21#include <stdlib.h>
22#include <string.h>
6591c335
UD
23#include <sys/ioctl.h>
24#include <sys/stat.h>
9b3c7c3c 25#include <sys/sysmacros.h>
6591c335 26#include <termios.h>
4bca4c17 27#include <unistd.h>
6591c335 28
eb96ffb0 29#include <_itoa.h>
6591c335 30
2a947279
UD
31/* Check if DEV corresponds to a master pseudo terminal device. */
32#define MASTER_P(Dev) \
33 (major ((Dev)) == 2 \
34 || (major ((Dev)) == 4 && minor ((Dev)) >= 128 && minor ((Dev)) < 192) \
35 || (major ((Dev)) >= 128 && major ((Dev)) < 136))
36
a1f8ec97 37/* Check if DEV corresponds to a slave pseudo terminal device. */
2a947279
UD
38#define SLAVE_P(Dev) \
39 (major ((Dev)) == 3 \
40 || (major ((Dev)) == 4 && minor ((Dev)) >= 192 && minor ((Dev)) < 256) \
41 || (major ((Dev)) >= 136 && major ((Dev)) < 144))
42
43/* Note that major number 4 corresponds to the old BSD style pseudo
44 terminal devices. As of Linux 2.1.115 these are no longer
45 supported. They have been replaced by major numbers 2 (masters)
46 and 3 (slaves). */
8edf6e0d 47
9b3c7c3c
UD
48/* Directory where we can find the slave pty nodes. */
49#define _PATH_DEVPTS "/dev/pts/"
6591c335 50
9b3c7c3c 51/* The are declared in getpt.c. */
ab26a24a
UD
52extern const char __libc_ptyname1[] attribute_hidden;
53extern const char __libc_ptyname2[] attribute_hidden;
6591c335 54
9b3c7c3c
UD
55/* Static buffer for `ptsname'. */
56static char buffer[sizeof (_PATH_DEVPTS) + 20];
57
58
6f65e668 59/* Return the pathname of the pseudo terminal slave associated with
9b3c7c3c
UD
60 the master FD is open on, or NULL on errors.
61 The returned storage is good until the next call to this function. */
6591c335 62char *
9b3c7c3c 63ptsname (int fd)
6591c335 64{
9b3c7c3c 65 return __ptsname_r (fd, buffer, sizeof (buffer)) != 0 ? NULL : buffer;
6591c335
UD
66}
67
9b3c7c3c 68
4bca4c17 69int
aa989023 70__ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp)
6591c335 71{
9b3c7c3c 72 int save_errno = errno;
57b36a0a 73 unsigned int ptyno;
e7c5513d 74
9b3c7c3c 75 if (buf == NULL)
4bca4c17
UD
76 {
77 __set_errno (EINVAL);
78 return EINVAL;
79 }
80
81 if (!__isatty (fd))
82 {
83 __set_errno (ENOTTY);
84 return ENOTTY;
85 }
86
87#ifdef TIOCGPTN
9b3c7c3c 88 if (__ioctl (fd, TIOCGPTN, &ptyno) == 0)
6591c335 89 {
9b3c7c3c 90 /* Buffer we use to print the number in. For a maximum size for
aa989023 91 `int' of 8 bytes we never need more than 20 digits. */
9b3c7c3c
UD
92 char numbuf[21];
93 const char *devpts = _PATH_DEVPTS;
814fc245 94 const size_t devptslen = strlen (_PATH_DEVPTS);
9b3c7c3c
UD
95 char *p;
96
814fc245
UD
97 numbuf[sizeof (numbuf) - 1] = '\0';
98 p = _itoa_word (ptyno, &numbuf[sizeof (numbuf) - 1], 10, 0);
9b3c7c3c 99
57b36a0a 100 if (buflen < devptslen + (&numbuf[sizeof (numbuf)] - p))
6591c335 101 {
9b3c7c3c
UD
102 __set_errno (ERANGE);
103 return ERANGE;
6591c335 104 }
6591c335 105
814fc245 106 memcpy (__stpcpy (buf, devpts), p, &numbuf[sizeof (numbuf)] - p);
9b3c7c3c 107 }
d0583c40
AJ
108 else if (errno != EINVAL)
109 return errno;
110 else
6591c335 111#endif
4bca4c17 112 {
9b3c7c3c 113 char *p;
e7c5513d 114
9b3c7c3c
UD
115 if (buflen < strlen (_PATH_TTY) + 3)
116 {
117 __set_errno (ERANGE);
118 return ERANGE;
119 }
4bca4c17 120
aa989023 121 if (__fxstat64 (_STAT_VER, fd, stp) < 0)
4bca4c17 122 return errno;
4bca4c17 123
2a947279 124 /* Check if FD really is a master pseudo terminal. */
aa989023 125 if (! MASTER_P (stp->st_rdev))
2a947279
UD
126 {
127 __set_errno (ENOTTY);
128 return ENOTTY;
129 }
130
aa989023 131 ptyno = minor (stp->st_rdev);
4bca4c17 132
9b3c7c3c
UD
133 if (ptyno / 16 >= strlen (__libc_ptyname1))
134 {
135 __set_errno (ENOTTY);
136 return ENOTTY;
137 }
e7c5513d 138
9b3c7c3c
UD
139 p = __stpcpy (buf, _PATH_TTY);
140 p[0] = __libc_ptyname1[ptyno / 16];
141 p[1] = __libc_ptyname2[ptyno % 16];
142 p[2] = '\0';
143 }
e7c5513d 144
aa989023 145 if (__xstat64 (_STAT_VER, buf, stp) < 0)
9b3c7c3c 146 return errno;
4bca4c17 147
2a947279
UD
148 /* Check if the name we're about to return really corresponds to a
149 slave pseudo terminal. */
aa989023 150 if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev))
2a947279
UD
151 {
152 /* This really is a configuration problem. */
153 __set_errno (ENOTTY);
154 return ENOTTY;
155 }
156
9b3c7c3c 157 __set_errno (save_errno);
4bca4c17 158 return 0;
6591c335 159}
aa989023
UD
160
161
162/* Store at most BUFLEN characters of the pathname of the slave pseudo
163 terminal associated with the master FD is open on in BUF.
164 Return 0 on success, otherwise an error number. */
165int
166__ptsname_r (int fd, char *buf, size_t buflen)
167{
168 struct stat64 st;
169 return __ptsname_internal (fd, buf, buflen, &st);
170}
6591c335 171weak_alias (__ptsname_r, ptsname_r)