blob: cbcc65c9704bb00eb1b06e47881ff8dcfe3f18ba [file] [log] [blame]
robbiewb8739092002-12-24 19:55:40 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2002
4 *
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.
9 *
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.
14 *
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
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiewb8739092002-12-24 19:55:40 +000018 */
19
20/* 12/23/2002 Port to LTP robbiew@us.ibm.com */
21/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
22
23#ifndef _GNU_SOURCE
24#define _GNU_SOURCE 1
25#endif
26
Garrett Coopera7143162010-10-18 23:12:54 -070027#include <sys/types.h>
28#include <sys/stat.h>
29#include <sys/wait.h>
robbiewb8739092002-12-24 19:55:40 +000030#include <errno.h>
Garrett Coopera7143162010-10-18 23:12:54 -070031#include <fcntl.h>
robbiewb8739092002-12-24 19:55:40 +000032#include <stdio.h>
33#include <stdlib.h>
Garrett Coopera7143162010-10-18 23:12:54 -070034#include <string.h>
robbiewb8739092002-12-24 19:55:40 +000035#include <termio.h>
36#include <unistd.h>
robbiewb8739092002-12-24 19:55:40 +000037
38/** LTP Port **/
39#include "test.h"
robbiewb8739092002-12-24 19:55:40 +000040
Wanlong Gao354ebb42012-12-07 10:10:04 +080041char *TCID = "pty01"; /* Test program identifier. */
42int TST_TOTAL = 5; /* Total number of test cases. */
robbiewb8739092002-12-24 19:55:40 +000043/**************/
44
robbiewb8739092002-12-24 19:55:40 +000045/*
46 * pty master clone device
47 */
48#define MASTERCLONE "/dev/ptmx"
49
50/*
51 * string for testing read/write on ptys
52 */
53#define STRING "Linux Test Project\n"
54
55/*
56 * test buffer size
57 */
58#define TESTSIZE 1024
59
60/*
61 * mode we expect grantpt() to leave pty as
62 */
63#define PTY_MODE 020622
64
65/*
66 * number of procs for parallel test
67 */
68#define NUMPROCS 15
subrata_modakbdbaec52009-02-26 12:14:51 +000069
robbiewb8739092002-12-24 19:55:40 +000070/*
71 * test slave locking
72 */
Wanlong Gao354ebb42012-12-07 10:10:04 +080073static int test1(void)
robbiewb8739092002-12-24 19:55:40 +000074{
75 int masterfd; /* master pty fd */
76 int slavefd; /* slave pty fd */
77 char *slavename;
78 struct stat st;
79 char buf[TESTSIZE];
80
81 masterfd = open(MASTERCLONE, O_RDWR);
82 if (masterfd < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +080083 tst_brkm(TBROK | TERRNO, NULL, MASTERCLONE);
robbiewb8739092002-12-24 19:55:40 +000084 }
subrata_modakbdbaec52009-02-26 12:14:51 +000085
robbiewb8739092002-12-24 19:55:40 +000086 slavename = ptsname(masterfd);
Garrett Coopera7143162010-10-18 23:12:54 -070087 if (slavename == NULL) {
Wanlong Gao354ebb42012-12-07 10:10:04 +080088 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
robbiewb8739092002-12-24 19:55:40 +000089 }
90
91 if (grantpt(masterfd) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +080092 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
robbiewb8739092002-12-24 19:55:40 +000093 }
94
95 if (stat(slavename, &st) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +080096 tst_brkm(TBROK | TERRNO, NULL, "stat(%s) failed", slavename);
robbiewb8739092002-12-24 19:55:40 +000097 }
98 if (st.st_uid != getuid()) {
Garrett Coopera7143162010-10-18 23:12:54 -070099 tst_brkm(TBROK, NULL, "uid mismatch");
robbiewb8739092002-12-24 19:55:40 +0000100 }
101
102 if (st.st_mode != (S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP)) {
Garrett Coopera7143162010-10-18 23:12:54 -0700103 tst_brkm(TBROK, NULL, "mode mismatch (mode=%o)", st.st_mode);
robbiewb8739092002-12-24 19:55:40 +0000104 }
105
106 slavefd = open(slavename, O_RDWR);
Garrett Coopera7143162010-10-18 23:12:54 -0700107 if (slavefd >= 0) {
108 tst_brkm(TBROK, NULL, "open didn't fail as expected!");
robbiewb8739092002-12-24 19:55:40 +0000109 }
110
111 if (unlockpt(masterfd) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800112 tst_brkm(TBROK | TERRNO, NULL, "unlockpt() failed");
robbiewb8739092002-12-24 19:55:40 +0000113 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000114
robbiewb8739092002-12-24 19:55:40 +0000115 slavefd = open(slavename, O_RDWR);
116 if (slavefd < 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700117 tst_brkm(TBROK, NULL, "Could not open %s", slavename);
robbiewb8739092002-12-24 19:55:40 +0000118 }
119
120 /*
121 * test writing to the master / reading from the slave
122 */
123 if (write(masterfd, STRING, strlen(STRING)) != strlen(STRING)) {
Garrett Coopera7143162010-10-18 23:12:54 -0700124 /*
125 * XXX: the errno printout might be garbage, but better to be
126 * safe than sorry..
127 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800128 tst_brkm(TFAIL | TERRNO, NULL, "write to master");
robbiewb8739092002-12-24 19:55:40 +0000129 }
robbiewb8739092002-12-24 19:55:40 +0000130
131 if (read(slavefd, buf, strlen(STRING)) != strlen(STRING)) {
Garrett Coopera7143162010-10-18 23:12:54 -0700132 /* XXX: Same as write above.. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800133 tst_brkm(TFAIL | TERRNO, NULL, "read from slave");
robbiewb8739092002-12-24 19:55:40 +0000134 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800135 if (strncmp(STRING, buf, strlen(STRING) - 1) != 0) {
Garrett Coopere959aa82010-10-13 08:01:19 -0700136 tst_brkm(TFAIL, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800137 "strings are different (STRING = '%s' != buf = '%s')",
138 STRING, buf);
robbiewb8739092002-12-24 19:55:40 +0000139 }
140
141 /*
142 * test writing to the slave / reading from the master
143 */
144 if (write(slavefd, STRING, strlen(STRING)) != strlen(STRING)) {
Garrett Coopera7143162010-10-18 23:12:54 -0700145 /* XXX: Same as write above.. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800146 tst_brkm(TFAIL | TERRNO, NULL, "write to slave");
robbiewb8739092002-12-24 19:55:40 +0000147 }
148
149 if (read(masterfd, buf, strlen(STRING)) != strlen(STRING)) {
Garrett Coopera7143162010-10-18 23:12:54 -0700150 /* XXX: Same as write above.. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800151 tst_brkm(TFAIL | TERRNO, NULL, "read from master");
robbiewb8739092002-12-24 19:55:40 +0000152 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800153 if (strncmp(STRING, buf, strlen(STRING) - 1) != 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700154 tst_brkm(TFAIL, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800155 "strings are different (STRING = '%s' != buf = '%s').",
156 STRING, buf);
robbiewb8739092002-12-24 19:55:40 +0000157 }
158
159 /*
160 * try an invalid ioctl on the slave...
161 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800162 if (ioctl(slavefd, TIOCGWINSZ, NULL) == 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700163 tst_brkm(TFAIL, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800164 "invalid slave TIOCGWINSZ ioctl succeeded.. it should "
165 "have failed");
robbiewb8739092002-12-24 19:55:40 +0000166 }
167
168 /*
169 * try an invalid ioctl on the master...
170 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800171 if (ioctl(masterfd, TIOCGWINSZ, NULL) == 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700172 tst_brkm(TFAIL, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800173 "invalid master TIOCGWINSZ ioctl succeeded.. it should "
174 "have failed");
robbiewb8739092002-12-24 19:55:40 +0000175 }
176
177 /*
178 * close pty fds
179 */
180 if (close(slavefd) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800181 tst_brkm(TBROK | TERRNO, NULL, "close of slave");
robbiewb8739092002-12-24 19:55:40 +0000182 }
183 if (close(masterfd) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800184 tst_brkm(TBROK | TERRNO, NULL, "close of master");
robbiewb8739092002-12-24 19:55:40 +0000185 }
Garrett Coopera7143162010-10-18 23:12:54 -0700186 tst_resm(TPASS, "test1");
187 /** NOTREACHED **/
subrata_modak43337a32009-02-26 11:43:51 +0000188 return 0;
robbiewb8739092002-12-24 19:55:40 +0000189}
190
191/*
192 * test slave operations with closed master
193 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800194static void test2(void)
robbiewb8739092002-12-24 19:55:40 +0000195{
196 int masterfd; /* master pty fd */
197 int slavefd; /* slave pty fd */
198 int i;
199 char *slavename;
200 char c;
201
202 masterfd = open(MASTERCLONE, O_RDWR);
203 if (masterfd < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800204 tst_brkm(TBROK | TERRNO, NULL, MASTERCLONE);
robbiewb8739092002-12-24 19:55:40 +0000205 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000206
robbiewb8739092002-12-24 19:55:40 +0000207 slavename = ptsname(masterfd);
Cyril Hrubis4e2bab82014-09-24 16:34:35 +0200208 if (slavename == NULL) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800209 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
robbiewb8739092002-12-24 19:55:40 +0000210 }
211
212 if (grantpt(masterfd) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800213 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
robbiewb8739092002-12-24 19:55:40 +0000214 }
215
216 if (unlockpt(masterfd) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800217 tst_brkm(TBROK | TERRNO, NULL, "unlockpt() call failed");
robbiewb8739092002-12-24 19:55:40 +0000218 }
219
220 slavefd = open(slavename, O_RDWR);
221 if (slavefd < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800222 tst_brkm(TBROK | TERRNO, NULL, "Could not open %s", slavename);
robbiewb8739092002-12-24 19:55:40 +0000223 }
224
225 /*
226 * close pty fds. See what happens when we close the master
227 * first.
228 */
229 if (close(masterfd) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800230 tst_brkm(TBROK | TERRNO, NULL, "close()");
robbiewb8739092002-12-24 19:55:40 +0000231 }
232
233 errno = 0;
234 if ((i = read(slavefd, &c, 1)) == 1) {
Garrett Coopere959aa82010-10-13 08:01:19 -0700235 tst_brkm(TFAIL, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800236 "reading from slave fd should have failed, but didn't"
237 "(read '%c')", c);
robbiewb8739092002-12-24 19:55:40 +0000238 }
239
240 if ((i = write(slavefd, &c, 1)) == 1) {
Garrett Coopere959aa82010-10-13 08:01:19 -0700241 tst_brkm(TFAIL, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800242 "writing to slave fd should have failed, but didn't");
robbiewb8739092002-12-24 19:55:40 +0000243 }
244
Wanlong Gao354ebb42012-12-07 10:10:04 +0800245 if (ioctl(slavefd, TIOCGWINSZ, NULL) == 0) {
Garrett Coopere959aa82010-10-13 08:01:19 -0700246 tst_brkm(TFAIL, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800247 "trying TIOCGWINSZ on slave fd should have failed, "
248 "but didn't");
robbiewb8739092002-12-24 19:55:40 +0000249 }
250
251 if (close(slavefd) != 0) {
Garrett Coopere959aa82010-10-13 08:01:19 -0700252 tst_brkm(TBROK, NULL, "close");
robbiewb8739092002-12-24 19:55:40 +0000253 }
Garrett Coopere959aa82010-10-13 08:01:19 -0700254 tst_resm(TPASS, "test2");
robbiewb8739092002-12-24 19:55:40 +0000255}
256
257/*
258 * test operations on master with closed slave
259 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800260static void test3(void)
robbiewb8739092002-12-24 19:55:40 +0000261{
262 int masterfd; /* master pty fd */
263
264 masterfd = open(MASTERCLONE, O_RDWR);
265 if (masterfd < 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700266 tst_brkm(TBROK, NULL, MASTERCLONE);
robbiewb8739092002-12-24 19:55:40 +0000267 }
268
Cyril Hrubis4e2bab82014-09-24 16:34:35 +0200269 if (ioctl(masterfd, TIOCGWINSZ, NULL) == 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800270 tst_brkm(TFAIL | TERRNO, NULL,
271 "trying TIOCGWINSZ on master with no open slave "
272 "succeeded unexpectedly");
robbiewb8739092002-12-24 19:55:40 +0000273 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800274 tst_resm(TPASS, "test3");
robbiewb8739092002-12-24 19:55:40 +0000275}
276
277/*
278 * test multiple opens on slave side of pty
279 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800280static void test4(void)
robbiewb8739092002-12-24 19:55:40 +0000281{
282 int masterfd; /* master pty fd */
283 int slavefd; /* slave pty fd */
subrata_modakbdbaec52009-02-26 12:14:51 +0000284 int slavefd2;
285 int slavefd3;
robbiewb8739092002-12-24 19:55:40 +0000286 char *slavename;
287
288 masterfd = open(MASTERCLONE, O_RDWR);
289 if (masterfd < 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100290 tst_brkm(TBROK, NULL, "%s", MASTERCLONE);
robbiewb8739092002-12-24 19:55:40 +0000291 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000292
robbiewb8739092002-12-24 19:55:40 +0000293 slavename = ptsname(masterfd);
Cyril Hrubis4e2bab82014-09-24 16:34:35 +0200294 if (slavename == NULL) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100295 tst_brkm(TBROK, NULL, "ptsname() call failed");
robbiewb8739092002-12-24 19:55:40 +0000296 }
297
298 if (grantpt(masterfd) != 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100299 tst_brkm(TBROK, NULL, "grantpt() call failed");
robbiewb8739092002-12-24 19:55:40 +0000300 }
301
302 if (unlockpt(masterfd) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800303 tst_brkm(TBROK | TERRNO, NULL, "unlockpt() call failed");
robbiewb8739092002-12-24 19:55:40 +0000304 }
305
306 slavefd = open(slavename, O_RDWR);
307 if (slavefd < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800308 tst_brkm(TBROK | TERRNO, NULL, "Could not open %s", slavename);
robbiewb8739092002-12-24 19:55:40 +0000309 }
310
311 slavefd2 = open(slavename, O_RDWR);
312 if (slavefd < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800313 tst_brkm(TFAIL | TERRNO, NULL, "Could not open %s (again)",
314 slavename);
robbiewb8739092002-12-24 19:55:40 +0000315 }
316
317 slavefd3 = open(slavename, O_RDWR);
318 if (slavefd < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800319 tst_brkm(TFAIL | TERRNO, NULL, "Could not open %s (once more)",
320 slavename);
robbiewb8739092002-12-24 19:55:40 +0000321 }
322
323 /*
324 * close pty fds.
325 */
326 if (close(slavefd) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800327 tst_brkm(TBROK | TERRNO, NULL, "close slave");
robbiewb8739092002-12-24 19:55:40 +0000328 }
329
330 if (close(slavefd2) != 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700331 tst_brkm(TBROK, NULL, "close slave again");
robbiewb8739092002-12-24 19:55:40 +0000332 }
333
334 if (close(slavefd3) != 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700335 tst_brkm(TBROK, NULL, "close slave once more");
robbiewb8739092002-12-24 19:55:40 +0000336 }
337
338 if (close(masterfd) != 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700339 tst_brkm(TBROK, NULL, "close master");
subrata_modakbdbaec52009-02-26 12:14:51 +0000340 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800341 tst_resm(TPASS, "test4");
robbiewb8739092002-12-24 19:55:40 +0000342}
343
344/*
345 * test opening/closing lots of ptys in parallel. We may run out
346 * of ptys for this test depending on how the system is configured,
Garrett Cooper2c282152010-12-16 00:55:50 -0800347 * but that's not a fatal error.
robbiewb8739092002-12-24 19:55:40 +0000348 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800349static void test5(void)
robbiewb8739092002-12-24 19:55:40 +0000350{
351 int masterfd; /* master pty fd */
352 char *slavename;
353 int status;
354 int i;
355
356 for (i = 0; i < NUMPROCS; ++i) {
357 switch (fork()) {
358 case -1:
Garrett Coopera7143162010-10-18 23:12:54 -0700359 tst_brkm(TBROK, NULL, "fork()");
robbiewb8739092002-12-24 19:55:40 +0000360 break;
361 case 0:
362 masterfd = open(MASTERCLONE, O_RDWR);
363 if (masterfd < 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700364 printf("proc %d: opening %s failed: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800365 i, MASTERCLONE, strerror(errno));
Garrett Coopera7143162010-10-18 23:12:54 -0700366 exit(1);
robbiewb8739092002-12-24 19:55:40 +0000367 }
368 if (grantpt(masterfd) != 0) {
Garrett Coopere959aa82010-10-13 08:01:19 -0700369 printf("proc %d: grantpt() call failed: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800370 i, strerror(errno));
Garrett Coopera7143162010-10-18 23:12:54 -0700371 exit(1);
robbiewb8739092002-12-24 19:55:40 +0000372 }
373 slavename = ptsname(masterfd);
Garrett Coopera7143162010-10-18 23:12:54 -0700374 if (slavename == NULL) {
375 printf("proc %d: ptsname() call failed: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800376 i, strerror(errno));
Garrett Coopera7143162010-10-18 23:12:54 -0700377 exit(1);
robbiewb8739092002-12-24 19:55:40 +0000378 }
379 sleep(10);
380 if (close(masterfd) != 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700381 printf("proc %d: close failed: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800382 i, strerror(errno));
Garrett Coopera7143162010-10-18 23:12:54 -0700383 exit(1);
subrata_modakbdbaec52009-02-26 12:14:51 +0000384 }
Garrett Coopera7143162010-10-18 23:12:54 -0700385 exit(0);
robbiewb8739092002-12-24 19:55:40 +0000386 default:
387 break;
388 }
389 }
390 while (wait(&status) > 0) {
Garrett Coopera7143162010-10-18 23:12:54 -0700391 if (status) {
392 tst_brkm(TFAIL, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800393 "child exited with non-zero status %d",
394 status);
robbiewb8739092002-12-24 19:55:40 +0000395 }
396 }
Garrett Coopera7143162010-10-18 23:12:54 -0700397 tst_resm(TPASS, "test5");
subrata_modakbdbaec52009-02-26 12:14:51 +0000398}
Garrett Cooper2c282152010-12-16 00:55:50 -0800399
robbiewb8739092002-12-24 19:55:40 +0000400/*
401 * main test driver
402 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800403int main(int argc, char **argv)
robbiewb8739092002-12-24 19:55:40 +0000404{
405 test1();
406 test2();
407 test3();
408 test4();
409 test5();
410
411 /*
Wanlong Gao354ebb42012-12-07 10:10:04 +0800412 * all done
robbiewb8739092002-12-24 19:55:40 +0000413 */
414 tst_exit();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700415}