Replace previous change by different test
[minix.git] / test / t40c.c
blob1302265d1088f994eed347b643c6df7fb2f214e2
1 /* t40c.c
3 * Test (pseudo) terminal devices
5 * Select works on regular files, (pseudo) terminal devices, streams-based
6 * files, FIFOs, pipes, and sockets. This test verifies selecting for (pseudo)
7 * terminal devices.
9 * This test is part of a bigger select test. It expects as argument which sub-
10 * test it is.
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <sys/select.h>
20 #include <errno.h>
21 #include <sys/wait.h>
22 #include <string.h>
24 #define TERMINALW "/dev/ttypf"
25 #define TERMINALR "/dev/ptypf"
26 #define SENDSTRING "minixrocks"
27 #define MAX_ERROR 5
29 int errct = 0, subtest = -1;
31 void e(int n, char *s) {
32 printf("Subtest %d, error %d, %s\n", subtest, n, s);
34 if (errct++ > MAX_ERROR) {
35 printf("Too many errors; test aborted\n");
36 exit(errct);
40 void open_terminal(int *child_fd, int *parent_fd) {
41 int fd1, fd2, i;
42 char opentermw[5+OPEN_MAX+1];
43 char opentermr[5+OPEN_MAX+1];
44 char *term[] = {"f","e","d","c","b","a","9","8","7","6","5","4","3","2","1"};
46 if (!child_fd || !parent_fd) exit(EXIT_FAILURE);
48 for (i = 0; i < 16; i++) {
49 snprintf(opentermw, 5+OPEN_MAX, "/dev/ttyp%s", term[i]);
50 snprintf(opentermr, 5+OPEN_MAX, "/dev/ptyp%s", term[i]);
52 /* Open master terminal for writing */
53 if((fd1 = open(opentermw, O_WRONLY)) == -1) continue;
55 /* Open slave terminal for reading */
56 if((fd2 = open(opentermr, O_RDONLY)) == -1) {
57 close(fd1);
58 continue;
61 *child_fd = fd1;
62 *parent_fd = fd2;
63 return;
66 /* If we get here we failed to find a terminal pair */
67 exit(EXIT_FAILURE);
70 int do_child(int terminal) {
71 struct timeval tv;
73 /* Going to sleep for two seconds to allow the parent proc to get ready */
74 tv.tv_sec = 2;
75 tv.tv_usec = 0;
76 select(0, NULL, NULL, NULL, &tv);
78 /* Try to write. Doesn't matter how many bytes we actually send. */
79 (void) write(terminal, SENDSTRING, strlen(SENDSTRING));
80 close(terminal);
82 /* Wait for another second to allow the parent to process incoming data */
83 tv.tv_usec = 1000000;
84 (void) select(0,NULL, NULL, NULL, &tv);
85 exit(0);
88 int do_parent(int child, int terminal) {
89 fd_set fds_read, fds_write, fds_error;
90 int retval;
92 /* Clear bit masks */
93 FD_ZERO(&fds_read); FD_ZERO(&fds_write); FD_ZERO(&fds_error);
94 /* Set read bits */
95 FD_SET(terminal, &fds_read);
96 FD_SET(terminal, &fds_write);
98 /* Test if we can read or write from/to fd. As fd is opened read only we
99 * cannot actually write, so the select should return immediately with fd
100 * set in fds_write, but not in fds_read. Note that the child waits two
101 * seconds before sending data. This gives us the opportunity run this
102 * sub-test as reading from fd is blocking at this point. */
103 retval = select(terminal+1, &fds_read, &fds_write, &fds_error, NULL);
105 if(retval != 1) e(1, "incorrect amount of ready file descriptors");
108 if(FD_ISSET(terminal, &fds_read)) e(2, "read should NOT be set");
109 if(!FD_ISSET(terminal, &fds_write)) e(3, "write should be set");
110 if(FD_ISSET(terminal, &fds_error)) e(4, "error should NOT be set");
112 /* Block until ready; until child wrote stuff */
113 FD_ZERO(&fds_read); FD_ZERO(&fds_write); FD_ZERO(&fds_error);
114 FD_SET(terminal, &fds_read);
115 retval = select(terminal+1, &fds_read, NULL, &fds_error, NULL);
117 if(retval != 1) e(5, "incorrect amount of ready file descriptors");
118 if(!FD_ISSET(terminal, &fds_read)) e(6, "read should be set");
119 if(FD_ISSET(terminal, &fds_error)) e(7, "error should not be set");
122 FD_ZERO(&fds_read); FD_ZERO(&fds_error);
123 FD_SET(terminal, &fds_write);
124 retval = select(terminal+1, NULL, &fds_write, NULL, NULL);
125 /* As it is impossible to write to a read only fd, this select should return
126 * immediately with fd set in fds_write. */
127 if(retval != 1) e(8, "incorrect amount or ready file descriptors");
129 close(terminal);
130 waitpid(child, &retval, 0);
131 exit(errct);
134 int main(int argc, char **argv) {
135 int forkres;
136 int master, slave;
138 /* Get subtest number */
139 if(argc != 2) {
140 printf("Usage: %s subtest_no\n", argv[0]);
141 exit(-1);
142 } else if(sscanf(argv[1], "%d", &subtest) != 1) {
143 printf("Usage: %s subtest_no\n", argv[0]);
144 exit(-1);
147 open_terminal(&master, &slave);
149 forkres = fork();
150 if(forkres == 0) do_child(master);
151 else if(forkres > 0) do_parent(forkres, slave);
152 else { /* Fork failed */
153 perror("Unable to fork");
154 exit(-1);
157 exit(-2); /* We're not supposed to get here. Both do_* routines should exit*/