Fix the creation of the dumpdir directory in stress_floppy Makefile
[ltp-debian.git] / testcases / kernel / pty / pty01.c
blobd1036e1c86a76dc0dade195bc67d2a6e829ad3de
1 /*
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 */
23 #ifndef _GNU_SOURCE
24 #define _GNU_SOURCE 1
25 #endif
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <termio.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <sys/wait.h>
34 #include <sys/types.h>
35 #include <sys/fcntl.h>
36 #include <sys/stat.h>
38 /** LTP Port **/
39 #include "test.h"
40 #include "usctest.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 */
46 /**************/
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"
60 * test buffer size
62 #define TESTSIZE 1024
65 * mode we expect grantpt() to leave pty as
67 #define PTY_MODE 020622
70 * number of procs for parallel test
72 #define NUMPROCS 15
76 * test slave locking
78 static int
79 test1(void)
81 int masterfd; /* master pty fd */
82 int slavefd; /* slave pty fd */
83 char *slavename;
84 struct stat st;
85 char buf[TESTSIZE];
87 masterfd = open(MASTERCLONE, O_RDWR);
88 if (masterfd < 0) {
89 tst_resm(TBROK,"%s",MASTERCLONE);
90 tst_exit();
93 slavename = ptsname(masterfd);
94 if (slavename == (char *)0) {
95 tst_resm(TBROK,"ptsname() call failed");
96 tst_exit();
99 if (grantpt(masterfd) != 0) {
100 tst_resm(TBROK,"grantpt() call failed");
101 tst_exit();
104 if (stat(slavename, &st) != 0) {
105 tst_resm(TBROK,"stat(%s) failed",slavename);
106 tst_exit();
108 if (st.st_uid != getuid()) {
109 tst_resm(TBROK, "uid mismatch");
110 tst_exit();
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);
116 tst_exit();
119 slavefd = open(slavename, O_RDWR);
120 if (slavefd < 0) {
121 /* expected */
122 } else {
123 tst_resm(TBROK, "open didn't fail!");
124 tst_exit();
127 if (unlockpt(masterfd) != 0) {
128 tst_resm(TBROK,"unlockpt() failed");
129 tst_exit();
132 slavefd = open(slavename, O_RDWR);
133 if (slavefd < 0) {
134 tst_resm(TBROK,"Could not open %s",slavename);
135 tst_exit();
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");
143 tst_exit();
146 if (read(slavefd, buf, strlen(STRING)) != strlen(STRING)) {
147 tst_resm(TFAIL,"read from slave");
148 tst_exit();
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);
154 tst_exit();
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");
162 tst_exit();
165 if (read(masterfd, buf, strlen(STRING)) != strlen(STRING)) {
166 tst_resm(TFAIL,"read from master");
167 tst_exit();
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);
173 tst_exit();
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");
181 tst_exit();
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");
189 tst_exit();
193 * close pty fds
195 if (close(slavefd) != 0) {
196 tst_resm(TBROK,"close of slave");
197 tst_exit();
199 if (close(masterfd) != 0) {
200 tst_resm(TBROK,"close of master");
201 tst_exit();
203 tst_resm(TPASS,"test1");
204 /** NOT REACHED **/
205 return 0;
209 * test slave operations with closed master
211 static int
212 test2(void)
214 int masterfd; /* master pty fd */
215 int slavefd; /* slave pty fd */
216 int i;
217 char *slavename;
218 char c;
220 masterfd = open(MASTERCLONE, O_RDWR);
221 if (masterfd < 0) {
222 tst_resm(TBROK,"%s",MASTERCLONE);
223 tst_exit();
226 slavename = ptsname(masterfd);
227 if (slavename == (char *)0) {
228 tst_resm(TBROK,"ptsname() call failed");
229 tst_exit();
232 if (grantpt(masterfd) != 0) {
233 tst_resm(TBROK,"grantpt() call failed");
234 tst_exit();
237 if (unlockpt(masterfd) != 0) {
238 tst_resm(TBROK,"unlockpt() call failed");
239 tst_exit();
242 slavefd = open(slavename, O_RDWR);
243 if (slavefd < 0) {
244 tst_resm(TBROK,"Could not open %s",slavename);
245 tst_exit();
249 * close pty fds. See what happens when we close the master
250 * first.
252 if (close(masterfd) != 0) {
253 tst_resm(TBROK,"close()");
254 tst_exit();
257 errno = 0;
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);
262 tst_exit();
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");
268 tst_exit();
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");
274 tst_exit();
277 if (close(slavefd) != 0) {
278 tst_resm(TBROK,"close");
279 tst_exit();
281 tst_resm(TPASS,"test2");
282 /** NOT REACHED **/
283 return 0;
287 * test operations on master with closed slave
289 static int
290 test3(void)
292 int masterfd; /* master pty fd */
294 masterfd = open(MASTERCLONE, O_RDWR);
295 if (masterfd < 0) {
296 tst_resm(TBROK,"%s",MASTERCLONE);
297 tst_exit();
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");
303 tst_exit();
305 tst_resm(TPASS,"test3");
306 /** NOT REACHED **/
307 return 0;
311 * test multiple opens on slave side of pty
313 static int
314 test4(void)
316 int masterfd; /* master pty fd */
317 int slavefd; /* slave pty fd */
318 int slavefd2;
319 int slavefd3;
320 char *slavename;
322 masterfd = open(MASTERCLONE, O_RDWR);
323 if (masterfd < 0) {
324 tst_resm(TBROK,"%s",MASTERCLONE);
325 tst_exit();
328 slavename = ptsname(masterfd);
329 if (slavename == (char *)0) {
330 tst_resm(TBROK,"ptsname() call failed");
331 tst_exit();
334 if (grantpt(masterfd) != 0) {
335 tst_resm(TBROK,"grantpt() call failed");
336 tst_exit();
339 if (unlockpt(masterfd) != 0) {
340 tst_resm(TBROK,"unlockpt() call failed");
341 tst_exit();
344 slavefd = open(slavename, O_RDWR);
345 if (slavefd < 0) {
346 tst_resm(TBROK,"Could not open %s",slavename);
347 tst_exit();
350 slavefd2 = open(slavename, O_RDWR);
351 if (slavefd < 0) {
352 tst_resm(TFAIL,"Could not open %s (again)",slavename);
353 tst_exit();
356 slavefd3 = open(slavename, O_RDWR);
357 if (slavefd < 0) {
358 tst_resm(TFAIL,"Could not open %s (once more)",slavename);
359 tst_exit();
363 * close pty fds.
365 if (close(slavefd) != 0) {
366 tst_resm(TBROK,"close slave");
367 tst_exit();
370 if (close(slavefd2) != 0) {
371 tst_resm(TBROK,"close slave again");
372 tst_exit();
375 if (close(slavefd3) != 0) {
376 tst_resm(TBROK,"close slave once more");
377 tst_exit();
380 if (close(masterfd) != 0) {
381 tst_resm(TBROK,"close master");
382 tst_exit();
384 tst_resm(TPASS,"test4");
385 /** NOT REACHED **/
386 return 0;
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.
394 static int
395 test5(void)
397 int masterfd; /* master pty fd */
398 char *slavename;
399 int status;
400 int i;
402 for (i = 0; i < NUMPROCS; ++i) {
403 switch (fork()) {
404 case -1:
405 tst_resm(TBROK,"fork()");
406 break;
407 case 0:
408 masterfd = open(MASTERCLONE, O_RDWR);
409 if (masterfd < 0) {
410 tst_resm(TFAIL,"proc %d: %s",i,MASTERCLONE);
411 tst_exit();
413 if (grantpt(masterfd) != 0) {
414 tst_resm(TFAIL,"proc %d: grantpt() call failed",i);
415 tst_exit();
417 slavename = ptsname(masterfd);
418 if (slavename == (char *)0) {
419 tst_resm(TFAIL,"proc %d: ptsname() call failed",i);
420 tst_exit();
422 sleep(10);
423 if (close(masterfd) != 0) {
424 tst_resm(TFAIL,"proc %d: close",i);
425 tst_exit();
427 tst_exit();
428 default:
429 break;
432 while (wait(&status) > 0) {
433 if (WEXITSTATUS(status) != 0) {
434 tst_resm(TFAIL,"child exitted with non-zero status");
435 tst_exit();
438 tst_resm(TPASS,"test5");
439 /** NOT REACHED **/
440 return 0;
444 * main test driver
447 main(int argc, char **argv)
449 test1();
450 test2();
451 test3();
452 test4();
453 test5();
456 * all done
458 tst_exit();
459 /*NOTREACHED*/
460 return 0;