release.sh: allow REPO and GITBRANCH env override
[minix.git] / test / select / test14.c
blob99cc009a31e7d07791feb1c09023f118e735313c
1 /*
2 * Test name: test14.c
4 * Objetive: The purpose of this test is to make sure that select works
5 * with ptys.
7 * Adapted from test11.c (pipe test).
8 *
9 * Ben Gras
11 #include <time.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
14 #include <sys/asynchio.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <sys/select.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <limits.h>
21 #include <string.h>
22 #include <signal.h>
23 #include <libutil.h>
24 char name[100];
25 void pipehandler(int sig)
28 #define CHILDFD 1
29 #define PARENTFD 0
30 void do_child(int pty_fds[])
32 /* reads from pipe and prints out the data */
33 char data[2048];
34 int retval;
35 fd_set fds_read;
36 fd_set fds_exception;
37 struct timeval timeout;
38 signal(SIGPIPE, pipehandler);
39 signal(SIGUSR1, pipehandler);
40 /* first, close the write part, since it is not needed */
41 close(pty_fds[PARENTFD]);
43 while(1) {
44 FD_ZERO(&fds_read);
45 FD_ZERO(&fds_exception);
46 FD_SET(pty_fds[CHILDFD], &fds_read);
47 FD_SET(pty_fds[CHILDFD], &fds_exception);
48 timeout.tv_sec = 5;
49 timeout.tv_usec = 0;
50 retval = select(pty_fds[CHILDFD]+2, &fds_read, NULL, &fds_exception, &timeout);
51 if (retval == -1) {
52 perror("select");
53 fprintf(stderr, "child: Error in select\n");
54 continue;
55 } else printf("child select: %d\n", retval);
56 if (FD_ISSET(pty_fds[CHILDFD], &fds_exception)) {
57 printf("child: exception fd set. quitting.\n");
58 break;
60 if (FD_ISSET(pty_fds[CHILDFD], &fds_read)) {
61 printf("child: read fd set. reading.\n");
62 if ((retval = read(pty_fds[CHILDFD], data, sizeof(data))) < 0) {
63 perror("read");
64 fprintf(stderr, "child: couldn't read from pty\n");
65 exit(-1);
67 if(retval == 0) {
68 fprintf(stderr, "child: eof on pty\n");
69 break;
71 data[retval] = '\0';
72 printf("pid %d pty reads (%d): %s\n", getpid(), retval, data);
73 } else printf("child: no fd set\n");
76 exit(0);
78 void do_parent(int pty_fds[])
80 char data[1024];
81 int retval;
82 fd_set fds_write;
83 signal(SIGPIPE, pipehandler);
84 signal(SIGUSR1, pipehandler);
85 /* first, close the read part of pty, since it is not needed */
86 close(pty_fds[CHILDFD]);
87 /* now enter a loop of read user input, and writing it to the pty */
88 while (1) {
89 FD_ZERO(&fds_write);
90 FD_SET(pty_fds[PARENTFD], &fds_write);
91 printf("pid %d Waiting for pty ready to write on %s...\n",
92 getpid(), name);
93 retval = select(pty_fds[PARENTFD]+2, NULL, &fds_write, NULL, NULL);
94 if (retval == -1) {
95 perror("select");
96 fprintf(stderr, "Parent: Error in select\n");
97 exit(-1);
99 printf("Input data: ");
100 if(!gets(data)) {
101 printf("parent: eof; exiting\n");
102 break;
104 if (!strcmp(data, "exit"))
105 break;
106 if (!FD_ISSET(pty_fds[PARENTFD], &fds_write)) {
107 fprintf(stderr, "parent: write fd not set?! retrying\n");
108 continue;
110 retval = write(pty_fds[PARENTFD], data, 1024);
111 if (retval == -1) {
112 perror("write");
113 fprintf(stderr, "Error writing on pty\n");
114 exit(-1);
115 } else printf("wrote %d\n", retval);
117 /* got exit from user */
118 close(pty_fds[PARENTFD]); /* close pty, let child know we're done */
119 wait(&retval);
120 printf("Child exited with status: %d\n", retval);
121 exit(0);
123 int main(int argc, char *argv[])
125 int ptys[2];
126 int retval;
127 int pid;
128 if(openpty(&ptys[0], &ptys[1], name, NULL, NULL) < 0) {
129 perror("openpty");
130 return 1;
132 printf("Using %s\n", name);
133 pid = fork();
134 if (pid == -1) {
135 fprintf(stderr, "Error forking\n");
136 exit(-1);
138 if (pid == 0) /* child proc */
139 do_child(ptys);
140 else
141 do_parent(ptys);
142 /* not reached */
143 return 0;