3 * Copyright (c) International Business Machines Corp., 2002
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program 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
13 * the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 /* 12/23/2002 Port to LTP robbiew@us.ibm.com */
21 /* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
34 #include <sys/types.h>
35 #include <sys/fcntl.h>
43 char *TCID
="pty01"; /* Test program identifier. */
44 int TST_TOTAL
=5; /* Total number of test cases. */
45 extern int Tst_count
; /* Test Case counter for tst_* routines */
50 * pty master clone device
52 #define MASTERCLONE "/dev/ptmx"
55 * string for testing read/write on ptys
57 #define STRING "Linux Test Project\n"
65 * mode we expect grantpt() to leave pty as
67 #define PTY_MODE 020622
70 * number of procs for parallel test
81 int masterfd
; /* master pty fd */
82 int slavefd
; /* slave pty fd */
87 masterfd
= open(MASTERCLONE
, O_RDWR
);
89 tst_resm(TBROK
,"%s",MASTERCLONE
);
93 slavename
= ptsname(masterfd
);
94 if (slavename
== (char *)0) {
95 tst_resm(TBROK
,"ptsname() call failed");
99 if (grantpt(masterfd
) != 0) {
100 tst_resm(TBROK
,"grantpt() call failed");
104 if (stat(slavename
, &st
) != 0) {
105 tst_resm(TBROK
,"stat(%s) failed",slavename
);
108 if (st
.st_uid
!= getuid()) {
109 tst_resm(TBROK
, "uid mismatch");
113 if (st
.st_mode
!= (S_IFCHR
| S_IRUSR
| S_IWUSR
| S_IWGRP
)) {
114 tst_resm(TBROK
, "mode mismatch");
115 tst_resm(TBROK
, "st.st_mode=%o",st
.st_mode
);
119 slavefd
= open(slavename
, O_RDWR
);
123 tst_resm(TBROK
, "open didn't fail!");
127 if (unlockpt(masterfd
) != 0) {
128 tst_resm(TBROK
,"unlockpt() failed");
132 slavefd
= open(slavename
, O_RDWR
);
134 tst_resm(TBROK
,"Could not open %s",slavename
);
139 * test writing to the master / reading from the slave
141 if (write(masterfd
, STRING
, strlen(STRING
)) != strlen(STRING
)) {
142 tst_resm(TFAIL
,"write to master");
146 if (read(slavefd
, buf
, strlen(STRING
)) != strlen(STRING
)) {
147 tst_resm(TFAIL
,"read from slave");
150 if (strncmp(STRING
, buf
,strlen(STRING
)-1) != 0) {
151 tst_resm(TFAIL
, "strings are different.");
152 tst_resm(TFAIL
, "STRING:%s",STRING
);
153 tst_resm(TFAIL
, "buf:%s",buf
);
158 * test writing to the slave / reading from the master
160 if (write(slavefd
, STRING
, strlen(STRING
)) != strlen(STRING
)) {
161 tst_resm(TFAIL
,"write to slave");
165 if (read(masterfd
, buf
, strlen(STRING
)) != strlen(STRING
)) {
166 tst_resm(TFAIL
,"read from master");
169 if (strncmp(STRING
, buf
,strlen(STRING
)-1) != 0) {
170 tst_resm(TFAIL
,"strings are different.");
171 tst_resm(TFAIL
, "STRING:%s",STRING
);
172 tst_resm(TFAIL
, "buf:%s",buf
);
177 * try an invalid ioctl on the slave...
179 if (ioctl(slavefd
, TIOCGWINSZ
, (char *)0) == 0) {
180 tst_resm(TFAIL
, "invalid slave TIOCGWINSZ ioctl succeeded.. it should have failed");
185 * try an invalid ioctl on the master...
187 if (ioctl(masterfd
, TIOCGWINSZ
, (char *)0) == 0) {
188 tst_resm(TFAIL
, "invalid master TIOCGWINSZ ioctl succeeded.. it should have failed");
195 if (close(slavefd
) != 0) {
196 tst_resm(TBROK
,"close of slave");
199 if (close(masterfd
) != 0) {
200 tst_resm(TBROK
,"close of master");
203 tst_resm(TPASS
,"test1");
209 * test slave operations with closed master
214 int masterfd
; /* master pty fd */
215 int slavefd
; /* slave pty fd */
220 masterfd
= open(MASTERCLONE
, O_RDWR
);
222 tst_resm(TBROK
,"%s",MASTERCLONE
);
226 slavename
= ptsname(masterfd
);
227 if (slavename
== (char *)0) {
228 tst_resm(TBROK
,"ptsname() call failed");
232 if (grantpt(masterfd
) != 0) {
233 tst_resm(TBROK
,"grantpt() call failed");
237 if (unlockpt(masterfd
) != 0) {
238 tst_resm(TBROK
,"unlockpt() call failed");
242 slavefd
= open(slavename
, O_RDWR
);
244 tst_resm(TBROK
,"Could not open %s",slavename
);
249 * close pty fds. See what happens when we close the master
252 if (close(masterfd
) != 0) {
253 tst_resm(TBROK
,"close()");
258 if ((i
= read(slavefd
, &c
, 1)) == 1) {
259 tst_resm(TFAIL
,"Try to read from slave (should return 0)");
260 tst_resm(TFAIL
, "read should have failed, but didn't");
261 tst_resm(TFAIL
, "read '%c'", c
);
265 if ((i
= write(slavefd
, &c
, 1)) == 1) {
266 tst_resm(TFAIL
,"try to write to slave (should fail)");
267 tst_resm(TFAIL
,"write should have failed, but didn't");
271 if (ioctl(slavefd
, TIOCGWINSZ
, (char *)0) == 0) {
272 tst_resm(TFAIL
,"trying TIOCGWINSZ on slave (should fail)");
273 tst_resm(TFAIL
, "ioctl succeeded.. it should have failed");
277 if (close(slavefd
) != 0) {
278 tst_resm(TBROK
,"close");
281 tst_resm(TPASS
,"test2");
287 * test operations on master with closed slave
292 int masterfd
; /* master pty fd */
294 masterfd
= open(MASTERCLONE
, O_RDWR
);
296 tst_resm(TBROK
,"%s",MASTERCLONE
);
300 if (ioctl(masterfd
, TIOCGWINSZ
, (char *)0) == 0) {
301 tst_resm(TFAIL
,"trying TIOCGWINSZ on master with no open slave (should fail)");
302 tst_resm(TFAIL
,"ioctl succeeded.. it should have failed");
305 tst_resm(TPASS
,"test3");
311 * test multiple opens on slave side of pty
316 int masterfd
; /* master pty fd */
317 int slavefd
; /* slave pty fd */
322 masterfd
= open(MASTERCLONE
, O_RDWR
);
324 tst_resm(TBROK
,"%s",MASTERCLONE
);
328 slavename
= ptsname(masterfd
);
329 if (slavename
== (char *)0) {
330 tst_resm(TBROK
,"ptsname() call failed");
334 if (grantpt(masterfd
) != 0) {
335 tst_resm(TBROK
,"grantpt() call failed");
339 if (unlockpt(masterfd
) != 0) {
340 tst_resm(TBROK
,"unlockpt() call failed");
344 slavefd
= open(slavename
, O_RDWR
);
346 tst_resm(TBROK
,"Could not open %s",slavename
);
350 slavefd2
= open(slavename
, O_RDWR
);
352 tst_resm(TFAIL
,"Could not open %s (again)",slavename
);
356 slavefd3
= open(slavename
, O_RDWR
);
358 tst_resm(TFAIL
,"Could not open %s (once more)",slavename
);
365 if (close(slavefd
) != 0) {
366 tst_resm(TBROK
,"close slave");
370 if (close(slavefd2
) != 0) {
371 tst_resm(TBROK
,"close slave again");
375 if (close(slavefd3
) != 0) {
376 tst_resm(TBROK
,"close slave once more");
380 if (close(masterfd
) != 0) {
381 tst_resm(TBROK
,"close master");
384 tst_resm(TPASS
,"test4");
390 * test opening/closing lots of ptys in parallel. We may run out
391 * of ptys for this test depending on how the system is configured,
392 * but that's not a fatal error.
397 int masterfd
; /* master pty fd */
402 for (i
= 0; i
< NUMPROCS
; ++i
) {
405 tst_resm(TBROK
,"fork()");
408 masterfd
= open(MASTERCLONE
, O_RDWR
);
410 tst_resm(TFAIL
,"proc %d: %s",i
,MASTERCLONE
);
413 if (grantpt(masterfd
) != 0) {
414 tst_resm(TFAIL
,"proc %d: grantpt() call failed",i
);
417 slavename
= ptsname(masterfd
);
418 if (slavename
== (char *)0) {
419 tst_resm(TFAIL
,"proc %d: ptsname() call failed",i
);
423 if (close(masterfd
) != 0) {
424 tst_resm(TFAIL
,"proc %d: close",i
);
432 while (wait(&status
) > 0) {
433 if (WEXITSTATUS(status
) != 0) {
434 tst_resm(TFAIL
,"child exitted with non-zero status");
438 tst_resm(TPASS
,"test5");
447 main(int argc
, char **argv
)