uchar C++ tests: Fix build error on FreeBSD 12.
[gnulib.git] / tests / test-ptsname_r.c
blob381e3da9b4d7d188e70677e0e71de66ad0a0d644
1 /* Test of ptsname_r(3).
2 Copyright (C) 2010-2020 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 <https://www.gnu.org/licenses/>. */
17 /* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
18 may "optimize" the null_ptr function, when its result gets passed to a
19 function that has an argument declared as _GL_ARG_NONNULL. */
20 #define _GL_ARG_NONNULL(params)
22 #include <config.h>
24 #include <stdlib.h>
26 #include "signature.h"
27 SIGNATURE_CHECK (ptsname_r, int, (int, char *, size_t));
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <signal.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/stat.h>
37 #include "same-inode.h"
39 #if GNULIB_defined_ptsname_r
40 # include "null-ptr.h"
41 #endif
43 #include "macros.h"
45 /* Compare two slave names.
46 On some systems, there are hard links in the /dev/ directory.
47 For example, on OSF/1 5.1,
48 /dev/ttyp0 == /dev/pts/0
49 /dev/ttyp9 == /dev/pts/9
50 /dev/ttypa == /dev/pts/10
51 /dev/ttype == /dev/pts/14
53 static int
54 same_slave (const char *slave_name1, const char *slave_name2)
56 struct stat statbuf1;
57 struct stat statbuf2;
59 return (strcmp (slave_name1, slave_name2) == 0
60 || (stat (slave_name1, &statbuf1) >= 0
61 && stat (slave_name2, &statbuf2) >= 0
62 && SAME_INODE (statbuf1, statbuf2)));
65 static void
66 test_errors (int fd, const char *slave)
68 char buffer[256];
69 size_t len;
70 size_t buflen_max;
71 size_t buflen;
72 int result;
74 len = strlen (slave);
75 buflen_max = len + 5;
76 if (buflen_max > sizeof buffer)
77 buflen_max = sizeof buffer;
78 for (buflen = 0; buflen <= buflen_max; buflen++)
80 memset (buffer, 'X', sizeof buffer);
81 result = ptsname_r (fd, buffer, buflen);
82 if (buflen > len)
84 ASSERT (result == 0);
85 ASSERT (buffer[0] == '/');
87 else
89 ASSERT (result != 0);
90 ASSERT (result == ERANGE);
91 ASSERT (buffer[0] == 'X');
95 /* This test works only if the ptsname_r implementation comes from gnulib.
96 If it comes from libc, we have no way to prevent gcc from "optimizing"
97 the null_ptr function in invalid ways. See
98 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93156>. */
99 #if GNULIB_defined_ptsname_r
100 result = ptsname_r (fd, null_ptr (), 0);
101 ASSERT (result != 0);
102 ASSERT (result == EINVAL);
103 #endif
107 main (void)
109 #if HAVE_DECL_ALARM
110 /* Declare failure if test takes too long, by using default abort
111 caused by SIGALRM. */
112 int alarm_value = 5;
113 signal (SIGALRM, SIG_DFL);
114 alarm (alarm_value);
115 #endif
118 char buffer[256];
119 int result;
121 result = ptsname_r (-1, buffer, sizeof buffer);
122 ASSERT (result != 0);
123 ASSERT (result == EBADF || result == ENOTTY);
127 int fd;
128 char buffer[256];
129 int result;
131 /* Open the controlling tty of the current process. */
132 fd = open ("/dev/tty", O_RDONLY);
133 if (fd < 0)
135 fprintf (stderr, "Skipping test: cannot open controlling tty\n");
136 return 77;
139 result = ptsname_r (fd, buffer, sizeof buffer);
140 /* The result is usually NULL, because /dev/tty is a slave, not a
141 master. */
142 if (result == 0)
144 ASSERT (memcmp (buffer, "/dev/", 5) == 0);
147 close (fd);
150 #if defined __sun
151 /* Solaris has BSD-style /dev/pty[p-r][0-9a-f] files, but the function
152 ptsname() does not work on them. */
154 int fd;
155 char buffer[256];
156 int result;
158 /* Open a pty master. */
159 fd = open ("/dev/ptmx", O_RDWR | O_NOCTTY);
160 if (fd < 0)
162 fprintf (stderr, "Skipping test: cannot open pseudo-terminal\n");
163 return 77;
166 result = ptsname_r (fd, buffer, sizeof buffer);
167 ASSERT (result == 0);
168 ASSERT (memcmp (buffer, "/dev/pts/", 9) == 0);
170 test_errors (fd, buffer);
172 close (fd);
175 #elif defined _AIX
176 /* AIX has BSD-style /dev/ptyp[0-9a-f] files, but the modern way to open
177 a pty is to go through /dev/ptc. */
179 int fd;
180 char buffer[256];
181 int result;
183 /* Open a pty master. */
184 fd = open ("/dev/ptc", O_RDWR | O_NOCTTY);
185 if (fd < 0)
187 fprintf (stderr, "Skipping test: cannot open pseudo-terminal\n");
188 return 77;
191 result = ptsname_r (fd, buffer, sizeof buffer);
192 ASSERT (result == 0);
193 ASSERT (memcmp (buffer, "/dev/pts/", 9) == 0);
195 test_errors (fd, buffer);
197 /* This call hangs on AIX. */
198 close (fd);
201 #else
203 /* Try various master names of Mac OS X: /dev/pty[p-w][0-9a-f] */
205 int char1;
206 int char2;
208 for (char1 = 'p'; char1 <= 'w'; char1++)
209 for (char2 = '0'; char2 <= 'f'; (char2 == '9' ? char2 = 'a' : char2++))
211 char master_name[32];
212 int fd;
214 sprintf (master_name, "/dev/pty%c%c", char1, char2);
215 fd = open (master_name, O_RDONLY);
216 if (fd >= 0)
218 char buffer[256];
219 int result;
220 char slave_name[32];
222 result = ptsname_r (fd, buffer, sizeof buffer);
223 ASSERT (result == 0);
224 sprintf (slave_name, "/dev/tty%c%c", char1, char2);
225 ASSERT (same_slave (buffer, slave_name));
227 test_errors (fd, buffer);
229 /* This call hangs on AIX. */
230 close (fd);
235 /* Try various master names of *BSD: /dev/pty[p-sP-S][0-9a-v] */
237 int upper;
238 int char1;
239 int char2;
241 for (upper = 0; upper <= 1; upper++)
242 for (char1 = (upper ? 'P' : 'p'); char1 <= (upper ? 'S' : 's'); char1++)
243 for (char2 = '0'; char2 <= 'v'; (char2 == '9' ? char2 = 'a' : char2++))
245 char master_name[32];
246 int fd;
248 sprintf (master_name, "/dev/pty%c%c", char1, char2);
249 fd = open (master_name, O_RDONLY);
250 if (fd >= 0)
252 char buffer[256];
253 int result;
254 char slave_name[32];
256 result = ptsname_r (fd, buffer, sizeof buffer);
257 ASSERT (result == 0);
258 sprintf (slave_name, "/dev/tty%c%c", char1, char2);
259 ASSERT (same_slave (buffer, slave_name));
261 test_errors (fd, buffer);
263 close (fd);
268 #endif
270 return 0;