]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/ptsname.c
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / ptsname.c
CommitLineData
d4697bc9 1/* Copyright (C) 1998-2014 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
UD
107 }
108 else if (errno == EINVAL)
6591c335 109#endif
4bca4c17 110 {
9b3c7c3c 111 char *p;
e7c5513d 112
9b3c7c3c
UD
113 if (buflen < strlen (_PATH_TTY) + 3)
114 {
115 __set_errno (ERANGE);
116 return ERANGE;
117 }
4bca4c17 118
aa989023 119 if (__fxstat64 (_STAT_VER, fd, stp) < 0)
4bca4c17 120 return errno;
4bca4c17 121
2a947279 122 /* Check if FD really is a master pseudo terminal. */
aa989023 123 if (! MASTER_P (stp->st_rdev))
2a947279
UD
124 {
125 __set_errno (ENOTTY);
126 return ENOTTY;
127 }
128
aa989023 129 ptyno = minor (stp->st_rdev);
4bca4c17 130
9b3c7c3c
UD
131 if (ptyno / 16 >= strlen (__libc_ptyname1))
132 {
133 __set_errno (ENOTTY);
134 return ENOTTY;
135 }
e7c5513d 136
9b3c7c3c
UD
137 p = __stpcpy (buf, _PATH_TTY);
138 p[0] = __libc_ptyname1[ptyno / 16];
139 p[1] = __libc_ptyname2[ptyno % 16];
140 p[2] = '\0';
141 }
e7c5513d 142
aa989023 143 if (__xstat64 (_STAT_VER, buf, stp) < 0)
9b3c7c3c 144 return errno;
4bca4c17 145
2a947279
UD
146 /* Check if the name we're about to return really corresponds to a
147 slave pseudo terminal. */
aa989023 148 if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev))
2a947279
UD
149 {
150 /* This really is a configuration problem. */
151 __set_errno (ENOTTY);
152 return ENOTTY;
153 }
154
9b3c7c3c 155 __set_errno (save_errno);
4bca4c17 156 return 0;
6591c335 157}
aa989023
UD
158
159
160/* Store at most BUFLEN characters of the pathname of the slave pseudo
161 terminal associated with the master FD is open on in BUF.
162 Return 0 on success, otherwise an error number. */
163int
164__ptsname_r (int fd, char *buf, size_t buflen)
165{
166 struct stat64 st;
167 return __ptsname_internal (fd, buf, buflen, &st);
168}
6591c335 169weak_alias (__ptsname_r, ptsname_r)