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)
9 * This test is part of a bigger select test. It expects as argument which sub-
16 #include <sys/types.h>
19 #include <sys/select.h>
24 #define TERMINALW "/dev/ttypf"
25 #define TERMINALR "/dev/ptypf"
26 #define SENDSTRING "minixrocks"
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");
40 void open_terminal(int *child_fd
, int *parent_fd
) {
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) {
66 /* If we get here we failed to find a terminal pair */
70 int do_child(int terminal
) {
74 /* Going to sleep for two seconds to allow the parent proc to get ready */
77 select(0, NULL
, NULL
, NULL
, &tv
);
79 /* Try to write. Doesn't matter how many bytes we actually send. */
80 retval
= write(terminal
, SENDSTRING
, strlen(SENDSTRING
));
83 /* Wait for another second to allow the parent to process incoming data */
85 retval
= select(0,NULL
, NULL
, NULL
, &tv
);
89 int do_parent(int child
, int terminal
) {
90 fd_set fds_read
, fds_write
, fds_error
;
94 FD_ZERO(&fds_read
); FD_ZERO(&fds_write
); FD_ZERO(&fds_error
);
96 FD_SET(terminal
, &fds_read
);
97 FD_SET(terminal
, &fds_write
);
99 /* Test if we can read or write from/to fd. As fd is opened read only we
100 * cannot actually write, so the select should return immediately with fd
101 * set in fds_write, but not in fds_read. Note that the child waits two
102 * seconds before sending data. This gives us the opportunity run this
103 * sub-test as reading from fd is blocking at this point. */
104 retval
= select(terminal
+1, &fds_read
, &fds_write
, &fds_error
, NULL
);
106 if(retval
!= 1) e(1, "incorrect amount of ready file descriptors");
109 if(FD_ISSET(terminal
, &fds_read
)) e(2, "read should NOT be set");
110 if(!FD_ISSET(terminal
, &fds_write
)) e(3, "write should be set");
111 if(FD_ISSET(terminal
, &fds_error
)) e(4, "error should NOT be set");
113 /* Block until ready; until child wrote stuff */
114 FD_ZERO(&fds_read
); FD_ZERO(&fds_write
); FD_ZERO(&fds_error
);
115 FD_SET(terminal
, &fds_read
);
116 retval
= select(terminal
+1, &fds_read
, NULL
, &fds_error
, NULL
);
118 if(retval
!= 1) e(5, "incorrect amount of ready file descriptors");
119 if(!FD_ISSET(terminal
, &fds_read
)) e(6, "read should be set");
120 if(FD_ISSET(terminal
, &fds_error
)) e(7, "error should not be set");
123 FD_ZERO(&fds_read
); FD_ZERO(&fds_error
);
124 FD_SET(terminal
, &fds_write
);
125 retval
= select(terminal
+1, NULL
, &fds_write
, NULL
, NULL
);
126 /* As it is impossible to write to a read only fd, this select should return
127 * immediately with fd set in fds_write. */
128 if(retval
!= 1) e(8, "incorrect amount or ready file descriptors");
131 waitpid(child
, &retval
, 0);
135 int main(int argc
, char **argv
) {
139 /* Get subtest number */
141 printf("Usage: %s subtest_no\n", argv
[0]);
143 } else if(sscanf(argv
[1], "%d", &subtest
) != 1) {
144 printf("Usage: %s subtest_no\n", argv
[0]);
148 open_terminal(&master
, &slave
);
151 if(forkres
== 0) do_child(master
);
152 else if(forkres
> 0) do_parent(forkres
, slave
);
153 else { /* Fork failed */
154 perror("Unable to fork");
158 exit(-2); /* We're not supposed to get here. Both do_* routines should exit*/