Commit | Line | Data |
---|---|---|
959f3c4c JH |
1 | ?RCS: $Id: nblock_io.U,v 3.0.1.2 1997/02/28 16:17:14 ram Exp $ |
2 | ?RCS: | |
3 | ?RCS: Copyright (c) 1991-1993, Raphael Manfredi | |
0065f4af | 4 | ?RCS: |
65a32477 | 5 | ?RCS: You may redistribute only under the terms of the Artistic License, |
959f3c4c JH |
6 | ?RCS: as specified in the README file that comes with the distribution. |
7 | ?RCS: You may reuse parts of this distribution only within the terms of | |
65a32477 | 8 | ?RCS: that same Artistic License; a copy of which may be found at the root |
959f3c4c JH |
9 | ?RCS: of the source tree for dist 3.0. |
10 | ?RCS: | |
11 | ?RCS: $Log: nblock_io.U,v $ | |
12 | ?RCS: Revision 3.0.1.2 1997/02/28 16:17:14 ram | |
13 | ?RCS: patch61: simplify here document for shells that can't handle them well | |
14 | ?RCS: patch61: force use of "startsh" at the head of the generated script | |
15 | ?RCS: patch61: added new files to the ?F: metalint hint | |
16 | ?RCS: | |
17 | ?RCS: Revision 3.0.1.1 1995/07/25 14:13:22 ram | |
18 | ?RCS: patch56: created | |
19 | ?RCS: | |
20 | ?X: | |
21 | ?X: Simplify here document for shells that can't handle them well. | |
22 | ?X: (Problem reported on FreeBSD; it's unclear if this helps.) --AD | |
23 | ?X: | |
2cb64bf6 | 24 | ?MAKE:o_nonblock eagain rd_nodata d_eofnblk: cat rm_try Compile run \ |
37a56d0d | 25 | d_open3 h_sysfile h_fcntl signal_t hint Oldconfig Setvar \ |
9b269d84 | 26 | startsh i_unistd i_string i_fcntl i_stdlib d_fork d_pipe |
959f3c4c JH |
27 | ?MAKE: -pick add $@ %< |
28 | ?S:o_nonblock: | |
29 | ?S: This variable bears the symbol value to be used during open() or fcntl() | |
30 | ?S: to turn on non-blocking I/O for a file descriptor. If you wish to switch | |
31 | ?S: between blocking and non-blocking, you may try ioctl(FIOSNBIO) instead, | |
32 | ?S: but that is only supported by some devices. | |
33 | ?S:. | |
34 | ?S:eagain: | |
35 | ?S: This variable bears the symbolic errno code set by read() when no | |
36 | ?S: data is present on the file and non-blocking I/O was enabled (otherwise, | |
37 | ?S: read() blocks naturally). | |
38 | ?S:. | |
39 | ?S:rd_nodata: | |
40 | ?S: This variable holds the return code from read() when no data is | |
41 | ?S: present. It should be -1, but some systems return 0 when O_NDELAY is | |
42 | ?S: used, which is a shame because you cannot make the difference between | |
43 | ?S: no data and an EOF.. Sigh! | |
44 | ?S:. | |
45 | ?S:d_eofnblk: | |
46 | ?S: This variable conditionally defines EOF_NONBLOCK if EOF can be seen | |
47 | ?S: when reading from a non-blocking I/O source. | |
48 | ?S:. | |
49 | ?C:VAL_O_NONBLOCK: | |
50 | ?C: This symbol is to be used during open() or fcntl(F_SETFL) to turn on | |
51 | ?C: non-blocking I/O for the file descriptor. Note that there is no way | |
52 | ?C: back, i.e. you cannot turn it blocking again this way. If you wish to | |
53 | ?C: alternatively switch between blocking and non-blocking, use the | |
54 | ?C: ioctl(FIOSNBIO) call instead, but that is not supported by all devices. | |
55 | ?C:. | |
56 | ?C:VAL_EAGAIN: | |
57 | ?C: This symbol holds the errno error code set by read() when no data was | |
58 | ?C: present on the non-blocking file descriptor. | |
59 | ?C:. | |
60 | ?C:RD_NODATA: | |
61 | ?C: This symbol holds the return code from read() when no data is present | |
62 | ?C: on the non-blocking file descriptor. Be careful! If EOF_NONBLOCK is | |
63 | ?C: not defined, then you can't distinguish between no data and EOF by | |
64 | ?C: issuing a read(). You'll have to find another way to tell for sure! | |
65 | ?C:. | |
66 | ?C:EOF_NONBLOCK: | |
67 | ?C: This symbol, if defined, indicates to the C program that a read() on | |
68 | ?C: a non-blocking file descriptor will return 0 on EOF, and not the value | |
69 | ?C: held in RD_NODATA (-1 usually, in that case!). | |
70 | ?C:. | |
71 | ?H:#define VAL_O_NONBLOCK $o_nonblock | |
72 | ?H:#define VAL_EAGAIN $eagain | |
73 | ?H:#define RD_NODATA $rd_nodata | |
74 | ?H:#$d_eofnblk EOF_NONBLOCK | |
75 | ?H:. | |
959f3c4c | 76 | ?T:status |
41322e17 | 77 | ?F:!try.out !try.ret !try.err !try !mtry |
959f3c4c JH |
78 | ?LINT:use d_open3 |
79 | : check for non-blocking I/O stuff | |
80 | case "$h_sysfile" in | |
cede5cd9 JH |
81 | true) echo "#include <sys/file.h>" > head.c;; |
82 | *) | |
83 | case "$h_fcntl" in | |
84 | true) echo "#include <fcntl.h>" > head.c;; | |
85 | *) echo "#include <sys/fcntl.h>" > head.c;; | |
86 | esac | |
87 | ;; | |
959f3c4c JH |
88 | esac |
89 | echo " " | |
90 | echo "Figuring out the flag used by open() for non-blocking I/O..." >&4 | |
91 | case "$o_nonblock" in | |
92 | '') | |
93 | $cat head.c > try.c | |
e8970d08 | 94 | $cat >>try.c <<EOCP |
37a56d0d | 95 | #include <stdio.h> |
1273bb5e JH |
96 | #$i_stdlib I_STDLIB |
97 | #ifdef I_STDLIB | |
d0abe53c | 98 | #include <stdlib.h> |
1273bb5e | 99 | #endif |
8411e286 JH |
100 | #$i_fcntl I_FCNTL |
101 | #ifdef I_FCNTL | |
102 | #include <fcntl.h> | |
103 | #endif | |
959f3c4c JH |
104 | int main() { |
105 | #ifdef O_NONBLOCK | |
106 | printf("O_NONBLOCK\n"); | |
107 | exit(0); | |
108 | #endif | |
109 | #ifdef O_NDELAY | |
110 | printf("O_NDELAY\n"); | |
111 | exit(0); | |
112 | #endif | |
113 | ?X: Stevens "Advanced Programming in the UNIX Environment" page 364 mentions | |
8411e286 | 114 | ?X: the FNDELAY symbol, used in 4.3BSD (source: Paul Marquess). |
959f3c4c JH |
115 | #ifdef FNDELAY |
116 | printf("FNDELAY\n"); | |
117 | exit(0); | |
118 | #endif | |
119 | exit(0); | |
120 | } | |
121 | EOCP | |
122 | set try | |
123 | if eval $compile_ok; then | |
0f00356b | 124 | o_nonblock=`$run ./try` |
959f3c4c JH |
125 | case "$o_nonblock" in |
126 | '') echo "I can't figure it out, assuming O_NONBLOCK will do.";; | |
127 | *) echo "Seems like we can use $o_nonblock.";; | |
128 | esac | |
129 | else | |
130 | echo "(I can't compile the test program; pray O_NONBLOCK is right!)" | |
131 | fi | |
132 | ;; | |
133 | *) echo "Using $hint value $o_nonblock.";; | |
134 | esac | |
2cb64bf6 | 135 | $rm_try |
959f3c4c JH |
136 | |
137 | echo " " | |
138 | echo "Let's see what value errno gets from read() on a $o_nonblock file..." >&4 | |
139 | case "$eagain" in | |
140 | '') | |
9b269d84 JH |
141 | case "$d_fork:$d_pipe" in |
142 | define:define) | |
959f3c4c JH |
143 | $cat head.c > try.c |
144 | $cat >>try.c <<EOCP | |
145 | #include <errno.h> | |
146 | #include <sys/types.h> | |
147 | #include <signal.h> | |
2cb64bf6 | 148 | #include <stdio.h> |
1273bb5e JH |
149 | #$i_stdlib I_STDLIB |
150 | #ifdef I_STDLIB | |
151 | #include <stdlib.h> | |
152 | #endif | |
80a8aa8f JH |
153 | #$i_fcntl I_FCNTL |
154 | #ifdef I_FCNTL | |
155 | #include <fcntl.h> | |
156 | #endif | |
959f3c4c JH |
157 | #define MY_O_NONBLOCK $o_nonblock |
158 | #ifndef errno /* XXX need better Configure test */ | |
159 | extern int errno; | |
160 | #endif | |
b8fb7a32 JH |
161 | #$i_unistd I_UNISTD |
162 | #ifdef I_UNISTD | |
37a56d0d JH |
163 | #include <unistd.h> |
164 | #endif | |
08b5bf24 JH |
165 | #$i_string I_STRING |
166 | #ifdef I_STRING | |
37a56d0d JH |
167 | #include <string.h> |
168 | #else | |
169 | #include <strings.h> | |
170 | #endif | |
dc952a08 | 171 | $signal_t blech(int x) { exit(3); } |
959f3c4c JH |
172 | EOCP |
173 | $cat >> try.c <<'EOCP' | |
174 | int main() | |
175 | { | |
176 | int pd[2]; | |
177 | int pu[2]; | |
178 | char buf[1]; | |
179 | char string[100]; | |
f29bc7d4 | 180 | int ret; |
959f3c4c | 181 | |
f29bc7d4 MBT |
182 | ret = pipe(pd); /* Down: child -> parent */ |
183 | if (ret != 0) | |
184 | exit(3); | |
185 | ret = pipe(pu); /* Up: parent -> child */ | |
186 | if (ret != 0) | |
187 | exit(3); | |
959f3c4c | 188 | if (0 != fork()) { |
959f3c4c JH |
189 | close(pd[1]); /* Parent reads from pd[0] */ |
190 | close(pu[0]); /* Parent writes (blocking) to pu[1] */ | |
cede5cd9 | 191 | #ifdef F_SETFL |
959f3c4c JH |
192 | if (-1 == fcntl(pd[0], F_SETFL, MY_O_NONBLOCK)) |
193 | exit(1); | |
cede5cd9 JH |
194 | #else |
195 | exit(4); | |
196 | #endif | |
959f3c4c JH |
197 | signal(SIGALRM, blech); |
198 | alarm(5); | |
199 | if ((ret = read(pd[0], buf, 1)) > 0) /* Nothing to read! */ | |
200 | exit(2); | |
201 | sprintf(string, "%d\n", ret); | |
f29bc7d4 MBT |
202 | ret = write(2, string, strlen(string)); |
203 | if (ret != strlen(string)) | |
204 | exit(3); | |
959f3c4c JH |
205 | alarm(0); |
206 | #ifdef EAGAIN | |
207 | if (errno == EAGAIN) { | |
208 | printf("EAGAIN\n"); | |
209 | goto ok; | |
210 | } | |
211 | #endif | |
212 | #ifdef EWOULDBLOCK | |
213 | if (errno == EWOULDBLOCK) | |
214 | printf("EWOULDBLOCK\n"); | |
215 | #endif | |
216 | ok: | |
f29bc7d4 MBT |
217 | ret = write(pu[1], buf, 1); /* Unblocks child, tell it to close our pipe */ |
218 | if (ret != 1) | |
219 | exit(3); | |
959f3c4c JH |
220 | sleep(2); /* Give it time to close our pipe */ |
221 | alarm(5); | |
222 | ret = read(pd[0], buf, 1); /* Should read EOF */ | |
223 | alarm(0); | |
224 | sprintf(string, "%d\n", ret); | |
f29bc7d4 MBT |
225 | ret = write(4, string, strlen(string)); |
226 | if (ret != strlen(string)) | |
227 | exit(3); | |
959f3c4c JH |
228 | exit(0); |
229 | } | |
230 | ||
231 | close(pd[0]); /* We write to pd[1] */ | |
232 | close(pu[1]); /* We read from pu[0] */ | |
f29bc7d4 MBT |
233 | ret = read(pu[0], buf, 1); /* Wait for parent to signal us we may continue */ |
234 | if (ret != 1) | |
235 | exit(3); | |
959f3c4c JH |
236 | close(pd[1]); /* Pipe pd is now fully closed! */ |
237 | exit(0); /* Bye bye, thank you for playing! */ | |
238 | } | |
239 | EOCP | |
240 | set try | |
241 | if eval $compile_ok; then | |
242 | ?X: Use script to avoid the possible 'alarm call' message | |
243 | echo "$startsh" >mtry | |
26470d78 | 244 | echo "$run ./try >try.out 2>try.ret 4>try.err || exit 4" >>mtry |
959f3c4c | 245 | chmod +x mtry |
9c11722e | 246 | $run ./mtry >/dev/null 2>&1 |
959f3c4c JH |
247 | case $? in |
248 | 0) eagain=`$cat try.out`;; | |
249 | 1) echo "Could not perform non-blocking setting!";; | |
250 | 2) echo "I did a successful read() for something that was not there!";; | |
251 | 3) echo "Hmm... non-blocking I/O does not seem to be working!";; | |
cede5cd9 | 252 | 4) echo "Could not find F_SETFL!";; |
959f3c4c JH |
253 | *) echo "Something terribly wrong happened during testing.";; |
254 | esac | |
255 | rd_nodata=`$cat try.ret` | |
256 | echo "A read() system call with no data present returns $rd_nodata." | |
257 | case "$rd_nodata" in | |
258 | 0|-1) ;; | |
259 | *) | |
260 | echo "(That's peculiar, fixing that to be -1.)" | |
261 | rd_nodata=-1 | |
262 | ;; | |
263 | esac | |
264 | case "$eagain" in | |
265 | '') | |
266 | echo "Forcing errno EAGAIN on read() with no data available." | |
267 | eagain=EAGAIN | |
268 | ;; | |
269 | *) | |
270 | echo "Your read() sets errno to $eagain when no data is available." | |
271 | ;; | |
272 | esac | |
273 | status=`$cat try.err` | |
274 | case "$status" in | |
275 | 0) echo "And it correctly returns 0 to signal EOF.";; | |
276 | -1) echo "But it also returns -1 to signal EOF, so be careful!";; | |
277 | *) echo "However, your read() returns '$status' on EOF??";; | |
278 | esac | |
279 | val="$define" | |
280 | if test "$status" = "$rd_nodata"; then | |
281 | echo "WARNING: you can't distinguish between EOF and no data!" | |
282 | val="$undef" | |
283 | fi | |
284 | else | |
285 | echo "I can't compile the test program--assuming errno EAGAIN will do." | |
286 | eagain=EAGAIN | |
287 | fi | |
9b269d84 JH |
288 | ;; |
289 | *) echo "Can't figure out how to test this--assuming errno EAGAIN will do." | |
290 | eagain=EAGAIN | |
291 | val="$define" | |
292 | ;; | |
293 | esac | |
959f3c4c JH |
294 | set d_eofnblk |
295 | eval $setvar | |
296 | ;; | |
297 | *) | |
298 | echo "Using $hint value $eagain." | |
299 | echo "Your read() returns $rd_nodata when no data is present." | |
300 | case "$d_eofnblk" in | |
301 | "$define") echo "And you can see EOF because read() returns 0.";; | |
302 | "$undef") echo "But you can't see EOF status from read() returned value.";; | |
303 | *) | |
304 | ?X: Should not happen, but if it does, assume the worst! | |
305 | echo "(Assuming you can't see EOF status from read anyway.)" | |
306 | d_eofnblk=$undef | |
307 | ;; | |
308 | esac | |
309 | ;; | |
310 | esac | |
2cb64bf6 | 311 | $rm_try head.c mtry |
959f3c4c | 312 |