usleep tests: Avoid failure due to known Cygwin 3.5.3 bug.
[gnulib.git] / tests / test-ptsname.c
blob934a12f2a15bf2dfb5c85c7563754260f2a64af4
1 /* Test of ptsname(3).
2 Copyright (C) 2010-2024 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 #include <config.h>
19 #include <stdlib.h>
21 #include "signature.h"
22 SIGNATURE_CHECK (ptsname, char *, (int));
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 "macros.h"
36 /* Compare two slave names.
37 On some systems, there are hard links in the /dev/ directory.
38 For example, on OSF/1 5.1,
39 /dev/ttyp0 == /dev/pts/0
40 /dev/ttyp9 == /dev/pts/9
41 /dev/ttypa == /dev/pts/10
42 /dev/ttype == /dev/pts/14
44 static int
45 same_slave (const char *slave_name1, const char *slave_name2)
47 struct stat statbuf1;
48 struct stat statbuf2;
50 return (strcmp (slave_name1, slave_name2) == 0
51 || (stat (slave_name1, &statbuf1) >= 0
52 && stat (slave_name2, &statbuf2) >= 0
53 && psame_inode (&statbuf1, &statbuf2)));
56 int
57 main (void)
59 #if HAVE_DECL_ALARM
60 /* Declare failure if test takes too long, by using default abort
61 caused by SIGALRM. */
62 # if defined _AIX
63 int alarm_value = 20;
64 # else
65 int alarm_value = 5;
66 # endif
67 signal (SIGALRM, SIG_DFL);
68 alarm (alarm_value);
69 #endif
72 char *result;
74 errno = 0;
75 result = ptsname (-1);
76 ASSERT (result == NULL);
77 ASSERT (errno == EBADF
78 || errno == ENOTTY /* seen on glibc */
83 int fd;
84 char *result;
86 /* Open the controlling tty of the current process. */
87 fd = open ("/dev/tty", O_RDONLY);
88 if (fd < 0)
90 if (test_exit_status != EXIT_SUCCESS)
91 return test_exit_status;
92 fprintf (stderr, "Skipping test: cannot open controlling tty\n");
93 return 77;
96 result = ptsname (fd);
97 /* The result is usually NULL, because /dev/tty is a slave, not a
98 master. */
99 if (result != NULL)
101 ASSERT (memcmp (result, "/dev/", 5) == 0);
104 close (fd);
107 #if defined __sun || defined __DragonFly__
108 /* Solaris has BSD-style /dev/pty[p-r][0-9a-f] files, but the function
109 ptsname() does not work on them.
110 DragonFly BSD has only /dev/ptmx. */
112 int fd;
113 char *result;
115 /* Open the controlling tty of the current process. */
116 fd = open ("/dev/ptmx", O_RDWR | O_NOCTTY);
117 if (fd < 0)
119 if (test_exit_status != EXIT_SUCCESS)
120 return test_exit_status;
121 fprintf (stderr, "Skipping test: cannot open pseudo-terminal\n");
122 return 77;
125 result = ptsname (fd);
126 ASSERT (result != NULL);
127 ASSERT (memcmp (result, "/dev/pts/", 9) == 0);
129 close (fd);
132 #elif defined _AIX
133 /* AIX has BSD-style /dev/ptyp[0-9a-f] files, and the function ptsname()
134 produces the corresponding /dev/ttyp[0-9a-f] file for each. But opening
135 such a pty causes the process to hang in a state where it does not even
136 react to the SIGALRM signal for N * 15 seconds, where N is the number of
137 opened ptys, either in the close (fd) call or - when this close (fd) call
138 is commented out - at the process exit.
139 So, better don't use these BSD-style ptys. The modern way to open a pty
140 is to go through /dev/ptc. */
142 int fd;
143 char *result;
145 /* Open a pty master. */
146 fd = open ("/dev/ptc", O_RDWR | O_NOCTTY);
147 if (fd < 0)
149 if (test_exit_status != EXIT_SUCCESS)
150 return test_exit_status;
151 fprintf (stderr, "Skipping test: cannot open pseudo-terminal\n");
152 return 77;
155 result = ptsname (fd);
156 ASSERT (result != NULL);
157 ASSERT (memcmp (result, "/dev/pts/", 9) == 0);
159 /* This close (fd) call takes 15 seconds. It would be interruptible by the
160 SIGALRM timer, but then this test would report failure. */
161 close (fd);
164 #elif defined __GNU__ /* Hurd */
166 /* Try various master names of Hurd: /dev/pty[p-q][0-9a-v] */
168 int char1;
169 int char2;
171 for (char1 = 'p'; char1 <= 'q'; char1++)
172 for (char2 = '0'; char2 <= 'v'; (char2 == '9' ? char2 = 'a' : char2++))
174 char master_name[32];
175 int fd;
177 sprintf (master_name, "/dev/pty%c%c", char1, char2);
178 fd = open (master_name, O_RDONLY);
179 if (fd >= 0)
181 char *result;
182 char slave_name[32];
184 result = ptsname (fd);
185 ASSERT (result != NULL);
186 sprintf (slave_name, "/dev/tty%c%c", char1, char2);
187 ASSERT (same_slave (result, slave_name));
189 close (fd);
194 #else
196 /* Try various master names of Mac OS X: /dev/pty[p-w][0-9a-f] */
198 int char1;
199 int char2;
201 for (char1 = 'p'; char1 <= 'w'; char1++)
202 for (char2 = '0'; char2 <= 'f'; (char2 == '9' ? char2 = 'a' : char2++))
204 char master_name[32];
205 int fd;
207 sprintf (master_name, "/dev/pty%c%c", char1, char2);
208 fd = open (master_name, O_RDONLY);
209 if (fd >= 0)
211 char *result;
212 char slave_name[32];
214 result = ptsname (fd);
215 ASSERT (result != NULL);
216 sprintf (slave_name, "/dev/tty%c%c", char1, char2);
217 ASSERT (same_slave (result, slave_name));
219 close (fd);
224 /* Try various master names of *BSD: /dev/pty[p-sP-S][0-9a-v] */
226 int upper;
227 int char1;
228 int char2;
230 for (upper = 0; upper <= 1; upper++)
231 for (char1 = (upper ? 'P' : 'p'); char1 <= (upper ? 'S' : 's'); char1++)
232 for (char2 = '0'; char2 <= 'v'; (char2 == '9' ? char2 = 'a' : char2++))
234 char master_name[32];
235 int fd;
237 sprintf (master_name, "/dev/pty%c%c", char1, char2);
238 fd = open (master_name, O_RDONLY);
239 if (fd >= 0)
241 char *result;
242 char slave_name[32];
244 result = ptsname (fd);
245 ASSERT (result != NULL);
246 sprintf (slave_name, "/dev/tty%c%c", char1, char2);
247 ASSERT (same_slave (result, slave_name));
249 close (fd);
254 #endif
256 return test_exit_status;