malloca: Silence a warning from clang's memory sanitizer.
[gnulib.git] / tests / test-ptsname_r.c
blob2faf4c74d134871de513ba3b28770b76d4220a1d
1 /* Test of ptsname_r(3).
2 Copyright (C) 2010-2017 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 #include <config.h>
19 #include <stdlib.h>
21 #include "signature.h"
22 SIGNATURE_CHECK (ptsname_r, int, (int, char *, size_t));
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
32 #include "same-inode.h"
34 #include "null-ptr.h"
35 #include "macros.h"
37 /* Compare two slave names.
38 On some systems, there are hard links in the /dev/ directory.
39 For example, on OSF/1 5.1,
40 /dev/ttyp0 == /dev/pts/0
41 /dev/ttyp9 == /dev/pts/9
42 /dev/ttypa == /dev/pts/10
43 /dev/ttype == /dev/pts/14
45 static int
46 same_slave (const char *slave_name1, const char *slave_name2)
48 struct stat statbuf1;
49 struct stat statbuf2;
51 return (strcmp (slave_name1, slave_name2) == 0
52 || (stat (slave_name1, &statbuf1) >= 0
53 && stat (slave_name2, &statbuf2) >= 0
54 && SAME_INODE (statbuf1, statbuf2)));
57 static void
58 test_errors (int fd, const char *slave)
60 char buffer[256];
61 size_t len;
62 size_t buflen_max;
63 size_t buflen;
64 int result;
66 len = strlen (slave);
67 buflen_max = len + 5;
68 if (buflen_max > sizeof buffer)
69 buflen_max = sizeof buffer;
70 for (buflen = 0; buflen <= buflen_max; buflen++)
72 memset (buffer, 'X', sizeof buffer);
73 errno = 0;
74 result = ptsname_r (fd, buffer, buflen);
75 if (buflen > len)
77 ASSERT (result == 0);
78 ASSERT (buffer[0] == '/');
80 else
82 ASSERT (result != 0);
83 ASSERT (result == errno);
84 ASSERT (errno == ERANGE);
85 ASSERT (buffer[0] == 'X');
89 errno = 0;
90 result = ptsname_r (fd, null_ptr (), 0);
91 ASSERT (result != 0);
92 ASSERT (result == errno);
93 ASSERT (errno == EINVAL);
96 int
97 main (void)
99 #if HAVE_DECL_ALARM
100 /* Declare failure if test takes too long, by using default abort
101 caused by SIGALRM. */
102 int alarm_value = 5;
103 signal (SIGALRM, SIG_DFL);
104 alarm (alarm_value);
105 #endif
108 char buffer[256];
109 int result;
111 errno = 0;
112 result = ptsname_r (-1, buffer, sizeof buffer);
113 ASSERT (result != 0);
114 ASSERT (result == errno);
115 ASSERT (errno == EBADF || errno == ENOTTY);
119 int fd;
120 char buffer[256];
121 int result;
123 /* Open the controlling tty of the current process. */
124 fd = open ("/dev/tty", O_RDONLY);
125 if (fd < 0)
127 fprintf (stderr, "Skipping test: cannot open controlling tty\n");
128 return 77;
131 result = ptsname_r (fd, buffer, sizeof buffer);
132 /* The result is usually NULL, because /dev/tty is a slave, not a
133 master. */
134 if (result == 0)
136 ASSERT (memcmp (buffer, "/dev/", 5) == 0);
139 close (fd);
142 #if defined __sun
143 /* Solaris has BSD-style /dev/pty[p-r][0-9a-f] files, but the function
144 ptsname() does not work on them. */
146 int fd;
147 char buffer[256];
148 int result;
150 /* Open a pty master. */
151 fd = open ("/dev/ptmx", O_RDWR | O_NOCTTY);
152 if (fd < 0)
154 fprintf (stderr, "Skipping test: cannot open pseudo-terminal\n");
155 return 77;
158 result = ptsname_r (fd, buffer, sizeof buffer);
159 ASSERT (result == 0);
160 ASSERT (memcmp (buffer, "/dev/pts/", 9) == 0);
162 test_errors (fd, buffer);
164 close (fd);
167 #elif defined _AIX
168 /* AIX has BSD-style /dev/ptyp[0-9a-f] files, but the modern way to open
169 a pty is to go through /dev/ptc. */
171 int fd;
172 char buffer[256];
173 int result;
175 /* Open a pty master. */
176 fd = open ("/dev/ptc", O_RDWR | O_NOCTTY);
177 if (fd < 0)
179 fprintf (stderr, "Skipping test: cannot open pseudo-terminal\n");
180 return 77;
183 result = ptsname_r (fd, buffer, sizeof buffer);
184 ASSERT (result == 0);
185 ASSERT (memcmp (buffer, "/dev/pts/", 9) == 0);
187 test_errors (fd, buffer);
189 /* This call hangs on AIX. */
190 close (fd);
193 #else
195 /* Try various master names of Mac OS X: /dev/pty[p-w][0-9a-f] */
197 int char1;
198 int char2;
200 for (char1 = 'p'; char1 <= 'w'; char1++)
201 for (char2 = '0'; char2 <= 'f'; (char2 == '9' ? char2 = 'a' : char2++))
203 char master_name[32];
204 int fd;
206 sprintf (master_name, "/dev/pty%c%c", char1, char2);
207 fd = open (master_name, O_RDONLY);
208 if (fd >= 0)
210 char buffer[256];
211 int result;
212 char slave_name[32];
214 result = ptsname_r (fd, buffer, sizeof buffer);
215 ASSERT (result == 0);
216 sprintf (slave_name, "/dev/tty%c%c", char1, char2);
217 ASSERT (same_slave (buffer, slave_name));
219 test_errors (fd, buffer);
221 /* This call hangs on AIX. */
222 close (fd);
227 /* Try various master names of *BSD: /dev/pty[p-sP-S][0-9a-v] */
229 int upper;
230 int char1;
231 int char2;
233 for (upper = 0; upper <= 1; upper++)
234 for (char1 = (upper ? 'P' : 'p'); char1 <= (upper ? 'S' : 's'); char1++)
235 for (char2 = '0'; char2 <= 'v'; (char2 == '9' ? char2 = 'a' : char2++))
237 char master_name[32];
238 int fd;
240 sprintf (master_name, "/dev/pty%c%c", char1, char2);
241 fd = open (master_name, O_RDONLY);
242 if (fd >= 0)
244 char buffer[256];
245 int result;
246 char slave_name[32];
248 result = ptsname_r (fd, buffer, sizeof buffer);
249 ASSERT (result == 0);
250 sprintf (slave_name, "/dev/tty%c%c", char1, char2);
251 ASSERT (same_slave (buffer, slave_name));
253 test_errors (fd, buffer);
255 close (fd);
260 #endif
262 return 0;