re-mark 1.29b-2 as not yet uploaded (merge madness!)
[debian/tar] / gnu / ptsname_r.c
1 /* -*- buffer-read-only: t -*- vi: set ro: */
2 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
3 /* Determine name of the slave side of a pseudo-terminal.
4    Copyright (C) 1998, 2002, 2010-2014 Free Software Foundation, Inc.
5
6    This program is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19 #include <config.h>
20
21 #include <stdlib.h>
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28
29 #ifdef _LIBC
30 # include <paths.h>
31 #else
32 # ifndef _PATH_TTY
33 #  define _PATH_TTY "/dev/tty"
34 # endif
35 # ifndef _PATH_DEV
36 #  define _PATH_DEV "/dev/"
37 # endif
38
39 # define __set_errno(e) errno = (e)
40 # define __isatty isatty
41 # define __stat stat
42 # define __ttyname_r ttyname_r
43 # define __ptsname_r ptsname_r
44
45 #endif
46
47 #ifdef __sun
48 /* Get ioctl() and 'struct strioctl'.  */
49 # include <stropts.h>
50 /* Get ISPTM.  */
51 # include <sys/stream.h>
52 # include <sys/ptms.h>
53 /* Get the major, minor macros.  */
54 # include <sys/sysmacros.h>
55 # include <stdio.h>
56 #endif
57
58 #if defined _AIX || defined __osf__
59 /* Get ioctl(), ISPTM.  */
60 # include <sys/ioctl.h>
61 /* Get the major, minor macros.  */
62 # include <sys/sysmacros.h>
63 # include <stdio.h>
64 #endif
65
66
67 /* Store at most BUFLEN characters of the pathname of the slave pseudo
68    terminal associated with the master FD is open on in BUF.
69    Return 0 on success, otherwise an error number.  */
70 int
71 __ptsname_r (int fd, char *buf, size_t buflen)
72 {
73   int save_errno = errno;
74   int err;
75   struct stat st;
76
77   if (buf == NULL)
78     {
79       __set_errno (EINVAL);
80       return EINVAL;
81     }
82
83 #if defined __sun /* Solaris */
84   if (fstat (fd, &st) < 0)
85     return errno;
86   if (!(S_ISCHR (st.st_mode) && major (st.st_rdev) == 0))
87     {
88       errno = ENOTTY;
89       return errno;
90     }
91   {
92     /* Master ptys can be recognized through a STREAMS ioctl.  See
93        "STREAMS-based Pseudo-Terminal Subsystem"
94        <http://docs.oracle.com/cd/E18752_01/html/816-4855/termsub15-44781.html>
95        and "STREAMS ioctl commands"
96        <http://docs.oracle.com/cd/E18752_01/html/816-5177/streamio-7i.html>
97      */
98     struct strioctl ioctl_arg;
99     ioctl_arg.ic_cmd = ISPTM;
100     ioctl_arg.ic_timout = 0;
101     ioctl_arg.ic_len = 0;
102     ioctl_arg.ic_dp = NULL;
103
104     if (ioctl (fd, I_STR, &ioctl_arg) < 0)
105       {
106         errno = ENOTTY;
107         return errno;
108       }
109   }
110   {
111     char tmpbuf[9 + 10 + 1];
112     int n = sprintf (tmpbuf, "/dev/pts/%u", minor (st.st_rdev));
113     if (n >= buflen)
114       {
115         errno = ERANGE;
116         return errno;
117       }
118     memcpy (buf, tmpbuf, n + 1);
119   }
120 #elif defined _AIX || defined __osf__ /* AIX, OSF/1 */
121   /* This implementation returns /dev/pts/N, like ptsname() does.
122      Whereas the generic implementation below returns /dev/ttypN.
123      Both are correct, but let's be consistent with ptsname().  */
124   if (fstat (fd, &st) < 0)
125     return errno;
126   if (!S_ISCHR (st.st_mode))
127     {
128       errno = ENOTTY;
129       return errno;
130     }
131   {
132     int ret;
133     int dev;
134     char tmpbuf[9 + 10 + 1];
135     int n;
136 # ifdef _AIX
137     ret = ioctl (fd, ISPTM, &dev);
138 # endif
139 # ifdef __osf__
140     ret = ioctl (fd, ISPTM, NULL);
141     dev = ret;
142 # endif
143     if (ret < 0)
144       {
145         errno = ENOTTY;
146         return errno;
147       }
148     n = sprintf (tmpbuf, "/dev/pts/%u", minor (dev));
149     if (n >= buflen)
150       {
151         errno = ERANGE;
152         return errno;
153       }
154     memcpy (buf, tmpbuf, n + 1);
155   }
156 #else
157   if (!__isatty (fd))
158     {
159 #if ISATTY_FAILS_WITHOUT_SETTING_ERRNO && defined F_GETFL /* IRIX, Solaris */
160       /* Set errno.  */
161       if (fcntl (fd, F_GETFL) != -1)
162         errno = ENOTTY;
163 #else
164       /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY).  */
165 #endif
166       return errno;
167     }
168
169   if (buflen < strlen (_PATH_TTY) + 3)
170     {
171       __set_errno (ERANGE);
172       return ERANGE;
173     }
174
175   err = __ttyname_r (fd, buf, buflen);
176   if (err != 0)
177     {
178       __set_errno (err);
179       return errno;
180     }
181
182   if (strncmp(buf, "/dev/pts/", strlen("/dev/pts/")) != 0)
183     buf[sizeof (_PATH_DEV) - 1] = 't';
184 #endif
185
186   if (__stat (buf, &st) < 0)
187     return errno;
188
189   __set_errno (save_errno);
190   return 0;
191 }