1 /* $NetBSD: fifo_rdonly_bug.c,v 1.1.1.1 2009/06/23 10:08:59 tron Exp $ */
2
3 /*++
4 /* NAME
5 /* fifo_rdonly_bug 1
6 /* SUMMARY
7 /* fifo server test program
8 /* SYNOPSIS
9 /* fifo_rdonly_bug
10 /* DESCRIPTION
11 /* fifo_rdonly_bug creates a FIFO and opens it read only. It
12 /* then opens the FIFO for writing, writes one byte, and closes
13 /* the writing end. On Linux Redhat 4.2 and 5.0, and HP-UX 9.05
14 /* and 10.20, select() will report that the FIFO remains readable
15 /* even after multiple read operations.
16 /* DIAGNOSTICS
17 /* Problems are reported to the standard error stream.
18 /* LICENSE
19 /* .ad
20 /* .fi
21 /* The Secure Mailer license must be distributed with this software.
22 /* AUTHOR(S)
23 /* Wietse Venema
24 /* IBM T.J. Watson Research
25 /* P.O. Box 704
26 /* Yorktown Heights, NY 10598, USA
27 /*--*/
28
29 #include <sys_defs.h>
30 #include <sys/stat.h>
31 #include <sys/time.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <fcntl.h>
36 #include <string.h>
37
38 #define FIFO_PATH "test-fifo"
39 #define TRIGGER_DELAY 5
40
41 #define perrorexit(s) { perror(s); exit(1); }
42
cleanup(void)43 static void cleanup(void)
44 {
45 printf("Removing fifo %s...\n", FIFO_PATH);
46 if (unlink(FIFO_PATH))
47 perrorexit("unlink");
48 printf("Done.\n");
49 }
50
perrorcleanup(char * str)51 static void perrorcleanup(char *str)
52 {
53 perror(str);
54 cleanup();
55 exit(0);
56 }
57
readable_event(int fd)58 static void readable_event(int fd)
59 {
60 char ch;
61 static int count = 0;
62
63 if (read(fd, &ch, 1) < 0) {
64 perror("read");
65 sleep(1);
66 }
67 if (count++ > 5) {
68 printf("FIFO remains readable after multiple reads.\n");
69 cleanup();
70 exit(1);
71 }
72 }
73
main(int unused_argc,char ** unused_argv)74 int main(int unused_argc, char **unused_argv)
75 {
76 struct timeval tv;
77 fd_set read_fds;
78 fd_set except_fds;
79 int fd;
80 int fd2;
81
82 (void) unlink(FIFO_PATH);
83
84 printf("Create fifo %s...\n", FIFO_PATH);
85 if (mkfifo(FIFO_PATH, 0600) < 0)
86 perrorexit("mkfifo");
87
88 printf("Open fifo %s, read-only mode...\n", FIFO_PATH);
89 if ((fd = open(FIFO_PATH, O_RDONLY | O_NONBLOCK, 0)) < 0)
90 perrorcleanup("open");
91
92 printf("Write one byte to the fifo, then close it...\n");
93 if ((fd2 = open(FIFO_PATH, O_WRONLY, 0)) < 0)
94 perrorcleanup("open fifo O_WRONLY");
95 if (write(fd2, "", 1) < 1)
96 perrorcleanup("write one byte to fifo");
97 if (close(fd2) < 0)
98 perrorcleanup("close fifo");
99
100 printf("Selecting the fifo for readability...\n");
101
102 for (;;) {
103 FD_ZERO(&read_fds);
104 FD_SET(fd, &read_fds);
105 FD_ZERO(&except_fds);
106 FD_SET(fd, &except_fds);
107 tv.tv_sec = 1;
108 tv.tv_usec = 0;
109
110 switch (select(fd + 1, &read_fds, (fd_set *) 0, &except_fds, &tv)) {
111 case -1:
112 perrorexit("select");
113 default:
114 if (FD_ISSET(fd, &except_fds)) {
115 printf("Exceptional fifo condition! You are not normal!\n");
116 readable_event(fd);
117 } else if (FD_ISSET(fd, &read_fds)) {
118 printf("Readable fifo condition\n");
119 readable_event(fd);
120 }
121 break;
122 case 0:
123 printf("The fifo is not readable. You're normal.\n");
124 cleanup();
125 exit(0);
126 break;
127 }
128 }
129 }
130