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