xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/fifo_rdonly_bug.c (revision 41fbaed053f8fbfdf9d2a4ee0a7386a3c83f8505)
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