File: | os_io.c |
Location: | line 6683, column 35 |
Description: | The left operand of '>=' is a garbage value |
1 | /* File: "os_io.c" */ | |||
2 | ||||
3 | /* Copyright (c) 1994-2013 by Marc Feeley, All Rights Reserved. */ | |||
4 | ||||
5 | /* | |||
6 | * This module implements the operating system specific routines | |||
7 | * related to I/O. | |||
8 | */ | |||
9 | ||||
10 | #define ___INCLUDED_FROM_OS_IO | |||
11 | #define ___VERSION407000 407000 | |||
12 | #include "gambit.h" | |||
13 | ||||
14 | #include "os_base.h" | |||
15 | #include "os_io.h" | |||
16 | #include "os_tty.h" | |||
17 | #include "os_files.h" | |||
18 | #include "setup.h" | |||
19 | #include "c_intf.h" | |||
20 | ||||
21 | /*---------------------------------------------------------------------------*/ | |||
22 | ||||
23 | ||||
24 | ___io_module ___io_mod = | |||
25 | { | |||
26 | 0, | |||
27 | 0 | |||
28 | ||||
29 | #ifdef ___IO_MODULE_INIT | |||
30 | ___IO_MODULE_INIT | |||
31 | #endif | |||
32 | }; | |||
33 | ||||
34 | ||||
35 | /*---------------------------------------------------------------------------*/ | |||
36 | ||||
37 | /* Device groups. */ | |||
38 | ||||
39 | ||||
40 | ___SCMOBJlong ___device_group_setup | |||
41 | ___P((___device_group **dgroup),(___device_group **dgroup) | |||
42 | (dgroup)(___device_group **dgroup) | |||
43 | ___device_group **dgroup;)(___device_group **dgroup) | |||
44 | { | |||
45 | ___SCMOBJlong e; | |||
46 | ___device_group *g; | |||
47 | ||||
48 | g = ___CAST(___device_group*,((___device_group*)(___alloc_mem (sizeof (___device_group)))) | |||
49 | ___alloc_mem (sizeof (___device_group)))((___device_group*)(___alloc_mem (sizeof (___device_group)))); | |||
50 | ||||
51 | if (g == NULL((void*)0)) | |||
52 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
53 | ||||
54 | g->list = NULL((void*)0); | |||
55 | ||||
56 | *dgroup = g; | |||
57 | ||||
58 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
59 | } | |||
60 | ||||
61 | ||||
62 | void ___device_group_cleanup | |||
63 | ___P((___device_group *dgroup),(___device_group *dgroup) | |||
64 | (dgroup)(___device_group *dgroup) | |||
65 | ___device_group *dgroup;)(___device_group *dgroup) | |||
66 | { | |||
67 | while (dgroup->list != NULL((void*)0)) | |||
68 | if (___device_cleanup (dgroup->list) != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
69 | break; | |||
70 | ||||
71 | ___free_mem (dgroup); | |||
72 | } | |||
73 | ||||
74 | ||||
75 | void ___device_add_to_group | |||
76 | ___P((___device_group *dgroup,(___device_group *dgroup, ___device *dev) | |||
77 | ___device *dev),(___device_group *dgroup, ___device *dev) | |||
78 | (dgroup,(___device_group *dgroup, ___device *dev) | |||
79 | dev)(___device_group *dgroup, ___device *dev) | |||
80 | ___device_group *dgroup;(___device_group *dgroup, ___device *dev) | |||
81 | ___device *dev;)(___device_group *dgroup, ___device *dev) | |||
82 | { | |||
83 | ___device *head = dgroup->list; | |||
84 | ||||
85 | dev->group = dgroup; | |||
86 | ||||
87 | if (head == NULL((void*)0)) | |||
88 | { | |||
89 | dev->next = dev; | |||
90 | dev->prev = dev; | |||
91 | dgroup->list = dev; | |||
92 | } | |||
93 | else | |||
94 | { | |||
95 | ___device *tail = head->prev; | |||
96 | dev->next = head; | |||
97 | dev->prev = tail; | |||
98 | tail->next = dev; | |||
99 | head->prev = dev; | |||
100 | } | |||
101 | } | |||
102 | ||||
103 | void ___device_remove_from_group | |||
104 | ___P((___device *dev),(___device *dev) | |||
105 | (dev)(___device *dev) | |||
106 | ___device *dev;)(___device *dev) | |||
107 | { | |||
108 | ___device_group *dgroup = dev->group; | |||
109 | ___device *prev = dev->prev; | |||
110 | ___device *next = dev->next; | |||
111 | ||||
112 | if (prev == dev) | |||
113 | dgroup->list = NULL((void*)0); | |||
114 | else | |||
115 | { | |||
116 | if (dgroup->list == dev) | |||
117 | dgroup->list = next; | |||
118 | prev->next = next; | |||
119 | next->prev = prev; | |||
120 | dev->next = dev; | |||
121 | dev->prev = dev; | |||
122 | } | |||
123 | ||||
124 | dev->group = NULL((void*)0); | |||
125 | } | |||
126 | ||||
127 | ___device_group *___global_device_group ___PVOID(void) | |||
128 | { | |||
129 | return ___io_mod.dgroup; | |||
130 | } | |||
131 | ||||
132 | ||||
133 | /*---------------------------------------------------------------------------*/ | |||
134 | ||||
135 | /* Nonblocking pipes */ | |||
136 | ||||
137 | #ifdef USE_PUMPS | |||
138 | ||||
139 | ___HIDDENstatic ___SCMOBJlong ___nonblocking_pipe_setup | |||
140 | ___P((___nonblocking_pipe *pipe,(___nonblocking_pipe *pipe, int size) | |||
141 | int size),(___nonblocking_pipe *pipe, int size) | |||
142 | (pipe,(___nonblocking_pipe *pipe, int size) | |||
143 | size)(___nonblocking_pipe *pipe, int size) | |||
144 | ___nonblocking_pipe *pipe;(___nonblocking_pipe *pipe, int size) | |||
145 | int size;)(___nonblocking_pipe *pipe, int size) | |||
146 | { | |||
147 | ___U8unsigned char *buffer; | |||
148 | HANDLE mutex; | |||
149 | HANDLE revent; | |||
150 | HANDLE wevent; | |||
151 | ||||
152 | buffer = ___CAST(___U8*,((unsigned char*)(___alloc_mem (size))) | |||
153 | ___alloc_mem (size))((unsigned char*)(___alloc_mem (size))); | |||
154 | ||||
155 | if (buffer == NULL((void*)0)) | |||
156 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
157 | ||||
158 | mutex = CreateMutex (NULL((void*)0), /* can't inherit */ | |||
159 | FALSE, /* unlocked */ | |||
160 | NULL((void*)0)); /* no name */ | |||
161 | ||||
162 | if (mutex == NULL((void*)0)) | |||
163 | { | |||
164 | ___SCMOBJlong e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
165 | ___free_mem (buffer); | |||
166 | return e; | |||
167 | } | |||
168 | ||||
169 | revent = CreateEvent (NULL((void*)0), /* can't inherit */ | |||
170 | TRUE, /* manual reset */ | |||
171 | FALSE, /* not signaled */ | |||
172 | NULL((void*)0)); /* no name */ | |||
173 | ||||
174 | if (revent == NULL((void*)0)) | |||
175 | { | |||
176 | ___SCMOBJlong e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
177 | CloseHandle (mutex); /* ignore error */ | |||
178 | ___free_mem (buffer); | |||
179 | return e; | |||
180 | } | |||
181 | ||||
182 | wevent = CreateEvent (NULL((void*)0), /* can't inherit */ | |||
183 | TRUE, /* manual reset */ | |||
184 | FALSE, /* not signaled */ | |||
185 | NULL((void*)0)); /* no name */ | |||
186 | ||||
187 | if (wevent == NULL((void*)0)) | |||
188 | { | |||
189 | ___SCMOBJlong e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
190 | CloseHandle (revent); /* ignore error */ | |||
191 | CloseHandle (mutex); /* ignore error */ | |||
192 | ___free_mem (buffer); | |||
193 | return e; | |||
194 | } | |||
195 | ||||
196 | pipe->mutex = mutex; | |||
197 | pipe->revent = revent; | |||
198 | pipe->wevent = wevent; | |||
199 | pipe->rerr = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
200 | pipe->werr = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
201 | pipe->oob = 0; | |||
202 | pipe->rd = 0; | |||
203 | pipe->wr = 0; | |||
204 | pipe->size = size; | |||
205 | pipe->buffer = buffer; | |||
206 | ||||
207 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
208 | } | |||
209 | ||||
210 | ___HIDDENstatic ___SCMOBJlong ___nonblocking_pipe_cleanup | |||
211 | ___P((___nonblocking_pipe *pipe),(___nonblocking_pipe *pipe) | |||
212 | (pipe)(___nonblocking_pipe *pipe) | |||
213 | ___nonblocking_pipe *pipe;)(___nonblocking_pipe *pipe) | |||
214 | { | |||
215 | CloseHandle (pipe->wevent); /* ignore error */ | |||
216 | CloseHandle (pipe->revent); /* ignore error */ | |||
217 | CloseHandle (pipe->mutex); /* ignore error */ | |||
218 | ___free_mem (pipe->buffer); | |||
219 | ||||
220 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
221 | } | |||
222 | ||||
223 | ___HIDDENstatic ___SCMOBJlong ___nonblocking_pipe_set_reader_err | |||
224 | ___P((___nonblocking_pipe *pipe,(___nonblocking_pipe *pipe, long err) | |||
225 | ___SCMOBJ err),(___nonblocking_pipe *pipe, long err) | |||
226 | (pipe,(___nonblocking_pipe *pipe, long err) | |||
227 | err)(___nonblocking_pipe *pipe, long err) | |||
228 | ___nonblocking_pipe *pipe;(___nonblocking_pipe *pipe, long err) | |||
229 | ___SCMOBJ err;)(___nonblocking_pipe *pipe, long err) | |||
230 | { | |||
231 | if (WaitForSingleObject (pipe->mutex, INFINITE) == WAIT_FAILED) | |||
232 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
233 | ||||
234 | /* note: the reader error indicator may get overwritten */ | |||
235 | ||||
236 | pipe->rerr = err; | |||
237 | ||||
238 | SetEvent (pipe->wevent); /* ignore error */ | |||
239 | ||||
240 | if (pipe->werr == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
241 | ResetEvent (pipe->revent); /* ignore error */ | |||
242 | ||||
243 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
244 | ||||
245 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
246 | } | |||
247 | ||||
248 | ___HIDDENstatic ___SCMOBJlong ___nonblocking_pipe_set_writer_err | |||
249 | ___P((___nonblocking_pipe *pipe,(___nonblocking_pipe *pipe, long err) | |||
250 | ___SCMOBJ err),(___nonblocking_pipe *pipe, long err) | |||
251 | (pipe,(___nonblocking_pipe *pipe, long err) | |||
252 | err)(___nonblocking_pipe *pipe, long err) | |||
253 | ___nonblocking_pipe *pipe;(___nonblocking_pipe *pipe, long err) | |||
254 | ___SCMOBJ err;)(___nonblocking_pipe *pipe, long err) | |||
255 | { | |||
256 | if (WaitForSingleObject (pipe->mutex, INFINITE) == WAIT_FAILED) | |||
257 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
258 | ||||
259 | /* note: the writer error indicator may get overwritten */ | |||
260 | ||||
261 | pipe->werr = err; | |||
262 | ||||
263 | SetEvent (pipe->revent); /* ignore error */ | |||
264 | ||||
265 | if (pipe->rerr == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
266 | ResetEvent (pipe->wevent); /* ignore error */ | |||
267 | ||||
268 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
269 | ||||
270 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
271 | } | |||
272 | ||||
273 | ___HIDDENstatic ___SCMOBJlong ___nonblocking_pipe_write_oob | |||
274 | ___P((___nonblocking_pipe *pipe,(___nonblocking_pipe *pipe, ___nonblocking_pipe_oob_msg *oob_msg ) | |||
275 | ___nonblocking_pipe_oob_msg *oob_msg),(___nonblocking_pipe *pipe, ___nonblocking_pipe_oob_msg *oob_msg ) | |||
276 | (pipe,(___nonblocking_pipe *pipe, ___nonblocking_pipe_oob_msg *oob_msg ) | |||
277 | oob_msg)(___nonblocking_pipe *pipe, ___nonblocking_pipe_oob_msg *oob_msg ) | |||
278 | ___nonblocking_pipe *pipe;(___nonblocking_pipe *pipe, ___nonblocking_pipe_oob_msg *oob_msg ) | |||
279 | ___nonblocking_pipe_oob_msg *oob_msg;)(___nonblocking_pipe *pipe, ___nonblocking_pipe_oob_msg *oob_msg ) | |||
280 | { | |||
281 | if (WaitForSingleObject (pipe->mutex, INFINITE) == WAIT_FAILED) | |||
282 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
283 | ||||
284 | if (pipe->werr != ___FIX(___NO_ERR)(((long)(0))<<2) || pipe->oob) | |||
285 | { | |||
286 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
287 | return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
288 | } | |||
289 | ||||
290 | pipe->oob = 1; | |||
291 | pipe->oob_msg = *oob_msg; | |||
292 | ||||
293 | if (pipe->rerr == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
294 | { | |||
295 | SetEvent (pipe->revent); /* ignore error */ | |||
296 | ResetEvent (pipe->wevent); /* ignore error */ | |||
297 | } | |||
298 | ||||
299 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
300 | ||||
301 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
302 | } | |||
303 | ||||
304 | ___HIDDENstatic ___SCMOBJlong ___nonblocking_pipe_read_ready_wait | |||
305 | ___P((___nonblocking_pipe *pipe),(___nonblocking_pipe *pipe) | |||
306 | (pipe)(___nonblocking_pipe *pipe) | |||
307 | ___nonblocking_pipe *pipe;)(___nonblocking_pipe *pipe) | |||
308 | { | |||
309 | ___SCMOBJlong werr; | |||
310 | ||||
311 | if (WaitForSingleObject (pipe->revent, INFINITE) == WAIT_FAILED || | |||
312 | WaitForSingleObject (pipe->mutex, INFINITE) == WAIT_FAILED) | |||
313 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
314 | ||||
315 | werr = pipe->werr; | |||
316 | ||||
317 | if (werr != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
318 | { | |||
319 | pipe->werr = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
320 | ||||
321 | if (pipe->rerr != ___FIX(___NO_ERR)(((long)(0))<<2) || | |||
322 | (pipe->rd == pipe->wr && !pipe->oob)) | |||
323 | ResetEvent (pipe->revent); /* ignore error */ | |||
324 | } | |||
325 | ||||
326 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
327 | ||||
328 | return werr; | |||
329 | } | |||
330 | ||||
331 | ___HIDDENstatic ___SCMOBJlong ___nonblocking_pipe_write_ready_wait | |||
332 | ___P((___nonblocking_pipe *pipe),(___nonblocking_pipe *pipe) | |||
333 | (pipe)(___nonblocking_pipe *pipe) | |||
334 | ___nonblocking_pipe *pipe;)(___nonblocking_pipe *pipe) | |||
335 | { | |||
336 | ___SCMOBJlong rerr; | |||
337 | ||||
338 | if (WaitForSingleObject (pipe->wevent, INFINITE) == WAIT_FAILED || | |||
339 | WaitForSingleObject (pipe->mutex, INFINITE) == WAIT_FAILED) | |||
340 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
341 | ||||
342 | rerr = pipe->rerr; | |||
343 | ||||
344 | if (rerr != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
345 | { | |||
346 | pipe->rerr = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
347 | ||||
348 | ResetEvent (pipe->wevent); /* ignore error */ | |||
349 | } | |||
350 | ||||
351 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
352 | ||||
353 | return rerr; | |||
354 | } | |||
355 | ||||
356 | ___HIDDENstatic ___SCMOBJlong ___nonblocking_pipe_read | |||
357 | ___P((___nonblocking_pipe *pipe,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
358 | ___U8 *buf,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
359 | ___stream_index len,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
360 | ___stream_index *len_done,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
361 | ___nonblocking_pipe_oob_msg *oob_msg),(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
362 | (pipe,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
363 | buf,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
364 | len,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
365 | len_done,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
366 | oob_msg)(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
367 | ___nonblocking_pipe *pipe;(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
368 | ___U8 *buf;(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
369 | ___stream_index len;(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
370 | ___stream_index *len_done;(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
371 | ___nonblocking_pipe_oob_msg *oob_msg;)(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done, ___nonblocking_pipe_oob_msg * oob_msg) | |||
372 | { | |||
373 | ___SCMOBJlong rerr; | |||
374 | ___SCMOBJlong werr; | |||
375 | DWORD rd; | |||
376 | DWORD wr; | |||
377 | ___U8unsigned char *p; | |||
378 | DWORD end; | |||
379 | DWORD n; | |||
380 | DWORD i; | |||
381 | ||||
382 | if (len <= 0) | |||
383 | return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
384 | ||||
385 | if (WaitForSingleObject (pipe->mutex, INFINITE) == WAIT_FAILED) | |||
386 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
387 | ||||
388 | rerr = pipe->rerr; | |||
389 | werr = pipe->werr; | |||
390 | rd = pipe->rd; | |||
391 | wr = pipe->wr; | |||
392 | ||||
393 | if (rerr != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
394 | { | |||
395 | /* there is a reader error */ | |||
396 | ||||
397 | if (werr == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
398 | werr = ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
399 | else | |||
400 | { | |||
401 | pipe->werr = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
402 | ResetEvent (pipe->revent); /* ignore error */ | |||
403 | } | |||
404 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
405 | return werr; | |||
406 | } | |||
407 | ||||
408 | /* there is no reader error */ | |||
409 | ||||
410 | if (rd == wr) | |||
411 | { | |||
412 | /* no bytes in FIFO buffer */ | |||
413 | ||||
414 | if (pipe->oob) | |||
415 | { | |||
416 | /* out-of-band present */ | |||
417 | ||||
418 | *oob_msg = pipe->oob_msg; | |||
419 | pipe->oob = 0; | |||
420 | if (werr == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
421 | { | |||
422 | ResetEvent (pipe->revent); /* ignore error */ | |||
423 | #if 0 | |||
424 | /******************zzzzzzzzzzzzzz****/ | |||
425 | SetEvent (pipe->wevent); /* ignore error */ | |||
426 | #endif | |||
427 | } | |||
428 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
429 | *len_done = 0; | |||
430 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
431 | } | |||
432 | ||||
433 | /* out-of-band not present */ | |||
434 | ||||
435 | if (werr != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
436 | { | |||
437 | /* there is a writer error */ | |||
438 | ||||
439 | pipe->werr = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
440 | ||||
441 | ResetEvent (pipe->revent); /* ignore error */ | |||
442 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
443 | return werr; | |||
444 | } | |||
445 | ||||
446 | /* there is no writer error */ | |||
447 | ||||
448 | SetEvent (pipe->wevent); /* ignore error */ | |||
449 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
450 | return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
451 | } | |||
452 | ||||
453 | /* at least one byte in FIFO buffer */ | |||
454 | ||||
455 | end = pipe->size - rd; /* number of bytes from rd to end */ | |||
456 | ||||
457 | n = wr + end; /* number of bytes available */ | |||
458 | if (n >= pipe->size) | |||
459 | n -= pipe->size; | |||
460 | ||||
461 | if (n > ___CAST(DWORD,len)((DWORD)(len))) /* don't transfer more than len */ | |||
462 | n = len; | |||
463 | ||||
464 | *len_done = n; | |||
465 | ||||
466 | p = pipe->buffer + rd; /* prepare transfer source */ | |||
467 | ||||
468 | rd = rd + n; | |||
469 | if (rd >= pipe->size) | |||
470 | rd -= pipe->size; | |||
471 | ||||
472 | pipe->rd = rd; | |||
473 | ||||
474 | if (werr == ___FIX(___NO_ERR)(((long)(0))<<2) && !pipe->oob) | |||
475 | { | |||
476 | /* there is no writer error and out-of-band not present */ | |||
477 | ||||
478 | if (rd == wr) /* the FIFO will be empty? */ | |||
479 | ResetEvent (pipe->revent); /* ignore error */ | |||
480 | ||||
481 | /* the FIFO will not be full */ | |||
482 | ||||
483 | SetEvent (pipe->wevent); /* ignore error */ | |||
484 | } | |||
485 | ||||
486 | if (n <= end) | |||
487 | { | |||
488 | /* only need to transfer n bytes starting from original rd */ | |||
489 | ||||
490 | for (i=n; i>0; i--) | |||
491 | *buf++ = *p++; | |||
492 | } | |||
493 | else | |||
494 | { | |||
495 | /* need to transfer end bytes starting from original rd */ | |||
496 | ||||
497 | for (i=end; i>0; i--) | |||
498 | *buf++ = *p++; | |||
499 | ||||
500 | /* and to transfer n-end bytes starting from 0 */ | |||
501 | ||||
502 | p = pipe->buffer; | |||
503 | ||||
504 | for (i=n-end; i>0; i--) | |||
505 | *buf++ = *p++; | |||
506 | } | |||
507 | ||||
508 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
509 | ||||
510 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
511 | } | |||
512 | ||||
513 | ___HIDDENstatic ___SCMOBJlong ___nonblocking_pipe_write | |||
514 | ___P((___nonblocking_pipe *pipe,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
515 | ___U8 *buf,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
516 | ___stream_index len,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
517 | ___stream_index *len_done),(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
518 | (pipe,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
519 | buf,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
520 | len,(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
521 | len_done)(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
522 | ___nonblocking_pipe *pipe;(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
523 | ___U8 *buf;(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
524 | ___stream_index len;(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
525 | ___stream_index *len_done;)(___nonblocking_pipe *pipe, unsigned char *buf, ___stream_index len, ___stream_index *len_done) | |||
526 | { | |||
527 | ___SCMOBJlong rerr; | |||
528 | ___SCMOBJlong werr; | |||
529 | DWORD rd; | |||
530 | DWORD wr; | |||
531 | ___U8unsigned char *p; | |||
532 | DWORD end; | |||
533 | DWORD n; | |||
534 | DWORD i; | |||
535 | ||||
536 | if (len <= 0) | |||
537 | return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
538 | ||||
539 | if (WaitForSingleObject (pipe->mutex, INFINITE) == WAIT_FAILED) | |||
540 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
541 | ||||
542 | rerr = pipe->rerr; | |||
543 | werr = pipe->werr; | |||
544 | rd = pipe->rd; | |||
545 | wr = pipe->wr; | |||
546 | ||||
547 | if (werr != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
548 | { | |||
549 | /* there is a writer error */ | |||
550 | ||||
551 | if (rerr == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
552 | rerr = ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
553 | else | |||
554 | { | |||
555 | pipe->rerr = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
556 | ResetEvent (pipe->wevent); /* ignore error */ | |||
557 | } | |||
558 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
559 | return rerr; | |||
560 | } | |||
561 | ||||
562 | /* there is no writer error */ | |||
563 | ||||
564 | if (rerr != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
565 | { | |||
566 | /* there is a reader error */ | |||
567 | ||||
568 | pipe->rerr = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
569 | ||||
570 | if (rd != wr || pipe->oob) /* FIFO is not empty */ | |||
571 | SetEvent (pipe->revent); /* ignore error */ | |||
572 | ||||
573 | ResetEvent (pipe->wevent); /* ignore error */ | |||
574 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
575 | return rerr; | |||
576 | } | |||
577 | ||||
578 | /* there is no reader error */ | |||
579 | ||||
580 | if (wr + 1 - rd == 0 || wr + 1 - rd == pipe->size || pipe->oob) | |||
581 | { | |||
582 | /* FIFO buffer is full or out-of-band present */ | |||
583 | ||||
584 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
585 | return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
586 | } | |||
587 | ||||
588 | /* FIFO buffer is not full and out-of-band not present */ | |||
589 | ||||
590 | end = pipe->size - wr; /* number of bytes from wr to end */ | |||
591 | ||||
592 | n = rd + end - 1; /* number of bytes available */ | |||
593 | if (n >= pipe->size) | |||
594 | n -= pipe->size; | |||
595 | ||||
596 | if (n > ___CAST(DWORD,len)((DWORD)(len))) /* don't transfer more than len */ | |||
597 | n = len; | |||
598 | ||||
599 | *len_done = n; | |||
600 | ||||
601 | p = pipe->buffer + wr; /* prepare transfer source */ | |||
602 | ||||
603 | wr = wr + n; | |||
604 | if (wr >= pipe->size) | |||
605 | wr -= pipe->size; | |||
606 | ||||
607 | pipe->wr = wr; | |||
608 | ||||
609 | if (wr + 1 - rd == 0 || wr + 1 - rd == pipe->size) /* FIFO will be full? */ | |||
610 | ResetEvent (pipe->wevent); /* ignore error */ | |||
611 | ||||
612 | /* FIFO will not be empty */ | |||
613 | ||||
614 | SetEvent (pipe->revent); /* ignore error */ | |||
615 | ||||
616 | if (n <= end) | |||
617 | { | |||
618 | /* only need to transfer n bytes starting from original wr */ | |||
619 | ||||
620 | for (i=n; i>0; i--) | |||
621 | *p++ = *buf++; | |||
622 | } | |||
623 | else | |||
624 | { | |||
625 | /* need to transfer end bytes starting from original wr */ | |||
626 | ||||
627 | for (i=end; i>0; i--) | |||
628 | *p++ = *buf++; | |||
629 | ||||
630 | /* and to transfer n-end bytes starting from 0 */ | |||
631 | ||||
632 | p = pipe->buffer; | |||
633 | ||||
634 | for (i=n-end; i>0; i--) | |||
635 | *p++ = *buf++; | |||
636 | } | |||
637 | ||||
638 | ReleaseMutex (pipe->mutex); /* ignore error */ | |||
639 | ||||
640 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
641 | } | |||
642 | ||||
643 | #endif | |||
644 | ||||
645 | ||||
646 | /*---------------------------------------------------------------------------*/ | |||
647 | ||||
648 | /* Operations on I/O devices. */ | |||
649 | ||||
650 | /* Miscellaneous utility functions. */ | |||
651 | ||||
652 | #ifdef USE_POSIX | |||
653 | ||||
654 | ||||
655 | #ifdef USE_sigaction | |||
656 | typedef sigset_t sigset_type; | |||
657 | #else | |||
658 | typedef int sigset_type; | |||
659 | #endif | |||
660 | ||||
661 | ||||
662 | ___HIDDENstatic sigset_type block_signal | |||
663 | ___P((int signum),(int signum) | |||
664 | (signum)(int signum) | |||
665 | int signum;)(int signum) | |||
666 | { | |||
667 | sigset_type oldmask; | |||
668 | ||||
669 | #ifdef USE_sigaction | |||
670 | ||||
671 | sigset_type toblock; | |||
672 | ||||
673 | sigemptyset (&toblock); | |||
674 | sigaddset (&toblock, signum); | |||
675 | sigprocmask (SIG_BLOCK0, &toblock, &oldmask); | |||
676 | ||||
677 | #endif | |||
678 | ||||
679 | #ifdef USE_signal | |||
680 | ||||
681 | oldmask = sigblock (sigmask (signum)(((unsigned long int) 1) << (((signum) - 1) % (8 * sizeof (unsigned long int))))); | |||
682 | ||||
683 | #endif | |||
684 | ||||
685 | return oldmask; | |||
686 | } | |||
687 | ||||
688 | ||||
689 | ___HIDDENstatic void restore_sigmask | |||
690 | ___P((sigset_type oldmask),(sigset_type oldmask) | |||
691 | (oldmask)(sigset_type oldmask) | |||
692 | sigset_type oldmask;)(sigset_type oldmask) | |||
693 | { | |||
694 | #ifdef USE_sigaction | |||
695 | ||||
696 | sigprocmask (SIG_SETMASK2, &oldmask, 0); | |||
697 | ||||
698 | #endif | |||
699 | ||||
700 | #ifdef USE_signal | |||
701 | ||||
702 | sigsetmask (oldmask); | |||
703 | ||||
704 | #endif | |||
705 | } | |||
706 | ||||
707 | ||||
708 | /* | |||
709 | * Some system calls can be interrupted by a signal and fail with | |||
710 | * errno == EINTR. The following functions are wrappers for system | |||
711 | * calls which may be interrupted. They simply ignore the EINTR and | |||
712 | * retry the operation. | |||
713 | * | |||
714 | * TODO: add wrappers for all the system calls which can fail | |||
715 | * with EINTR. Also, move these functions to a central place. | |||
716 | */ | |||
717 | ||||
718 | pid_t waitpid_no_EINTR | |||
719 | ___P((pid_t pid,(pid_t pid, int *stat_loc, int options) | |||
720 | int *stat_loc,(pid_t pid, int *stat_loc, int options) | |||
721 | int options),(pid_t pid, int *stat_loc, int options) | |||
722 | (pid,(pid_t pid, int *stat_loc, int options) | |||
723 | stat_loc,(pid_t pid, int *stat_loc, int options) | |||
724 | options)(pid_t pid, int *stat_loc, int options) | |||
725 | pid_t pid;(pid_t pid, int *stat_loc, int options) | |||
726 | int *stat_loc;(pid_t pid, int *stat_loc, int options) | |||
727 | int options;)(pid_t pid, int *stat_loc, int options) | |||
728 | { | |||
729 | pid_t result; | |||
730 | ||||
731 | for (;;) | |||
732 | { | |||
733 | result = waitpid (pid, stat_loc, options); | |||
734 | if (result >= 0 || errno(*__errno_location ()) != EINTR4) | |||
735 | break; | |||
736 | } | |||
737 | ||||
738 | return result; | |||
739 | } | |||
740 | ||||
741 | ||||
742 | ___SSIZE_Tlong read_no_EINTR | |||
743 | ___P((int fd,(int fd, void *buf, unsigned long len) | |||
744 | void *buf,(int fd, void *buf, unsigned long len) | |||
745 | ___SIZE_T len),(int fd, void *buf, unsigned long len) | |||
746 | (fd,(int fd, void *buf, unsigned long len) | |||
747 | buf,(int fd, void *buf, unsigned long len) | |||
748 | len)(int fd, void *buf, unsigned long len) | |||
749 | int fd;(int fd, void *buf, unsigned long len) | |||
750 | void *buf;(int fd, void *buf, unsigned long len) | |||
751 | ___SIZE_T len;)(int fd, void *buf, unsigned long len) | |||
752 | { | |||
753 | char *p = ___CAST(char*,buf)((char*)(buf)); | |||
754 | ___SSIZE_Tlong result = 0; | |||
755 | int n; | |||
756 | ||||
757 | while (result < len) | |||
758 | { | |||
759 | n = read (fd, p+result, len-result); | |||
760 | if (n > 0) | |||
761 | result += n; | |||
762 | else if (n == 0) | |||
763 | break; | |||
764 | else if (errno(*__errno_location ()) != EINTR4) | |||
765 | return n; /* this forgets that some bytes were transferred */ | |||
766 | } | |||
767 | ||||
768 | return result; | |||
769 | } | |||
770 | ||||
771 | ||||
772 | int close_no_EINTR | |||
773 | ___P((int fd),(int fd) | |||
774 | (fd)(int fd) | |||
775 | int fd;)(int fd) | |||
776 | { | |||
777 | int result; | |||
778 | ||||
779 | for (;;) | |||
780 | { | |||
781 | result = close (fd); | |||
782 | if (result >= 0 || errno(*__errno_location ()) != EINTR4) | |||
783 | break; | |||
784 | } | |||
785 | ||||
786 | return result; | |||
787 | } | |||
788 | ||||
789 | ||||
790 | int dup_no_EINTR | |||
791 | ___P((int fd),(int fd) | |||
792 | (fd)(int fd) | |||
793 | int fd;)(int fd) | |||
794 | { | |||
795 | int result; | |||
796 | ||||
797 | for (;;) | |||
798 | { | |||
799 | result = dup (fd); | |||
800 | if (result >= 0 || errno(*__errno_location ()) != EINTR4) | |||
801 | break; | |||
802 | } | |||
803 | ||||
804 | return result; | |||
805 | } | |||
806 | ||||
807 | ||||
808 | int dup2_no_EINTR | |||
809 | ___P((int fd,(int fd, int fd2) | |||
810 | int fd2),(int fd, int fd2) | |||
811 | (fd,(int fd, int fd2) | |||
812 | fd2)(int fd, int fd2) | |||
813 | int fd;(int fd, int fd2) | |||
814 | int fd2;)(int fd, int fd2) | |||
815 | { | |||
816 | int result; | |||
817 | ||||
818 | for (;;) | |||
819 | { | |||
820 | result = dup2 (fd, fd2); | |||
821 | if (result >= 0 || errno(*__errno_location ()) != EINTR4) | |||
822 | break; | |||
823 | } | |||
824 | ||||
825 | return result; | |||
826 | } | |||
827 | ||||
828 | ||||
829 | int set_fd_blocking_mode | |||
830 | ___P((int fd,(int fd, int blocking) | |||
831 | ___BOOL blocking),(int fd, int blocking) | |||
832 | (fd,(int fd, int blocking) | |||
833 | blocking)(int fd, int blocking) | |||
834 | int fd;(int fd, int blocking) | |||
835 | ___BOOL blocking;)(int fd, int blocking) | |||
836 | { | |||
837 | int fl; | |||
838 | ||||
839 | #ifdef USE_fcntl | |||
840 | ||||
841 | if ((fl = fcntl (fd, F_GETFL3, 0)) >= 0) | |||
842 | fl = fcntl (fd, | |||
843 | F_SETFL4, | |||
844 | blocking ? (fl & ~O_NONBLOCK04000) : (fl | O_NONBLOCK04000)); | |||
845 | ||||
846 | #else | |||
847 | ||||
848 | fl = 0; | |||
849 | ||||
850 | #endif | |||
851 | ||||
852 | return fl; | |||
853 | } | |||
854 | ||||
855 | #endif | |||
856 | ||||
857 | ||||
858 | /*---------------------------------------------------------------------------*/ | |||
859 | ||||
860 | /* Generic device operations. */ | |||
861 | ||||
862 | ___SCMOBJlong ___device_select | |||
863 | ___P((___device **devs,(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
864 | int nb_read_devs,(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
865 | int nb_write_devs,(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
866 | ___time timeout),(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
867 | (devs,(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
868 | nb_read_devs,(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
869 | nb_write_devs,(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
870 | timeout)(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
871 | ___device **devs;(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
872 | int nb_read_devs;(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
873 | int nb_write_devs;(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
874 | ___time timeout;)(___device **devs, int nb_read_devs, int nb_write_devs, ___time timeout) | |||
875 | { | |||
876 | int nb_devs; | |||
877 | ___device_select_state state; | |||
878 | int pass; | |||
879 | int dev_list; | |||
880 | int i; | |||
881 | int prev; | |||
882 | ___time delta; | |||
883 | ||||
884 | nb_devs = nb_read_devs + nb_write_devs; | |||
885 | ||||
886 | state.devs = devs; | |||
887 | ||||
888 | state.timeout = timeout; | |||
889 | state.relative_timeout = POS_INFINITY(1.7976931348623157e308); | |||
890 | ||||
891 | #ifdef USE_select | |||
892 | ||||
893 | state.highest_fd_plus_1 = 0; | |||
894 | ||||
895 | ___FD_ZERO(&state.readfds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&state.readfds)->__fds_bits )[0]) : "memory"); } while (0); | |||
896 | ___FD_ZERO(&state.writefds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&state.writefds)->__fds_bits )[0]) : "memory"); } while (0); | |||
897 | ___FD_ZERO(&state.exceptfds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&state.exceptfds)->__fds_bits )[0]) : "memory"); } while (0); | |||
898 | ||||
899 | #endif | |||
900 | ||||
901 | #ifdef USE_poll | |||
902 | ||||
903 | state.pollfd_count = 0; | |||
904 | ___FD_ZERO (&state.readfds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&state.readfds)->__fds_bits )[0]) : "memory"); } while (0); | |||
905 | ___FD_ZERO (&state.writefds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&state.writefds)->__fds_bits )[0]) : "memory"); } while (0); | |||
906 | ||||
907 | #endif | |||
908 | ||||
909 | #ifdef USE_MsgWaitForMultipleObjects | |||
910 | ||||
911 | state.message_queue_mask = 0; | |||
912 | state.message_queue_dev_pos = -1; | |||
913 | ||||
914 | state.wait_objs_buffer[0] = ___io_mod.abort_select; | |||
915 | state.wait_objs_buffer[1] = ___time_mod.heartbeat_thread; | |||
916 | ||||
917 | state.nb_wait_objs = 2; | |||
918 | ||||
919 | #endif | |||
920 | ||||
921 | if (nb_devs > 0) | |||
922 | { | |||
923 | state.devs_next[nb_devs-1] = -1; | |||
924 | ||||
925 | for (i=nb_devs-2; i>=0; i--) | |||
926 | state.devs_next[i] = i+1; | |||
927 | ||||
928 | dev_list = 0; | |||
929 | } | |||
930 | else | |||
931 | dev_list = -1; | |||
932 | ||||
933 | pass = ___SELECT_PASS_11; | |||
934 | ||||
935 | while (dev_list != -1) | |||
936 | { | |||
937 | i = dev_list; | |||
938 | prev = -1; | |||
939 | ||||
940 | while (i != -1) | |||
941 | { | |||
942 | ___SCMOBJlong e; | |||
943 | ___device *d = devs[i]; | |||
944 | if ((e = ___device_select_virt((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,pass,&state) | |||
945 | (d,((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,pass,&state) | |||
946 | i>=nb_read_devs,((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,pass,&state) | |||
947 | i,((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,pass,&state) | |||
948 | pass,((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,pass,&state) | |||
949 | &state)((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,pass,&state)) | |||
950 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
951 | { | |||
952 | prev = i; | |||
953 | i = state.devs_next[i]; | |||
954 | } | |||
955 | else | |||
956 | { | |||
957 | int j; | |||
958 | if (e != ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2)) | |||
959 | return e; | |||
960 | j = state.devs_next[i]; | |||
961 | if (prev == -1) | |||
962 | dev_list = j; | |||
963 | else | |||
964 | state.devs_next[prev] = j; | |||
965 | #ifdef USE_MsgWaitForMultipleObjects | |||
966 | state.devs_next[i] = -1; | |||
967 | #endif | |||
968 | i = j; | |||
969 | } | |||
970 | } | |||
971 | ||||
972 | pass++; | |||
973 | } | |||
974 | ||||
975 | ___absolute_time_to_relative_time (state.timeout, &delta); | |||
976 | ||||
977 | if (___time_less (state.relative_timeout, delta)) | |||
978 | { | |||
979 | delta = state.relative_timeout; | |||
980 | state.timeout = ___time_mod.time_neg_infinity; | |||
981 | } | |||
982 | else | |||
983 | state.relative_timeout = NEG_INFINITY(-1.7976931348623157e308); | |||
984 | ||||
985 | #ifdef USE_select | |||
986 | ||||
987 | { | |||
988 | struct timeval delta_tv_struct; | |||
989 | struct timeval *delta_tv = &delta_tv_struct; | |||
990 | int result; | |||
991 | ||||
992 | ___absolute_time_to_nonnegative_timeval (delta, &delta_tv); | |||
993 | ||||
994 | if (delta_tv != NULL((void*)0) && | |||
995 | state.highest_fd_plus_1 == 0) | |||
996 | { | |||
997 | /* | |||
998 | * ___device_select is only being called for sleeping until a | |||
999 | * certain timeout or interrupt occurs. This is a case that | |||
1000 | * can be optimized. | |||
1001 | */ | |||
1002 | ||||
1003 | if (delta_tv->tv_sec < 0 || | |||
1004 | (delta_tv->tv_sec == 0 && | |||
1005 | delta_tv->tv_usec == 0)) | |||
1006 | { | |||
1007 | /* | |||
1008 | * The timeout has already passed, so we don't need to | |||
1009 | * sleep. This simple optimization avoids doing a system | |||
1010 | * call to the select or nanosleep functions (which can be | |||
1011 | * expensive on some operating systems). | |||
1012 | */ | |||
1013 | ||||
1014 | result = 0; | |||
1015 | ||||
1016 | goto select_done; | |||
1017 | } | |||
1018 | #ifdef USE_nanosleep | |||
1019 | else | |||
1020 | { | |||
1021 | ||||
1022 | /* | |||
1023 | * For better timeout resolution, the nanosleep function | |||
1024 | * is used instead of the select function. On some | |||
1025 | * operating systems (e.g. OpenBSD 4.5) the nanosleep | |||
1026 | * function can be more expensive than a call to select, | |||
1027 | * but the better timeout resolution outweighs the run | |||
1028 | * time cost. | |||
1029 | */ | |||
1030 | ||||
1031 | struct timespec delta_ts_struct; | |||
1032 | delta_ts_struct.tv_sec = delta_tv->tv_sec; | |||
1033 | delta_ts_struct.tv_nsec = delta_tv->tv_usec * 1000; | |||
1034 | result = nanosleep (&delta_ts_struct, NULL((void*)0)); | |||
1035 | ||||
1036 | goto select_done; | |||
1037 | } | |||
1038 | #endif | |||
1039 | } | |||
1040 | ||||
1041 | /* | |||
1042 | * Heartbeat interrupts must be disabled in case they are based on the | |||
1043 | * real-time timer. This is needed to bypass issues in two buggy | |||
1044 | * operating systems: | |||
1045 | * | |||
1046 | * - On MacOS X, the virtual-time timer does not fire at the correct | |||
1047 | * rate (apparently this happens only on machines with more than | |||
1048 | * one core). | |||
1049 | * | |||
1050 | * - On CYGWIN, the select system call can be interrupted by the | |||
1051 | * timer and in some cases the error "No child processes" will | |||
1052 | * be returned by select. | |||
1053 | */ | |||
1054 | ||||
1055 | ___disable_heartbeat_interrupts (); | |||
1056 | ||||
1057 | result = | |||
1058 | select (state.highest_fd_plus_1, | |||
1059 | &state.readfds, | |||
1060 | &state.writefds, | |||
1061 | &state.exceptfds, | |||
1062 | delta_tv); | |||
1063 | ||||
1064 | ___enable_heartbeat_interrupts (); | |||
1065 | ||||
1066 | select_done: | |||
1067 | ||||
1068 | if (result < 0) | |||
1069 | return err_code_from_errno ()___err_code_from_errno(); | |||
1070 | ||||
1071 | state.timeout_reached = (result == 0); | |||
1072 | } | |||
1073 | ||||
1074 | #endif | |||
1075 | ||||
1076 | #ifdef USE_poll | |||
1077 | { | |||
1078 | struct timeval delta_tv_struct; | |||
1079 | struct timeval *delta_tv = &delta_tv_struct; | |||
1080 | ||||
1081 | #ifdef USE_ppoll | |||
1082 | struct timespec delta_ts_struct; | |||
1083 | struct timespec *delta_ts; | |||
1084 | #else | |||
1085 | int delta_msecs; | |||
1086 | #endif | |||
1087 | int result; | |||
1088 | ||||
1089 | ___absolute_time_to_nonnegative_timeval (delta, &delta_tv); | |||
1090 | ||||
1091 | /* pure sleep optimizations */ | |||
1092 | if (state.pollfd_count == 0 && delta_tv != NULL((void*)0)) | |||
1093 | { | |||
1094 | if (delta_tv->tv_sec < 0 || | |||
1095 | (delta_tv->tv_sec == 0 && | |||
1096 | delta_tv->tv_usec == 0)) | |||
1097 | { | |||
1098 | result = 0; | |||
1099 | goto poll_done; | |||
1100 | } | |||
1101 | #ifdef USE_nanosleep | |||
1102 | else | |||
1103 | { | |||
1104 | struct timespec delta_ts_struct; | |||
1105 | delta_ts_struct.tv_sec = delta_tv->tv_sec; | |||
1106 | delta_ts_struct.tv_nsec = delta_tv->tv_usec * 1000; | |||
1107 | ||||
1108 | result = nanosleep (&delta_ts_struct, NULL((void*)0)); | |||
1109 | ||||
1110 | goto poll_done; | |||
1111 | } | |||
1112 | #endif | |||
1113 | } | |||
1114 | ||||
1115 | /* setup timeout */ | |||
1116 | #ifdef USE_ppoll | |||
1117 | ||||
1118 | if (delta_tv != NULL((void*)0)) | |||
1119 | { | |||
1120 | /* ppoll doesn't like negative times */ | |||
1121 | if (delta_tv->tv_sec < 0) | |||
1122 | { | |||
1123 | delta_ts_struct.tv_sec = 0; | |||
1124 | delta_ts_struct.tv_nsec = 0; | |||
1125 | } | |||
1126 | else | |||
1127 | { | |||
1128 | delta_ts_struct.tv_sec = delta_tv->tv_sec; | |||
1129 | delta_ts_struct.tv_nsec = delta_tv->tv_usec * 1000; | |||
1130 | } | |||
1131 | ||||
1132 | delta_ts = &delta_ts_struct; | |||
1133 | } | |||
1134 | else | |||
1135 | delta_ts = NULL((void*)0); | |||
1136 | ||||
1137 | #else | |||
1138 | ||||
1139 | if (delta_tv != NULL((void*)0)) | |||
1140 | { | |||
1141 | if (delta_tv->tv_sec < 0) | |||
1142 | delta_msecs = 0; | |||
1143 | else if (delta_tv->tv_sec < (INT_MAX2147483647 / 1000)) | |||
1144 | delta_msecs = delta_tv->tv_sec * 1000 + delta_tv->tv_usec / 1000; | |||
1145 | else | |||
1146 | delta_msecs = INT_MAX2147483647; | |||
1147 | } | |||
1148 | else | |||
1149 | delta_msecs = -1; | |||
1150 | ||||
1151 | #endif | |||
1152 | ||||
1153 | /* see comments on select above regarding heartbeat interrupts */ | |||
1154 | ___disable_heartbeat_interrupts (); | |||
1155 | ||||
1156 | #ifdef USE_ppoll | |||
1157 | result = ppoll (state.pollfds, state.pollfd_count, delta_ts, NULL((void*)0)); | |||
1158 | #else | |||
1159 | result = poll (state.pollfds, state.pollfd_count, delta_msecs); | |||
1160 | #endif | |||
1161 | ||||
1162 | ___enable_heartbeat_interrupts (); | |||
1163 | ||||
1164 | /* Set the active bitmaps */ | |||
1165 | if (result > 0) | |||
1166 | { | |||
1167 | int errmask = (POLLERR | POLLHUP | POLLNVAL); | |||
1168 | int active = result; | |||
1169 | int x; | |||
1170 | ||||
1171 | for (x = 0; active > 0; ++x) | |||
1172 | { | |||
1173 | if (state.pollfds[x].revents) | |||
1174 | { | |||
1175 | if (state.pollfds[x].events & POLLIN) | |||
1176 | { | |||
1177 | if (state.pollfds[x].revents & (POLLIN | errmask)) | |||
1178 | ___FD_SET (state.pollfds[x].fd, &state.readfds)((void) (((&state.readfds)->__fds_bits)[((state.pollfds [x].fd) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) 1 << ((state.pollfds[x].fd) % (8 * (int) sizeof (__fd_mask)))))); | |||
1179 | } | |||
1180 | ||||
1181 | if (state.pollfds[x].events & POLLOUT) | |||
1182 | { | |||
1183 | if (state.pollfds[x].revents & (POLLOUT | errmask)) | |||
1184 | ___FD_SET (state.pollfds[x].fd, &state.writefds)((void) (((&state.writefds)->__fds_bits)[((state.pollfds [x].fd) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) 1 << ((state.pollfds[x].fd) % (8 * (int) sizeof (__fd_mask)))))); | |||
1185 | } | |||
1186 | ||||
1187 | --active; | |||
1188 | } | |||
1189 | } | |||
1190 | } | |||
1191 | ||||
1192 | poll_done: | |||
1193 | ||||
1194 | if (result < 0) | |||
1195 | return err_code_from_errno ()___err_code_from_errno(); | |||
1196 | ||||
1197 | state.timeout_reached = (result == 0); | |||
1198 | } | |||
1199 | #endif | |||
1200 | ||||
1201 | #ifdef USE_MsgWaitForMultipleObjects | |||
1202 | ||||
1203 | { | |||
1204 | DWORD delta_msecs; | |||
1205 | int first_iteration = TRUE; | |||
1206 | ||||
1207 | ___absolute_time_to_nonnegative_msecs (delta, &delta_msecs); | |||
1208 | ||||
1209 | state.timeout_reached = 0; | |||
1210 | ||||
1211 | while (state.nb_wait_objs > 0 || state.message_queue_mask != 0) | |||
1212 | { | |||
1213 | DWORD n; | |||
1214 | ||||
1215 | n = MsgWaitForMultipleObjects | |||
1216 | (state.nb_wait_objs, | |||
1217 | state.wait_objs_buffer, | |||
1218 | FALSE, | |||
1219 | delta_msecs, | |||
1220 | state.message_queue_mask); | |||
1221 | ||||
1222 | if (n == WAIT_FAILED) | |||
1223 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
1224 | ||||
1225 | if ((n - WAIT_OBJECT_0) <= WAIT_OBJECT_0 + state.nb_wait_objs) | |||
1226 | n -= WAIT_OBJECT_0; | |||
1227 | else if (n >= WAIT_ABANDONED_0 && | |||
1228 | n <= WAIT_ABANDONED_0+state.nb_wait_objs-1) | |||
1229 | n -= WAIT_ABANDONED_0; | |||
1230 | else | |||
1231 | { | |||
1232 | /* n == WAIT_TIMEOUT */ | |||
1233 | ||||
1234 | /* | |||
1235 | * The call to MsgWaitForMultipleObjects timed out. Mark | |||
1236 | * the appropriate device "ready". | |||
1237 | */ | |||
1238 | ||||
1239 | if (first_iteration) | |||
1240 | { | |||
1241 | /* first call to MsgWaitForMultipleObjects */ | |||
1242 | ||||
1243 | state.timeout_reached = 1; | |||
1244 | } | |||
1245 | ||||
1246 | break; | |||
1247 | } | |||
1248 | ||||
1249 | if (n == state.nb_wait_objs) | |||
1250 | { | |||
1251 | /* | |||
1252 | * The message queue contains a message that is of interest. | |||
1253 | * Mark the appropriate device "ready". | |||
1254 | */ | |||
1255 | ||||
1256 | i = state.message_queue_dev_pos; | |||
1257 | if (i >= 0) | |||
1258 | state.devs_next[i] = 0; | |||
1259 | ||||
1260 | /* | |||
1261 | * Don't check if other devices are ready because this might | |||
1262 | * cause an infinite loop. | |||
1263 | */ | |||
1264 | ||||
1265 | break; | |||
1266 | } | |||
1267 | else if (n == 0) | |||
1268 | { | |||
1269 | /* | |||
1270 | * The call to ___device_select must be aborted because the | |||
1271 | * abort_select event is set. This occurs when an interrupt | |||
1272 | * (such as a CTRL-C user interrupt) needs to be serviced | |||
1273 | * promptly by the main program. | |||
1274 | */ | |||
1275 | ||||
1276 | ResetEvent (___io_mod.abort_select); /* ignore error */ | |||
1277 | ||||
1278 | return ___FIX(___ERRNO_ERR(EINTR))(((long)(((4)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(4)))))<<2); | |||
1279 | } | |||
1280 | else if (n == 1) | |||
1281 | { | |||
1282 | /* | |||
1283 | * The heartbeat thread has died. This is normally due to | |||
1284 | * the program being terminated abruptly by the user (for | |||
1285 | * example by using the thread manager or the "shutdown" | |||
1286 | * item in the start menu). When this happens we must | |||
1287 | * initiate a clean termination of the program. | |||
1288 | */ | |||
1289 | ||||
1290 | return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
1291 | } | |||
1292 | else | |||
1293 | { | |||
1294 | /* Mark the appropriate device "ready". */ | |||
1295 | ||||
1296 | i = state.wait_obj_to_dev_pos[n]; | |||
1297 | if (i >= 0) | |||
1298 | state.devs_next[i] = 0; | |||
1299 | ||||
1300 | /* Prepare to check remaining devices. */ | |||
1301 | ||||
1302 | state.nb_wait_objs--; | |||
1303 | ||||
1304 | state.wait_objs_buffer[n] = | |||
1305 | state.wait_objs_buffer[state.nb_wait_objs]; | |||
1306 | ||||
1307 | state.wait_obj_to_dev_pos[n] = | |||
1308 | state.wait_obj_to_dev_pos[state.nb_wait_objs]; | |||
1309 | } | |||
1310 | ||||
1311 | first_iteration = FALSE; | |||
1312 | delta_msecs = 0; /* next MsgWaitForMultipleObjects will only poll */ | |||
1313 | } | |||
1314 | } | |||
1315 | ||||
1316 | #endif | |||
1317 | ||||
1318 | for (i=nb_devs-1; i>=0; i--) | |||
1319 | { | |||
1320 | ___SCMOBJlong e; | |||
1321 | ___device *d = devs[i]; | |||
1322 | if (d != NULL((void*)0)) | |||
1323 | if ((e = ___device_select_virt((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,0,&state) | |||
1324 | (d,((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,0,&state) | |||
1325 | i>=nb_read_devs,((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,0,&state) | |||
1326 | i,((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,0,&state) | |||
1327 | ___SELECT_PASS_CHECK,((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,0,&state) | |||
1328 | &state)((___device_vtbl*)((d)->vtbl))->select_virt(d,i>=nb_read_devs ,i,0,&state)) | |||
1329 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
1330 | return e; | |||
1331 | } | |||
1332 | ||||
1333 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1334 | } | |||
1335 | ||||
1336 | ||||
1337 | void ___device_select_add_relative_timeout | |||
1338 | ___P((___device_select_state *state,(___device_select_state *state, int i, double seconds) | |||
1339 | int i,(___device_select_state *state, int i, double seconds) | |||
1340 | ___F64 seconds),(___device_select_state *state, int i, double seconds) | |||
1341 | (state,(___device_select_state *state, int i, double seconds) | |||
1342 | i,(___device_select_state *state, int i, double seconds) | |||
1343 | seconds)(___device_select_state *state, int i, double seconds) | |||
1344 | ___device_select_state *state;(___device_select_state *state, int i, double seconds) | |||
1345 | int i;(___device_select_state *state, int i, double seconds) | |||
1346 | ___F64 seconds;)(___device_select_state *state, int i, double seconds) | |||
1347 | { | |||
1348 | if (seconds < state->relative_timeout) | |||
1349 | state->relative_timeout = seconds; | |||
1350 | } | |||
1351 | ||||
1352 | ||||
1353 | void ___device_select_add_timeout | |||
1354 | ___P((___device_select_state *state,(___device_select_state *state, int i, ___time timeout) | |||
1355 | int i,(___device_select_state *state, int i, ___time timeout) | |||
1356 | ___time timeout),(___device_select_state *state, int i, ___time timeout) | |||
1357 | (state,(___device_select_state *state, int i, ___time timeout) | |||
1358 | i,(___device_select_state *state, int i, ___time timeout) | |||
1359 | timeout)(___device_select_state *state, int i, ___time timeout) | |||
1360 | ___device_select_state *state;(___device_select_state *state, int i, ___time timeout) | |||
1361 | int i;(___device_select_state *state, int i, ___time timeout) | |||
1362 | ___time timeout;)(___device_select_state *state, int i, ___time timeout) | |||
1363 | { | |||
1364 | if (___time_less (timeout, state->timeout)) | |||
1365 | state->timeout = timeout; | |||
1366 | } | |||
1367 | ||||
1368 | ||||
1369 | #ifdef USE_select | |||
1370 | ||||
1371 | void ___device_select_add_fd | |||
1372 | ___P((___device_select_state *state,(___device_select_state *state, int fd, int for_writing) | |||
1373 | int fd,(___device_select_state *state, int fd, int for_writing) | |||
1374 | ___BOOL for_writing),(___device_select_state *state, int fd, int for_writing) | |||
1375 | (state,(___device_select_state *state, int fd, int for_writing) | |||
1376 | fd,(___device_select_state *state, int fd, int for_writing) | |||
1377 | for_writing)(___device_select_state *state, int fd, int for_writing) | |||
1378 | ___device_select_state *state;(___device_select_state *state, int fd, int for_writing) | |||
1379 | int fd;(___device_select_state *state, int fd, int for_writing) | |||
1380 | ___BOOL for_writing;)(___device_select_state *state, int fd, int for_writing) | |||
1381 | { | |||
1382 | if (for_writing) | |||
1383 | ___FD_SET(fd, &state->writefds)((void) (((&state->writefds)->__fds_bits)[((fd) / ( 8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) 1 << (( fd) % (8 * (int) sizeof (__fd_mask)))))); | |||
1384 | else | |||
1385 | ___FD_SET(fd, &state->readfds)((void) (((&state->readfds)->__fds_bits)[((fd) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) 1 << ((fd ) % (8 * (int) sizeof (__fd_mask)))))); | |||
1386 | ||||
1387 | if (fd >= state->highest_fd_plus_1) | |||
1388 | state->highest_fd_plus_1 = fd+1; | |||
1389 | } | |||
1390 | ||||
1391 | #endif | |||
1392 | ||||
1393 | #ifdef USE_poll | |||
1394 | ||||
1395 | void ___device_select_add_fd | |||
1396 | ___P((___device_select_state *state,(___device_select_state *state, int fd, int for_writing) | |||
1397 | int fd,(___device_select_state *state, int fd, int for_writing) | |||
1398 | ___BOOL for_writing),(___device_select_state *state, int fd, int for_writing) | |||
1399 | (state,(___device_select_state *state, int fd, int for_writing) | |||
1400 | fd,(___device_select_state *state, int fd, int for_writing) | |||
1401 | for_writing)(___device_select_state *state, int fd, int for_writing) | |||
1402 | ___device_select_state *state;(___device_select_state *state, int fd, int for_writing) | |||
1403 | int fd;(___device_select_state *state, int fd, int for_writing) | |||
1404 | ___BOOL for_writing;)(___device_select_state *state, int fd, int for_writing) | |||
1405 | { | |||
1406 | state->pollfds[state->pollfd_count].fd = fd; | |||
1407 | ||||
1408 | if (for_writing) | |||
1409 | state->pollfds[state->pollfd_count].events = POLLOUT; | |||
1410 | else | |||
1411 | state->pollfds[state->pollfd_count].events = POLLIN; | |||
1412 | ||||
1413 | ++state->pollfd_count; | |||
1414 | } | |||
1415 | ||||
1416 | #endif | |||
1417 | ||||
1418 | ||||
1419 | #ifdef USE_MsgWaitForMultipleObjects | |||
1420 | ||||
1421 | void ___device_select_add_wait_obj | |||
1422 | ___P((___device_select_state *state,(___device_select_state *state, int i, HANDLE wait_obj) | |||
1423 | int i,(___device_select_state *state, int i, HANDLE wait_obj) | |||
1424 | HANDLE wait_obj),(___device_select_state *state, int i, HANDLE wait_obj) | |||
1425 | (state,(___device_select_state *state, int i, HANDLE wait_obj) | |||
1426 | i,(___device_select_state *state, int i, HANDLE wait_obj) | |||
1427 | wait_obj)(___device_select_state *state, int i, HANDLE wait_obj) | |||
1428 | ___device_select_state *state;(___device_select_state *state, int i, HANDLE wait_obj) | |||
1429 | int i;(___device_select_state *state, int i, HANDLE wait_obj) | |||
1430 | HANDLE wait_obj;)(___device_select_state *state, int i, HANDLE wait_obj) | |||
1431 | { | |||
1432 | DWORD j = state->nb_wait_objs; | |||
1433 | ||||
1434 | if (j < MAXIMUM_WAIT_OBJECTS) | |||
1435 | { | |||
1436 | state->wait_objs_buffer[j] = wait_obj; | |||
1437 | state->wait_obj_to_dev_pos[j] = i; | |||
1438 | state->nb_wait_objs = j+1; | |||
1439 | } | |||
1440 | } | |||
1441 | ||||
1442 | #endif | |||
1443 | ||||
1444 | ||||
1445 | ___SCMOBJlong ___device_force_output | |||
1446 | ___P((___device *self,(___device *self, int level) | |||
1447 | int level),(___device *self, int level) | |||
1448 | (self,(___device *self, int level) | |||
1449 | level)(___device *self, int level) | |||
1450 | ___device *self;(___device *self, int level) | |||
1451 | int level;)(___device *self, int level) | |||
1452 | { | |||
1453 | return ___device_force_output_virt (self, level)((___device_vtbl*)((self)->vtbl))->force_output_virt(self ,level); | |||
1454 | } | |||
1455 | ||||
1456 | ___SCMOBJlong ___device_close | |||
1457 | ___P((___device *self,(___device *self, int direction) | |||
1458 | int direction),(___device *self, int direction) | |||
1459 | (self,(___device *self, int direction) | |||
1460 | direction)(___device *self, int direction) | |||
1461 | ___device *self;(___device *self, int direction) | |||
1462 | int direction;)(___device *self, int direction) | |||
1463 | { | |||
1464 | return ___device_close_virt (self, direction)((___device_vtbl*)((self)->vtbl))->close_virt(self,direction ); | |||
1465 | } | |||
1466 | ||||
1467 | ___HIDDENstatic void device_transfer_close_responsibility | |||
1468 | ___P((___device *self),(___device *self) | |||
1469 | (self)(___device *self) | |||
1470 | ___device *self;)(___device *self) | |||
1471 | { | |||
1472 | /* | |||
1473 | * Transfer responsibility for closing device to the runtime system. | |||
1474 | */ | |||
1475 | ||||
1476 | self->close_direction = self->direction; | |||
1477 | } | |||
1478 | ||||
1479 | ___HIDDENstatic void device_add_ref | |||
1480 | ___P((___device *self),(___device *self) | |||
1481 | (self)(___device *self) | |||
1482 | ___device *self;)(___device *self) | |||
1483 | { | |||
1484 | #ifdef USE_PUMPS | |||
1485 | InterlockedIncrement (&self->refcount); | |||
1486 | #else | |||
1487 | self->refcount++; | |||
1488 | #endif | |||
1489 | } | |||
1490 | ||||
1491 | ___SCMOBJlong ___device_release | |||
1492 | ___P((___device *self),(___device *self) | |||
1493 | (self)(___device *self) | |||
1494 | ___device *self;)(___device *self) | |||
1495 | { | |||
1496 | ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1497 | ||||
1498 | if ( | |||
1499 | #ifdef USE_PUMPS | |||
1500 | InterlockedDecrement (&self->refcount) == 0 | |||
1501 | #else | |||
1502 | --self->refcount == 0 | |||
1503 | #endif | |||
1504 | ) | |||
1505 | { | |||
1506 | e = ___device_release_virt (self)((___device_vtbl*)((self)->vtbl))->release_virt(self); | |||
1507 | ___free_mem (self); | |||
1508 | } | |||
1509 | ||||
1510 | return e; | |||
1511 | } | |||
1512 | ||||
1513 | ___SCMOBJlong ___device_cleanup | |||
1514 | ___P((___device *self),(___device *self) | |||
1515 | (self)(___device *self) | |||
1516 | ___device *self;)(___device *self) | |||
1517 | { | |||
1518 | ___SCMOBJlong e; | |||
1519 | ___device *devs[1]; | |||
1520 | ||||
1521 | if (self->group == NULL((void*)0)) | |||
1522 | return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
1523 | ||||
1524 | ___device_remove_from_group (self); | |||
1525 | ||||
1526 | for (;;) | |||
1527 | { | |||
1528 | e = ___device_close (self, ___DIRECTION_RD1); | |||
1529 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
1530 | break; | |||
1531 | if (e != ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2)) | |||
1532 | return e; | |||
1533 | ||||
1534 | devs[0] = self; | |||
1535 | e = ___device_select (devs, 1, 0, ___time_mod.time_pos_infinity); | |||
1536 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
1537 | return e; | |||
1538 | } | |||
1539 | ||||
1540 | for (;;) | |||
1541 | { | |||
1542 | e = ___device_close (self, ___DIRECTION_WR2); | |||
1543 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
1544 | break; | |||
1545 | if (e != ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2)) | |||
1546 | return e; | |||
1547 | ||||
1548 | devs[0] = self; | |||
1549 | e = ___device_select (devs, 0, 1, ___time_mod.time_pos_infinity); | |||
1550 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
1551 | return e; | |||
1552 | } | |||
1553 | ||||
1554 | return ___device_release (self); | |||
1555 | } | |||
1556 | ||||
1557 | ||||
1558 | /* | |||
1559 | * Procedure called by the Scheme runtime when a device is no longer | |||
1560 | * reachable. | |||
1561 | */ | |||
1562 | ||||
1563 | ___SCMOBJlong ___device_cleanup_from_ptr | |||
1564 | ___P((void *ptr),(void *ptr) | |||
1565 | (ptr)(void *ptr) | |||
1566 | void *ptr;)(void *ptr) | |||
1567 | { | |||
1568 | return ___device_cleanup (___CAST(___device*,ptr)((___device*)(ptr))); | |||
1569 | } | |||
1570 | ||||
1571 | ||||
1572 | /* - - - - - - - - - - - - - - - - - - */ | |||
1573 | ||||
1574 | /* Timer device. */ | |||
1575 | ||||
1576 | /* | |||
1577 | * Timer devices are not particularly useful, given that the scheduler | |||
1578 | * implements timeouts. Use this as an example. | |||
1579 | */ | |||
1580 | ||||
1581 | ___HIDDENstatic int device_timer_kind | |||
1582 | ___P((___device *self),(___device *self) | |||
1583 | (self)(___device *self) | |||
1584 | ___device *self;)(___device *self) | |||
1585 | { | |||
1586 | return ___TIMER_KIND(1 +4096); | |||
1587 | } | |||
1588 | ||||
1589 | ___HIDDENstatic ___SCMOBJlong device_timer_select_virt | |||
1590 | ___P((___device *self,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1591 | ___BOOL for_writing,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1592 | int i,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1593 | int pass,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1594 | ___device_select_state *state),(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1595 | (self,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1596 | for_writing,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1597 | i,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1598 | pass,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1599 | state)(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1600 | ___device *self;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1601 | ___BOOL for_writing;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1602 | int i;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1603 | int pass;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1604 | ___device_select_state *state;)(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1605 | { | |||
1606 | ___device_timer *d = ___CAST(___device_timer*,self)((___device_timer*)(self)); | |||
1607 | ||||
1608 | if (pass == ___SELECT_PASS_11) | |||
1609 | { | |||
1610 | if (___time_less (d->expiry, state->timeout)) | |||
1611 | state->timeout = d->expiry; | |||
1612 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
1613 | } | |||
1614 | ||||
1615 | /* pass == ___SELECT_PASS_CHECK */ | |||
1616 | ||||
1617 | if (state->timeout_reached) | |||
1618 | { | |||
1619 | if (___time_equal (d->expiry, state->timeout)) | |||
1620 | state->devs[i] = NULL((void*)0); | |||
1621 | } | |||
1622 | ||||
1623 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1624 | } | |||
1625 | ||||
1626 | ___HIDDENstatic ___SCMOBJlong device_timer_release_virt | |||
1627 | ___P((___device *self),(___device *self) | |||
1628 | (self)(___device *self) | |||
1629 | ___device *self;)(___device *self) | |||
1630 | { | |||
1631 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1632 | } | |||
1633 | ||||
1634 | ___HIDDENstatic ___SCMOBJlong device_timer_force_output_virt | |||
1635 | ___P((___device *self,(___device *self, int level) | |||
1636 | int level),(___device *self, int level) | |||
1637 | (self,(___device *self, int level) | |||
1638 | level)(___device *self, int level) | |||
1639 | ___device *self;(___device *self, int level) | |||
1640 | int level;)(___device *self, int level) | |||
1641 | { | |||
1642 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1643 | } | |||
1644 | ||||
1645 | ___HIDDENstatic ___SCMOBJlong device_timer_close_virt | |||
1646 | ___P((___device *self,(___device *self, int direction) | |||
1647 | int direction),(___device *self, int direction) | |||
1648 | (self,(___device *self, int direction) | |||
1649 | direction)(___device *self, int direction) | |||
1650 | ___device *self;(___device *self, int direction) | |||
1651 | int direction;)(___device *self, int direction) | |||
1652 | { | |||
1653 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1654 | } | |||
1655 | ||||
1656 | ___HIDDENstatic ___device_timer_vtbl ___device_timer_table = | |||
1657 | { | |||
1658 | { | |||
1659 | device_timer_kind, | |||
1660 | device_timer_select_virt, | |||
1661 | device_timer_release_virt, | |||
1662 | device_timer_force_output_virt, | |||
1663 | device_timer_close_virt | |||
1664 | } | |||
1665 | }; | |||
1666 | ||||
1667 | ___SCMOBJlong ___device_timer_setup | |||
1668 | ___P((___device_timer **dev,(___device_timer **dev, ___device_group *dgroup) | |||
1669 | ___device_group *dgroup),(___device_timer **dev, ___device_group *dgroup) | |||
1670 | (dev,(___device_timer **dev, ___device_group *dgroup) | |||
1671 | dgroup)(___device_timer **dev, ___device_group *dgroup) | |||
1672 | ___device_timer **dev;(___device_timer **dev, ___device_group *dgroup) | |||
1673 | ___device_group *dgroup;)(___device_timer **dev, ___device_group *dgroup) | |||
1674 | { | |||
1675 | ___device_timer *d; | |||
1676 | ||||
1677 | d = ___CAST(___device_timer*,((___device_timer*)(___alloc_mem (sizeof (___device_timer)))) | |||
1678 | ___alloc_mem (sizeof (___device_timer)))((___device_timer*)(___alloc_mem (sizeof (___device_timer)))); | |||
1679 | ||||
1680 | if (d == NULL((void*)0)) | |||
1681 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
1682 | ||||
1683 | d->base.vtbl = &___device_timer_table; | |||
1684 | d->base.refcount = 1; | |||
1685 | d->base.direction = ___DIRECTION_RD1 | ___DIRECTION_WR2; | |||
1686 | d->base.close_direction = 0; /* prevent closing on errors */ | |||
1687 | d->base.read_stage = ___STAGE_OPEN0; | |||
1688 | d->base.write_stage = ___STAGE_OPEN0; | |||
1689 | ||||
1690 | d->expiry = ___time_mod.time_pos_infinity; | |||
1691 | ||||
1692 | *dev = d; | |||
1693 | ||||
1694 | ___device_add_to_group (dgroup, &d->base); | |||
1695 | ||||
1696 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1697 | } | |||
1698 | ||||
1699 | void ___device_timer_set_expiry | |||
1700 | ___P((___device_timer *dev,(___device_timer *dev, ___time expiry) | |||
1701 | ___time expiry),(___device_timer *dev, ___time expiry) | |||
1702 | (dev,(___device_timer *dev, ___time expiry) | |||
1703 | expiry)(___device_timer *dev, ___time expiry) | |||
1704 | ___device_timer *dev;(___device_timer *dev, ___time expiry) | |||
1705 | ___time expiry;)(___device_timer *dev, ___time expiry) | |||
1706 | { | |||
1707 | dev->expiry = expiry; | |||
1708 | } | |||
1709 | ||||
1710 | /* - - - - - - - - - - - - - - - - - - */ | |||
1711 | ||||
1712 | /* Byte stream devices. */ | |||
1713 | ||||
1714 | #ifdef USE_PUMPS | |||
1715 | ||||
1716 | ___HIDDENstatic ___SCMOBJlong ___device_stream_pump_setup | |||
1717 | ___P((___device_stream_pump **pump,(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1718 | DWORD committed_stack_size,(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1719 | LPTHREAD_START_ROUTINE proc,(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1720 | LPVOID arg),(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1721 | (pump,(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1722 | committed_stack_size,(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1723 | proc,(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1724 | arg)(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1725 | ___device_stream_pump **pump;(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1726 | DWORD committed_stack_size;(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1727 | LPTHREAD_START_ROUTINE proc;(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1728 | LPVOID arg;)(___device_stream_pump **pump, DWORD committed_stack_size, LPTHREAD_START_ROUTINE proc, LPVOID arg) | |||
1729 | { | |||
1730 | ___SCMOBJlong e; | |||
1731 | ___device_stream_pump *p; | |||
1732 | HANDLE thread_handle; | |||
1733 | DWORD thread_id; | |||
1734 | ||||
1735 | p = ___CAST(___device_stream_pump*,((___device_stream_pump*)(___alloc_mem (sizeof (___device_stream_pump )))) | |||
1736 | ___alloc_mem (sizeof (___device_stream_pump)))((___device_stream_pump*)(___alloc_mem (sizeof (___device_stream_pump )))); | |||
1737 | ||||
1738 | if (p == NULL((void*)0)) | |||
1739 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
1740 | ||||
1741 | e = ___nonblocking_pipe_setup (&p->pipe, PIPE_BUFFER_SIZE+1); | |||
1742 | ||||
1743 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
1744 | { | |||
1745 | ___free_mem (p); | |||
1746 | return e; | |||
1747 | } | |||
1748 | ||||
1749 | *pump = p; /* set before thread created to avoid race condition */ | |||
1750 | ||||
1751 | thread_handle = | |||
1752 | CreateThread (NULL((void*)0), /* no security attributes */ | |||
1753 | committed_stack_size, /* committed stack size */ | |||
1754 | proc, /* thread procedure */ | |||
1755 | arg, /* argument to thread procedure */ | |||
1756 | 0, /* use default creation flags */ | |||
1757 | &thread_id); | |||
1758 | ||||
1759 | if (thread_handle == NULL((void*)0) || | |||
1760 | !SetThreadPriority (thread_handle, PUMP_PRIORITY)) | |||
1761 | { | |||
1762 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
1763 | ___nonblocking_pipe_cleanup (&p->pipe); | |||
1764 | ___free_mem (p); | |||
1765 | *pump = NULL((void*)0); /* make sure caller does not think a pump was created */ | |||
1766 | return e; | |||
1767 | } | |||
1768 | ||||
1769 | p->thread = thread_handle; | |||
1770 | ||||
1771 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1772 | } | |||
1773 | ||||
1774 | ___HIDDENstatic ___SCMOBJlong ___device_stream_pump_reader_kill | |||
1775 | ___P((___device_stream_pump *pump),(___device_stream_pump *pump) | |||
1776 | (pump)(___device_stream_pump *pump) | |||
1777 | ___device_stream_pump *pump;)(___device_stream_pump *pump) | |||
1778 | { | |||
1779 | return ___nonblocking_pipe_set_reader_err | |||
1780 | (&pump->pipe, | |||
1781 | ___FIX(___KILL_PUMP)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+13)))<<2)); | |||
1782 | } | |||
1783 | ||||
1784 | ___HIDDENstatic ___SCMOBJlong ___device_stream_pump_writer_kill | |||
1785 | ___P((___device_stream_pump *pump),(___device_stream_pump *pump) | |||
1786 | (pump)(___device_stream_pump *pump) | |||
1787 | ___device_stream_pump *pump;)(___device_stream_pump *pump) | |||
1788 | { | |||
1789 | return ___nonblocking_pipe_set_writer_err | |||
1790 | (&pump->pipe, | |||
1791 | ___FIX(___KILL_PUMP)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+13)))<<2)); | |||
1792 | } | |||
1793 | ||||
1794 | ___HIDDENstatic ___SCMOBJlong ___device_stream_pump_wait | |||
1795 | ___P((___device_stream_pump *pump),(___device_stream_pump *pump) | |||
1796 | (pump)(___device_stream_pump *pump) | |||
1797 | ___device_stream_pump *pump;)(___device_stream_pump *pump) | |||
1798 | { | |||
1799 | DWORD code; | |||
1800 | ||||
1801 | code = WaitForSingleObject (pump->thread, 0); | |||
1802 | ||||
1803 | if (code == WAIT_FAILED) | |||
1804 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
1805 | ||||
1806 | if (code == WAIT_TIMEOUT) | |||
1807 | return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
1808 | ||||
1809 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1810 | } | |||
1811 | ||||
1812 | ___HIDDENstatic ___SCMOBJlong ___device_stream_pump_cleanup | |||
1813 | ___P((___device_stream_pump *pump),(___device_stream_pump *pump) | |||
1814 | (pump)(___device_stream_pump *pump) | |||
1815 | ___device_stream_pump *pump;)(___device_stream_pump *pump) | |||
1816 | { | |||
1817 | CloseHandle (pump->thread); /* ignore error */ | |||
1818 | ___nonblocking_pipe_cleanup (&pump->pipe); /* ignore error */ | |||
1819 | ___free_mem (pump); | |||
1820 | ||||
1821 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1822 | } | |||
1823 | ||||
1824 | #endif | |||
1825 | ||||
1826 | ___SCMOBJlong ___device_stream_select_virt | |||
1827 | ___P((___device *self,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1828 | ___BOOL for_writing,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1829 | int i,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1830 | int pass,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1831 | ___device_select_state *state),(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1832 | (self,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1833 | for_writing,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1834 | i,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1835 | pass,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1836 | state)(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1837 | ___device *self;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1838 | ___BOOL for_writing;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1839 | int i;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1840 | int pass;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1841 | ___device_select_state *state;)(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
1842 | { | |||
1843 | ___device_stream *d = ___CAST(___device_stream*,self)((___device_stream*)(self)); | |||
1844 | ||||
1845 | #ifdef USE_PUMPS | |||
1846 | ||||
1847 | int stage = (for_writing | |||
1848 | ? d->base.write_stage | |||
1849 | : d->base.read_stage); | |||
1850 | ___device_stream_pump *p = (for_writing | |||
1851 | ? d->write_pump | |||
1852 | : d->read_pump); | |||
1853 | ||||
1854 | if (p != NULL((void*)0)) | |||
1855 | { | |||
1856 | if (pass == ___SELECT_PASS_11) | |||
1857 | { | |||
1858 | HANDLE wait_obj; | |||
1859 | ||||
1860 | if (stage != ___STAGE_OPEN0) | |||
1861 | wait_obj = p->thread; | |||
1862 | else | |||
1863 | { | |||
1864 | if (for_writing) | |||
1865 | wait_obj = p->pipe.wevent; | |||
1866 | else | |||
1867 | wait_obj = p->pipe.revent; | |||
1868 | } | |||
1869 | ||||
1870 | ___device_select_add_wait_obj (state, i, wait_obj); | |||
1871 | ||||
1872 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
1873 | } | |||
1874 | ||||
1875 | /* pass == ___SELECT_PASS_CHECK */ | |||
1876 | ||||
1877 | if (stage != ___STAGE_OPEN0) | |||
1878 | state->devs[i] = NULL((void*)0); | |||
1879 | else | |||
1880 | { | |||
1881 | if (state->devs_next[i] != -1) | |||
1882 | state->devs[i] = NULL((void*)0); | |||
1883 | } | |||
1884 | ||||
1885 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
1886 | } | |||
1887 | ||||
1888 | #endif | |||
1889 | ||||
1890 | return ___device_stream_select_raw_virt((___device_stream_vtbl*)((d)->base.vtbl))->select_raw_virt (d,for_writing,i,pass,state) | |||
1891 | (d,((___device_stream_vtbl*)((d)->base.vtbl))->select_raw_virt (d,for_writing,i,pass,state) | |||
1892 | for_writing,((___device_stream_vtbl*)((d)->base.vtbl))->select_raw_virt (d,for_writing,i,pass,state) | |||
1893 | i,((___device_stream_vtbl*)((d)->base.vtbl))->select_raw_virt (d,for_writing,i,pass,state) | |||
1894 | pass,((___device_stream_vtbl*)((d)->base.vtbl))->select_raw_virt (d,for_writing,i,pass,state) | |||
1895 | state)((___device_stream_vtbl*)((d)->base.vtbl))->select_raw_virt (d,for_writing,i,pass,state); | |||
1896 | } | |||
1897 | ||||
1898 | ||||
1899 | ___SCMOBJlong ___device_stream_release_virt | |||
1900 | ___P((___device *self),(___device *self) | |||
1901 | (self)(___device *self) | |||
1902 | ___device *self;)(___device *self) | |||
1903 | { | |||
1904 | ___SCMOBJlong e; | |||
1905 | ___device_stream *d = ___CAST(___device_stream*,self)((___device_stream*)(self)); | |||
1906 | ||||
1907 | e = ___device_stream_release_raw_virt (d)((___device_stream_vtbl*)((d)->base.vtbl))->release_raw_virt (d); | |||
1908 | ||||
1909 | #ifdef USE_PUMPS | |||
1910 | ||||
1911 | { | |||
1912 | ___device_stream_pump *p; | |||
1913 | ||||
1914 | p = d->read_pump; | |||
1915 | if (p != NULL((void*)0)) | |||
1916 | ___device_stream_pump_cleanup (p); /* ignore error */ | |||
1917 | ||||
1918 | p = d->write_pump; | |||
1919 | if (p != NULL((void*)0)) | |||
1920 | ___device_stream_pump_cleanup (p); /* ignore error */ | |||
1921 | } | |||
1922 | ||||
1923 | #endif | |||
1924 | ||||
1925 | return e; | |||
1926 | } | |||
1927 | ||||
1928 | ||||
1929 | ___SCMOBJlong ___device_stream_force_output_virt | |||
1930 | ___P((___device *self,(___device *self, int level) | |||
1931 | int level),(___device *self, int level) | |||
1932 | (self,(___device *self, int level) | |||
1933 | level)(___device *self, int level) | |||
1934 | ___device *self;(___device *self, int level) | |||
1935 | int level;)(___device *self, int level) | |||
1936 | { | |||
1937 | ___device_stream *d = ___CAST(___device_stream*,self)((___device_stream*)(self)); | |||
1938 | ||||
1939 | #ifdef USE_PUMPS | |||
1940 | ||||
1941 | { | |||
1942 | ___device_stream_pump *p = d->write_pump; | |||
1943 | ||||
1944 | if (p != NULL((void*)0)) | |||
1945 | { | |||
1946 | ___nonblocking_pipe_oob_msg oob_msg; | |||
1947 | ||||
1948 | oob_msg.op = OOB_FORCE_OUTPUT0 + level; | |||
1949 | ||||
1950 | return ___nonblocking_pipe_write_oob (&p->pipe, &oob_msg); | |||
1951 | } | |||
1952 | } | |||
1953 | ||||
1954 | #endif | |||
1955 | ||||
1956 | return ___device_stream_force_output_raw_virt (d, level)((___device_stream_vtbl*)((d)->base.vtbl))->force_output_raw_virt (d,level); | |||
1957 | } | |||
1958 | ||||
1959 | ||||
1960 | ___SCMOBJlong ___device_stream_close_virt | |||
1961 | ___P((___device *self,(___device *self, int direction) | |||
1962 | int direction),(___device *self, int direction) | |||
1963 | (self,(___device *self, int direction) | |||
1964 | direction)(___device *self, int direction) | |||
1965 | ___device *self;(___device *self, int direction) | |||
1966 | int direction;)(___device *self, int direction) | |||
1967 | { | |||
1968 | ___device_stream *d = ___CAST(___device_stream*,self)((___device_stream*)(self)); | |||
1969 | ||||
1970 | #ifdef USE_PUMPS | |||
1971 | ||||
1972 | if (direction & ___DIRECTION_RD1) | |||
1973 | { | |||
1974 | ___device_stream_pump *p = d->read_pump; | |||
1975 | ||||
1976 | if (p != NULL((void*)0)) | |||
1977 | ___device_stream_pump_reader_kill (p); | |||
1978 | } | |||
1979 | ||||
1980 | if (direction & ___DIRECTION_WR2) | |||
1981 | { | |||
1982 | ___device_stream_pump *p = d->write_pump; | |||
1983 | ||||
1984 | if (p != NULL((void*)0)) | |||
1985 | ___device_stream_pump_writer_kill (p); | |||
1986 | } | |||
1987 | ||||
1988 | #endif | |||
1989 | ||||
1990 | return ___device_stream_close_raw_virt (d, direction)((___device_stream_vtbl*)((d)->base.vtbl))->close_raw_virt (d,direction); | |||
1991 | } | |||
1992 | ||||
1993 | ||||
1994 | ___SCMOBJlong ___device_stream_seek | |||
1995 | ___P((___device_stream *self,(___device_stream *self, ___stream_index *pos, int whence) | |||
1996 | ___stream_index *pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
1997 | int whence),(___device_stream *self, ___stream_index *pos, int whence) | |||
1998 | (self,(___device_stream *self, ___stream_index *pos, int whence) | |||
1999 | pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
2000 | whence)(___device_stream *self, ___stream_index *pos, int whence) | |||
2001 | ___device_stream *self;(___device_stream *self, ___stream_index *pos, int whence) | |||
2002 | ___stream_index *pos;(___device_stream *self, ___stream_index *pos, int whence) | |||
2003 | int whence;)(___device_stream *self, ___stream_index *pos, int whence) | |||
2004 | { | |||
2005 | #ifdef USE_PUMPS | |||
2006 | ||||
2007 | { | |||
2008 | ___device_stream_pump *p = self->write_pump; | |||
2009 | ||||
2010 | if (p != NULL((void*)0)) | |||
2011 | { | |||
2012 | ___nonblocking_pipe_oob_msg oob_msg; | |||
2013 | ||||
2014 | oob_msg.op = OOB_SEEK_ABS + whence; | |||
2015 | oob_msg.stream_index_param = *pos; | |||
2016 | ||||
2017 | return ___nonblocking_pipe_write_oob (&p->pipe, &oob_msg); | |||
2018 | } | |||
2019 | } | |||
2020 | ||||
2021 | #endif | |||
2022 | ||||
2023 | return ___device_stream_seek_raw_virt (self, pos, whence)((___device_stream_vtbl*)((self)->base.vtbl))->seek_raw_virt (self,pos,whence); | |||
2024 | } | |||
2025 | ||||
2026 | ___SCMOBJlong ___device_stream_read | |||
2027 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2028 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2029 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2030 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2031 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2032 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2033 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2034 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2035 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2036 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2037 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2038 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2039 | { | |||
2040 | #ifdef USE_PUMPS | |||
2041 | ||||
2042 | { | |||
2043 | ___device_stream_pump *p = self->read_pump; | |||
2044 | ||||
2045 | if (p != NULL((void*)0)) | |||
2046 | { | |||
2047 | ___nonblocking_pipe_oob_msg oob_msg; | |||
2048 | return ___nonblocking_pipe_read | |||
2049 | (&p->pipe, | |||
2050 | buf, | |||
2051 | len, | |||
2052 | len_done, | |||
2053 | &oob_msg); | |||
2054 | } | |||
2055 | } | |||
2056 | ||||
2057 | #endif | |||
2058 | ||||
2059 | return ___device_stream_read_raw_virt (self, buf, len, len_done)((___device_stream_vtbl*)((self)->base.vtbl))->read_raw_virt (self,buf,len,len_done); | |||
2060 | } | |||
2061 | ||||
2062 | ___SCMOBJlong ___device_stream_write | |||
2063 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2064 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2065 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2066 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2067 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2068 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2069 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2070 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2071 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2072 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2073 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2074 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2075 | { | |||
2076 | #ifdef USE_PUMPS | |||
2077 | ||||
2078 | { | |||
2079 | ___device_stream_pump *p = self->write_pump; | |||
2080 | ||||
2081 | if (p != NULL((void*)0)) | |||
2082 | return ___nonblocking_pipe_write (&p->pipe, buf, len, len_done); | |||
2083 | } | |||
2084 | ||||
2085 | #endif | |||
2086 | ||||
2087 | return ___device_stream_write_raw_virt (self, buf, len, len_done)((___device_stream_vtbl*)((self)->base.vtbl))->write_raw_virt (self,buf,len,len_done); | |||
2088 | } | |||
2089 | ||||
2090 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |||
2091 | ||||
2092 | #ifdef USE_PUMPS | |||
2093 | ||||
2094 | ___HIDDENstatic DWORD WINAPI ___device_stream_read_pump_proc | |||
2095 | ___P((LPVOID param),(LPVOID param) | |||
2096 | (param)(LPVOID param) | |||
2097 | LPVOID param;)(LPVOID param) | |||
2098 | { | |||
2099 | ___device_stream *dev = ___CAST(___device_stream*,param)((___device_stream*)(param)); | |||
2100 | ___nonblocking_pipe *p = &dev->read_pump->pipe; | |||
2101 | ___SCMOBJlong e; | |||
2102 | ___stream_index len; | |||
2103 | ___stream_index n; | |||
2104 | ___stream_index i; | |||
2105 | ___U8unsigned char buf[PIPE_BUFFER_SIZE]; | |||
2106 | ___nonblocking_pipe_oob_msg oob_msg; | |||
2107 | ||||
2108 | for (;;) | |||
2109 | { | |||
2110 | /* wait until the reader needs some data */ | |||
2111 | ||||
2112 | e = ___nonblocking_pipe_write_ready_wait (p); | |||
2113 | ||||
2114 | /* read some characters from device */ | |||
2115 | ||||
2116 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2117 | e = ___device_stream_read_raw_virt (dev, buf, PIPE_BUFFER_SIZE, &len)((___device_stream_vtbl*)((dev)->base.vtbl))->read_raw_virt (dev,buf,PIPE_BUFFER_SIZE,&len); | |||
2118 | ||||
2119 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2120 | { | |||
2121 | if (len == 0) | |||
2122 | { | |||
2123 | /* we reached the end-of-stream */ | |||
2124 | ||||
2125 | oob_msg.op = OOB_EOS; | |||
2126 | ||||
2127 | while ((e = ___nonblocking_pipe_write_oob (p, &oob_msg)) | |||
2128 | == ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2)) | |||
2129 | { | |||
2130 | /* suspend thread until operation can be performed */ | |||
2131 | ||||
2132 | e = ___nonblocking_pipe_write_ready_wait (p); | |||
2133 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2134 | break; | |||
2135 | } | |||
2136 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2137 | break; | |||
2138 | } | |||
2139 | else | |||
2140 | { | |||
2141 | /* write to the pipe the bytes that were read */ | |||
2142 | ||||
2143 | i = 0; | |||
2144 | ||||
2145 | while (i < len) | |||
2146 | { | |||
2147 | while ((e = ___nonblocking_pipe_write (p, buf+i, len-i, &n)) | |||
2148 | == ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2)) | |||
2149 | { | |||
2150 | /* suspend thread until operation can be performed */ | |||
2151 | ||||
2152 | e = ___nonblocking_pipe_write_ready_wait (p); | |||
2153 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2154 | break; | |||
2155 | } | |||
2156 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2157 | break; | |||
2158 | i += n; | |||
2159 | } | |||
2160 | } | |||
2161 | } | |||
2162 | ||||
2163 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2164 | { | |||
2165 | if (e == ___FIX(___KILL_PUMP)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+13)))<<2)) /* terminate? */ | |||
2166 | break; | |||
2167 | ||||
2168 | if (e == ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2)) | |||
2169 | continue; | |||
2170 | ||||
2171 | /* report the failure back through the pipe */ | |||
2172 | ||||
2173 | e = ___nonblocking_pipe_set_writer_err (p, e); | |||
2174 | ||||
2175 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2176 | { | |||
2177 | /* | |||
2178 | * The failure could not be reported. To avoid an | |||
2179 | * infinite loop the thread is terminated. | |||
2180 | */ | |||
2181 | ||||
2182 | ExitThread (0); | |||
2183 | } | |||
2184 | } | |||
2185 | } | |||
2186 | ||||
2187 | ___device_release (&dev->base); /* ignore error */ | |||
2188 | ||||
2189 | return 0; | |||
2190 | } | |||
2191 | ||||
2192 | ___HIDDENstatic DWORD WINAPI ___device_stream_write_pump_proc | |||
2193 | ___P((LPVOID param),(LPVOID param) | |||
2194 | (param)(LPVOID param) | |||
2195 | LPVOID param;)(LPVOID param) | |||
2196 | { | |||
2197 | ___device_stream *dev = ___CAST(___device_stream*,param)((___device_stream*)(param)); | |||
2198 | ___nonblocking_pipe *p = &dev->write_pump->pipe; | |||
2199 | ___SCMOBJlong e; | |||
2200 | ___stream_index len; | |||
2201 | ___stream_index n; | |||
2202 | ___stream_index i; | |||
2203 | ___U8unsigned char buf[PIPE_BUFFER_SIZE]; | |||
2204 | ___nonblocking_pipe_oob_msg oob_msg; | |||
2205 | ||||
2206 | for (;;) | |||
2207 | { | |||
2208 | /* get from the pipe some bytes to write to the device */ | |||
2209 | ||||
2210 | while ((e = ___nonblocking_pipe_read | |||
2211 | (p, | |||
2212 | buf, | |||
2213 | PIPE_BUFFER_SIZE, | |||
2214 | &len, | |||
2215 | &oob_msg)) | |||
2216 | == ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2)) | |||
2217 | { | |||
2218 | /* suspend thread until operation can be performed */ | |||
2219 | ||||
2220 | e = ___nonblocking_pipe_read_ready_wait (p); | |||
2221 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2222 | break; | |||
2223 | } | |||
2224 | ||||
2225 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2226 | { | |||
2227 | if (len > 0) | |||
2228 | { | |||
2229 | /* write to the device the bytes that were read from the pipe */ | |||
2230 | ||||
2231 | i = 0; | |||
2232 | ||||
2233 | while (i < len) | |||
2234 | { | |||
2235 | e = ___device_stream_write_raw_virt (dev, buf+i, len-i, &n)((___device_stream_vtbl*)((dev)->base.vtbl))->write_raw_virt (dev,buf+i,len-i,&n); | |||
2236 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2237 | break; | |||
2238 | i += n; | |||
2239 | } | |||
2240 | } | |||
2241 | else | |||
2242 | { | |||
2243 | switch (oob_msg.op) | |||
2244 | { | |||
2245 | case OOB_FORCE_OUTPUT0: | |||
2246 | case OOB_FORCE_OUTPUT1: | |||
2247 | case OOB_FORCE_OUTPUT2: | |||
2248 | case OOB_FORCE_OUTPUT3: | |||
2249 | #ifdef ___DEBUG | |||
2250 | ___printf ("***** got OOB_FORCE_OUTPUT%d\n", | |||
2251 | oob_msg.op - OOB_FORCE_OUTPUT0); | |||
2252 | #endif | |||
2253 | e = ___device_stream_force_output_raw_virt (dev, oob_msg.op - OOB_FORCE_OUTPUT0)((___device_stream_vtbl*)((dev)->base.vtbl))->force_output_raw_virt (dev,oob_msg.op - OOB_FORCE_OUTPUT0); | |||
2254 | break; | |||
2255 | case OOB_SEEK_ABS: | |||
2256 | case OOB_SEEK_REL: | |||
2257 | case OOB_SEEK_REL_END: | |||
2258 | #ifdef ___DEBUG | |||
2259 | ___printf ("***** got OOB_SEEK %d %d\n", | |||
2260 | oob_msg.stream_index_param, | |||
2261 | oob_msg.op - OOB_SEEK_ABS); | |||
2262 | #endif | |||
2263 | e = ___device_stream_seek_raw_virt((___device_stream_vtbl*)((dev)->base.vtbl))->seek_raw_virt (dev,&oob_msg.stream_index_param,oob_msg.op - OOB_SEEK_ABS ) | |||
2264 | (dev,((___device_stream_vtbl*)((dev)->base.vtbl))->seek_raw_virt (dev,&oob_msg.stream_index_param,oob_msg.op - OOB_SEEK_ABS ) | |||
2265 | &oob_msg.stream_index_param,((___device_stream_vtbl*)((dev)->base.vtbl))->seek_raw_virt (dev,&oob_msg.stream_index_param,oob_msg.op - OOB_SEEK_ABS ) | |||
2266 | oob_msg.op - OOB_SEEK_ABS)((___device_stream_vtbl*)((dev)->base.vtbl))->seek_raw_virt (dev,&oob_msg.stream_index_param,oob_msg.op - OOB_SEEK_ABS ); | |||
2267 | break; | |||
2268 | case OOB_EOS: | |||
2269 | #ifdef ___DEBUG | |||
2270 | ___printf ("***** got OOB_EOS\n"); | |||
2271 | #endif | |||
2272 | break; | |||
2273 | } | |||
2274 | } | |||
2275 | } | |||
2276 | ||||
2277 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2278 | { | |||
2279 | if (e == ___FIX(___KILL_PUMP)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+13)))<<2)) /* terminate? */ | |||
2280 | break; | |||
2281 | ||||
2282 | /* report the failure back through the pipe */ | |||
2283 | ||||
2284 | e = ___nonblocking_pipe_set_reader_err (p, e); | |||
2285 | ||||
2286 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2287 | { | |||
2288 | /* | |||
2289 | * The failure could not be reported. To avoid an | |||
2290 | * infinite loop the thread is terminated. | |||
2291 | */ | |||
2292 | ||||
2293 | ExitThread (0); | |||
2294 | } | |||
2295 | } | |||
2296 | } | |||
2297 | ||||
2298 | ___device_release (&dev->base); /* ignore error */ | |||
2299 | ||||
2300 | return 0; | |||
2301 | } | |||
2302 | ||||
2303 | #endif | |||
2304 | ||||
2305 | ___SCMOBJlong ___device_stream_setup | |||
2306 | ___P((___device_stream *dev,(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2307 | ___device_group *dgroup,(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2308 | int direction,(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2309 | int pumps_on),(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2310 | (dev,(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2311 | dgroup,(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2312 | direction,(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2313 | pumps_on)/*********************/(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2314 | ___device_stream *dev;(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2315 | ___device_group *dgroup;(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2316 | int direction;(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2317 | int pumps_on;)(___device_stream *dev, ___device_group *dgroup, int direction , int pumps_on) | |||
2318 | { | |||
2319 | dev->base.refcount = 1; | |||
2320 | dev->base.direction = direction; | |||
2321 | dev->base.close_direction = 0; /* prevent closing on errors */ | |||
2322 | dev->base.read_stage = ___STAGE_CLOSED3; | |||
2323 | dev->base.write_stage = ___STAGE_CLOSED3; | |||
2324 | ||||
2325 | #ifdef USE_PUMPS | |||
2326 | dev->read_pump = NULL((void*)0); | |||
2327 | dev->write_pump = NULL((void*)0); | |||
2328 | #endif | |||
2329 | ||||
2330 | ___device_add_to_group (dgroup, &dev->base); | |||
2331 | ||||
2332 | if (direction & ___DIRECTION_RD1) | |||
2333 | { | |||
2334 | dev->base.read_stage = ___STAGE_OPEN0; | |||
2335 | ||||
2336 | #ifdef USE_PUMPS | |||
2337 | ||||
2338 | if (pumps_on & ___DIRECTION_RD1) | |||
2339 | { | |||
2340 | ___SCMOBJlong e; | |||
2341 | ||||
2342 | device_add_ref (&dev->base); | |||
2343 | ||||
2344 | if ((e = ___device_stream_pump_setup | |||
2345 | (&dev->read_pump, | |||
2346 | 65536, | |||
2347 | ___device_stream_read_pump_proc, | |||
2348 | dev)) | |||
2349 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2350 | { | |||
2351 | ___device_release (&dev->base); /* ignore error */ | |||
2352 | ___device_cleanup (&dev->base); /* ignore error */ | |||
2353 | return e; | |||
2354 | } | |||
2355 | } | |||
2356 | ||||
2357 | #endif | |||
2358 | } | |||
2359 | ||||
2360 | if (direction & ___DIRECTION_WR2) | |||
2361 | { | |||
2362 | dev->base.write_stage = ___STAGE_OPEN0; | |||
2363 | ||||
2364 | #ifdef USE_PUMPS | |||
2365 | ||||
2366 | if (pumps_on & ___DIRECTION_WR2) | |||
2367 | { | |||
2368 | ___SCMOBJlong e; | |||
2369 | ||||
2370 | device_add_ref (&dev->base); | |||
2371 | ||||
2372 | if ((e = ___device_stream_pump_setup | |||
2373 | (&dev->write_pump, | |||
2374 | 65536, | |||
2375 | ___device_stream_write_pump_proc, | |||
2376 | dev)) | |||
2377 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2378 | { | |||
2379 | ___device_release (&dev->base); /* ignore error */ | |||
2380 | ___device_cleanup (&dev->base); /* ignore error */ | |||
2381 | return e; | |||
2382 | } | |||
2383 | } | |||
2384 | ||||
2385 | #endif | |||
2386 | } | |||
2387 | ||||
2388 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2389 | } | |||
2390 | ||||
2391 | ||||
2392 | /*---------------------------------------------------------------------------*/ | |||
2393 | ||||
2394 | /* Serial stream device */ | |||
2395 | ||||
2396 | #ifdef USE_WIN32 | |||
2397 | ||||
2398 | typedef struct ___device_serial_struct | |||
2399 | { | |||
2400 | ___device_stream base; | |||
2401 | HANDLE h; | |||
2402 | } ___device_serial; | |||
2403 | ||||
2404 | typedef struct ___device_serial_vtbl_struct | |||
2405 | { | |||
2406 | ___device_stream_vtbl base; | |||
2407 | } ___device_serial_vtbl; | |||
2408 | ||||
2409 | ___HIDDENstatic int ___device_serial_kind | |||
2410 | ___P((___device *self),(___device *self) | |||
2411 | (self)(___device *self) | |||
2412 | ___device *self;)(___device *self) | |||
2413 | { | |||
2414 | return ___SERIAL_DEVICE_KIND(15 +128); | |||
2415 | } | |||
2416 | ||||
2417 | ___HIDDENstatic ___SCMOBJlong ___device_serial_close_raw_virt | |||
2418 | ___P((___device_stream *self,(___device_stream *self, int direction) | |||
2419 | int direction),(___device_stream *self, int direction) | |||
2420 | (self,(___device_stream *self, int direction) | |||
2421 | direction)(___device_stream *self, int direction) | |||
2422 | ___device_stream *self;(___device_stream *self, int direction) | |||
2423 | int direction;)(___device_stream *self, int direction) | |||
2424 | { | |||
2425 | ___device_serial *d = ___CAST(___device_serial*,self)((___device_serial*)(self)); | |||
2426 | int is_not_closed = 0; | |||
2427 | ||||
2428 | if (d->base.base.read_stage != ___STAGE_CLOSED3) | |||
2429 | is_not_closed |= ___DIRECTION_RD1; | |||
2430 | ||||
2431 | if (d->base.base.write_stage != ___STAGE_CLOSED3) | |||
2432 | is_not_closed |= ___DIRECTION_WR2; | |||
2433 | ||||
2434 | if (is_not_closed == 0) | |||
2435 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2436 | ||||
2437 | if (is_not_closed == (___DIRECTION_RD1|___DIRECTION_WR2)) | |||
2438 | { | |||
2439 | d->base.base.read_stage = ___STAGE_CLOSED3; | |||
2440 | d->base.base.write_stage = ___STAGE_CLOSED3; | |||
2441 | ||||
2442 | if ((d->base.base.close_direction & (___DIRECTION_RD1|___DIRECTION_WR2)) | |||
2443 | == (___DIRECTION_RD1|___DIRECTION_WR2)) | |||
2444 | { | |||
2445 | if (!CloseHandle (d->h)) | |||
2446 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
2447 | } | |||
2448 | } | |||
2449 | ||||
2450 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2451 | } | |||
2452 | ||||
2453 | ___HIDDENstatic ___SCMOBJlong ___device_serial_select_raw_virt | |||
2454 | ___P((___device_stream *self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2455 | ___BOOL for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2456 | int i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2457 | int pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2458 | ___device_select_state *state),(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2459 | (self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2460 | for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2461 | i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2462 | pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2463 | state)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2464 | ___device_stream *self;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2465 | ___BOOL for_writing;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2466 | int i;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2467 | int pass;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2468 | ___device_select_state *state;)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2469 | { | |||
2470 | ___device_serial *d = ___CAST(___device_serial*,self)((___device_serial*)(self)); | |||
2471 | int stage = (for_writing | |||
2472 | ? d->base.base.write_stage | |||
2473 | : d->base.base.read_stage); | |||
2474 | ||||
2475 | if (pass == ___SELECT_PASS_11) | |||
2476 | { | |||
2477 | if (stage != ___STAGE_OPEN0) | |||
2478 | state->timeout = ___time_mod.time_neg_infinity; | |||
2479 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
2480 | } | |||
2481 | ||||
2482 | /* pass == ___SELECT_PASS_CHECK */ | |||
2483 | ||||
2484 | if (stage != ___STAGE_OPEN0) | |||
2485 | state->devs[i] = NULL((void*)0); | |||
2486 | else | |||
2487 | { | |||
2488 | if (state->devs_next[i] != -1) | |||
2489 | state->devs[i] = NULL((void*)0); | |||
2490 | } | |||
2491 | ||||
2492 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2493 | } | |||
2494 | ||||
2495 | ___HIDDENstatic ___SCMOBJlong ___device_serial_release_raw_virt | |||
2496 | ___P((___device_stream *self),(___device_stream *self) | |||
2497 | (self)(___device_stream *self) | |||
2498 | ___device_stream *self;)(___device_stream *self) | |||
2499 | { | |||
2500 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2501 | } | |||
2502 | ||||
2503 | ___HIDDENstatic ___SCMOBJlong ___device_serial_force_output_raw_virt | |||
2504 | ___P((___device_stream *self,(___device_stream *self, int level) | |||
2505 | int level),(___device_stream *self, int level) | |||
2506 | (self,(___device_stream *self, int level) | |||
2507 | level)(___device_stream *self, int level) | |||
2508 | ___device_stream *self;(___device_stream *self, int level) | |||
2509 | int level;)(___device_stream *self, int level) | |||
2510 | { | |||
2511 | ___device_serial *d = ___CAST(___device_serial*,self)((___device_serial*)(self)); | |||
2512 | ||||
2513 | if (d->base.base.write_stage == ___STAGE_OPEN0) | |||
2514 | { | |||
2515 | if (level > 0) | |||
2516 | { | |||
2517 | if (!FlushFileBuffers (d->h)) | |||
2518 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
2519 | } | |||
2520 | } | |||
2521 | ||||
2522 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2523 | } | |||
2524 | ||||
2525 | ___HIDDENstatic ___SCMOBJlong ___device_serial_seek_raw_virt | |||
2526 | ___P((___device_stream *self,(___device_stream *self, ___stream_index *pos, int whence) | |||
2527 | ___stream_index *pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
2528 | int whence),(___device_stream *self, ___stream_index *pos, int whence) | |||
2529 | (self,(___device_stream *self, ___stream_index *pos, int whence) | |||
2530 | pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
2531 | whence)(___device_stream *self, ___stream_index *pos, int whence) | |||
2532 | ___device_stream *self;(___device_stream *self, ___stream_index *pos, int whence) | |||
2533 | ___stream_index *pos;(___device_stream *self, ___stream_index *pos, int whence) | |||
2534 | int whence;)(___device_stream *self, ___stream_index *pos, int whence) | |||
2535 | { | |||
2536 | return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+7)))<<2); | |||
2537 | } | |||
2538 | ||||
2539 | ___HIDDENstatic ___SCMOBJlong ___device_serial_read_raw_virt | |||
2540 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2541 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2542 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2543 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2544 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2545 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2546 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2547 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2548 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2549 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2550 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2551 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2552 | { | |||
2553 | ___device_serial *d = ___CAST(___device_serial*,self)((___device_serial*)(self)); | |||
2554 | ||||
2555 | if (d->base.base.read_stage != ___STAGE_OPEN0) | |||
2556 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
2557 | ||||
2558 | { | |||
2559 | DWORD n; | |||
2560 | ||||
2561 | if (!ReadFile (d->h, buf, len, &n, NULL((void*)0))) | |||
2562 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
2563 | ||||
2564 | if (n == 0) | |||
2565 | return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
2566 | ||||
2567 | *len_done = n; | |||
2568 | } | |||
2569 | ||||
2570 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2571 | } | |||
2572 | ||||
2573 | ___HIDDENstatic ___SCMOBJlong ___device_serial_write_raw_virt | |||
2574 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2575 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2576 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2577 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2578 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2579 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2580 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2581 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2582 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2583 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2584 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2585 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
2586 | { | |||
2587 | ___device_serial *d = ___CAST(___device_serial*,self)((___device_serial*)(self)); | |||
2588 | ||||
2589 | if (d->base.base.write_stage != ___STAGE_OPEN0) | |||
2590 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
2591 | ||||
2592 | { | |||
2593 | DWORD n; | |||
2594 | ||||
2595 | if (!WriteFile (d->h, buf, len, &n, NULL((void*)0))) | |||
2596 | { | |||
2597 | /* | |||
2598 | * Even though WriteFile has reported a failure, the operation | |||
2599 | * was executed correctly (i.e. len_done contains the number | |||
2600 | * of bytes written) if GetLastError returns ERROR_SUCCESS. | |||
2601 | */ | |||
2602 | ||||
2603 | if (GetLastError () != ERROR_SUCCESS) | |||
2604 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
2605 | } | |||
2606 | ||||
2607 | *len_done = n; | |||
2608 | } | |||
2609 | ||||
2610 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2611 | } | |||
2612 | ||||
2613 | ___HIDDENstatic ___SCMOBJlong ___device_serial_width_virt | |||
2614 | ___P((___device_stream *self),(___device_stream *self) | |||
2615 | (self)(___device_stream *self) | |||
2616 | ___device_stream *self;)(___device_stream *self) | |||
2617 | { | |||
2618 | return ___FIX(80)(((long)(80))<<2); | |||
2619 | } | |||
2620 | ||||
2621 | ___HIDDENstatic ___SCMOBJlong ___device_serial_default_options_virt | |||
2622 | ___P((___device_stream *self),(___device_stream *self) | |||
2623 | (self)(___device_stream *self) | |||
2624 | ___device_stream *self;)(___device_stream *self) | |||
2625 | { | |||
2626 | int char_encoding_errors = ___CHAR_ENCODING_ERRORS_ON(1<<5); | |||
2627 | int char_encoding = ___CHAR_ENCODING_ISO_8859_1(2<<0); | |||
2628 | int eol_encoding = ___EOL_ENCODING_LF(1<<7); | |||
2629 | int buffering = ___FULL_BUFFERING(3<<9); | |||
2630 | ||||
2631 | return ___FIX(___STREAM_OPTIONS(char_encoding_errors,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
2632 | char_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
2633 | eol_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
2634 | buffering,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
2635 | char_encoding_errors,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
2636 | char_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
2637 | eol_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
2638 | buffering))(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2); | |||
2639 | } | |||
2640 | ||||
2641 | ||||
2642 | ___HIDDENstatic ___SCMOBJlong ___device_serial_options_set_virt | |||
2643 | ___P((___device_stream *self,(___device_stream *self, long options) | |||
2644 | ___SCMOBJ options),(___device_stream *self, long options) | |||
2645 | (self,(___device_stream *self, long options) | |||
2646 | options)(___device_stream *self, long options) | |||
2647 | ___device_stream *self;(___device_stream *self, long options) | |||
2648 | ___SCMOBJ options;)(___device_stream *self, long options) | |||
2649 | { | |||
2650 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2651 | } | |||
2652 | ||||
2653 | ||||
2654 | ___HIDDENstatic ___device_serial_vtbl ___device_serial_table = | |||
2655 | { | |||
2656 | { | |||
2657 | { | |||
2658 | ___device_serial_kind, | |||
2659 | ___device_stream_select_virt, | |||
2660 | ___device_stream_release_virt, | |||
2661 | ___device_stream_force_output_virt, | |||
2662 | ___device_stream_close_virt | |||
2663 | }, | |||
2664 | ___device_serial_select_raw_virt, | |||
2665 | ___device_serial_release_raw_virt, | |||
2666 | ___device_serial_force_output_raw_virt, | |||
2667 | ___device_serial_close_raw_virt, | |||
2668 | ___device_serial_seek_raw_virt, | |||
2669 | ___device_serial_read_raw_virt, | |||
2670 | ___device_serial_write_raw_virt, | |||
2671 | ___device_serial_width_virt, | |||
2672 | ___device_serial_default_options_virt, | |||
2673 | ___device_serial_options_set_virt | |||
2674 | } | |||
2675 | }; | |||
2676 | ||||
2677 | ||||
2678 | ___HIDDENstatic ___SCMOBJlong ___device_serial_set_comm_state | |||
2679 | ___P((___device_serial *dev,(___device_serial *dev, LPCTSTR def) | |||
2680 | LPCTSTR def),(___device_serial *dev, LPCTSTR def) | |||
2681 | (dev,(___device_serial *dev, LPCTSTR def) | |||
2682 | def)(___device_serial *dev, LPCTSTR def) | |||
2683 | ___device_serial *dev;(___device_serial *dev, LPCTSTR def) | |||
2684 | LPCTSTR def;)(___device_serial *dev, LPCTSTR def) | |||
2685 | { | |||
2686 | DCB dcb; | |||
2687 | ||||
2688 | FillMemory (&dcb, sizeof (dcb), 0); | |||
2689 | ||||
2690 | if (!GetCommState (dev->h, &dcb) || | |||
2691 | !BuildCommDCB (def, &dcb) || | |||
2692 | !SetCommState (dev->h, &dcb)) | |||
2693 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
2694 | ||||
2695 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2696 | } | |||
2697 | ||||
2698 | ___SCMOBJlong ___device_serial_setup_from_handle | |||
2699 | ___P((___device_serial **dev,(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2700 | ___device_group *dgroup,(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2701 | HANDLE h,(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2702 | int direction),(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2703 | (dev,(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2704 | dgroup,(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2705 | h,(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2706 | direction)(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2707 | ___device_serial **dev;(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2708 | ___device_group *dgroup;(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2709 | HANDLE h;(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2710 | int direction;)(___device_serial **dev, ___device_group *dgroup, HANDLE h, int direction) | |||
2711 | { | |||
2712 | ___device_serial *d; | |||
2713 | ___SCMOBJlong e; | |||
2714 | COMMTIMEOUTS cto; | |||
2715 | ||||
2716 | d = ___CAST(___device_serial*,((___device_serial*)(___alloc_mem (sizeof (___device_serial)) )) | |||
2717 | ___alloc_mem (sizeof (___device_serial)))((___device_serial*)(___alloc_mem (sizeof (___device_serial)) )); | |||
2718 | ||||
2719 | if (d == NULL((void*)0)) | |||
2720 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
2721 | ||||
2722 | d->base.base.vtbl = &___device_serial_table; | |||
2723 | d->h = h; | |||
2724 | ||||
2725 | *dev = d; | |||
2726 | ||||
2727 | e = ___device_serial_set_comm_state (d, _T("baud=38400 parity=N data=8 stop=1")); | |||
2728 | ||||
2729 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
2730 | { | |||
2731 | ___free_mem (d); | |||
2732 | return e; | |||
2733 | } | |||
2734 | ||||
2735 | /* | |||
2736 | * Setup serial device so that ReadFile will return as soon as a | |||
2737 | * character is available. | |||
2738 | */ | |||
2739 | ||||
2740 | cto.ReadIntervalTimeout = MAXDWORD; | |||
2741 | cto.ReadTotalTimeoutMultiplier = MAXDWORD; | |||
2742 | cto.ReadTotalTimeoutConstant = 1; /* wait no more than 1 ms */ | |||
2743 | cto.WriteTotalTimeoutMultiplier = 0; | |||
2744 | cto.WriteTotalTimeoutConstant = 0; | |||
2745 | ||||
2746 | if (!SetCommTimeouts (h, &cto) | |||
2747 | #ifdef USE_BIG_SERIAL_BUFFERS | |||
2748 | || !SetupComm (h, 65536, 65536)) | |||
2749 | #endif | |||
2750 | ) | |||
2751 | { | |||
2752 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
2753 | ___free_mem (d); | |||
2754 | return e; | |||
2755 | } | |||
2756 | ||||
2757 | return ___device_stream_setup | |||
2758 | (&d->base, | |||
2759 | dgroup, | |||
2760 | direction, | |||
2761 | ___DIRECTION_RD1|___DIRECTION_WR2); | |||
2762 | } | |||
2763 | ||||
2764 | #endif | |||
2765 | ||||
2766 | ||||
2767 | /*---------------------------------------------------------------------------*/ | |||
2768 | ||||
2769 | /* Pipe stream device */ | |||
2770 | ||||
2771 | /* | |||
2772 | * Pipes may be unidirectional or bidirectional. Bidirectional pipes | |||
2773 | * are implemented with 2 OS pipes: a "write" pipe and a "read" pipe. | |||
2774 | */ | |||
2775 | ||||
2776 | typedef struct ___device_pipe_struct | |||
2777 | { | |||
2778 | ___device_stream base; | |||
2779 | ||||
2780 | #ifdef USE_POSIX | |||
2781 | int fd_wr; /* file descriptor for "write" pipe (-1 if none) */ | |||
2782 | int fd_rd; /* file descriptor for "read" pipe (-1 if none) */ | |||
2783 | #endif | |||
2784 | ||||
2785 | #ifdef USE_WIN32 | |||
2786 | HANDLE h_wr; /* handle for "write" pipe (NULL if none) */ | |||
2787 | HANDLE h_rd; /* handle for "read" pipe (NULL if none) */ | |||
2788 | int poll_interval_nsecs; /* interval between read attempts */ | |||
2789 | #endif | |||
2790 | } ___device_pipe; | |||
2791 | ||||
2792 | ||||
2793 | typedef struct ___device_pipe_vtbl_struct | |||
2794 | { | |||
2795 | ___device_stream_vtbl base; | |||
2796 | } ___device_pipe_vtbl; | |||
2797 | ||||
2798 | ___HIDDENstatic int ___device_pipe_kind | |||
2799 | ___P((___device *self),(___device *self) | |||
2800 | (self)(___device *self) | |||
2801 | ___device *self;)(___device *self) | |||
2802 | { | |||
2803 | return ___PIPE_DEVICE_KIND(15 +32); | |||
2804 | } | |||
2805 | ||||
2806 | ___SCMOBJlong ___device_pipe_cleanup | |||
2807 | ___P((___device_pipe *dev),(___device_pipe *dev) | |||
2808 | (dev)(___device_pipe *dev) | |||
2809 | ___device_pipe *dev;)(___device_pipe *dev) | |||
2810 | { | |||
2811 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2812 | } | |||
2813 | ||||
2814 | ||||
2815 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_close_raw_virt | |||
2816 | ___P((___device_stream *self,(___device_stream *self, int direction) | |||
2817 | int direction),(___device_stream *self, int direction) | |||
2818 | (self,(___device_stream *self, int direction) | |||
2819 | direction)(___device_stream *self, int direction) | |||
2820 | ___device_stream *self;(___device_stream *self, int direction) | |||
2821 | int direction;)(___device_stream *self, int direction) | |||
2822 | { | |||
2823 | ___device_pipe *d = ___CAST(___device_pipe*,self)((___device_pipe*)(self)); | |||
2824 | int is_not_closed = 0; | |||
2825 | ||||
2826 | if (d->base.base.read_stage != ___STAGE_CLOSED3) | |||
2827 | is_not_closed |= ___DIRECTION_RD1; | |||
2828 | ||||
2829 | if (d->base.base.write_stage != ___STAGE_CLOSED3) | |||
2830 | is_not_closed |= ___DIRECTION_WR2; | |||
2831 | ||||
2832 | if (is_not_closed == 0) | |||
2833 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2834 | ||||
2835 | if (is_not_closed & direction & ___DIRECTION_RD1) | |||
2836 | { | |||
2837 | /* Close "read" pipe */ | |||
2838 | ||||
2839 | d->base.base.read_stage = ___STAGE_CLOSED3; | |||
2840 | ||||
2841 | if ((d->base.base.close_direction & ___DIRECTION_RD1) | |||
2842 | == ___DIRECTION_RD1) | |||
2843 | { | |||
2844 | #ifdef USE_POSIX | |||
2845 | if (d->fd_rd >= 0 && | |||
2846 | d->fd_rd != d->fd_wr && | |||
2847 | close_no_EINTR (d->fd_rd) < 0) | |||
2848 | return err_code_from_errno ()___err_code_from_errno(); | |||
2849 | #endif | |||
2850 | ||||
2851 | #ifdef USE_WIN32 | |||
2852 | if (d->h_rd != NULL((void*)0) && | |||
2853 | d->h_rd != d->h_wr) | |||
2854 | CloseHandle (d->h_rd); /* ignore error */ | |||
2855 | #endif | |||
2856 | } | |||
2857 | } | |||
2858 | ||||
2859 | if (is_not_closed & direction & ___DIRECTION_WR2) | |||
2860 | { | |||
2861 | /* Close "write" pipe */ | |||
2862 | ||||
2863 | d->base.base.write_stage = ___STAGE_CLOSED3; | |||
2864 | ||||
2865 | if ((d->base.base.close_direction & ___DIRECTION_WR2) | |||
2866 | == ___DIRECTION_WR2) | |||
2867 | { | |||
2868 | #ifdef USE_POSIX | |||
2869 | if (d->fd_wr >= 0 && | |||
2870 | close_no_EINTR (d->fd_wr) < 0) | |||
2871 | return err_code_from_errno ()___err_code_from_errno(); | |||
2872 | #endif | |||
2873 | ||||
2874 | #ifdef USE_WIN32 | |||
2875 | if (d->h_wr != NULL((void*)0)) | |||
2876 | CloseHandle (d->h_wr); /* ignore error */ | |||
2877 | #endif | |||
2878 | } | |||
2879 | } | |||
2880 | ||||
2881 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2882 | } | |||
2883 | ||||
2884 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_select_raw_virt | |||
2885 | ___P((___device_stream *self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2886 | ___BOOL for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2887 | int i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2888 | int pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2889 | ___device_select_state *state),(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2890 | (self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2891 | for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2892 | i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2893 | pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2894 | state)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2895 | ___device_stream *self;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2896 | ___BOOL for_writing;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2897 | int i;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2898 | int pass;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2899 | ___device_select_state *state;)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
2900 | { | |||
2901 | ___device_pipe *d = ___CAST(___device_pipe*,self)((___device_pipe*)(self)); | |||
2902 | int stage = (for_writing | |||
2903 | ? d->base.base.write_stage | |||
2904 | : d->base.base.read_stage); | |||
2905 | ||||
2906 | if (pass == ___SELECT_PASS_11) | |||
2907 | { | |||
2908 | if (stage != ___STAGE_OPEN0) | |||
2909 | state->timeout = ___time_mod.time_neg_infinity; | |||
2910 | else | |||
2911 | { | |||
2912 | #ifdef USE_POSIX | |||
2913 | if (for_writing) | |||
2914 | { | |||
2915 | if (d->fd_wr >= 0) | |||
2916 | ___device_select_add_fd (state, d->fd_wr, 1); | |||
2917 | } | |||
2918 | else | |||
2919 | { | |||
2920 | if (d->fd_rd >= 0) | |||
2921 | ___device_select_add_fd (state, d->fd_rd, 0); | |||
2922 | } | |||
2923 | #endif | |||
2924 | ||||
2925 | #ifdef USE_WIN32 | |||
2926 | if (for_writing) | |||
2927 | { | |||
2928 | if (d->h_wr != NULL((void*)0)) | |||
2929 | ___device_select_add_wait_obj (state, i, d->h_wr); | |||
2930 | } | |||
2931 | else | |||
2932 | { | |||
2933 | if (d->h_rd != NULL((void*)0)) | |||
2934 | { | |||
2935 | int interval = d->poll_interval_nsecs * 6 / 5; | |||
2936 | if (interval < 1000000) | |||
2937 | interval = 1000000; /* min interval = 0.001 secs */ | |||
2938 | else if (interval > 200000000) | |||
2939 | interval = 200000000; /* max interval = 0.2 sec */ | |||
2940 | d->poll_interval_nsecs = interval; | |||
2941 | ___device_select_add_relative_timeout (state, i, interval * 1e-9); | |||
2942 | } | |||
2943 | } | |||
2944 | #endif | |||
2945 | } | |||
2946 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
2947 | } | |||
2948 | ||||
2949 | /* pass == ___SELECT_PASS_CHECK */ | |||
2950 | ||||
2951 | if (stage != ___STAGE_OPEN0) | |||
2952 | state->devs[i] = NULL((void*)0); | |||
2953 | else | |||
2954 | { | |||
2955 | #ifdef USE_POSIX | |||
2956 | ||||
2957 | if (for_writing) | |||
2958 | { | |||
2959 | if (d->fd_wr < 0 || ___FD_ISSET(d->fd_wr, &state->writefds)((((&state->writefds)->__fds_bits)[((d->fd_wr) / (8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) 1 << ((d->fd_wr) % (8 * (int) sizeof (__fd_mask))))) != 0)) | |||
2960 | state->devs[i] = NULL((void*)0); | |||
2961 | } | |||
2962 | else | |||
2963 | { | |||
2964 | if (d->fd_rd < 0 || ___FD_ISSET(d->fd_rd, &state->readfds)((((&state->readfds)->__fds_bits)[((d->fd_rd) / ( 8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) 1 << ((d->fd_rd) % (8 * (int) sizeof (__fd_mask))))) != 0)) | |||
2965 | state->devs[i] = NULL((void*)0); | |||
2966 | } | |||
2967 | ||||
2968 | #endif | |||
2969 | ||||
2970 | #ifdef USE_WIN32 | |||
2971 | ||||
2972 | if (for_writing) | |||
2973 | { | |||
2974 | if (d->h_wr != NULL((void*)0) && state->devs_next[i] != -1) | |||
2975 | state->devs[i] = NULL((void*)0); | |||
2976 | } | |||
2977 | else | |||
2978 | { | |||
2979 | if (d->h_rd != NULL((void*)0)) | |||
2980 | state->devs[i] = NULL((void*)0); | |||
2981 | } | |||
2982 | ||||
2983 | #endif | |||
2984 | } | |||
2985 | ||||
2986 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2987 | } | |||
2988 | ||||
2989 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_release_raw_virt | |||
2990 | ___P((___device_stream *self),(___device_stream *self) | |||
2991 | (self)(___device_stream *self) | |||
2992 | ___device_stream *self;)(___device_stream *self) | |||
2993 | { | |||
2994 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
2995 | } | |||
2996 | ||||
2997 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_force_output_raw_virt | |||
2998 | ___P((___device_stream *self,(___device_stream *self, int level) | |||
2999 | int level),(___device_stream *self, int level) | |||
3000 | (self,(___device_stream *self, int level) | |||
3001 | level)(___device_stream *self, int level) | |||
3002 | ___device_stream *self;(___device_stream *self, int level) | |||
3003 | int level;)(___device_stream *self, int level) | |||
3004 | { | |||
3005 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3006 | } | |||
3007 | ||||
3008 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_seek_raw_virt | |||
3009 | ___P((___device_stream *self,(___device_stream *self, ___stream_index *pos, int whence) | |||
3010 | ___stream_index *pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
3011 | int whence),(___device_stream *self, ___stream_index *pos, int whence) | |||
3012 | (self,(___device_stream *self, ___stream_index *pos, int whence) | |||
3013 | pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
3014 | whence)(___device_stream *self, ___stream_index *pos, int whence) | |||
3015 | ___device_stream *self;(___device_stream *self, ___stream_index *pos, int whence) | |||
3016 | ___stream_index *pos;(___device_stream *self, ___stream_index *pos, int whence) | |||
3017 | int whence;)(___device_stream *self, ___stream_index *pos, int whence) | |||
3018 | { | |||
3019 | return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+7)))<<2); | |||
3020 | } | |||
3021 | ||||
3022 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_read_raw_virt | |||
3023 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3024 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3025 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3026 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3027 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3028 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3029 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3030 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3031 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3032 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3033 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3034 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3035 | { | |||
3036 | ___device_pipe *d = ___CAST(___device_pipe*,self)((___device_pipe*)(self)); | |||
3037 | ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3038 | ||||
3039 | if (d->base.base.read_stage != ___STAGE_OPEN0) | |||
3040 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
3041 | ||||
3042 | #ifdef USE_POSIX | |||
3043 | ||||
3044 | if (d->fd_rd < 0) | |||
3045 | *len_done = 0; | |||
3046 | else | |||
3047 | { | |||
3048 | int n = 0; | |||
3049 | ||||
3050 | if ((n = read (d->fd_rd, buf, len)) < 0) | |||
3051 | { | |||
3052 | #if 0 | |||
3053 | if (errno(*__errno_location ()) == EIO5) errno(*__errno_location ()) = EAGAIN11; | |||
3054 | #else | |||
3055 | if (errno(*__errno_location ()) == EIO5) /* on linux, treating EIO as EAGAIN gives an infinite loop */ | |||
3056 | n = 0; | |||
3057 | else | |||
3058 | #endif | |||
3059 | e = err_code_from_errno ()___err_code_from_errno(); | |||
3060 | } | |||
3061 | ||||
3062 | *len_done = n; | |||
3063 | } | |||
3064 | ||||
3065 | #endif | |||
3066 | ||||
3067 | #ifdef USE_WIN32 | |||
3068 | ||||
3069 | if (d->h_rd == NULL((void*)0)) | |||
3070 | *len_done = 0; | |||
3071 | else | |||
3072 | { | |||
3073 | DWORD n = 0; | |||
3074 | ||||
3075 | if (!PeekNamedPipe (d->h_rd, NULL((void*)0), 0, NULL((void*)0), &n, NULL((void*)0))) | |||
3076 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
3077 | else if (n == 0) | |||
3078 | e = ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
3079 | else | |||
3080 | { | |||
3081 | if (len > n) | |||
3082 | len = n; | |||
3083 | ||||
3084 | if (!ReadFile (d->h_rd, buf, len, &n, NULL((void*)0))) | |||
3085 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
3086 | else | |||
3087 | d->poll_interval_nsecs = 0; | |||
3088 | } | |||
3089 | ||||
3090 | if (e == ___FIX(___WIN32_ERR(ERROR_BROKEN_PIPE))(((long)((((HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE))&~(~((int )(0))<<25)) | (((HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE)) &~((int)(0))<<27)>>2))))<<2)) | |||
3091 | e = ___FIX(___NO_ERR)(((long)(0))<<2); /* generate end-of-file on broken pipe */ | |||
3092 | ||||
3093 | *len_done = n; | |||
3094 | } | |||
3095 | ||||
3096 | #endif | |||
3097 | ||||
3098 | return e; | |||
3099 | } | |||
3100 | ||||
3101 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_write_raw_virt | |||
3102 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3103 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3104 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3105 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3106 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3107 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3108 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3109 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3110 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3111 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3112 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3113 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3114 | { | |||
3115 | ___device_pipe *d = ___CAST(___device_pipe*,self)((___device_pipe*)(self)); | |||
3116 | ||||
3117 | if (d->base.base.write_stage != ___STAGE_OPEN0) | |||
3118 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
3119 | ||||
3120 | #ifdef USE_POSIX | |||
3121 | ||||
3122 | if (d->fd_wr < 0) | |||
3123 | *len_done = len; | |||
3124 | else | |||
3125 | { | |||
3126 | int n; | |||
3127 | ||||
3128 | if ((n = write (d->fd_wr, buf, len)) < 0) | |||
3129 | return err_code_from_errno ()___err_code_from_errno(); | |||
3130 | ||||
3131 | *len_done = n; | |||
3132 | } | |||
3133 | ||||
3134 | #endif | |||
3135 | ||||
3136 | #ifdef USE_WIN32 | |||
3137 | ||||
3138 | if (d->h_wr == NULL((void*)0)) | |||
3139 | *len_done = len; | |||
3140 | else | |||
3141 | { | |||
3142 | DWORD n; | |||
3143 | ||||
3144 | if (!WriteFile (d->h_wr, buf, len, &n, NULL((void*)0))) | |||
3145 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
3146 | ||||
3147 | *len_done = n; | |||
3148 | } | |||
3149 | ||||
3150 | #endif | |||
3151 | ||||
3152 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3153 | } | |||
3154 | ||||
3155 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_width_virt | |||
3156 | ___P((___device_stream *self),(___device_stream *self) | |||
3157 | (self)(___device_stream *self) | |||
3158 | ___device_stream *self;)(___device_stream *self) | |||
3159 | { | |||
3160 | return ___FIX(80)(((long)(80))<<2); | |||
3161 | } | |||
3162 | ||||
3163 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_default_options_virt | |||
3164 | ___P((___device_stream *self),(___device_stream *self) | |||
3165 | (self)(___device_stream *self) | |||
3166 | ___device_stream *self;)(___device_stream *self) | |||
3167 | { | |||
3168 | int char_encoding_errors = ___CHAR_ENCODING_ERRORS_ON(1<<5); | |||
3169 | int char_encoding = ___CHAR_ENCODING_ISO_8859_1(2<<0); | |||
3170 | int eol_encoding = ___EOL_ENCODING_LF(1<<7); | |||
3171 | int buffering = ___FULL_BUFFERING(3<<9); | |||
3172 | ||||
3173 | return ___FIX(___STREAM_OPTIONS(char_encoding_errors,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
3174 | char_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
3175 | eol_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
3176 | buffering,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
3177 | char_encoding_errors,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
3178 | char_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
3179 | eol_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
3180 | buffering))(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2); | |||
3181 | } | |||
3182 | ||||
3183 | ||||
3184 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_options_set_virt | |||
3185 | ___P((___device_stream *self,(___device_stream *self, long options) | |||
3186 | ___SCMOBJ options),(___device_stream *self, long options) | |||
3187 | (self,(___device_stream *self, long options) | |||
3188 | options)(___device_stream *self, long options) | |||
3189 | ___device_stream *self;(___device_stream *self, long options) | |||
3190 | ___SCMOBJ options;)(___device_stream *self, long options) | |||
3191 | { | |||
3192 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3193 | } | |||
3194 | ||||
3195 | ||||
3196 | ___HIDDENstatic ___device_pipe_vtbl ___device_pipe_table = | |||
3197 | { | |||
3198 | { | |||
3199 | { | |||
3200 | ___device_pipe_kind, | |||
3201 | ___device_stream_select_virt, | |||
3202 | ___device_stream_release_virt, | |||
3203 | ___device_stream_force_output_virt, | |||
3204 | ___device_stream_close_virt | |||
3205 | }, | |||
3206 | ___device_pipe_select_raw_virt, | |||
3207 | ___device_pipe_release_raw_virt, | |||
3208 | ___device_pipe_force_output_raw_virt, | |||
3209 | ___device_pipe_close_raw_virt, | |||
3210 | ___device_pipe_seek_raw_virt, | |||
3211 | ___device_pipe_read_raw_virt, | |||
3212 | ___device_pipe_write_raw_virt, | |||
3213 | ___device_pipe_width_virt, | |||
3214 | ___device_pipe_default_options_virt, | |||
3215 | ___device_pipe_options_set_virt | |||
3216 | } | |||
3217 | }; | |||
3218 | ||||
3219 | ||||
3220 | #ifdef USE_POSIX | |||
3221 | ||||
3222 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_setup_from_fd | |||
3223 | ___P((___device_pipe **dev,(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3224 | ___device_group *dgroup,(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3225 | int fd_rd,(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3226 | int fd_wr,(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3227 | int direction),(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3228 | (dev,(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3229 | dgroup,(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3230 | fd_rd,(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3231 | fd_wr,(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3232 | direction)(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3233 | ___device_pipe **dev;(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3234 | ___device_group *dgroup;(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3235 | int fd_rd;(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3236 | int fd_wr;(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3237 | int direction;)(___device_pipe **dev, ___device_group *dgroup, int fd_rd, int fd_wr, int direction) | |||
3238 | { | |||
3239 | ___device_pipe *d; | |||
3240 | ||||
3241 | d = ___CAST(___device_pipe*,((___device_pipe*)(___alloc_mem (sizeof (___device_pipe)))) | |||
3242 | ___alloc_mem (sizeof (___device_pipe)))((___device_pipe*)(___alloc_mem (sizeof (___device_pipe)))); | |||
3243 | ||||
3244 | if (d == NULL((void*)0)) | |||
3245 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
3246 | ||||
3247 | d->base.base.vtbl = &___device_pipe_table; | |||
3248 | d->fd_rd = fd_rd; | |||
3249 | d->fd_wr = fd_wr; | |||
3250 | ||||
3251 | *dev = d; | |||
3252 | ||||
3253 | return ___device_stream_setup | |||
3254 | (&d->base, | |||
3255 | dgroup, | |||
3256 | direction, | |||
3257 | 0); | |||
3258 | } | |||
3259 | ||||
3260 | #endif | |||
3261 | ||||
3262 | ||||
3263 | #ifdef USE_WIN32 | |||
3264 | ||||
3265 | ___HIDDENstatic ___SCMOBJlong ___device_pipe_setup_from_handle | |||
3266 | ___P((___device_pipe **dev,(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3267 | ___device_group *dgroup,(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3268 | HANDLE h_rd,(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3269 | HANDLE h_wr,(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3270 | int direction,(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3271 | int pumps_on),(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3272 | (dev,(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3273 | dgroup,(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3274 | h_rd,(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3275 | h_wr,(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3276 | direction,(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3277 | pumps_on)(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3278 | ___device_pipe **dev;(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3279 | ___device_group *dgroup;(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3280 | HANDLE h_rd;(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3281 | HANDLE h_wr;(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3282 | int direction;(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3283 | int pumps_on;)(___device_pipe **dev, ___device_group *dgroup, HANDLE h_rd, HANDLE h_wr, int direction, int pumps_on) | |||
3284 | { | |||
3285 | ___device_pipe *d; | |||
3286 | ||||
3287 | d = ___CAST(___device_pipe*,((___device_pipe*)(___alloc_mem (sizeof (___device_pipe)))) | |||
3288 | ___alloc_mem (sizeof (___device_pipe)))((___device_pipe*)(___alloc_mem (sizeof (___device_pipe)))); | |||
3289 | ||||
3290 | if (d == NULL((void*)0)) | |||
3291 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
3292 | ||||
3293 | d->base.base.vtbl = &___device_pipe_table; | |||
3294 | d->h_rd = h_rd; | |||
3295 | d->h_wr = h_wr; | |||
3296 | d->poll_interval_nsecs = 0; | |||
3297 | ||||
3298 | *dev = d; | |||
3299 | ||||
3300 | return ___device_stream_setup | |||
3301 | (&d->base, | |||
3302 | dgroup, | |||
3303 | direction, | |||
3304 | pumps_on); | |||
3305 | } | |||
3306 | ||||
3307 | #endif | |||
3308 | ||||
3309 | ||||
3310 | /*---------------------------------------------------------------------------*/ | |||
3311 | ||||
3312 | /* Process stream device */ | |||
3313 | ||||
3314 | typedef struct ___device_process_struct | |||
3315 | { | |||
3316 | ___device_pipe base; | |||
3317 | ||||
3318 | #ifdef USE_POSIX | |||
3319 | pid_t pid; /* pid of the process */ | |||
3320 | #endif | |||
3321 | ||||
3322 | #ifdef USE_WIN32 | |||
3323 | PROCESS_INFORMATION pi; /* process information */ | |||
3324 | #endif | |||
3325 | ||||
3326 | int status; /* process status */ | |||
3327 | ___BOOLint got_status; /* was the status retrieved? */ | |||
3328 | ___BOOLint cleanuped; /* has process been cleaned-up? */ | |||
3329 | } ___device_process; | |||
3330 | ||||
3331 | typedef struct ___device_process_vtbl_struct | |||
3332 | { | |||
3333 | ___device_stream_vtbl base; | |||
3334 | } ___device_process_vtbl; | |||
3335 | ||||
3336 | ___HIDDENstatic int ___device_process_kind | |||
3337 | ___P((___device *self),(___device *self) | |||
3338 | (self)(___device *self) | |||
3339 | ___device *self;)(___device *self) | |||
3340 | { | |||
3341 | return ___PROCESS_DEVICE_KIND((15 +32)+65536); | |||
3342 | } | |||
3343 | ||||
3344 | ___SCMOBJlong ___device_process_cleanup | |||
3345 | ___P((___device_process *dev),(___device_process *dev) | |||
3346 | (dev)(___device_process *dev) | |||
3347 | ___device_process *dev;)(___device_process *dev) | |||
3348 | { | |||
3349 | if (!dev->cleanuped) | |||
3350 | { | |||
3351 | dev->cleanuped = 1; | |||
3352 | ||||
3353 | #ifdef USE_POSIX | |||
3354 | #endif | |||
3355 | ||||
3356 | #ifdef USE_WIN32 | |||
3357 | ||||
3358 | CloseHandle (dev->pi.hProcess); /* ignore error */ | |||
3359 | CloseHandle (dev->pi.hThread); /* ignore error */ | |||
3360 | ||||
3361 | #endif | |||
3362 | } | |||
3363 | ||||
3364 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3365 | } | |||
3366 | ||||
3367 | ||||
3368 | ___SCMOBJlong ___device_process_status_set | |||
3369 | ___P((___device_process *dev,(___device_process *dev, int status) | |||
3370 | int status),(___device_process *dev, int status) | |||
3371 | (dev,(___device_process *dev, int status) | |||
3372 | status)(___device_process *dev, int status) | |||
3373 | ___device_process *dev;(___device_process *dev, int status) | |||
3374 | int status;)(___device_process *dev, int status) | |||
3375 | { | |||
3376 | ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3377 | ||||
3378 | if (!dev->got_status) | |||
3379 | { | |||
3380 | dev->status = status; | |||
3381 | dev->got_status = 1; | |||
3382 | e = ___device_process_cleanup (dev); /* ignore error */ | |||
3383 | } | |||
3384 | ||||
3385 | return e; | |||
3386 | } | |||
3387 | ||||
3388 | ||||
3389 | ___SCMOBJlong ___device_process_status_poll | |||
3390 | ___P((___device_process *dev),(___device_process *dev) | |||
3391 | (dev)(___device_process *dev) | |||
3392 | ___device_process *dev;)(___device_process *dev) | |||
3393 | { | |||
3394 | if (!dev->got_status) | |||
3395 | { | |||
3396 | #ifdef USE_POSIX | |||
3397 | ||||
3398 | /* | |||
3399 | * The process status is updated asynchronously by | |||
3400 | * sigchld_signal_handler. | |||
3401 | */ | |||
3402 | ||||
3403 | #endif | |||
3404 | ||||
3405 | #ifdef USE_WIN32 | |||
3406 | ||||
3407 | DWORD status; | |||
3408 | ||||
3409 | if (!GetExitCodeProcess (dev->pi.hProcess, &status)) | |||
3410 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
3411 | ||||
3412 | if (status != STILL_ACTIVE) | |||
3413 | ___device_process_status_set (dev, status << 8); /* ignore error */ | |||
3414 | ||||
3415 | #endif | |||
3416 | } | |||
3417 | ||||
3418 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3419 | } | |||
3420 | ||||
3421 | ___HIDDENstatic ___SCMOBJlong ___device_process_close_raw_virt | |||
3422 | ___P((___device_stream *self,(___device_stream *self, int direction) | |||
3423 | int direction),(___device_stream *self, int direction) | |||
3424 | (self,(___device_stream *self, int direction) | |||
3425 | direction)(___device_stream *self, int direction) | |||
3426 | ___device_stream *self;(___device_stream *self, int direction) | |||
3427 | int direction;)(___device_stream *self, int direction) | |||
3428 | { | |||
3429 | ___device_process *d = ___CAST(___device_process*,self)((___device_process*)(self)); | |||
3430 | ___SCMOBJlong e = ___device_pipe_close_raw_virt (self, direction); | |||
3431 | ||||
3432 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
3433 | { | |||
3434 | if (d->base.base.base.read_stage == ___STAGE_CLOSED3 && | |||
3435 | d->base.base.base.write_stage == ___STAGE_CLOSED3) | |||
3436 | ___device_process_status_poll (d); /* ignore error */ | |||
3437 | } | |||
3438 | ||||
3439 | return e; | |||
3440 | } | |||
3441 | ||||
3442 | ___HIDDENstatic ___SCMOBJlong ___device_process_select_raw_virt | |||
3443 | ___P((___device_stream *self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3444 | ___BOOL for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3445 | int i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3446 | int pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3447 | ___device_select_state *state),(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3448 | (self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3449 | for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3450 | i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3451 | pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3452 | state)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3453 | ___device_stream *self;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3454 | ___BOOL for_writing;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3455 | int i;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3456 | int pass;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3457 | ___device_select_state *state;)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3458 | { | |||
3459 | return ___device_pipe_select_raw_virt (self, for_writing, i, pass, state); | |||
3460 | } | |||
3461 | ||||
3462 | ___HIDDENstatic ___SCMOBJlong ___device_process_release_raw_virt | |||
3463 | ___P((___device_stream *self),(___device_stream *self) | |||
3464 | (self)(___device_stream *self) | |||
3465 | ___device_stream *self;)(___device_stream *self) | |||
3466 | { | |||
3467 | ___device_process *d = ___CAST(___device_process*,self)((___device_process*)(self)); | |||
3468 | ___SCMOBJlong e1 = ___device_pipe_release_raw_virt (self); | |||
3469 | ___SCMOBJlong e2 = ___device_process_cleanup (d); | |||
3470 | if (e1 == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
3471 | e1 = e2; | |||
3472 | return e1; | |||
3473 | } | |||
3474 | ||||
3475 | ___HIDDENstatic ___SCMOBJlong ___device_process_force_output_raw_virt | |||
3476 | ___P((___device_stream *self,(___device_stream *self, int level) | |||
3477 | int level),(___device_stream *self, int level) | |||
3478 | (self,(___device_stream *self, int level) | |||
3479 | level)(___device_stream *self, int level) | |||
3480 | ___device_stream *self;(___device_stream *self, int level) | |||
3481 | int level;)(___device_stream *self, int level) | |||
3482 | { | |||
3483 | return ___device_pipe_force_output_raw_virt (self, level); | |||
3484 | } | |||
3485 | ||||
3486 | ___HIDDENstatic ___SCMOBJlong ___device_process_seek_raw_virt | |||
3487 | ___P((___device_stream *self,(___device_stream *self, ___stream_index *pos, int whence) | |||
3488 | ___stream_index *pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
3489 | int whence),(___device_stream *self, ___stream_index *pos, int whence) | |||
3490 | (self,(___device_stream *self, ___stream_index *pos, int whence) | |||
3491 | pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
3492 | whence)(___device_stream *self, ___stream_index *pos, int whence) | |||
3493 | ___device_stream *self;(___device_stream *self, ___stream_index *pos, int whence) | |||
3494 | ___stream_index *pos;(___device_stream *self, ___stream_index *pos, int whence) | |||
3495 | int whence;)(___device_stream *self, ___stream_index *pos, int whence) | |||
3496 | { | |||
3497 | return ___device_pipe_seek_raw_virt (self, pos, whence); | |||
3498 | } | |||
3499 | ||||
3500 | ___HIDDENstatic ___SCMOBJlong ___device_process_read_raw_virt | |||
3501 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3502 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3503 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3504 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3505 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3506 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3507 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3508 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3509 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3510 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3511 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3512 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3513 | { | |||
3514 | return ___device_pipe_read_raw_virt (self, buf, len, len_done); | |||
3515 | } | |||
3516 | ||||
3517 | ___HIDDENstatic ___SCMOBJlong ___device_process_write_raw_virt | |||
3518 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3519 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3520 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3521 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3522 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3523 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3524 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3525 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3526 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3527 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3528 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3529 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
3530 | { | |||
3531 | return ___device_pipe_write_raw_virt (self, buf, len, len_done); | |||
3532 | } | |||
3533 | ||||
3534 | ___HIDDENstatic ___SCMOBJlong ___device_process_width_virt | |||
3535 | ___P((___device_stream *self),(___device_stream *self) | |||
3536 | (self)(___device_stream *self) | |||
3537 | ___device_stream *self;)(___device_stream *self) | |||
3538 | { | |||
3539 | return ___FIX(80)(((long)(80))<<2); | |||
3540 | } | |||
3541 | ||||
3542 | ___HIDDENstatic ___SCMOBJlong ___device_process_default_options_virt | |||
3543 | ___P((___device_stream *self),(___device_stream *self) | |||
3544 | (self)(___device_stream *self) | |||
3545 | ___device_stream *self;)(___device_stream *self) | |||
3546 | { | |||
3547 | return ___device_pipe_default_options_virt (self); | |||
3548 | } | |||
3549 | ||||
3550 | ||||
3551 | ___HIDDENstatic ___SCMOBJlong ___device_process_options_set_virt | |||
3552 | ___P((___device_stream *self,(___device_stream *self, long options) | |||
3553 | ___SCMOBJ options),(___device_stream *self, long options) | |||
3554 | (self,(___device_stream *self, long options) | |||
3555 | options)(___device_stream *self, long options) | |||
3556 | ___device_stream *self;(___device_stream *self, long options) | |||
3557 | ___SCMOBJ options;)(___device_stream *self, long options) | |||
3558 | { | |||
3559 | return ___device_pipe_options_set_virt (self, options); | |||
3560 | } | |||
3561 | ||||
3562 | ||||
3563 | ___HIDDENstatic ___device_process_vtbl ___device_process_table = | |||
3564 | { | |||
3565 | { | |||
3566 | { | |||
3567 | ___device_process_kind, | |||
3568 | ___device_stream_select_virt, | |||
3569 | ___device_stream_release_virt, | |||
3570 | ___device_stream_force_output_virt, | |||
3571 | ___device_stream_close_virt | |||
3572 | }, | |||
3573 | ___device_process_select_raw_virt, | |||
3574 | ___device_process_release_raw_virt, | |||
3575 | ___device_process_force_output_raw_virt, | |||
3576 | ___device_process_close_raw_virt, | |||
3577 | ___device_process_seek_raw_virt, | |||
3578 | ___device_process_read_raw_virt, | |||
3579 | ___device_process_write_raw_virt, | |||
3580 | ___device_process_width_virt, | |||
3581 | ___device_process_default_options_virt, | |||
3582 | ___device_process_options_set_virt | |||
3583 | } | |||
3584 | }; | |||
3585 | ||||
3586 | #ifdef USE_POSIX | |||
3587 | ||||
3588 | ___SCMOBJlong ___device_process_setup_from_pid | |||
3589 | ___P((___device_process **dev,(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3590 | ___device_group *dgroup,(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3591 | pid_t pid,(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3592 | int fd_stdin,(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3593 | int fd_stdout,(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3594 | int direction),(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3595 | (dev,(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3596 | dgroup,(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3597 | pid,(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3598 | fd_stdin,(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3599 | fd_stdout,(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3600 | direction)(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3601 | ___device_process **dev;(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3602 | ___device_group *dgroup;(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3603 | pid_t pid;(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3604 | int fd_stdin;(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3605 | int fd_stdout;(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3606 | int direction;)(___device_process **dev, ___device_group *dgroup, pid_t pid, int fd_stdin, int fd_stdout, int direction) | |||
3607 | { | |||
3608 | ___device_process *d; | |||
3609 | ||||
3610 | d = ___CAST(___device_process*,((___device_process*)(___alloc_mem (sizeof (___device_process )))) | |||
3611 | ___alloc_mem (sizeof (___device_process)))((___device_process*)(___alloc_mem (sizeof (___device_process )))); | |||
3612 | ||||
3613 | if (d == NULL((void*)0)) | |||
3614 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
3615 | ||||
3616 | /* | |||
3617 | * Setup file descriptors to perform nonblocking I/O. | |||
3618 | */ | |||
3619 | ||||
3620 | if ((fd_stdout >= 0 && | |||
3621 | (direction & ___DIRECTION_RD1) && | |||
3622 | (set_fd_blocking_mode (fd_stdout, 0) < 0)) || | |||
3623 | (fd_stdin >= 0 && | |||
3624 | (direction & ___DIRECTION_WR2) && | |||
3625 | (set_fd_blocking_mode (fd_stdin, 0) < 0))) | |||
3626 | { | |||
3627 | ___SCMOBJlong e = err_code_from_errno ()___err_code_from_errno(); | |||
3628 | ___free_mem (d); | |||
3629 | return e; | |||
3630 | } | |||
3631 | ||||
3632 | d->base.base.base.vtbl = &___device_process_table; | |||
3633 | d->base.fd_rd = fd_stdout; | |||
3634 | d->base.fd_wr = fd_stdin; | |||
3635 | d->pid = pid; | |||
3636 | d->status = -1; | |||
3637 | d->got_status = 0; | |||
3638 | d->cleanuped = 0; | |||
3639 | ||||
3640 | *dev = d; | |||
3641 | ||||
3642 | return ___device_stream_setup | |||
3643 | (&d->base.base, | |||
3644 | dgroup, | |||
3645 | direction, | |||
3646 | 0); | |||
3647 | } | |||
3648 | ||||
3649 | #endif | |||
3650 | ||||
3651 | #ifdef USE_WIN32 | |||
3652 | ||||
3653 | ___SCMOBJlong ___device_process_setup_from_process | |||
3654 | ___P((___device_process **dev,(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3655 | ___device_group *dgroup,(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3656 | PROCESS_INFORMATION pi,(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3657 | HANDLE hstdin,(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3658 | HANDLE hstdout,(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3659 | int direction),(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3660 | (dev,(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3661 | dgroup,(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3662 | pi,(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3663 | hstdin,(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3664 | hstdout,(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3665 | direction)(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3666 | ___device_process **dev;(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3667 | ___device_group *dgroup;(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3668 | PROCESS_INFORMATION pi;(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3669 | HANDLE hstdin;(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3670 | HANDLE hstdout;(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3671 | int direction;)(___device_process **dev, ___device_group *dgroup, PROCESS_INFORMATION pi, HANDLE hstdin, HANDLE hstdout, int direction) | |||
3672 | { | |||
3673 | ___device_process *d; | |||
3674 | ||||
3675 | d = ___CAST(___device_process*,((___device_process*)(___alloc_mem (sizeof (___device_process )))) | |||
3676 | ___alloc_mem (sizeof (___device_process)))((___device_process*)(___alloc_mem (sizeof (___device_process )))); | |||
3677 | ||||
3678 | if (d == NULL((void*)0)) | |||
3679 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
3680 | ||||
3681 | d->base.base.base.vtbl = &___device_process_table; | |||
3682 | d->base.h_rd = hstdout; | |||
3683 | d->base.h_wr = hstdin; | |||
3684 | d->pi = pi; | |||
3685 | d->status = -1; | |||
3686 | d->got_status = 0; | |||
3687 | d->cleanuped = 0; | |||
3688 | ||||
3689 | *dev = d; | |||
3690 | ||||
3691 | return ___device_stream_setup | |||
3692 | (&d->base.base, | |||
3693 | dgroup, | |||
3694 | direction, | |||
3695 | 0); | |||
3696 | } | |||
3697 | ||||
3698 | #endif | |||
3699 | ||||
3700 | ||||
3701 | /*---------------------------------------------------------------------------*/ | |||
3702 | ||||
3703 | #ifdef USE_NETWORKING | |||
3704 | ||||
3705 | /* Socket utilities */ | |||
3706 | ||||
3707 | #ifdef USE_POSIX | |||
3708 | #define SOCKET_TYPEint int | |||
3709 | #define SOCKET_CALL_ERROR(s)((s) < 0) ((s) < 0) | |||
3710 | #define SOCKET_CALL_ERROR2(s)((s) < 0) ((s) < 0) | |||
3711 | #define CONNECT_IN_PROGRESS((*__errno_location ()) == 115) (errno(*__errno_location ()) == EINPROGRESS115) | |||
3712 | #define CONNECT_WOULD_BLOCK((*__errno_location ()) == 11) (errno(*__errno_location ()) == EAGAIN11) | |||
3713 | #define NOT_CONNECTED(e)((e) == (((long)(((107)==0?0:((((int)(-1))<<29)+(((int) (320))<<16)+(107)))))<<2)) ((e) == ___FIX(___ERRNO_ERR(ENOTCONN))(((long)(((107)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(107)))))<<2)) | |||
3714 | #define CLOSE_SOCKET(s)close_no_EINTR (s) close_no_EINTR (s) | |||
3715 | #define ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno() err_code_from_errno ()___err_code_from_errno() | |||
3716 | #define IOCTL_SOCKET(s,cmd,argp)ioctl (s,cmd,argp) ioctl (s,cmd,argp) | |||
3717 | #define SOCKET_LEN_TYPEsocklen_t socklen_t | |||
3718 | #endif | |||
3719 | ||||
3720 | #ifdef USE_WIN32 | |||
3721 | #define SOCKET_TYPEint SOCKET | |||
3722 | #define SOCKET_CALL_ERROR(s)((s) < 0) ((s) == SOCKET_ERROR) | |||
3723 | #define SOCKET_CALL_ERROR2(s)((s) < 0) ((s) == INVALID_SOCKET) | |||
3724 | #define CONNECT_IN_PROGRESS((*__errno_location ()) == 115) ((WSAGetLastError () == WSAEALREADY) || \ | |||
3725 | (WSAGetLastError () == WSAEISCONN)) | |||
3726 | #define CONNECT_WOULD_BLOCK((*__errno_location ()) == 11) ((WSAGetLastError () == WSAEWOULDBLOCK) || \ | |||
3727 | (WSAGetLastError () == WSAEINVAL)) | |||
3728 | #define NOT_CONNECTED(e)((e) == (((long)(((107)==0?0:((((int)(-1))<<29)+(((int) (320))<<16)+(107)))))<<2)) ((e) == ___FIX(___WIN32_ERR(WSAENOTCONN))(((long)((((HRESULT_FROM_WIN32(WSAENOTCONN))&~(~((int)(0) )<<25)) | (((HRESULT_FROM_WIN32(WSAENOTCONN))&~((int )(0))<<27)>>2))))<<2)) | |||
3729 | #define CLOSE_SOCKET(s)close_no_EINTR (s) closesocket (s) | |||
3730 | #define ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno() err_code_from_WSAGetLastError ()___err_code_from_WSAGetLastError() | |||
3731 | #define IOCTL_SOCKET(s,cmd,argp)ioctl (s,cmd,argp) ioctlsocket (s,cmd,argp) | |||
3732 | #define SOCKET_LEN_TYPEsocklen_t int | |||
3733 | #endif | |||
3734 | ||||
3735 | #ifdef SHUT_RDSHUT_RD | |||
3736 | #define SHUTDOWN_RDSHUT_RD SHUT_RDSHUT_RD | |||
3737 | #else | |||
3738 | #ifdef SD_RECEIVE | |||
3739 | #define SHUTDOWN_RDSHUT_RD SD_RECEIVE | |||
3740 | #else | |||
3741 | #define SHUTDOWN_RDSHUT_RD 0 | |||
3742 | #endif | |||
3743 | #endif | |||
3744 | ||||
3745 | #ifdef SHUT_WRSHUT_WR | |||
3746 | #define SHUTDOWN_WRSHUT_WR SHUT_WRSHUT_WR | |||
3747 | #else | |||
3748 | #ifdef SD_SEND | |||
3749 | #define SHUTDOWN_WRSHUT_WR SD_SEND | |||
3750 | #else | |||
3751 | #define SHUTDOWN_WRSHUT_WR 1 | |||
3752 | #endif | |||
3753 | #endif | |||
3754 | ||||
3755 | #endif | |||
3756 | ||||
3757 | ||||
3758 | /*---------------------------------------------------------------------------*/ | |||
3759 | ||||
3760 | #ifdef USE_NETWORKING | |||
3761 | ||||
3762 | /* TCP client stream device */ | |||
3763 | ||||
3764 | typedef struct ___device_tcp_client_struct | |||
3765 | { | |||
3766 | ___device_stream base; | |||
3767 | SOCKET_TYPEint s; | |||
3768 | struct sockaddr server_addr; | |||
3769 | SOCKET_LEN_TYPEsocklen_t server_addrlen; | |||
3770 | int try_connect_again; | |||
3771 | int connect_done; | |||
3772 | ||||
3773 | #ifdef USE_POSIX | |||
3774 | ||||
3775 | int try_connect_interval_nsecs; | |||
3776 | ||||
3777 | #endif | |||
3778 | ||||
3779 | #ifdef USE_WIN32 | |||
3780 | ||||
3781 | long io_events; /* used by ___device_tcp_client_select_raw_virt */ | |||
3782 | HANDLE io_event; /* used by ___device_tcp_client_select_raw_virt */ | |||
3783 | ||||
3784 | #endif | |||
3785 | } ___device_tcp_client; | |||
3786 | ||||
3787 | ||||
3788 | typedef struct ___device_tcp_client_vtbl_struct | |||
3789 | { | |||
3790 | ___device_stream_vtbl base; | |||
3791 | } ___device_tcp_client_vtbl; | |||
3792 | ||||
3793 | ||||
3794 | ___HIDDENstatic int try_connect | |||
3795 | ___P((___device_tcp_client *dev),(___device_tcp_client *dev) | |||
3796 | (dev)(___device_tcp_client *dev) | |||
3797 | ___device_tcp_client *dev;)(___device_tcp_client *dev) | |||
3798 | { | |||
3799 | if (!SOCKET_CALL_ERROR(connect (dev->s,((connect (dev->s, &dev->server_addr, dev->server_addrlen )) < 0) | |||
3800 | &dev->server_addr,((connect (dev->s, &dev->server_addr, dev->server_addrlen )) < 0) | |||
3801 | dev->server_addrlen))((connect (dev->s, &dev->server_addr, dev->server_addrlen )) < 0) || | |||
3802 | CONNECT_IN_PROGRESS((*__errno_location ()) == 115) || /* establishing connection in background */ | |||
3803 | dev->try_connect_again == 2) /* last connect attempt? */ | |||
3804 | { | |||
3805 | dev->try_connect_again = 0; /* we're done waiting */ | |||
3806 | return 0; | |||
3807 | } | |||
3808 | ||||
3809 | if (CONNECT_WOULD_BLOCK((*__errno_location ()) == 11)) /* connect can't be performed now */ | |||
3810 | return 0; | |||
3811 | ||||
3812 | return -1; | |||
3813 | } | |||
3814 | ||||
3815 | ___HIDDENstatic int ___device_tcp_client_kind | |||
3816 | ___P((___device *self),(___device *self) | |||
3817 | (self)(___device *self) | |||
3818 | ___device *self;)(___device *self) | |||
3819 | { | |||
3820 | return ___TCP_CLIENT_DEVICE_KIND(15 +256); | |||
3821 | } | |||
3822 | ||||
3823 | ||||
3824 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_client_close_raw_virt | |||
3825 | ___P((___device_stream *self,(___device_stream *self, int direction) | |||
3826 | int direction),(___device_stream *self, int direction) | |||
3827 | (self,(___device_stream *self, int direction) | |||
3828 | direction)(___device_stream *self, int direction) | |||
3829 | ___device_stream *self;(___device_stream *self, int direction) | |||
3830 | int direction;)(___device_stream *self, int direction) | |||
3831 | { | |||
3832 | ___device_tcp_client *d = ___CAST(___device_tcp_client*,self)((___device_tcp_client*)(self)); | |||
3833 | int is_not_closed = 0; | |||
3834 | ||||
3835 | if (d->base.base.read_stage != ___STAGE_CLOSED3) | |||
3836 | is_not_closed |= ___DIRECTION_RD1; | |||
3837 | ||||
3838 | if (d->base.base.write_stage != ___STAGE_CLOSED3) | |||
3839 | is_not_closed |= ___DIRECTION_WR2; | |||
3840 | ||||
3841 | if (is_not_closed == 0) | |||
3842 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3843 | ||||
3844 | if ((is_not_closed & ~direction) == 0) | |||
3845 | { | |||
3846 | /* Close socket when both sides are closed. */ | |||
3847 | ||||
3848 | d->base.base.read_stage = ___STAGE_CLOSED3; /* avoid multiple closes */ | |||
3849 | d->base.base.write_stage = ___STAGE_CLOSED3; | |||
3850 | ||||
3851 | #ifdef USE_WIN32 | |||
3852 | ||||
3853 | if (d->io_event != NULL((void*)0)) | |||
3854 | CloseHandle (d->io_event); /* ignore error */ | |||
3855 | ||||
3856 | #endif | |||
3857 | ||||
3858 | if ((d->base.base.close_direction & (___DIRECTION_RD1|___DIRECTION_WR2)) | |||
3859 | == (___DIRECTION_RD1|___DIRECTION_WR2)) | |||
3860 | { | |||
3861 | if (CLOSE_SOCKET(d->s)close_no_EINTR (d->s) != 0) | |||
3862 | return ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
3863 | } | |||
3864 | } | |||
3865 | else if (is_not_closed & direction & ___DIRECTION_RD1) | |||
3866 | { | |||
3867 | /* Shutdown receiving side. */ | |||
3868 | ||||
3869 | if ((d->base.base.close_direction & ___DIRECTION_RD1) | |||
3870 | == ___DIRECTION_RD1) | |||
3871 | { | |||
3872 | if (shutdown (d->s, SHUTDOWN_RDSHUT_RD) != 0) | |||
3873 | { | |||
3874 | ___SCMOBJlong e = ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
3875 | if (!NOT_CONNECTED(e)((e) == (((long)(((107)==0?0:((((int)(-1))<<29)+(((int) (320))<<16)+(107)))))<<2))) | |||
3876 | return e; | |||
3877 | } | |||
3878 | } | |||
3879 | ||||
3880 | d->base.base.read_stage = ___STAGE_CLOSED3; | |||
3881 | } | |||
3882 | else if (is_not_closed & direction & ___DIRECTION_WR2) | |||
3883 | { | |||
3884 | /* Shutdown sending side. */ | |||
3885 | ||||
3886 | if ((d->base.base.close_direction & ___DIRECTION_WR2) | |||
3887 | == ___DIRECTION_WR2) | |||
3888 | { | |||
3889 | if (shutdown (d->s, SHUTDOWN_WRSHUT_WR) != 0) | |||
3890 | { | |||
3891 | ___SCMOBJlong e = ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
3892 | if (!NOT_CONNECTED(e)((e) == (((long)(((107)==0?0:((((int)(-1))<<29)+(((int) (320))<<16)+(107)))))<<2))) | |||
3893 | return e; | |||
3894 | } | |||
3895 | } | |||
3896 | ||||
3897 | d->base.base.write_stage = ___STAGE_CLOSED3; | |||
3898 | } | |||
3899 | ||||
3900 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3901 | } | |||
3902 | ||||
3903 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_client_select_raw_virt | |||
3904 | ___P((___device_stream *self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3905 | ___BOOL for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3906 | int i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3907 | int pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3908 | ___device_select_state *state),(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3909 | (self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3910 | for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3911 | i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3912 | pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3913 | state)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3914 | ___device_stream *self;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3915 | ___BOOL for_writing;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3916 | int i;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3917 | int pass;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3918 | ___device_select_state *state;)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
3919 | { | |||
3920 | ___device_tcp_client *d = ___CAST(___device_tcp_client*,self)((___device_tcp_client*)(self)); | |||
3921 | int stage = (for_writing | |||
3922 | ? d->base.base.write_stage | |||
3923 | : d->base.base.read_stage); | |||
3924 | ||||
3925 | if (pass == ___SELECT_PASS_11) | |||
3926 | { | |||
3927 | if (stage != ___STAGE_OPEN0) | |||
3928 | { | |||
3929 | state->timeout = ___time_mod.time_neg_infinity; | |||
3930 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
3931 | } | |||
3932 | else | |||
3933 | { | |||
3934 | #ifdef USE_POSIX | |||
3935 | ||||
3936 | if (d->try_connect_again != 0) | |||
3937 | { | |||
3938 | int interval = d->try_connect_interval_nsecs * 6 / 5; | |||
3939 | if (interval > 200000000) /* max interval = 0.2 sec */ | |||
3940 | interval = 200000000; | |||
3941 | d->try_connect_interval_nsecs = interval; | |||
3942 | ___device_select_add_relative_timeout (state, i, interval * 1e-9); | |||
3943 | } | |||
3944 | else | |||
3945 | ___device_select_add_fd (state, d->s, for_writing); | |||
3946 | ||||
3947 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
3948 | ||||
3949 | #endif | |||
3950 | ||||
3951 | #ifdef USE_WIN32 | |||
3952 | ||||
3953 | d->io_events = 0; | |||
3954 | ||||
3955 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3956 | ||||
3957 | #endif | |||
3958 | } | |||
3959 | } | |||
3960 | ||||
3961 | #ifdef USE_WIN32 | |||
3962 | ||||
3963 | else if (pass == ___SELECT_PASS_22) | |||
3964 | { | |||
3965 | if (d->try_connect_again != 0) | |||
3966 | d->io_events = (FD_CONNECT | FD_CLOSE); | |||
3967 | else if (for_writing) | |||
3968 | d->io_events |= (FD_WRITE | FD_CLOSE); | |||
3969 | else | |||
3970 | d->io_events |= (FD_READ | FD_CLOSE); | |||
3971 | ||||
3972 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
3973 | } | |||
3974 | else if (pass == ___SELECT_PASS_33) | |||
3975 | { | |||
3976 | HANDLE wait_obj = d->io_event; | |||
3977 | ||||
3978 | ResetEvent (wait_obj); /* ignore error */ | |||
3979 | ||||
3980 | WSAEventSelect (d->s, wait_obj, d->io_events); | |||
3981 | ||||
3982 | ___device_select_add_wait_obj (state, i, wait_obj); | |||
3983 | ||||
3984 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
3985 | } | |||
3986 | ||||
3987 | #endif | |||
3988 | ||||
3989 | /* pass == ___SELECT_PASS_CHECK */ | |||
3990 | ||||
3991 | if (stage != ___STAGE_OPEN0) | |||
3992 | state->devs[i] = NULL((void*)0); | |||
3993 | else | |||
3994 | { | |||
3995 | #ifdef USE_POSIX | |||
3996 | ||||
3997 | if (d->try_connect_again != 0 || | |||
3998 | (for_writing | |||
3999 | ? ___FD_ISSET(d->s, &state->writefds)((((&state->writefds)->__fds_bits)[((d->s) / (8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) 1 << (( d->s) % (8 * (int) sizeof (__fd_mask))))) != 0) | |||
4000 | : ___FD_ISSET(d->s, &state->readfds)((((&state->readfds)->__fds_bits)[((d->s) / (8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) 1 << (( d->s) % (8 * (int) sizeof (__fd_mask))))) != 0))) | |||
4001 | { | |||
4002 | d->connect_done = 1; | |||
4003 | state->devs[i] = NULL((void*)0); | |||
4004 | } | |||
4005 | ||||
4006 | #endif | |||
4007 | ||||
4008 | #ifdef USE_WIN32 | |||
4009 | ||||
4010 | if (state->devs_next[i] != -1) | |||
4011 | { | |||
4012 | state->devs[i] = NULL((void*)0); | |||
4013 | if (d->try_connect_again != 0) | |||
4014 | { | |||
4015 | d->connect_done = 1; | |||
4016 | d->try_connect_again = 2; | |||
4017 | } | |||
4018 | } | |||
4019 | ||||
4020 | #endif | |||
4021 | } | |||
4022 | ||||
4023 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4024 | } | |||
4025 | ||||
4026 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_client_release_raw_virt | |||
4027 | ___P((___device_stream *self),(___device_stream *self) | |||
4028 | (self)(___device_stream *self) | |||
4029 | ___device_stream *self;)(___device_stream *self) | |||
4030 | { | |||
4031 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4032 | } | |||
4033 | ||||
4034 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_client_force_output_raw_virt | |||
4035 | ___P((___device_stream *self,(___device_stream *self, int level) | |||
4036 | int level),(___device_stream *self, int level) | |||
4037 | (self,(___device_stream *self, int level) | |||
4038 | level)(___device_stream *self, int level) | |||
4039 | ___device_stream *self;(___device_stream *self, int level) | |||
4040 | int level;)(___device_stream *self, int level) | |||
4041 | { | |||
4042 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4043 | } | |||
4044 | ||||
4045 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_client_seek_raw_virt | |||
4046 | ___P((___device_stream *self,(___device_stream *self, ___stream_index *pos, int whence) | |||
4047 | ___stream_index *pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
4048 | int whence),(___device_stream *self, ___stream_index *pos, int whence) | |||
4049 | (self,(___device_stream *self, ___stream_index *pos, int whence) | |||
4050 | pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
4051 | whence)(___device_stream *self, ___stream_index *pos, int whence) | |||
4052 | ___device_stream *self;(___device_stream *self, ___stream_index *pos, int whence) | |||
4053 | ___stream_index *pos;(___device_stream *self, ___stream_index *pos, int whence) | |||
4054 | int whence;)(___device_stream *self, ___stream_index *pos, int whence) | |||
4055 | { | |||
4056 | return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+7)))<<2); | |||
4057 | } | |||
4058 | ||||
4059 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_client_read_raw_virt | |||
4060 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4061 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4062 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4063 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4064 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4065 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4066 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4067 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4068 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4069 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4070 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4071 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4072 | { | |||
4073 | ___device_tcp_client *d = ___CAST(___device_tcp_client*,self)((___device_tcp_client*)(self)); | |||
4074 | int n; | |||
4075 | ||||
4076 | if (d->base.base.read_stage != ___STAGE_OPEN0) | |||
4077 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
4078 | ||||
4079 | if (d->try_connect_again != 0) | |||
4080 | { | |||
4081 | if (try_connect (d) == 0) | |||
4082 | { | |||
4083 | if (d->try_connect_again != 0) | |||
4084 | return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
4085 | } | |||
4086 | else | |||
4087 | return ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4088 | } | |||
4089 | ||||
4090 | if (SOCKET_CALL_ERROR(n = recv (d->s, ___CAST(char*,buf), len, 0))((n = recv (d->s, ((char*)(buf)), len, 0)) < 0)) | |||
4091 | { | |||
4092 | ___SCMOBJlong e = ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4093 | if (NOT_CONNECTED(e)((e) == (((long)(((107)==0?0:((((int)(-1))<<29)+(((int) (320))<<16)+(107)))))<<2)) && !d->connect_done) | |||
4094 | e = ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
4095 | return e; | |||
4096 | } | |||
4097 | ||||
4098 | *len_done = n; | |||
4099 | ||||
4100 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4101 | } | |||
4102 | ||||
4103 | ||||
4104 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_client_write_raw_virt | |||
4105 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4106 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4107 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4108 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4109 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4110 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4111 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4112 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4113 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4114 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4115 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4116 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
4117 | { | |||
4118 | ___device_tcp_client *d = ___CAST(___device_tcp_client*,self)((___device_tcp_client*)(self)); | |||
4119 | int n; | |||
4120 | ||||
4121 | if (d->base.base.write_stage != ___STAGE_OPEN0) | |||
4122 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
4123 | ||||
4124 | if (d->try_connect_again != 0) | |||
4125 | { | |||
4126 | if (try_connect (d) == 0) | |||
4127 | { | |||
4128 | if (d->try_connect_again != 0) | |||
4129 | return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
4130 | } | |||
4131 | else | |||
4132 | return ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4133 | } | |||
4134 | ||||
4135 | if (SOCKET_CALL_ERROR(n = send (d->s, ___CAST(char*,buf), len, 0))((n = send (d->s, ((char*)(buf)), len, 0)) < 0)) | |||
4136 | { | |||
4137 | ___SCMOBJlong e = ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4138 | if (NOT_CONNECTED(e)((e) == (((long)(((107)==0?0:((((int)(-1))<<29)+(((int) (320))<<16)+(107)))))<<2)) && !d->connect_done) | |||
4139 | e = ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
4140 | return e; | |||
4141 | } | |||
4142 | ||||
4143 | *len_done = n; | |||
4144 | ||||
4145 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4146 | } | |||
4147 | ||||
4148 | ||||
4149 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_client_width_virt | |||
4150 | ___P((___device_stream *self),(___device_stream *self) | |||
4151 | (self)(___device_stream *self) | |||
4152 | ___device_stream *self;)(___device_stream *self) | |||
4153 | { | |||
4154 | return ___FIX(80)(((long)(80))<<2); | |||
4155 | } | |||
4156 | ||||
4157 | ||||
4158 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_client_default_options_virt | |||
4159 | ___P((___device_stream *self),(___device_stream *self) | |||
4160 | (self)(___device_stream *self) | |||
4161 | ___device_stream *self;)(___device_stream *self) | |||
4162 | { | |||
4163 | int char_encoding_errors = ___CHAR_ENCODING_ERRORS_ON(1<<5); | |||
4164 | int char_encoding = ___CHAR_ENCODING_ISO_8859_1(2<<0); | |||
4165 | int eol_encoding = ___EOL_ENCODING_LF(1<<7); | |||
4166 | int buffering = ___FULL_BUFFERING(3<<9); | |||
4167 | ||||
4168 | return ___FIX(___STREAM_OPTIONS(char_encoding_errors,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
4169 | char_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
4170 | eol_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
4171 | buffering,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
4172 | char_encoding_errors,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
4173 | char_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
4174 | eol_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
4175 | buffering))(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2); | |||
4176 | } | |||
4177 | ||||
4178 | ||||
4179 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_client_options_set_virt | |||
4180 | ___P((___device_stream *self,(___device_stream *self, long options) | |||
4181 | ___SCMOBJ options),(___device_stream *self, long options) | |||
4182 | (self,(___device_stream *self, long options) | |||
4183 | options)(___device_stream *self, long options) | |||
4184 | ___device_stream *self;(___device_stream *self, long options) | |||
4185 | ___SCMOBJ options;)(___device_stream *self, long options) | |||
4186 | { | |||
4187 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4188 | } | |||
4189 | ||||
4190 | ||||
4191 | ___HIDDENstatic ___device_tcp_client_vtbl ___device_tcp_client_table = | |||
4192 | { | |||
4193 | { | |||
4194 | { | |||
4195 | ___device_tcp_client_kind, | |||
4196 | ___device_stream_select_virt, | |||
4197 | ___device_stream_release_virt, | |||
4198 | ___device_stream_force_output_virt, | |||
4199 | ___device_stream_close_virt | |||
4200 | }, | |||
4201 | ___device_tcp_client_select_raw_virt, | |||
4202 | ___device_tcp_client_release_raw_virt, | |||
4203 | ___device_tcp_client_force_output_raw_virt, | |||
4204 | ___device_tcp_client_close_raw_virt, | |||
4205 | ___device_tcp_client_seek_raw_virt, | |||
4206 | ___device_tcp_client_read_raw_virt, | |||
4207 | ___device_tcp_client_write_raw_virt, | |||
4208 | ___device_tcp_client_width_virt, | |||
4209 | ___device_tcp_client_default_options_virt, | |||
4210 | ___device_tcp_client_options_set_virt | |||
4211 | } | |||
4212 | }; | |||
4213 | ||||
4214 | ||||
4215 | #define ___SOCK_KEEPALIVE_FLAG(options)(((options) & 1) != 0) (((options) & 1) != 0) | |||
4216 | #define ___SOCK_NO_COALESCE_FLAG(options)(((options) & 2) != 0) (((options) & 2) != 0) | |||
4217 | #define ___SOCK_REUSE_ADDRESS_FLAG(options)(((options) & 2048) != 0) (((options) & 2048) != 0) | |||
4218 | ||||
4219 | ||||
4220 | ___HIDDENstatic ___SCMOBJlong create_tcp_socket | |||
4221 | ___P((SOCKET_TYPE *sock,(int *sock, int options) | |||
4222 | int options),(int *sock, int options) | |||
4223 | (sock,(int *sock, int options) | |||
4224 | options)(int *sock, int options) | |||
4225 | SOCKET_TYPE *sock;(int *sock, int options) | |||
4226 | int options;)(int *sock, int options) | |||
4227 | { | |||
4228 | int keepalive_flag = ___SOCK_KEEPALIVE_FLAG(options)(((options) & 1) != 0); | |||
4229 | int no_coalesce_flag = ___SOCK_NO_COALESCE_FLAG(options)(((options) & 2) != 0); | |||
4230 | int reuse_address_flag = ___SOCK_REUSE_ADDRESS_FLAG(options)(((options) & 2048) != 0); | |||
4231 | SOCKET_TYPEint s; | |||
4232 | ||||
4233 | if (SOCKET_CALL_ERROR2(s = socket (AF_INET, SOCK_STREAM, 0))((s = socket (2, SOCK_STREAM, 0)) < 0)) | |||
4234 | return ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4235 | ||||
4236 | #ifndef TCP_NODELAY1 | |||
4237 | #define TCP_NODELAY1 1 | |||
4238 | #endif | |||
4239 | ||||
4240 | if ((keepalive_flag != 0 && | |||
4241 | setsockopt (s, /* keep connection alive or not */ | |||
4242 | SOL_SOCKET1, | |||
4243 | SO_KEEPALIVE9, | |||
4244 | ___CAST(char*,&keepalive_flag)((char*)(&keepalive_flag)), | |||
4245 | sizeof (keepalive_flag)) != 0) || | |||
4246 | (reuse_address_flag != 0 && | |||
4247 | setsockopt (s, /* allow reusing the same address */ | |||
4248 | SOL_SOCKET1, | |||
4249 | SO_REUSEADDR2, | |||
4250 | ___CAST(char*,&reuse_address_flag)((char*)(&reuse_address_flag)), | |||
4251 | sizeof (reuse_address_flag)) != 0) || | |||
4252 | (no_coalesce_flag != 0 && | |||
4253 | setsockopt (s, /* enable or disable packet coalescing algorithm */ | |||
4254 | IPPROTO_TCPIPPROTO_TCP, | |||
4255 | TCP_NODELAY1, | |||
4256 | ___CAST(char*,&no_coalesce_flag)((char*)(&no_coalesce_flag)), | |||
4257 | sizeof (no_coalesce_flag)) != 0)) | |||
4258 | { | |||
4259 | ___SCMOBJlong e = ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4260 | CLOSE_SOCKET(s)close_no_EINTR (s); /* ignore error */ | |||
4261 | return e; | |||
4262 | } | |||
4263 | ||||
4264 | *sock = s; | |||
4265 | ||||
4266 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4267 | } | |||
4268 | ||||
4269 | ||||
4270 | ___HIDDENstatic int set_socket_non_blocking | |||
4271 | ___P((SOCKET_TYPE s),(int s) | |||
4272 | (s)(int s) | |||
4273 | SOCKET_TYPE s;)(int s) | |||
4274 | { | |||
4275 | #ifndef USE_ioctl | |||
4276 | #undef FIONBIO0x5421 | |||
4277 | #endif | |||
4278 | ||||
4279 | #ifdef FIONBIO0x5421 | |||
4280 | ||||
4281 | unsigned long param = 1; | |||
4282 | ||||
4283 | return SOCKET_CALL_ERROR(IOCTL_SOCKET(s, FIONBIO, ¶m))((ioctl (s,0x5421,¶m)) < 0); | |||
4284 | ||||
4285 | #else | |||
4286 | ||||
4287 | return set_fd_blocking_mode (s, 0); | |||
4288 | ||||
4289 | #endif | |||
4290 | } | |||
4291 | ||||
4292 | ||||
4293 | ___SCMOBJlong ___device_tcp_client_setup_from_socket | |||
4294 | ___P((___device_tcp_client **dev,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4295 | ___device_group *dgroup,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4296 | SOCKET_TYPE s,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4297 | struct sockaddr *server_addr,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4298 | SOCKET_LEN_TYPE server_addrlen,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4299 | int try_connect_again,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4300 | int direction),(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4301 | (dev,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4302 | dgroup,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4303 | s,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4304 | server_addr,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4305 | server_addrlen,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4306 | try_connect_again,(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4307 | direction)(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4308 | ___device_tcp_client **dev;(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4309 | ___device_group *dgroup;(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4310 | SOCKET_TYPE s;(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4311 | struct sockaddr *server_addr;(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4312 | SOCKET_LEN_TYPE server_addrlen;(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4313 | int try_connect_again;(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4314 | int direction;)(___device_tcp_client **dev, ___device_group *dgroup, int s, struct sockaddr *server_addr, socklen_t server_addrlen, int try_connect_again , int direction) | |||
4315 | { | |||
4316 | ___SCMOBJlong e; | |||
4317 | ___device_tcp_client *d; | |||
4318 | ||||
4319 | d = ___CAST(___device_tcp_client*,((___device_tcp_client*)(___alloc_mem (sizeof (___device_tcp_client )))) | |||
4320 | ___alloc_mem (sizeof (___device_tcp_client)))((___device_tcp_client*)(___alloc_mem (sizeof (___device_tcp_client )))); | |||
4321 | ||||
4322 | if (d == NULL((void*)0)) | |||
4323 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
4324 | ||||
4325 | /* | |||
4326 | * Setup socket to perform nonblocking I/O. | |||
4327 | */ | |||
4328 | ||||
4329 | if (set_socket_non_blocking (s) != 0) /* set nonblocking mode */ | |||
4330 | { | |||
4331 | e = ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4332 | ___free_mem (d); | |||
4333 | return e; | |||
4334 | } | |||
4335 | ||||
4336 | d->base.base.vtbl = &___device_tcp_client_table; | |||
4337 | d->s = s; | |||
4338 | d->server_addr = *server_addr; | |||
4339 | d->server_addrlen = server_addrlen; | |||
4340 | d->try_connect_again = try_connect_again; | |||
4341 | d->connect_done = 0; | |||
4342 | ||||
4343 | #ifdef USE_POSIX | |||
4344 | ||||
4345 | d->try_connect_interval_nsecs = 1000000; /* 0.001 secs */ | |||
4346 | ||||
4347 | #endif | |||
4348 | ||||
4349 | #ifdef USE_WIN32 | |||
4350 | ||||
4351 | d->io_event = | |||
4352 | CreateEvent (NULL((void*)0), /* can't inherit */ | |||
4353 | TRUE, /* manual reset */ | |||
4354 | FALSE, /* not signaled */ | |||
4355 | NULL((void*)0)); /* no name */ | |||
4356 | ||||
4357 | if (d->io_event == NULL((void*)0)) | |||
4358 | { | |||
4359 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
4360 | ___free_mem (d); | |||
4361 | return e; | |||
4362 | } | |||
4363 | ||||
4364 | #endif | |||
4365 | ||||
4366 | *dev = d; | |||
4367 | ||||
4368 | return ___device_stream_setup | |||
4369 | (&d->base, | |||
4370 | dgroup, | |||
4371 | direction, | |||
4372 | 0); | |||
4373 | } | |||
4374 | ||||
4375 | ||||
4376 | ___SCMOBJlong ___device_tcp_client_setup_from_sockaddr | |||
4377 | ___P((___device_tcp_client **dev,(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4378 | ___device_group *dgroup,(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4379 | struct sockaddr *server_addr,(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4380 | SOCKET_LEN_TYPE server_addrlen,(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4381 | int options,(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4382 | int direction),(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4383 | (dev,(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4384 | dgroup,(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4385 | server_addr,(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4386 | server_addrlen,(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4387 | options,(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4388 | direction)(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4389 | ___device_tcp_client **dev;(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4390 | ___device_group *dgroup;(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4391 | struct sockaddr *server_addr;(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4392 | SOCKET_LEN_TYPE server_addrlen;(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4393 | int options;(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4394 | int direction;)(___device_tcp_client **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int options, int direction ) | |||
4395 | { | |||
4396 | ___SCMOBJlong e; | |||
4397 | SOCKET_TYPEint s; | |||
4398 | ___device_tcp_client *d; | |||
4399 | ||||
4400 | if ((e = create_tcp_socket (&s, options)) != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
4401 | return e; | |||
4402 | ||||
4403 | if ((e = ___device_tcp_client_setup_from_socket | |||
4404 | (&d, | |||
4405 | dgroup, | |||
4406 | s, | |||
4407 | server_addr, | |||
4408 | server_addrlen, | |||
4409 | 1, | |||
4410 | direction)) | |||
4411 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
4412 | { | |||
4413 | CLOSE_SOCKET(s)close_no_EINTR (s); /* ignore error */ | |||
4414 | return e; | |||
4415 | } | |||
4416 | ||||
4417 | device_transfer_close_responsibility (___CAST(___device*,d)((___device*)(d))); | |||
4418 | ||||
4419 | *dev = d; | |||
4420 | ||||
4421 | if (try_connect (d) != 0) | |||
4422 | { | |||
4423 | e = ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4424 | ___device_cleanup (&d->base.base); /* ignore error */ | |||
4425 | return e; | |||
4426 | } | |||
4427 | ||||
4428 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4429 | } | |||
4430 | ||||
4431 | #endif | |||
4432 | ||||
4433 | ||||
4434 | /*---------------------------------------------------------------------------*/ | |||
4435 | ||||
4436 | #ifdef USE_NETWORKING | |||
4437 | ||||
4438 | /* TCP server device. */ | |||
4439 | ||||
4440 | typedef struct ___device_tcp_server_struct | |||
4441 | { | |||
4442 | ___device base; | |||
4443 | SOCKET_TYPEint s; | |||
4444 | ||||
4445 | #ifdef USE_WIN32 | |||
4446 | ||||
4447 | HANDLE io_event; /* used by ___device_tcp_server_select_raw_virt */ | |||
4448 | ||||
4449 | #endif | |||
4450 | } ___device_tcp_server; | |||
4451 | ||||
4452 | typedef struct ___device_tcp_server_vtbl_struct | |||
4453 | { | |||
4454 | ___device_vtbl base; | |||
4455 | } ___device_tcp_server_vtbl; | |||
4456 | ||||
4457 | ___HIDDENstatic int ___device_tcp_server_kind | |||
4458 | ___P((___device *self),(___device *self) | |||
4459 | (self)(___device *self) | |||
4460 | ___device *self;)(___device *self) | |||
4461 | { | |||
4462 | return ___TCP_SERVER_DEVICE_KIND(1 +512); | |||
4463 | } | |||
4464 | ||||
4465 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_server_close_virt | |||
4466 | ___P((___device *self,(___device *self, int direction) | |||
4467 | int direction),(___device *self, int direction) | |||
4468 | (self,(___device *self, int direction) | |||
4469 | direction)(___device *self, int direction) | |||
4470 | ___device *self;(___device *self, int direction) | |||
4471 | int direction;)(___device *self, int direction) | |||
4472 | { | |||
4473 | ___device_tcp_server *d = ___CAST(___device_tcp_server*,self)((___device_tcp_server*)(self)); | |||
4474 | ||||
4475 | if (d->base.read_stage == ___STAGE_CLOSED3) | |||
4476 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4477 | ||||
4478 | if (direction & ___DIRECTION_RD1) | |||
4479 | { | |||
4480 | d->base.read_stage = ___STAGE_CLOSED3; /* avoid multiple closes */ | |||
4481 | ||||
4482 | #ifdef USE_WIN32 | |||
4483 | ||||
4484 | if (d->io_event != NULL((void*)0)) | |||
4485 | CloseHandle (d->io_event); /* ignore error */ | |||
4486 | ||||
4487 | #endif | |||
4488 | ||||
4489 | if ((d->base.close_direction & ___DIRECTION_RD1) | |||
4490 | == ___DIRECTION_RD1) | |||
4491 | { | |||
4492 | if (CLOSE_SOCKET(d->s)close_no_EINTR (d->s) != 0) | |||
4493 | return ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4494 | } | |||
4495 | } | |||
4496 | ||||
4497 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4498 | } | |||
4499 | ||||
4500 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_server_select_virt | |||
4501 | ___P((___device *self,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4502 | ___BOOL for_writing,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4503 | int i,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4504 | int pass,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4505 | ___device_select_state *state),(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4506 | (self,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4507 | for_writing,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4508 | i,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4509 | pass,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4510 | state)(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4511 | ___device *self;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4512 | ___BOOL for_writing;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4513 | int i;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4514 | int pass;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4515 | ___device_select_state *state;)(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4516 | { | |||
4517 | ___device_tcp_server *d = ___CAST(___device_tcp_server*,self)((___device_tcp_server*)(self)); | |||
4518 | int stage = (for_writing | |||
4519 | ? d->base.write_stage | |||
4520 | : d->base.read_stage); | |||
4521 | ||||
4522 | if (pass == ___SELECT_PASS_11) | |||
4523 | { | |||
4524 | if (stage != ___STAGE_OPEN0) | |||
4525 | state->timeout = ___time_mod.time_neg_infinity; | |||
4526 | else | |||
4527 | { | |||
4528 | #ifdef USE_POSIX | |||
4529 | ___device_select_add_fd (state, d->s, for_writing); | |||
4530 | #endif | |||
4531 | ||||
4532 | #ifdef USE_WIN32 | |||
4533 | ||||
4534 | HANDLE wait_obj = d->io_event; | |||
4535 | ||||
4536 | ResetEvent (wait_obj); /* ignore error */ | |||
4537 | ||||
4538 | WSAEventSelect (d->s, wait_obj, FD_ACCEPT); | |||
4539 | ||||
4540 | ___device_select_add_wait_obj (state, i, wait_obj); | |||
4541 | ||||
4542 | #endif | |||
4543 | } | |||
4544 | ||||
4545 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
4546 | } | |||
4547 | ||||
4548 | /* pass == ___SELECT_PASS_CHECK */ | |||
4549 | ||||
4550 | if (stage != ___STAGE_OPEN0) | |||
4551 | state->devs[i] = NULL((void*)0); | |||
4552 | else | |||
4553 | { | |||
4554 | #ifdef USE_POSIX | |||
4555 | ||||
4556 | if (___FD_ISSET(d->s, &state->readfds)((((&state->readfds)->__fds_bits)[((d->s) / (8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) 1 << (( d->s) % (8 * (int) sizeof (__fd_mask))))) != 0)) | |||
4557 | state->devs[i] = NULL((void*)0); | |||
4558 | ||||
4559 | #endif | |||
4560 | ||||
4561 | #ifdef USE_WIN32 | |||
4562 | ||||
4563 | if (state->devs_next[i] != -1) | |||
4564 | state->devs[i] = NULL((void*)0); | |||
4565 | ||||
4566 | #endif | |||
4567 | } | |||
4568 | ||||
4569 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4570 | } | |||
4571 | ||||
4572 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_server_release_virt | |||
4573 | ___P((___device *self),(___device *self) | |||
4574 | (self)(___device *self) | |||
4575 | ___device *self;)(___device *self) | |||
4576 | { | |||
4577 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4578 | } | |||
4579 | ||||
4580 | ___HIDDENstatic ___SCMOBJlong ___device_tcp_server_force_output_virt | |||
4581 | ___P((___device *self,(___device *self, int level) | |||
4582 | int level),(___device *self, int level) | |||
4583 | (self,(___device *self, int level) | |||
4584 | level)(___device *self, int level) | |||
4585 | ___device *self;(___device *self, int level) | |||
4586 | int level;)(___device *self, int level) | |||
4587 | { | |||
4588 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4589 | } | |||
4590 | ||||
4591 | ___HIDDENstatic ___device_tcp_server_vtbl ___device_tcp_server_table = | |||
4592 | { | |||
4593 | { | |||
4594 | ___device_tcp_server_kind, | |||
4595 | ___device_tcp_server_select_virt, | |||
4596 | ___device_tcp_server_release_virt, | |||
4597 | ___device_tcp_server_force_output_virt, | |||
4598 | ___device_tcp_server_close_virt | |||
4599 | } | |||
4600 | }; | |||
4601 | ||||
4602 | ||||
4603 | ___SCMOBJlong ___device_tcp_server_setup | |||
4604 | ___P((___device_tcp_server **dev,(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4605 | ___device_group *dgroup,(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4606 | struct sockaddr *server_addr,(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4607 | SOCKET_LEN_TYPE server_addrlen,(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4608 | int backlog,(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4609 | int options),(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4610 | (dev,(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4611 | dgroup,(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4612 | server_addr,(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4613 | server_addrlen,(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4614 | backlog,(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4615 | options)(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4616 | ___device_tcp_server **dev;(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4617 | ___device_group *dgroup;(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4618 | struct sockaddr *server_addr;(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4619 | SOCKET_LEN_TYPE server_addrlen;(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4620 | int backlog;(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4621 | int options;)(___device_tcp_server **dev, ___device_group *dgroup, struct sockaddr *server_addr, socklen_t server_addrlen, int backlog, int options ) | |||
4622 | { | |||
4623 | ___SCMOBJlong e; | |||
4624 | SOCKET_TYPEint s; | |||
4625 | ___device_tcp_server *d; | |||
4626 | ||||
4627 | if ((e = create_tcp_socket (&s, options)) != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
4628 | return e; | |||
4629 | ||||
4630 | if (set_socket_non_blocking (s) != 0 || /* set nonblocking mode */ | |||
4631 | bind (s, server_addr, server_addrlen) != 0 || | |||
4632 | listen (s, backlog) != 0) | |||
4633 | { | |||
4634 | e = ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4635 | CLOSE_SOCKET(s)close_no_EINTR (s); /* ignore error */ | |||
4636 | return e; | |||
4637 | } | |||
4638 | ||||
4639 | d = ___CAST(___device_tcp_server*,((___device_tcp_server*)(___alloc_mem (sizeof (___device_tcp_server )))) | |||
4640 | ___alloc_mem (sizeof (___device_tcp_server)))((___device_tcp_server*)(___alloc_mem (sizeof (___device_tcp_server )))); | |||
4641 | ||||
4642 | if (d == NULL((void*)0)) | |||
4643 | { | |||
4644 | CLOSE_SOCKET(s)close_no_EINTR (s); /* ignore error */ | |||
4645 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
4646 | } | |||
4647 | ||||
4648 | d->base.vtbl = &___device_tcp_server_table; | |||
4649 | d->base.refcount = 1; | |||
4650 | d->base.direction = ___DIRECTION_RD1; | |||
4651 | d->base.close_direction = 0; /* prevent closing on errors */ | |||
4652 | d->base.read_stage = ___STAGE_OPEN0; | |||
4653 | d->base.write_stage = ___STAGE_CLOSED3; | |||
4654 | ||||
4655 | #ifdef USE_WIN32 | |||
4656 | ||||
4657 | d->io_event = | |||
4658 | CreateEvent (NULL((void*)0), /* can't inherit */ | |||
4659 | TRUE, /* manual reset */ | |||
4660 | FALSE, /* not signaled */ | |||
4661 | NULL((void*)0)); /* no name */ | |||
4662 | ||||
4663 | if (d->io_event == NULL((void*)0)) | |||
4664 | { | |||
4665 | ___SCMOBJlong e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
4666 | CLOSE_SOCKET(s)close_no_EINTR (s); /* ignore error */ | |||
4667 | ___free_mem (d); | |||
4668 | return e; | |||
4669 | } | |||
4670 | ||||
4671 | #endif | |||
4672 | ||||
4673 | d->s = s; | |||
4674 | ||||
4675 | device_transfer_close_responsibility (___CAST(___device*,d)((___device*)(d))); | |||
4676 | ||||
4677 | *dev = d; | |||
4678 | ||||
4679 | ___device_add_to_group (dgroup, &d->base); | |||
4680 | ||||
4681 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4682 | } | |||
4683 | ||||
4684 | ||||
4685 | ___SCMOBJlong ___device_tcp_server_read | |||
4686 | ___P((___device_tcp_server *dev,(___device_tcp_server *dev, ___device_group *dgroup, ___device_tcp_client **client) | |||
4687 | ___device_group *dgroup,(___device_tcp_server *dev, ___device_group *dgroup, ___device_tcp_client **client) | |||
4688 | ___device_tcp_client **client),(___device_tcp_server *dev, ___device_group *dgroup, ___device_tcp_client **client) | |||
4689 | (dev,(___device_tcp_server *dev, ___device_group *dgroup, ___device_tcp_client **client) | |||
4690 | dgroup,(___device_tcp_server *dev, ___device_group *dgroup, ___device_tcp_client **client) | |||
4691 | client)(___device_tcp_server *dev, ___device_group *dgroup, ___device_tcp_client **client) | |||
4692 | ___device_tcp_server *dev;(___device_tcp_server *dev, ___device_group *dgroup, ___device_tcp_client **client) | |||
4693 | ___device_group *dgroup;(___device_tcp_server *dev, ___device_group *dgroup, ___device_tcp_client **client) | |||
4694 | ___device_tcp_client **client;)(___device_tcp_server *dev, ___device_group *dgroup, ___device_tcp_client **client) | |||
4695 | { | |||
4696 | ___SCMOBJlong e; | |||
4697 | struct sockaddr_in addr; | |||
4698 | SOCKET_LEN_TYPEsocklen_t addrlen; | |||
4699 | SOCKET_TYPEint s; | |||
4700 | ||||
4701 | if (dev->base.read_stage != ___STAGE_OPEN0) | |||
4702 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
4703 | ||||
4704 | addrlen = sizeof (addr); | |||
4705 | ||||
4706 | if (SOCKET_CALL_ERROR2(s = accept (dev->s,((s = accept (dev->s, ((struct sockaddr*)(&addr)), & addrlen)) < 0) | |||
4707 | ___CAST(struct sockaddr*,&addr),((s = accept (dev->s, ((struct sockaddr*)(&addr)), & addrlen)) < 0) | |||
4708 | &addrlen))((s = accept (dev->s, ((struct sockaddr*)(&addr)), & addrlen)) < 0)) | |||
4709 | return ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
4710 | ||||
4711 | if ((e = ___device_tcp_client_setup_from_socket | |||
4712 | (client, | |||
4713 | dgroup, | |||
4714 | s, | |||
4715 | ___CAST(struct sockaddr*,&addr)((struct sockaddr*)(&addr)), | |||
4716 | addrlen, | |||
4717 | 0, | |||
4718 | ___DIRECTION_RD1|___DIRECTION_WR2)) | |||
4719 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
4720 | { | |||
4721 | CLOSE_SOCKET(s)close_no_EINTR (s); /* ignore error */ | |||
4722 | return e; | |||
4723 | } | |||
4724 | ||||
4725 | device_transfer_close_responsibility (___CAST(___device*,*client)((___device*)(*client))); | |||
4726 | ||||
4727 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4728 | } | |||
4729 | ||||
4730 | #endif | |||
4731 | ||||
4732 | ||||
4733 | /*---------------------------------------------------------------------------*/ | |||
4734 | ||||
4735 | /* Directory device. */ | |||
4736 | ||||
4737 | typedef struct ___device_directory_struct | |||
4738 | { | |||
4739 | ___device base; | |||
4740 | ||||
4741 | int ignore_hidden; | |||
4742 | ||||
4743 | #ifdef USE_opendir | |||
4744 | DIR *dir; | |||
4745 | #endif | |||
4746 | ||||
4747 | #ifdef USE_FindFirstFile | |||
4748 | HANDLE h; | |||
4749 | WIN32_FIND_DATA fdata; | |||
4750 | ___BOOLint first_file; | |||
4751 | #endif | |||
4752 | } ___device_directory; | |||
4753 | ||||
4754 | typedef struct ___device_directory_vtbl_struct | |||
4755 | { | |||
4756 | ___device_vtbl base; | |||
4757 | } ___device_directory_vtbl; | |||
4758 | ||||
4759 | ___HIDDENstatic int ___device_directory_kind | |||
4760 | ___P((___device *self),(___device *self) | |||
4761 | (self)(___device *self) | |||
4762 | ___device *self;)(___device *self) | |||
4763 | { | |||
4764 | return ___DIRECTORY_KIND(1 +1024); | |||
4765 | } | |||
4766 | ||||
4767 | ___HIDDENstatic ___SCMOBJlong ___device_directory_close_virt | |||
4768 | ___P((___device *self,(___device *self, int direction) | |||
4769 | int direction),(___device *self, int direction) | |||
4770 | (self,(___device *self, int direction) | |||
4771 | direction)(___device *self, int direction) | |||
4772 | ___device *self;(___device *self, int direction) | |||
4773 | int direction;)(___device *self, int direction) | |||
4774 | { | |||
4775 | ___device_directory *d = ___CAST(___device_directory*,self)((___device_directory*)(self)); | |||
4776 | ||||
4777 | if (d->base.read_stage == ___STAGE_CLOSED3) | |||
4778 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4779 | ||||
4780 | if (direction & ___DIRECTION_RD1) | |||
4781 | { | |||
4782 | d->base.read_stage = ___STAGE_CLOSED3; /* avoid multiple closes */ | |||
4783 | ||||
4784 | if ((d->base.close_direction & ___DIRECTION_RD1) | |||
4785 | == ___DIRECTION_RD1) | |||
4786 | { | |||
4787 | ||||
4788 | #ifdef USE_opendir | |||
4789 | if (closedir (d->dir) < 0) | |||
4790 | return err_code_from_errno ()___err_code_from_errno(); | |||
4791 | #endif | |||
4792 | ||||
4793 | #ifdef USE_FindFirstFile | |||
4794 | if (!FindClose (d->h)) | |||
4795 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
4796 | #endif | |||
4797 | } | |||
4798 | } | |||
4799 | ||||
4800 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4801 | } | |||
4802 | ||||
4803 | ___HIDDENstatic ___SCMOBJlong ___device_directory_select_virt | |||
4804 | ___P((___device *self,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4805 | ___BOOL for_writing,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4806 | int i,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4807 | int pass,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4808 | ___device_select_state *state),(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4809 | (self,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4810 | for_writing,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4811 | i,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4812 | pass,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4813 | state)(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4814 | ___device *self;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4815 | ___BOOL for_writing;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4816 | int i;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4817 | int pass;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4818 | ___device_select_state *state;)(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
4819 | { | |||
4820 | if (pass == ___SELECT_PASS_11) | |||
4821 | { | |||
4822 | state->timeout = ___time_mod.time_neg_infinity; | |||
4823 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
4824 | } | |||
4825 | ||||
4826 | /* pass == ___SELECT_PASS_CHECK */ | |||
4827 | ||||
4828 | state->devs[i] = NULL((void*)0); | |||
4829 | ||||
4830 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4831 | } | |||
4832 | ||||
4833 | ___HIDDENstatic ___SCMOBJlong ___device_directory_release_virt | |||
4834 | ___P((___device *self),(___device *self) | |||
4835 | (self)(___device *self) | |||
4836 | ___device *self;)(___device *self) | |||
4837 | { | |||
4838 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4839 | } | |||
4840 | ||||
4841 | ___HIDDENstatic ___SCMOBJlong ___device_directory_force_output_virt | |||
4842 | ___P((___device *self,(___device *self, int level) | |||
4843 | int level),(___device *self, int level) | |||
4844 | (self,(___device *self, int level) | |||
4845 | level)(___device *self, int level) | |||
4846 | ___device *self;(___device *self, int level) | |||
4847 | int level;)(___device *self, int level) | |||
4848 | { | |||
4849 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4850 | } | |||
4851 | ||||
4852 | ___HIDDENstatic ___device_directory_vtbl ___device_directory_table = | |||
4853 | { | |||
4854 | { | |||
4855 | ___device_directory_kind, | |||
4856 | ___device_directory_select_virt, | |||
4857 | ___device_directory_release_virt, | |||
4858 | ___device_directory_force_output_virt, | |||
4859 | ___device_directory_close_virt | |||
4860 | } | |||
4861 | }; | |||
4862 | ||||
4863 | ||||
4864 | #ifdef USE_opendir | |||
4865 | #define ___DIR_OPEN_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native)native native | |||
4866 | #endif | |||
4867 | ||||
4868 | #ifdef USE_FindFirstFile | |||
4869 | #ifdef _UNICODE | |||
4870 | #define ___DIR_OPEN_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native)native ucs2 | |||
4871 | #else | |||
4872 | #define ___DIR_OPEN_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native)native native | |||
4873 | #endif | |||
4874 | #endif | |||
4875 | ||||
4876 | ||||
4877 | #ifdef ___DIR_OPEN_PATH_CE_SELECT | |||
4878 | ||||
4879 | ___SCMOBJlong ___device_directory_setup | |||
4880 | ___P((___device_directory **dev,(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4881 | ___device_group *dgroup,(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4882 | ___STRING_TYPE(___DIR_OPEN_PATH_CE_SELECT) path,(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4883 | int ignore_hidden),(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4884 | (dev,(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4885 | dgroup,(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4886 | path,(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4887 | ignore_hidden)(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4888 | ___device_directory **dev;(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4889 | ___device_group *dgroup;(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4890 | ___STRING_TYPE(___DIR_OPEN_PATH_CE_SELECT) path;(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4891 | int ignore_hidden;)(___device_directory **dev, ___device_group *dgroup, char* path , int ignore_hidden) | |||
4892 | { | |||
4893 | ___device_directory *d; | |||
4894 | ||||
4895 | d = ___CAST(___device_directory*,((___device_directory*)(___alloc_mem (sizeof (___device_directory )))) | |||
4896 | ___alloc_mem (sizeof (___device_directory)))((___device_directory*)(___alloc_mem (sizeof (___device_directory )))); | |||
4897 | ||||
4898 | if (d == NULL((void*)0)) | |||
4899 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
4900 | ||||
4901 | d->base.vtbl = &___device_directory_table; | |||
4902 | d->base.refcount = 1; | |||
4903 | d->base.direction = ___DIRECTION_RD1; | |||
4904 | d->base.close_direction = 0; /* prevent closing on errors */ | |||
4905 | d->base.read_stage = ___STAGE_OPEN0; | |||
4906 | d->base.write_stage = ___STAGE_CLOSED3; | |||
4907 | ||||
4908 | #ifdef USE_opendir | |||
4909 | ||||
4910 | d->ignore_hidden = ignore_hidden; | |||
4911 | ||||
4912 | d->dir = opendir (path); | |||
4913 | ||||
4914 | if (d->dir == NULL((void*)0)) | |||
4915 | { | |||
4916 | ___SCMOBJlong e = fnf_or_err_code_from_errno ()___err_code_from_errno(); | |||
4917 | ___free_mem (d); | |||
4918 | return e; | |||
4919 | } | |||
4920 | ||||
4921 | #endif | |||
4922 | ||||
4923 | #ifdef USE_FindFirstFile | |||
4924 | ||||
4925 | { | |||
4926 | ___CHAR_TYPE(___DIR_OPEN_PATH_CE_SELECT)char dir[___PATH_MAX_LENGTH1024+2+1]; | |||
4927 | int i = 0; | |||
4928 | ||||
4929 | while (path[i] != '\0' && i < ___PATH_MAX_LENGTH1024) | |||
4930 | { | |||
4931 | dir[i] = path[i]; | |||
4932 | i++; | |||
4933 | } | |||
4934 | ||||
4935 | if (i == 0 || (dir[i-1] != '\\' && dir[i-1] != '/')) | |||
4936 | dir[i++] = '\\'; | |||
4937 | ||||
4938 | dir[i++] = '*'; | |||
4939 | dir[i++] = '\0'; | |||
4940 | ||||
4941 | d->ignore_hidden = ignore_hidden; | |||
4942 | d->first_file = 1; | |||
4943 | ||||
4944 | d->h = FindFirstFile (dir, &d->fdata); | |||
4945 | ||||
4946 | if (d->h == INVALID_HANDLE_VALUE) | |||
4947 | { | |||
4948 | ___SCMOBJlong e = fnf_or_err_code_from_GetLastError ()___fnf_or_err_code_from_GetLastError(); | |||
4949 | ___free_mem (d); | |||
4950 | return e; | |||
4951 | } | |||
4952 | } | |||
4953 | ||||
4954 | #endif | |||
4955 | ||||
4956 | device_transfer_close_responsibility (___CAST(___device*,d)((___device*)(d))); | |||
4957 | ||||
4958 | *dev = d; | |||
4959 | ||||
4960 | ___device_add_to_group (dgroup, &d->base); | |||
4961 | ||||
4962 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4963 | } | |||
4964 | ||||
4965 | ___SCMOBJlong ___device_directory_read | |||
4966 | ___P((___device_directory *dev,(___device_directory *dev, char* *name) | |||
4967 | ___STRING_TYPE(___DIR_OPEN_PATH_CE_SELECT) *name),(___device_directory *dev, char* *name) | |||
4968 | (dev,(___device_directory *dev, char* *name) | |||
4969 | name)(___device_directory *dev, char* *name) | |||
4970 | ___device_directory *dev;(___device_directory *dev, char* *name) | |||
4971 | ___STRING_TYPE(___DIR_OPEN_PATH_CE_SELECT) *name;)(___device_directory *dev, char* *name) | |||
4972 | { | |||
4973 | ___SCMOBJlong e; | |||
4974 | ||||
4975 | if (dev->base.read_stage != ___STAGE_OPEN0) | |||
4976 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
4977 | ||||
4978 | for (;;) | |||
4979 | { | |||
4980 | ___STRING_TYPE(___DIR_OPEN_PATH_CE_SELECT)char* temp; | |||
4981 | ||||
4982 | #ifdef USE_opendir | |||
4983 | ||||
4984 | struct dirent *de = readdir (dev->dir); | |||
4985 | ||||
4986 | if (de == NULL((void*)0)) | |||
4987 | { | |||
4988 | #if 0 | |||
4989 | /* this seems to be broken, at least under Linux */ | |||
4990 | if (errno(*__errno_location ()) != 0) | |||
4991 | return err_code_from_errno ()___err_code_from_errno(); | |||
4992 | #endif | |||
4993 | *name = NULL((void*)0); | |||
4994 | e = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
4995 | break; | |||
4996 | } | |||
4997 | ||||
4998 | temp = de->d_name; | |||
4999 | ||||
5000 | switch (dev->ignore_hidden) | |||
5001 | { | |||
5002 | default: | |||
5003 | case 2: | |||
5004 | if (temp[0] == '.') | |||
5005 | break; | |||
5006 | ||||
5007 | case 1: | |||
5008 | if (temp[0] == '.' && | |||
5009 | (temp[1] == '\0' || | |||
5010 | (temp[1] == '.' && (temp[2] == '\0')))) | |||
5011 | break; | |||
5012 | ||||
5013 | case 0: | |||
5014 | *name = temp; | |||
5015 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5016 | } | |||
5017 | ||||
5018 | #endif | |||
5019 | ||||
5020 | #ifdef USE_FindFirstFile | |||
5021 | ||||
5022 | if (dev->first_file) | |||
5023 | dev->first_file = 0; | |||
5024 | else if (!FindNextFile (dev->h, &dev->fdata)) | |||
5025 | { | |||
5026 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
5027 | *name = NULL((void*)0); | |||
5028 | if (e == ___FIX(___WIN32_ERR(ERROR_NO_MORE_FILES))(((long)((((HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES))&~(~( (int)(0))<<25)) | (((HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES ))&~((int)(0))<<27)>>2))))<<2)) | |||
5029 | e = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5030 | break; | |||
5031 | } | |||
5032 | ||||
5033 | temp = dev->fdata.cFileName; | |||
5034 | ||||
5035 | if (temp[0] == '\0') | |||
5036 | temp = dev->fdata.cAlternateFileName; /* use 8.3 name */ | |||
5037 | ||||
5038 | switch (dev->ignore_hidden) | |||
5039 | { | |||
5040 | default: | |||
5041 | case 2: | |||
5042 | if (dev->fdata.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) | |||
5043 | break; | |||
5044 | ||||
5045 | case 1: | |||
5046 | if (temp[0] == '.' && | |||
5047 | (temp[1] == '\0' || | |||
5048 | (temp[1] == '.' && (temp[2] == '\0')))) | |||
5049 | break; | |||
5050 | ||||
5051 | case 0: | |||
5052 | *name = temp; | |||
5053 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5054 | } | |||
5055 | ||||
5056 | #endif | |||
5057 | } | |||
5058 | ||||
5059 | return e; | |||
5060 | } | |||
5061 | ||||
5062 | #endif | |||
5063 | ||||
5064 | ||||
5065 | /*---------------------------------------------------------------------------*/ | |||
5066 | ||||
5067 | /* Event-queue device. */ | |||
5068 | ||||
5069 | typedef struct ___device_event_queue_struct | |||
5070 | { | |||
5071 | ___device base; | |||
5072 | ||||
5073 | int index; | |||
5074 | ||||
5075 | #ifdef USE_WIN32 | |||
5076 | ||||
5077 | DWORD event_mask; | |||
5078 | ||||
5079 | #endif | |||
5080 | } ___device_event_queue; | |||
5081 | ||||
5082 | typedef struct ___device_event_queue_vtbl_struct | |||
5083 | { | |||
5084 | ___device_vtbl base; | |||
5085 | } ___device_event_queue_vtbl; | |||
5086 | ||||
5087 | ___HIDDENstatic int ___device_event_queue_kind | |||
5088 | ___P((___device *self),(___device *self) | |||
5089 | (self)(___device *self) | |||
5090 | ___device *self;)(___device *self) | |||
5091 | { | |||
5092 | return ___EVENT_QUEUE_KIND(1 +2048); | |||
5093 | } | |||
5094 | ||||
5095 | ___HIDDENstatic ___SCMOBJlong ___device_event_queue_close_virt | |||
5096 | ___P((___device *self,(___device *self, int direction) | |||
5097 | int direction),(___device *self, int direction) | |||
5098 | (self,(___device *self, int direction) | |||
5099 | direction)(___device *self, int direction) | |||
5100 | ___device *self;(___device *self, int direction) | |||
5101 | int direction;)(___device *self, int direction) | |||
5102 | { | |||
5103 | ___device_event_queue *d = ___CAST(___device_event_queue*,self)((___device_event_queue*)(self)); | |||
5104 | ||||
5105 | if (d->base.read_stage == ___STAGE_CLOSED3) | |||
5106 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5107 | ||||
5108 | if (direction & ___DIRECTION_RD1) | |||
5109 | { | |||
5110 | d->base.read_stage = ___STAGE_CLOSED3; /* avoid multiple closes */ | |||
5111 | } | |||
5112 | ||||
5113 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5114 | } | |||
5115 | ||||
5116 | ___HIDDENstatic ___SCMOBJlong ___device_event_queue_select_virt | |||
5117 | ___P((___device *self,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5118 | ___BOOL for_writing,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5119 | int i,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5120 | int pass,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5121 | ___device_select_state *state),(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5122 | (self,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5123 | for_writing,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5124 | i,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5125 | pass,(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5126 | state)(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5127 | ___device *self;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5128 | ___BOOL for_writing;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5129 | int i;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5130 | int pass;(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5131 | ___device_select_state *state;)(___device *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5132 | { | |||
5133 | ___device_event_queue *d = ___CAST(___device_event_queue*,self)((___device_event_queue*)(self)); | |||
5134 | int stage = (for_writing | |||
5135 | ? d->base.write_stage | |||
5136 | : d->base.read_stage); | |||
5137 | ||||
5138 | if (pass == ___SELECT_PASS_11) | |||
5139 | { | |||
5140 | if (stage != ___STAGE_OPEN0) | |||
5141 | state->timeout = ___time_mod.time_neg_infinity; | |||
5142 | else | |||
5143 | { | |||
5144 | #ifdef USE_WIN32 | |||
5145 | ||||
5146 | state->message_queue_mask = d->event_mask; | |||
5147 | state->message_queue_dev_pos = i; | |||
5148 | ||||
5149 | #endif | |||
5150 | } | |||
5151 | ||||
5152 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
5153 | } | |||
5154 | ||||
5155 | /* pass == ___SELECT_PASS_CHECK */ | |||
5156 | ||||
5157 | if (stage != ___STAGE_OPEN0) | |||
5158 | state->devs[i] = NULL((void*)0); | |||
5159 | else | |||
5160 | { | |||
5161 | #ifdef USE_WIN32 | |||
5162 | ||||
5163 | if (state->devs_next[i] != -1) | |||
5164 | state->devs[i] = NULL((void*)0); | |||
5165 | ||||
5166 | #endif | |||
5167 | } | |||
5168 | ||||
5169 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5170 | } | |||
5171 | ||||
5172 | ___HIDDENstatic ___SCMOBJlong ___device_event_queue_release_virt | |||
5173 | ___P((___device *self),(___device *self) | |||
5174 | (self)(___device *self) | |||
5175 | ___device *self;)(___device *self) | |||
5176 | { | |||
5177 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5178 | } | |||
5179 | ||||
5180 | ___HIDDENstatic ___SCMOBJlong ___device_event_queue_force_output_virt | |||
5181 | ___P((___device *self,(___device *self, int level) | |||
5182 | int level),(___device *self, int level) | |||
5183 | (self,(___device *self, int level) | |||
5184 | level)(___device *self, int level) | |||
5185 | ___device *self;(___device *self, int level) | |||
5186 | int level;)(___device *self, int level) | |||
5187 | { | |||
5188 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5189 | } | |||
5190 | ||||
5191 | ___HIDDENstatic ___device_event_queue_vtbl ___device_event_queue_table = | |||
5192 | { | |||
5193 | { | |||
5194 | ___device_event_queue_kind, | |||
5195 | ___device_event_queue_select_virt, | |||
5196 | ___device_event_queue_release_virt, | |||
5197 | ___device_event_queue_force_output_virt, | |||
5198 | ___device_event_queue_close_virt | |||
5199 | } | |||
5200 | }; | |||
5201 | ||||
5202 | ||||
5203 | ___SCMOBJlong ___device_event_queue_setup | |||
5204 | ___P((___device_event_queue **dev,(___device_event_queue **dev, ___device_group *dgroup, long selector ) | |||
5205 | ___device_group *dgroup,(___device_event_queue **dev, ___device_group *dgroup, long selector ) | |||
5206 | ___SCMOBJ selector),(___device_event_queue **dev, ___device_group *dgroup, long selector ) | |||
5207 | (dev,(___device_event_queue **dev, ___device_group *dgroup, long selector ) | |||
5208 | dgroup,(___device_event_queue **dev, ___device_group *dgroup, long selector ) | |||
5209 | selector)(___device_event_queue **dev, ___device_group *dgroup, long selector ) | |||
5210 | ___device_event_queue **dev;(___device_event_queue **dev, ___device_group *dgroup, long selector ) | |||
5211 | ___device_group *dgroup;(___device_event_queue **dev, ___device_group *dgroup, long selector ) | |||
5212 | ___SCMOBJ selector;)(___device_event_queue **dev, ___device_group *dgroup, long selector ) | |||
5213 | { | |||
5214 | ___device_event_queue *d; | |||
5215 | ||||
5216 | d = ___CAST(___device_event_queue*,((___device_event_queue*)(___alloc_mem (sizeof (___device_event_queue )))) | |||
5217 | ___alloc_mem (sizeof (___device_event_queue)))((___device_event_queue*)(___alloc_mem (sizeof (___device_event_queue )))); | |||
5218 | ||||
5219 | if (d == NULL((void*)0)) | |||
5220 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
5221 | ||||
5222 | d->base.vtbl = &___device_event_queue_table; | |||
5223 | d->base.refcount = 1; | |||
5224 | d->base.direction = ___DIRECTION_RD1; | |||
5225 | d->base.close_direction = 0; /* prevent closing on errors */ | |||
5226 | d->base.read_stage = ___STAGE_OPEN0; | |||
5227 | d->base.write_stage = ___STAGE_CLOSED3; | |||
5228 | ||||
5229 | #ifdef USE_WIN32 | |||
5230 | ||||
5231 | d->event_mask = ___INT(selector)((selector)>>2); | |||
5232 | ||||
5233 | #endif | |||
5234 | ||||
5235 | *dev = d; | |||
5236 | ||||
5237 | ___device_add_to_group (dgroup, &d->base); | |||
5238 | ||||
5239 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5240 | } | |||
5241 | ||||
5242 | ||||
5243 | ___HIDDENstatic ___SCMOBJlong ___release_event | |||
5244 | ___P((void *x),(void *x) | |||
5245 | (x)(void *x) | |||
5246 | void *x;)(void *x) | |||
5247 | { | |||
5248 | ___release_rc (x); | |||
5249 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5250 | } | |||
5251 | ||||
5252 | ||||
5253 | ___SCMOBJlong ___device_event_queue_read | |||
5254 | ___P((___device_event_queue *dev,(___device_event_queue *dev, long *event) | |||
5255 | ___SCMOBJ *event),(___device_event_queue *dev, long *event) | |||
5256 | (dev,(___device_event_queue *dev, long *event) | |||
5257 | event)(___device_event_queue *dev, long *event) | |||
5258 | ___device_event_queue *dev;(___device_event_queue *dev, long *event) | |||
5259 | ___SCMOBJ *event;)(___device_event_queue *dev, long *event) | |||
5260 | { | |||
5261 | if (dev->base.read_stage != ___STAGE_OPEN0) | |||
5262 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
5263 | ||||
5264 | #ifdef USE_WIN32 | |||
5265 | ||||
5266 | { | |||
5267 | MSG *msg = ___CAST(MSG*, ___alloc_rc (sizeof (MSG)))((MSG*)(___alloc_rc (sizeof (MSG)))); | |||
5268 | ||||
5269 | if (msg == 0) | |||
5270 | return ___FIX(___STOC_HEAP_OVERFLOW_ERR+___RETURN_POS)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+(61<<7))+127))<<2); | |||
5271 | ||||
5272 | if (GetQueueStatus (dev->event_mask) != 0 && | |||
5273 | PeekMessage (msg, | |||
5274 | NULL((void*)0), /* retrieve messages for window and thread */ | |||
5275 | 0, /* no constraint on the message type */ | |||
5276 | 0, | |||
5277 | PM_REMOVE)) /* remove message */ | |||
5278 | return ___NONNULLPOINTER_to_SCMOBJ | |||
5279 | (___CAST(void*,msg)((void*)(msg)), | |||
5280 | ___FAL((((long)(-1))<<2)+2), | |||
5281 | ___release_event, | |||
5282 | event, | |||
5283 | ___RETURN_POS127); | |||
5284 | ||||
5285 | ___release_rc (msg); | |||
5286 | } | |||
5287 | ||||
5288 | #endif | |||
5289 | ||||
5290 | return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
5291 | } | |||
5292 | ||||
5293 | ||||
5294 | /*---------------------------------------------------------------------------*/ | |||
5295 | ||||
5296 | /* File stream device */ | |||
5297 | ||||
5298 | typedef struct ___device_file_struct | |||
5299 | { | |||
5300 | ___device_stream base; | |||
5301 | ||||
5302 | #ifndef USE_POSIX | |||
5303 | #ifndef USE_WIN32 | |||
5304 | ||||
5305 | ___FILE *stream; | |||
5306 | ||||
5307 | #endif | |||
5308 | #endif | |||
5309 | ||||
5310 | #ifdef USE_POSIX | |||
5311 | int fd; | |||
5312 | #endif | |||
5313 | ||||
5314 | #ifdef USE_WIN32 | |||
5315 | HANDLE h; | |||
5316 | int flags; | |||
5317 | #endif | |||
5318 | } ___device_file; | |||
5319 | ||||
5320 | typedef struct ___device_file_vtbl_struct | |||
5321 | { | |||
5322 | ___device_stream_vtbl base; | |||
5323 | } ___device_file_vtbl; | |||
5324 | ||||
5325 | ___HIDDENstatic int ___device_file_kind | |||
5326 | ___P((___device *self),(___device *self) | |||
5327 | (self)(___device *self) | |||
5328 | ___device *self;)(___device *self) | |||
5329 | { | |||
5330 | return ___FILE_DEVICE_KIND(15 +16); | |||
5331 | } | |||
5332 | ||||
5333 | #if 0 | |||
5334 | ||||
5335 | ___HIDDENstatic void ___device_file_restore_initial_mode | |||
5336 | ___P((___device_file *d),(___device_file *d) | |||
5337 | (d)(___device_file *d) | |||
5338 | ___device_file *d;)(___device_file *d) | |||
5339 | { | |||
5340 | #ifdef USE_POSIX | |||
5341 | ||||
5342 | /* set blocking mode */ | |||
5343 | ||||
5344 | set_fd_blocking_mode (d->fd, 1); /* ignore error */ | |||
5345 | ||||
5346 | #endif | |||
5347 | } | |||
5348 | ||||
5349 | #endif | |||
5350 | ||||
5351 | ___HIDDENstatic ___SCMOBJlong ___device_file_close_raw_virt | |||
5352 | ___P((___device_stream *self,(___device_stream *self, int direction) | |||
5353 | int direction),(___device_stream *self, int direction) | |||
5354 | (self,(___device_stream *self, int direction) | |||
5355 | direction)(___device_stream *self, int direction) | |||
5356 | ___device_stream *self;(___device_stream *self, int direction) | |||
5357 | int direction;)(___device_stream *self, int direction) | |||
5358 | { | |||
5359 | ___device_file *d = ___CAST(___device_file*,self)((___device_file*)(self)); | |||
5360 | int is_not_closed = 0; | |||
5361 | ||||
5362 | if (d->base.base.read_stage != ___STAGE_CLOSED3) | |||
5363 | is_not_closed |= ___DIRECTION_RD1; | |||
5364 | ||||
5365 | if (d->base.base.write_stage != ___STAGE_CLOSED3) | |||
5366 | is_not_closed |= ___DIRECTION_WR2; | |||
5367 | ||||
5368 | if (is_not_closed == 0) | |||
5369 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5370 | ||||
5371 | if ((is_not_closed & ~direction) == 0) | |||
5372 | { | |||
5373 | /* Close file when both sides are closed. */ | |||
5374 | ||||
5375 | d->base.base.read_stage = ___STAGE_CLOSED3; /* avoid multiple closes */ | |||
5376 | d->base.base.write_stage = ___STAGE_CLOSED3; | |||
5377 | ||||
5378 | if ((d->base.base.close_direction & d->base.base.direction) | |||
5379 | == d->base.base.direction) | |||
5380 | { | |||
5381 | #if 0 | |||
5382 | ___device_file_restore_initial_mode (d); | |||
5383 | #endif | |||
5384 | ||||
5385 | #ifndef USE_POSIX | |||
5386 | #ifndef USE_WIN32 | |||
5387 | ||||
5388 | if (d->stream != 0) | |||
5389 | if (___fclose (d->stream) != 0) | |||
5390 | return err_code_from_errno ()___err_code_from_errno(); | |||
5391 | ||||
5392 | #endif | |||
5393 | #endif | |||
5394 | ||||
5395 | #ifdef USE_POSIX | |||
5396 | if (close_no_EINTR (d->fd) < 0) | |||
5397 | return err_code_from_errno ()___err_code_from_errno(); | |||
5398 | #endif | |||
5399 | ||||
5400 | #ifdef USE_WIN32 | |||
5401 | if (!CloseHandle (d->h)) | |||
5402 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
5403 | #endif | |||
5404 | } | |||
5405 | } | |||
5406 | else if (is_not_closed & direction & ___DIRECTION_RD1) | |||
5407 | d->base.base.read_stage = ___STAGE_CLOSED3; | |||
5408 | else if (is_not_closed & direction & ___DIRECTION_WR2) | |||
5409 | d->base.base.write_stage = ___STAGE_CLOSED3; | |||
5410 | ||||
5411 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5412 | } | |||
5413 | ||||
5414 | ___HIDDENstatic ___SCMOBJlong ___device_file_select_raw_virt | |||
5415 | ___P((___device_stream *self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5416 | ___BOOL for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5417 | int i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5418 | int pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5419 | ___device_select_state *state),(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5420 | (self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5421 | for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5422 | i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5423 | pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5424 | state)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5425 | ___device_stream *self;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5426 | ___BOOL for_writing;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5427 | int i;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5428 | int pass;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5429 | ___device_select_state *state;)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state *state) | |||
5430 | { | |||
5431 | ___device_file *d = ___CAST(___device_file*,self)((___device_file*)(self)); | |||
5432 | int stage = (for_writing | |||
5433 | ? d->base.base.write_stage | |||
5434 | : d->base.base.read_stage); | |||
5435 | ||||
5436 | if (pass == ___SELECT_PASS_11) | |||
5437 | { | |||
5438 | if (stage != ___STAGE_OPEN0) | |||
5439 | state->timeout = ___time_mod.time_neg_infinity; | |||
5440 | else | |||
5441 | { | |||
5442 | #ifndef USE_POSIX | |||
5443 | #ifndef USE_WIN32 | |||
5444 | ||||
5445 | state->timeout = ___time_mod.time_neg_infinity; | |||
5446 | ||||
5447 | #endif | |||
5448 | #endif | |||
5449 | ||||
5450 | #ifdef USE_POSIX | |||
5451 | ___device_select_add_fd (state, d->fd, for_writing); | |||
5452 | #endif | |||
5453 | } | |||
5454 | return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+14)))<<2); | |||
5455 | } | |||
5456 | ||||
5457 | /* pass == ___SELECT_PASS_CHECK */ | |||
5458 | ||||
5459 | if (stage != ___STAGE_OPEN0) | |||
5460 | state->devs[i] = NULL((void*)0); | |||
5461 | else | |||
5462 | { | |||
5463 | #ifndef USE_POSIX | |||
5464 | #ifndef USE_WIN32 | |||
5465 | ||||
5466 | state->devs[i] = NULL((void*)0); | |||
5467 | ||||
5468 | #endif | |||
5469 | #endif | |||
5470 | ||||
5471 | #ifdef USE_POSIX | |||
5472 | ||||
5473 | if (for_writing | |||
5474 | ? ___FD_ISSET(d->fd, &state->writefds)((((&state->writefds)->__fds_bits)[((d->fd) / (8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) 1 << ( (d->fd) % (8 * (int) sizeof (__fd_mask))))) != 0) | |||
5475 | : ___FD_ISSET(d->fd, &state->readfds)((((&state->readfds)->__fds_bits)[((d->fd) / (8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) 1 << (( d->fd) % (8 * (int) sizeof (__fd_mask))))) != 0)) | |||
5476 | state->devs[i] = NULL((void*)0); | |||
5477 | ||||
5478 | #endif | |||
5479 | ||||
5480 | #ifdef USE_WIN32 | |||
5481 | ||||
5482 | if (state->devs_next[i] != -1) | |||
5483 | state->devs[i] = NULL((void*)0); | |||
5484 | ||||
5485 | #endif | |||
5486 | } | |||
5487 | ||||
5488 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5489 | } | |||
5490 | ||||
5491 | ___HIDDENstatic ___SCMOBJlong ___device_file_release_raw_virt | |||
5492 | ___P((___device_stream *self),(___device_stream *self) | |||
5493 | (self)(___device_stream *self) | |||
5494 | ___device_stream *self;)(___device_stream *self) | |||
5495 | { | |||
5496 | #if 0 | |||
5497 | ||||
5498 | ___device_file *d = ___CAST(___device_file*,self)((___device_file*)(self)); | |||
5499 | ||||
5500 | if (d->base.base.read_stage != ___STAGE_CLOSED3 || | |||
5501 | d->base.base.write_stage != ___STAGE_CLOSED3) | |||
5502 | ___device_file_restore_initial_mode (d); | |||
5503 | ||||
5504 | #endif | |||
5505 | ||||
5506 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5507 | } | |||
5508 | ||||
5509 | ___HIDDENstatic ___SCMOBJlong ___device_file_force_output_raw_virt | |||
5510 | ___P((___device_stream *self,(___device_stream *self, int level) | |||
5511 | int level),(___device_stream *self, int level) | |||
5512 | (self,(___device_stream *self, int level) | |||
5513 | level)(___device_stream *self, int level) | |||
5514 | ___device_stream *self;(___device_stream *self, int level) | |||
5515 | int level;)(___device_stream *self, int level) | |||
5516 | { | |||
5517 | ___device_file *d = ___CAST(___device_file*,self)((___device_file*)(self)); | |||
5518 | ||||
5519 | if (d->base.base.write_stage == ___STAGE_OPEN0) | |||
5520 | { | |||
5521 | #ifndef USE_POSIX | |||
5522 | #ifndef USE_WIN32 | |||
5523 | ||||
5524 | if (level > 0) | |||
5525 | { | |||
5526 | ___FILE *stream = d->stream; | |||
5527 | ||||
5528 | if (stream == 0) | |||
5529 | stream = ___stdoutstdout; | |||
5530 | ||||
5531 | ___fflush (stream); /* ignore error */ | |||
5532 | } | |||
5533 | ||||
5534 | #endif | |||
5535 | #endif | |||
5536 | ||||
5537 | #ifdef USE_POSIX | |||
5538 | ||||
5539 | switch (level) | |||
5540 | { | |||
5541 | case 2: | |||
5542 | case 3: | |||
5543 | ||||
5544 | #ifdef USE_fcntl | |||
5545 | #ifdef F_FULLFSYNC | |||
5546 | ||||
5547 | if (fcntl (d->fd, F_FULLFSYNC, 0) < 0) | |||
5548 | return err_code_from_errno ()___err_code_from_errno(); | |||
5549 | break; | |||
5550 | ||||
5551 | #endif | |||
5552 | #endif | |||
5553 | ||||
5554 | case 1: | |||
5555 | ||||
5556 | if (fsync (d->fd) < 0) | |||
5557 | return err_code_from_errno ()___err_code_from_errno(); | |||
5558 | break; | |||
5559 | ||||
5560 | } | |||
5561 | ||||
5562 | #endif | |||
5563 | } | |||
5564 | ||||
5565 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5566 | } | |||
5567 | ||||
5568 | ___HIDDENstatic ___SCMOBJlong ___device_file_seek_raw_virt | |||
5569 | ___P((___device_stream *self,(___device_stream *self, ___stream_index *pos, int whence) | |||
5570 | ___stream_index *pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
5571 | int whence),(___device_stream *self, ___stream_index *pos, int whence) | |||
5572 | (self,(___device_stream *self, ___stream_index *pos, int whence) | |||
5573 | pos,(___device_stream *self, ___stream_index *pos, int whence) | |||
5574 | whence)(___device_stream *self, ___stream_index *pos, int whence) | |||
5575 | ___device_stream *self;(___device_stream *self, ___stream_index *pos, int whence) | |||
5576 | ___stream_index *pos;(___device_stream *self, ___stream_index *pos, int whence) | |||
5577 | int whence;)(___device_stream *self, ___stream_index *pos, int whence) | |||
5578 | { | |||
5579 | ___device_file *d = ___CAST(___device_file*,self)((___device_file*)(self)); | |||
5580 | ||||
5581 | if (d->base.base.read_stage == ___STAGE_OPEN0 || | |||
5582 | d->base.base.write_stage == ___STAGE_OPEN0) | |||
5583 | { | |||
5584 | #ifndef USE_POSIX | |||
5585 | #ifndef USE_WIN32 | |||
5586 | ||||
5587 | int new_pos; | |||
5588 | ___FILE *stream = d->stream; | |||
5589 | ||||
5590 | if (stream == 0) | |||
5591 | stream = ___stdoutstdout; | |||
5592 | ||||
5593 | if (fseek (stream, *pos, whence) < 0 || | |||
5594 | (new_pos = ftell (stream)) < 0) | |||
5595 | return err_code_from_errno ()___err_code_from_errno(); | |||
5596 | ||||
5597 | *pos = new_pos; | |||
5598 | ||||
5599 | #endif | |||
5600 | #endif | |||
5601 | ||||
5602 | #ifdef USE_POSIX | |||
5603 | ||||
5604 | int new_pos; | |||
5605 | ||||
5606 | if ((new_pos = lseek (d->fd, *pos, whence)) < 0) | |||
5607 | return err_code_from_errno ()___err_code_from_errno(); | |||
5608 | ||||
5609 | *pos = new_pos; | |||
5610 | ||||
5611 | #endif | |||
5612 | ||||
5613 | #ifdef USE_WIN32 | |||
5614 | ||||
5615 | LARGE_INTEGER new_pos; | |||
5616 | ||||
5617 | new_pos.QuadPart = *pos; | |||
5618 | ||||
5619 | new_pos.LowPart = SetFilePointer (d->h, | |||
5620 | new_pos.LowPart, | |||
5621 | &new_pos.HighPart, | |||
5622 | whence); | |||
5623 | ||||
5624 | if (new_pos.LowPart == 0xFFFFFFFF | |||
5625 | && GetLastError () != NO_ERROR) | |||
5626 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
5627 | ||||
5628 | *pos = new_pos.LowPart; /************* incomplete... support large offsets */ | |||
5629 | ||||
5630 | #endif | |||
5631 | } | |||
5632 | ||||
5633 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5634 | } | |||
5635 | ||||
5636 | ___HIDDENstatic ___SCMOBJlong ___device_file_read_raw_virt | |||
5637 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5638 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5639 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5640 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5641 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5642 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5643 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5644 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5645 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5646 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5647 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5648 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5649 | { | |||
5650 | ___device_file *d = ___CAST(___device_file*,self)((___device_file*)(self)); | |||
5651 | ||||
5652 | if (d->base.base.read_stage != ___STAGE_OPEN0) | |||
5653 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
5654 | ||||
5655 | #ifndef USE_POSIX | |||
5656 | #ifndef USE_WIN32 | |||
5657 | ||||
5658 | { | |||
5659 | int n; | |||
5660 | ___FILE *stream = d->stream; | |||
5661 | ||||
5662 | if (stream == 0) | |||
5663 | stream = ___stdinstdin; | |||
5664 | ||||
5665 | if (stream == ___stdinstdin) | |||
5666 | len = 1; /* only read 1 byte at a time to prevent blocking on tty */ | |||
5667 | ||||
5668 | if ((n = fread (buf, 1, len, stream)) == 0) | |||
5669 | { | |||
5670 | if (ferror (stream)) | |||
5671 | { | |||
5672 | clearerr (stream); | |||
5673 | return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
5674 | } | |||
5675 | clearerr (stream); | |||
5676 | } | |||
5677 | ||||
5678 | *len_done = n; | |||
5679 | } | |||
5680 | ||||
5681 | #endif | |||
5682 | #endif | |||
5683 | ||||
5684 | #ifdef USE_POSIX | |||
5685 | ||||
5686 | { | |||
5687 | int n; | |||
5688 | ||||
5689 | if ((n = read (d->fd, buf, len)) < 0) | |||
5690 | return err_code_from_errno ()___err_code_from_errno(); | |||
5691 | ||||
5692 | *len_done = n; | |||
5693 | } | |||
5694 | ||||
5695 | #endif | |||
5696 | ||||
5697 | #ifdef USE_WIN32 | |||
5698 | ||||
5699 | { | |||
5700 | DWORD n; | |||
5701 | ||||
5702 | if (!ReadFile (d->h, buf, len, &n, NULL((void*)0))) | |||
5703 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
5704 | ||||
5705 | *len_done = n; | |||
5706 | } | |||
5707 | ||||
5708 | #endif | |||
5709 | ||||
5710 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5711 | } | |||
5712 | ||||
5713 | ___HIDDENstatic ___SCMOBJlong ___device_file_write_raw_virt | |||
5714 | ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5715 | ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5716 | ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5717 | ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5718 | (self,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5719 | buf,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5720 | len,(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5721 | len_done)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5722 | ___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5723 | ___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5724 | ___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5725 | ___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len , ___stream_index *len_done) | |||
5726 | { | |||
5727 | ___device_file *d = ___CAST(___device_file*,self)((___device_file*)(self)); | |||
5728 | ||||
5729 | if (d->base.base.write_stage != ___STAGE_OPEN0) | |||
5730 | return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+6)))<<2); | |||
5731 | ||||
5732 | #ifndef USE_POSIX | |||
5733 | #ifndef USE_WIN32 | |||
5734 | ||||
5735 | { | |||
5736 | int n; | |||
5737 | ___FILE *stream = d->stream; | |||
5738 | ||||
5739 | if (stream == 0) | |||
5740 | stream = ___stdoutstdout; | |||
5741 | ||||
5742 | if ((n = fwrite (buf, 1, len, stream)) == 0) | |||
5743 | { | |||
5744 | if (ferror (stream)) | |||
5745 | { | |||
5746 | clearerr (stream); | |||
5747 | return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
5748 | } | |||
5749 | } | |||
5750 | ||||
5751 | *len_done = n; | |||
5752 | } | |||
5753 | ||||
5754 | #endif | |||
5755 | #endif | |||
5756 | ||||
5757 | #ifdef USE_POSIX | |||
5758 | ||||
5759 | { | |||
5760 | int n; | |||
5761 | ||||
5762 | if ((n = write (d->fd, buf, len)) < 0) | |||
5763 | return err_code_from_errno ()___err_code_from_errno(); | |||
5764 | ||||
5765 | *len_done = n; | |||
5766 | } | |||
5767 | ||||
5768 | #endif | |||
5769 | ||||
5770 | #ifdef USE_WIN32 | |||
5771 | ||||
5772 | { | |||
5773 | DWORD n; | |||
5774 | ||||
5775 | if (d->flags & (1 << 3)) | |||
5776 | { | |||
5777 | ___stream_index pos = 0; /* end of file */ | |||
5778 | ___SCMOBJlong e = ___device_file_seek_raw_virt (self, &pos, FILE_END); | |||
5779 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
5780 | return e; | |||
5781 | } | |||
5782 | ||||
5783 | if (!WriteFile (d->h, buf, len, &n, NULL((void*)0))) | |||
5784 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
5785 | ||||
5786 | *len_done = n; | |||
5787 | } | |||
5788 | ||||
5789 | #endif | |||
5790 | ||||
5791 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5792 | } | |||
5793 | ||||
5794 | ||||
5795 | ___HIDDENstatic ___SCMOBJlong ___device_file_width_virt | |||
5796 | ___P((___device_stream *self),(___device_stream *self) | |||
5797 | (self)(___device_stream *self) | |||
5798 | ___device_stream *self;)(___device_stream *self) | |||
5799 | { | |||
5800 | return ___FIX(80)(((long)(80))<<2); | |||
5801 | } | |||
5802 | ||||
5803 | ||||
5804 | ___HIDDENstatic ___SCMOBJlong ___device_file_default_options_virt | |||
5805 | ___P((___device_stream *self),(___device_stream *self) | |||
5806 | (self)(___device_stream *self) | |||
5807 | ___device_stream *self;)(___device_stream *self) | |||
5808 | { | |||
5809 | int settings = ___setup_params.file_settings; | |||
5810 | int char_encoding_errors = ___CHAR_ENCODING_ERRORS(settings)((settings)&(3<<5)); | |||
5811 | int char_encoding = ___CHAR_ENCODING(settings)((settings)&(31<<0)); | |||
5812 | int eol_encoding = ___EOL_ENCODING(settings)((settings)&(3<<7)); | |||
5813 | int buffering = ___BUFFERING(settings)((settings)&(3<<9)); | |||
5814 | ||||
5815 | if (char_encoding_errors == 0) | |||
5816 | char_encoding_errors = ___CHAR_ENCODING_ERRORS_ON(1<<5); | |||
5817 | ||||
5818 | if (char_encoding == 0) | |||
5819 | char_encoding = ___CHAR_ENCODING_ISO_8859_1(2<<0); | |||
5820 | ||||
5821 | if (eol_encoding == 0) | |||
5822 | eol_encoding = ___EOL_ENCODING_LF(1<<7); | |||
5823 | ||||
5824 | #ifdef USE_WIN32 | |||
5825 | ||||
5826 | if (buffering == 0) | |||
5827 | { | |||
5828 | ___device_file *d = ___CAST(___device_file*,self)((___device_file*)(self)); | |||
5829 | ||||
5830 | if (GetFileType (d->h) == FILE_TYPE_PIPE) | |||
5831 | buffering = ___NO_BUFFERING(1<<9); | |||
5832 | else | |||
5833 | buffering = ___FULL_BUFFERING(3<<9); | |||
5834 | } | |||
5835 | ||||
5836 | #else | |||
5837 | ||||
5838 | if (buffering == 0) | |||
5839 | buffering = ___FULL_BUFFERING(3<<9); | |||
5840 | ||||
5841 | #endif | |||
5842 | ||||
5843 | #ifdef ___DEBUG | |||
5844 | ||||
5845 | ___printf ("file char_encoding_errors=%d char_encoding=%d eol_encoding=%d buffering=%d\n", | |||
5846 | char_encoding_errors, | |||
5847 | char_encoding, | |||
5848 | eol_encoding, | |||
5849 | buffering); | |||
5850 | ||||
5851 | #endif | |||
5852 | ||||
5853 | return ___FIX(___STREAM_OPTIONS(char_encoding_errors,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
5854 | char_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
5855 | eol_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
5856 | buffering,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
5857 | char_encoding_errors,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
5858 | char_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
5859 | eol_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2) | |||
5860 | buffering))(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering )+((char_encoding_errors+char_encoding+eol_encoding+buffering )<<15)))<<2); | |||
5861 | } | |||
5862 | ||||
5863 | ||||
5864 | ___HIDDENstatic ___SCMOBJlong ___device_file_options_set_virt | |||
5865 | ___P((___device_stream *self,(___device_stream *self, long options) | |||
5866 | ___SCMOBJ options),(___device_stream *self, long options) | |||
5867 | (self,(___device_stream *self, long options) | |||
5868 | options)(___device_stream *self, long options) | |||
5869 | ___device_stream *self;(___device_stream *self, long options) | |||
5870 | ___SCMOBJ options;)(___device_stream *self, long options) | |||
5871 | { | |||
5872 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
5873 | } | |||
5874 | ||||
5875 | ||||
5876 | ___HIDDENstatic ___device_file_vtbl ___device_file_table = | |||
5877 | { | |||
5878 | { | |||
5879 | { | |||
5880 | ___device_file_kind, | |||
5881 | ___device_stream_select_virt, | |||
5882 | ___device_stream_release_virt, | |||
5883 | ___device_stream_force_output_virt, | |||
5884 | ___device_stream_close_virt | |||
5885 | }, | |||
5886 | ___device_file_select_raw_virt, | |||
5887 | ___device_file_release_raw_virt, | |||
5888 | ___device_file_force_output_raw_virt, | |||
5889 | ___device_file_close_raw_virt, | |||
5890 | ___device_file_seek_raw_virt, | |||
5891 | ___device_file_read_raw_virt, | |||
5892 | ___device_file_write_raw_virt, | |||
5893 | ___device_file_width_virt, | |||
5894 | ___device_file_default_options_virt, | |||
5895 | ___device_file_options_set_virt | |||
5896 | } | |||
5897 | }; | |||
5898 | ||||
5899 | ||||
5900 | #ifndef USE_POSIX | |||
5901 | #ifndef USE_WIN32 | |||
5902 | ||||
5903 | ___HIDDENstatic ___SCMOBJlong ___device_file_setup_from_stream | |||
5904 | ___P((___device_file **dev,(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5905 | ___device_group *dgroup,(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5906 | ___FILE *stream,(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5907 | int direction),(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5908 | (dev,(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5909 | dgroup,(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5910 | stream,(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5911 | direction)(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5912 | ___device_file **dev;(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5913 | ___device_group *dgroup;(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5914 | ___FILE *stream;(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5915 | int direction;)(___device_file **dev, ___device_group *dgroup, ___FILE *stream , int direction) | |||
5916 | { | |||
5917 | ___device_file *d; | |||
5918 | ||||
5919 | d = ___CAST(___device_file*,((___device_file*)(___alloc_mem (sizeof (___device_file)))) | |||
5920 | ___alloc_mem (sizeof (___device_file)))((___device_file*)(___alloc_mem (sizeof (___device_file)))); | |||
5921 | ||||
5922 | if (d == NULL((void*)0)) | |||
5923 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
5924 | ||||
5925 | d->base.base.vtbl = &___device_file_table; | |||
5926 | d->stream = stream; | |||
5927 | ||||
5928 | *dev = d; | |||
5929 | ||||
5930 | return ___device_stream_setup | |||
5931 | (&d->base, | |||
5932 | dgroup, | |||
5933 | direction, | |||
5934 | 0); | |||
5935 | } | |||
5936 | ||||
5937 | #endif | |||
5938 | #endif | |||
5939 | ||||
5940 | ||||
5941 | #ifdef USE_POSIX | |||
5942 | ||||
5943 | ___HIDDENstatic ___SCMOBJlong ___device_file_setup_from_fd | |||
5944 | ___P((___device_file **dev,(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5945 | ___device_group *dgroup,(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5946 | int fd,(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5947 | int direction),(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5948 | (dev,(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5949 | dgroup,(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5950 | fd,(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5951 | direction)(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5952 | ___device_file **dev;(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5953 | ___device_group *dgroup;(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5954 | int fd;(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5955 | int direction;)(___device_file **dev, ___device_group *dgroup, int fd, int direction ) | |||
5956 | { | |||
5957 | ___device_file *d; | |||
5958 | ||||
5959 | d = ___CAST(___device_file*,((___device_file*)(___alloc_mem (sizeof (___device_file)))) | |||
5960 | ___alloc_mem (sizeof (___device_file)))((___device_file*)(___alloc_mem (sizeof (___device_file)))); | |||
5961 | ||||
5962 | if (d == NULL((void*)0)) | |||
5963 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
5964 | ||||
5965 | d->base.base.vtbl = &___device_file_table; | |||
5966 | d->fd = fd; | |||
5967 | ||||
5968 | *dev = d; | |||
5969 | ||||
5970 | return ___device_stream_setup | |||
5971 | (&d->base, | |||
5972 | dgroup, | |||
5973 | direction, | |||
5974 | 0); | |||
5975 | } | |||
5976 | ||||
5977 | #endif | |||
5978 | ||||
5979 | ||||
5980 | #ifdef USE_WIN32 | |||
5981 | ||||
5982 | ___HIDDENstatic ___SCMOBJlong ___device_file_setup_from_handle | |||
5983 | ___P((___device_file **dev,(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5984 | ___device_group *dgroup,(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5985 | HANDLE h,(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5986 | int flags,(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5987 | int direction,(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5988 | int pumps_on),(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5989 | (dev,(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5990 | dgroup,(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5991 | h,(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5992 | flags,(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5993 | direction,(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5994 | pumps_on)(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5995 | ___device_file **dev;(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5996 | ___device_group *dgroup;(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5997 | HANDLE h;(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5998 | int flags;(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
5999 | int direction;(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
6000 | int pumps_on;)(___device_file **dev, ___device_group *dgroup, HANDLE h, int flags, int direction, int pumps_on) | |||
6001 | { | |||
6002 | ___device_file *d; | |||
6003 | ||||
6004 | d = ___CAST(___device_file*,((___device_file*)(___alloc_mem (sizeof (___device_file)))) | |||
6005 | ___alloc_mem (sizeof (___device_file)))((___device_file*)(___alloc_mem (sizeof (___device_file)))); | |||
6006 | ||||
6007 | if (d == NULL((void*)0)) | |||
6008 | return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
6009 | ||||
6010 | d->base.base.vtbl = &___device_file_table; | |||
6011 | d->h = h; | |||
6012 | d->flags = flags; | |||
6013 | ||||
6014 | *dev = d; | |||
6015 | ||||
6016 | return ___device_stream_setup | |||
6017 | (&d->base, | |||
6018 | dgroup, | |||
6019 | direction, | |||
6020 | pumps_on); | |||
6021 | } | |||
6022 | ||||
6023 | #endif | |||
6024 | ||||
6025 | ||||
6026 | /*---------------------------------------------------------------------------*/ | |||
6027 | ||||
6028 | #ifndef USE_POSIX | |||
6029 | #ifndef USE_WIN32 | |||
6030 | ||||
6031 | ___SCMOBJlong ___device_stream_setup_from_stream | |||
6032 | ___P((___device_stream **dev,(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6033 | ___device_group *dgroup,(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6034 | ___FILE *stream,(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6035 | int kind,(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6036 | int direction),(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6037 | (dev,(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6038 | dgroup,(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6039 | ___FILE *stream,(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6040 | kind,(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6041 | direction)(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6042 | ___device_stream **dev;(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6043 | ___device_group *dgroup;(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6044 | ___FILE *stream;(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6045 | int kind;(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6046 | int direction;)(___device_stream **dev, ___device_group *dgroup, ___FILE *stream , int kind, int direction) | |||
6047 | { | |||
6048 | ___SCMOBJlong e; | |||
6049 | ___device_file *d; | |||
6050 | ||||
6051 | if ((e = ___device_file_setup_from_stream | |||
6052 | (&d, | |||
6053 | dgroup, | |||
6054 | stream, | |||
6055 | direction)) | |||
6056 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
6057 | *dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
6058 | ||||
6059 | return e; | |||
6060 | } | |||
6061 | ||||
6062 | ||||
6063 | ___HIDDENstatic void device_translate_flags | |||
6064 | ___P((int flags,(int flags, char **mode, int *direction) | |||
6065 | char **mode,(int flags, char **mode, int *direction) | |||
6066 | int *direction),(int flags, char **mode, int *direction) | |||
6067 | (flags,(int flags, char **mode, int *direction) | |||
6068 | mode,(int flags, char **mode, int *direction) | |||
6069 | direction)(int flags, char **mode, int *direction) | |||
6070 | int flags;(int flags, char **mode, int *direction) | |||
6071 | char **mode;(int flags, char **mode, int *direction) | |||
6072 | int *direction;)(int flags, char **mode, int *direction) | |||
6073 | { | |||
6074 | switch ((flags >> 4) & 3) | |||
6075 | { | |||
6076 | default: | |||
6077 | case 1: | |||
6078 | *mode = "rb"; | |||
6079 | *direction = ___DIRECTION_RD1; | |||
6080 | break; | |||
6081 | case 2: | |||
6082 | *mode = "wb"; | |||
6083 | *direction = ___DIRECTION_WR2; | |||
6084 | break; | |||
6085 | case 3: | |||
6086 | *mode = "w+b"; | |||
6087 | *direction = ___DIRECTION_RD1|___DIRECTION_WR2; | |||
6088 | break; | |||
6089 | } | |||
6090 | } | |||
6091 | ||||
6092 | #endif | |||
6093 | #endif | |||
6094 | ||||
6095 | ||||
6096 | #ifdef USE_POSIX | |||
6097 | ||||
6098 | ___HIDDENstatic int ___device_stream_kind_from_fd | |||
6099 | ___P((int fd),(int fd) | |||
6100 | (fd)(int fd) | |||
6101 | int fd;)(int fd) | |||
6102 | { | |||
6103 | /* | |||
6104 | * Determine what kind of device is attached to the file descriptor | |||
6105 | * (tty, socket, or regular file). | |||
6106 | */ | |||
6107 | ||||
6108 | if (isatty (fd)) | |||
6109 | return ___TTY_DEVICE_KIND(15 +64); | |||
6110 | ||||
6111 | #ifdef USE_stat | |||
6112 | ||||
6113 | { | |||
6114 | ___struct_statstruct stat s; | |||
6115 | ||||
6116 | if (___fstatfstat (fd, &s) < 0) | |||
6117 | return ___NONE_KIND0; | |||
6118 | ||||
6119 | if (S_ISREG(s.st_mode)((((s.st_mode)) & 0170000) == (0100000))) | |||
6120 | return ___FILE_DEVICE_KIND(15 +16); | |||
6121 | ||||
6122 | #if 0 | |||
6123 | ||||
6124 | if (S_ISDIR(s.st_mode)((((s.st_mode)) & 0170000) == (0040000))) | |||
6125 | return ???; | |||
6126 | ||||
6127 | if (S_ISLNK(s.st_mode)((((s.st_mode)) & 0170000) == (0120000))) | |||
6128 | return ???; | |||
6129 | ||||
6130 | #endif | |||
6131 | ||||
6132 | if (S_ISCHR(s.st_mode)((((s.st_mode)) & 0170000) == (0020000))) | |||
6133 | return ___FILE_DEVICE_KIND(15 +16); | |||
6134 | ||||
6135 | if (S_ISBLK(s.st_mode)((((s.st_mode)) & 0170000) == (0060000))) | |||
6136 | return ___FILE_DEVICE_KIND(15 +16); | |||
6137 | ||||
6138 | if (S_ISFIFO(s.st_mode)((((s.st_mode)) & 0170000) == (0010000))) | |||
6139 | return ___FILE_DEVICE_KIND(15 +16); | |||
6140 | ||||
6141 | #ifdef USE_NETWORKING | |||
6142 | if (S_ISSOCK(s.st_mode)((((s.st_mode)) & 0170000) == (0140000))) | |||
6143 | return ___TCP_CLIENT_DEVICE_KIND(15 +256); | |||
6144 | #endif | |||
6145 | } | |||
6146 | ||||
6147 | return ___NONE_KIND0; | |||
6148 | ||||
6149 | #else | |||
6150 | ||||
6151 | return ___FILE_DEVICE_KIND(15 +16); | |||
6152 | ||||
6153 | #endif | |||
6154 | } | |||
6155 | ||||
6156 | ||||
6157 | ___HIDDENstatic int ___device_stream_direction_from_fd | |||
6158 | ___P((int fd),(int fd) | |||
6159 | (fd)(int fd) | |||
6160 | int fd;)(int fd) | |||
6161 | { | |||
6162 | int direction = ___DIRECTION_RD1|___DIRECTION_WR2; | |||
6163 | char buf[1]; | |||
6164 | ||||
6165 | /* | |||
6166 | * A "read" and "write" of 0 bytes is attempted to tell which | |||
6167 | * directions the file descriptor supports. | |||
6168 | */ | |||
6169 | ||||
6170 | if (read (fd, buf, 0) < 0) | |||
6171 | direction &= ~___DIRECTION_RD1; | |||
6172 | ||||
6173 | if (write (fd, buf, 0) < 0) | |||
6174 | direction &= ~___DIRECTION_WR2; | |||
6175 | ||||
6176 | /* | |||
6177 | * It is likely that on some systems a zero length "read" and | |||
6178 | * "write" will return an error, regardless of the possible | |||
6179 | * operations. In this case assume that both operations are | |||
6180 | * possible. | |||
6181 | */ | |||
6182 | ||||
6183 | if (direction == 0) | |||
6184 | direction = ___DIRECTION_RD1|___DIRECTION_WR2; | |||
6185 | ||||
6186 | return direction; | |||
6187 | } | |||
6188 | ||||
6189 | ||||
6190 | ___SCMOBJlong ___device_stream_setup_from_fd | |||
6191 | ___P((___device_stream **dev,(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6192 | ___device_group *dgroup,(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6193 | int fd,(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6194 | int kind,(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6195 | int direction),(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6196 | (dev,(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6197 | dgroup,(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6198 | fd,(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6199 | kind,(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6200 | direction)(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6201 | ___device_stream **dev;(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6202 | ___device_group *dgroup;(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6203 | int fd;(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6204 | int kind;(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6205 | int direction;)(___device_stream **dev, ___device_group *dgroup, int fd, int kind, int direction) | |||
6206 | { | |||
6207 | ___SCMOBJlong e = ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
6208 | ||||
6209 | if (kind == ___NONE_KIND0) | |||
6210 | kind = ___device_stream_kind_from_fd (fd); | |||
6211 | ||||
6212 | if (direction == 0) | |||
6213 | direction = ___device_stream_direction_from_fd (fd); | |||
6214 | ||||
6215 | #ifdef ___DEBUG | |||
6216 | ___printf ("fd=%d kind=%d direction=%d\n", fd, kind, direction); | |||
6217 | #endif | |||
6218 | ||||
6219 | if (kind == ___TTY_DEVICE_KIND(15 +64)) | |||
6220 | { | |||
6221 | /* | |||
6222 | * No need to setup the file descriptor to perform nonblocking | |||
6223 | * I/O because that is done by os_tty.c in a way that restores | |||
6224 | * the blocking mode to its original mode when the process | |||
6225 | * exits. Restoring the original mode avoids some issues when | |||
6226 | * running under a shell in emacs (which gives a "Process | |||
6227 | * shell finished" error when the program terminates). | |||
6228 | */ | |||
6229 | ||||
6230 | ___device_tty *d; | |||
6231 | ||||
6232 | if ((e = ___device_tty_setup_from_fd | |||
6233 | (&d, | |||
6234 | dgroup, | |||
6235 | fd, | |||
6236 | direction)) | |||
6237 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
6238 | *dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
6239 | } | |||
6240 | else | |||
6241 | { | |||
6242 | switch (kind) | |||
6243 | { | |||
6244 | ||||
6245 | #ifdef USE_NETWORKING | |||
6246 | ||||
6247 | case ___TCP_CLIENT_DEVICE_KIND(15 +256): | |||
6248 | { | |||
6249 | ___device_tcp_client *d; | |||
6250 | struct sockaddr server_addr; | |||
6251 | ||||
6252 | if ((e = ___device_tcp_client_setup_from_socket | |||
6253 | (&d, | |||
6254 | dgroup, | |||
6255 | fd, | |||
6256 | &server_addr, | |||
6257 | 0, | |||
6258 | 0, | |||
6259 | direction)) | |||
6260 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
6261 | *dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
6262 | ||||
6263 | break; | |||
6264 | } | |||
6265 | ||||
6266 | #endif | |||
6267 | ||||
6268 | case ___FILE_DEVICE_KIND(15 +16): | |||
6269 | { | |||
6270 | ___device_file *d; | |||
6271 | ||||
6272 | #ifdef USE_NONBLOCKING_FILE_IO | |||
6273 | ||||
6274 | /* | |||
6275 | * Setup file descriptor to perform nonblocking I/O. | |||
6276 | */ | |||
6277 | ||||
6278 | if (set_fd_blocking_mode (fd, 0) != 0) /* set nonblocking mode */ | |||
6279 | return err_code_from_errno ()___err_code_from_errno(); | |||
6280 | ||||
6281 | #endif | |||
6282 | ||||
6283 | if ((e = ___device_file_setup_from_fd | |||
6284 | (&d, | |||
6285 | dgroup, | |||
6286 | fd, | |||
6287 | direction)) | |||
6288 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
6289 | *dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
6290 | ||||
6291 | break; | |||
6292 | } | |||
6293 | ||||
6294 | default: | |||
6295 | { | |||
6296 | e = ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
6297 | break; | |||
6298 | } | |||
6299 | } | |||
6300 | } | |||
6301 | ||||
6302 | return e; | |||
6303 | } | |||
6304 | ||||
6305 | ||||
6306 | ___HIDDENstatic void device_translate_flags | |||
6307 | ___P((int flags,(int flags, int *fl, int *direction) | |||
6308 | int *fl,(int flags, int *fl, int *direction) | |||
6309 | int *direction),(int flags, int *fl, int *direction) | |||
6310 | (flags,(int flags, int *fl, int *direction) | |||
6311 | fl,(int flags, int *fl, int *direction) | |||
6312 | direction)(int flags, int *fl, int *direction) | |||
6313 | int flags;(int flags, int *fl, int *direction) | |||
6314 | int *fl;(int flags, int *fl, int *direction) | |||
6315 | int *direction;)(int flags, int *fl, int *direction) | |||
6316 | { | |||
6317 | int f; | |||
6318 | ||||
6319 | switch ((flags >> 4) & 3) | |||
6320 | { | |||
6321 | default: | |||
6322 | case 1: | |||
6323 | f = O_RDONLY00; | |||
6324 | *direction = ___DIRECTION_RD1; | |||
6325 | break; | |||
6326 | case 2: | |||
6327 | f = O_WRONLY01; | |||
6328 | *direction = ___DIRECTION_WR2; | |||
6329 | break; | |||
6330 | case 3: | |||
6331 | f = O_RDWR02; | |||
6332 | *direction = ___DIRECTION_RD1|___DIRECTION_WR2; | |||
6333 | break; | |||
6334 | } | |||
6335 | ||||
6336 | if (flags & (1 << 3)) | |||
6337 | f |= O_APPEND02000; | |||
6338 | ||||
6339 | switch ((flags >> 1) & 3) | |||
6340 | { | |||
6341 | default: | |||
6342 | case 0: break; | |||
6343 | case 1: f |= O_CREAT0100; break; | |||
6344 | case 2: f |= O_CREAT0100|O_EXCL0200; break; | |||
6345 | } | |||
6346 | ||||
6347 | if (flags & 1) | |||
6348 | f |= O_TRUNC01000; | |||
6349 | ||||
6350 | /* | |||
6351 | * The O_NONBLOCK flag is not needed here because the file | |||
6352 | * descriptor will be set to nonblocking mode later on. But we do | |||
6353 | * it anyway so there is no moment in time when it is in blocking | |||
6354 | * mode. | |||
6355 | */ | |||
6356 | ||||
6357 | f |= O_NONBLOCK04000; | |||
6358 | ||||
6359 | *fl = f; | |||
6360 | } | |||
6361 | ||||
6362 | #endif | |||
6363 | ||||
6364 | ||||
6365 | #ifdef USE_WIN32 | |||
6366 | ||||
6367 | ___HIDDENstatic int ___device_stream_kind_from_handle | |||
6368 | ___P((HANDLE h),(HANDLE h) | |||
6369 | (h)(HANDLE h) | |||
6370 | HANDLE h;)(HANDLE h) | |||
6371 | { | |||
6372 | DWORD n; | |||
6373 | CONSOLE_CURSOR_INFO cinfo; | |||
6374 | DCB dcb; | |||
6375 | BY_HANDLE_FILE_INFORMATION finfo; | |||
6376 | ||||
6377 | #ifdef ___DEBUG | |||
6378 | ___printf ("GetFileType -> %d\n", ___CAST(int,GetFileType (h))((int)(GetFileType (h)))); | |||
6379 | #endif | |||
6380 | ||||
6381 | if (GetNumberOfConsoleInputEvents (h, &n)) | |||
6382 | return ___TTY_DEVICE_KIND(15 +64); | |||
6383 | ||||
6384 | if (GetConsoleCursorInfo (h, &cinfo)) | |||
6385 | return ___TTY_DEVICE_KIND(15 +64); | |||
6386 | ||||
6387 | if (GetCommState (h, &dcb)) | |||
6388 | return ___SERIAL_DEVICE_KIND(15 +128); | |||
6389 | ||||
6390 | if (GetFileType (h) == FILE_TYPE_PIPE) | |||
6391 | return ___PIPE_DEVICE_KIND(15 +32); | |||
6392 | ||||
6393 | if (GetFileType (h) == FILE_TYPE_CHAR) | |||
6394 | return ___FILE_DEVICE_KIND(15 +16); | |||
6395 | ||||
6396 | if (GetFileInformationByHandle (h, &finfo)) | |||
6397 | return ___FILE_DEVICE_KIND(15 +16); | |||
6398 | ||||
6399 | return ___NONE_KIND0; | |||
6400 | } | |||
6401 | ||||
6402 | ||||
6403 | ___HIDDENstatic int ___device_stream_direction_from_handle | |||
6404 | ___P((HANDLE h),(HANDLE h) | |||
6405 | (h)(HANDLE h) | |||
6406 | HANDLE h;)(HANDLE h) | |||
6407 | { | |||
6408 | DWORD n; | |||
6409 | int direction = ___DIRECTION_RD1|___DIRECTION_WR2; | |||
6410 | ||||
6411 | /* | |||
6412 | * A "ReadFile" and "WriteFile" of 0 bytes is attempted to tell which | |||
6413 | * directions the file handle supports. | |||
6414 | */ | |||
6415 | ||||
6416 | if (!ReadFile (h, NULL((void*)0), 0, &n, NULL((void*)0))) | |||
6417 | direction &= ~___DIRECTION_RD1; | |||
6418 | ||||
6419 | if (!WriteFile (h, NULL((void*)0), 0, &n, NULL((void*)0))) | |||
6420 | direction &= ~___DIRECTION_WR2; | |||
6421 | ||||
6422 | /* | |||
6423 | * It is likely that on some systems a zero length "ReadFile" and | |||
6424 | * "WriteFile" will return an error, regardless of the possible | |||
6425 | * operations. In this case assume that both operations are | |||
6426 | * possible. | |||
6427 | */ | |||
6428 | ||||
6429 | if (direction == 0) | |||
6430 | direction = ___DIRECTION_RD1|___DIRECTION_WR2; | |||
6431 | ||||
6432 | return direction; | |||
6433 | } | |||
6434 | ||||
6435 | ||||
6436 | ___SCMOBJlong ___device_stream_setup_from_handle | |||
6437 | ___P((___device_stream **dev,(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6438 | ___device_group *dgroup,(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6439 | HANDLE h,(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6440 | int flags,(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6441 | int kind,(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6442 | int direction),(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6443 | (dev,(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6444 | dgroup,(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6445 | h,(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6446 | flags,(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6447 | kind,(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6448 | direction)(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6449 | ___device_stream **dev;(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6450 | ___device_group *dgroup;(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6451 | HANDLE h;(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6452 | int flags;(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6453 | int kind;(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6454 | int direction;)(___device_stream **dev, ___device_group *dgroup, HANDLE h, int flags, int kind, int direction) | |||
6455 | { | |||
6456 | ___SCMOBJlong e = ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
6457 | ||||
6458 | if (kind == ___NONE_KIND0) | |||
6459 | kind = ___device_stream_kind_from_handle (h); | |||
6460 | ||||
6461 | if (direction == 0) | |||
6462 | direction = ___device_stream_direction_from_handle (h); | |||
6463 | ||||
6464 | #ifdef ___DEBUG | |||
6465 | ___printf ("kind=%d direction=%d\n", kind, direction); | |||
6466 | #endif | |||
6467 | ||||
6468 | switch (kind) | |||
6469 | { | |||
6470 | case ___TTY_DEVICE_KIND(15 +64): | |||
6471 | { | |||
6472 | ___device_tty *d; | |||
6473 | if ((e = ___device_tty_setup_from_console | |||
6474 | (&d, | |||
6475 | dgroup, | |||
6476 | direction)) | |||
6477 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
6478 | *dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
6479 | break; | |||
6480 | } | |||
6481 | ||||
6482 | case ___SERIAL_DEVICE_KIND(15 +128): | |||
6483 | { | |||
6484 | ___device_serial *d; | |||
6485 | if ((e = ___device_serial_setup_from_handle | |||
6486 | (&d, | |||
6487 | dgroup, | |||
6488 | h, | |||
6489 | direction)) | |||
6490 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
6491 | *dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
6492 | break; | |||
6493 | } | |||
6494 | ||||
6495 | case ___FILE_DEVICE_KIND(15 +16): | |||
6496 | { | |||
6497 | ___device_file *d; | |||
6498 | if ((e = ___device_file_setup_from_handle | |||
6499 | (&d, | |||
6500 | dgroup, | |||
6501 | h, | |||
6502 | flags, | |||
6503 | direction, | |||
6504 | 0)) | |||
6505 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
6506 | *dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
6507 | break; | |||
6508 | } | |||
6509 | ||||
6510 | case ___PIPE_DEVICE_KIND(15 +32): | |||
6511 | { | |||
6512 | ___device_pipe *d; | |||
6513 | if ((e = ___device_pipe_setup_from_handle | |||
6514 | (&d, | |||
6515 | dgroup, | |||
6516 | h, | |||
6517 | h, | |||
6518 | direction, | |||
6519 | 0)) | |||
6520 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
6521 | *dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
6522 | break; | |||
6523 | } | |||
6524 | ||||
6525 | default: | |||
6526 | { | |||
6527 | e = ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
6528 | break; | |||
6529 | } | |||
6530 | } | |||
6531 | ||||
6532 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
6533 | device_transfer_close_responsibility (___CAST(___device*,*dev)((___device*)(*dev))); | |||
6534 | ||||
6535 | return e; | |||
6536 | } | |||
6537 | ||||
6538 | ||||
6539 | ___HIDDENstatic void device_translate_flags | |||
6540 | ___P((int flags,(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6541 | DWORD *access_mode,(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6542 | DWORD *share_mode,(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6543 | DWORD *creation_mode,(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6544 | DWORD *attributes,(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6545 | int *direction),(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6546 | (flags,(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6547 | access_mode,(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6548 | share_mode,(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6549 | creation_mode,(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6550 | attributes,(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6551 | direction)(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6552 | int flags;(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6553 | DWORD *access_mode;(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6554 | DWORD *share_mode;(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6555 | DWORD *creation_mode;(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6556 | DWORD *attributes;(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6557 | int *direction;)(int flags, DWORD *access_mode, DWORD *share_mode, DWORD *creation_mode , DWORD *attributes, int *direction) | |||
6558 | { | |||
6559 | DWORD am; | |||
6560 | DWORD cm; | |||
6561 | ||||
6562 | switch ((flags >> 4) & 3) | |||
6563 | { | |||
6564 | default: | |||
6565 | case 1: | |||
6566 | am = GENERIC_READ; | |||
6567 | *direction = ___DIRECTION_RD1; | |||
6568 | break; | |||
6569 | case 2: | |||
6570 | am = GENERIC_WRITE; | |||
6571 | *direction = ___DIRECTION_WR2; | |||
6572 | break; | |||
6573 | case 3: | |||
6574 | am = GENERIC_READ|GENERIC_WRITE; | |||
6575 | *direction = ___DIRECTION_RD1|___DIRECTION_WR2; | |||
6576 | break; | |||
6577 | } | |||
6578 | ||||
6579 | switch ((flags >> 1) & 3) | |||
6580 | { | |||
6581 | default: | |||
6582 | case 0: | |||
6583 | if (flags & 1) | |||
6584 | cm = TRUNCATE_EXISTING; | |||
6585 | else | |||
6586 | cm = OPEN_EXISTING; | |||
6587 | break; | |||
6588 | ||||
6589 | case 1: | |||
6590 | if (flags & 1) | |||
6591 | cm = CREATE_ALWAYS; | |||
6592 | else | |||
6593 | cm = OPEN_ALWAYS; | |||
6594 | break; | |||
6595 | ||||
6596 | case 2: | |||
6597 | cm = CREATE_NEW; | |||
6598 | break; | |||
6599 | } | |||
6600 | ||||
6601 | *access_mode = am; | |||
6602 | *share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE; | |||
6603 | *creation_mode = cm; | |||
6604 | *attributes = FILE_ATTRIBUTE_NORMAL; | |||
6605 | } | |||
6606 | ||||
6607 | #endif | |||
6608 | ||||
6609 | ||||
6610 | /*---------------------------------------------------------------------------*/ | |||
6611 | ||||
6612 | #ifdef USE_execvp | |||
6613 | #define ___STREAM_OPEN_PROCESS_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native)native native | |||
6614 | #ifndef USE_openpty | |||
6615 | #ifndef USE_ptsname | |||
6616 | #undef ___STREAM_OPEN_PROCESS_CE_SELECT | |||
6617 | #endif | |||
6618 | #endif | |||
6619 | #endif | |||
6620 | ||||
6621 | #ifdef USE_CreateProcess | |||
6622 | #ifdef _UNICODE | |||
6623 | #define ___STREAM_OPEN_PROCESS_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native)native ucs2 | |||
6624 | #define CP_ENV_FLAGS CREATE_UNICODE_ENVIRONMENT | |||
6625 | #else | |||
6626 | #define ___STREAM_OPEN_PROCESS_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native)native native | |||
6627 | #define CP_ENV_FLAGS 0 | |||
6628 | #endif | |||
6629 | #endif | |||
6630 | ||||
6631 | ||||
6632 | #ifdef ___STREAM_OPEN_PROCESS_CE_SELECT | |||
6633 | ||||
6634 | #ifdef USE_execvp | |||
6635 | ||||
6636 | /**********************************/ | |||
6637 | #define USE_pipe | |||
6638 | ||||
6639 | typedef struct half_duplex_pipe | |||
6640 | { | |||
6641 | int reading_fd; | |||
6642 | int writing_fd; | |||
6643 | } half_duplex_pipe; | |||
6644 | ||||
6645 | typedef struct full_duplex_pipe | |||
6646 | { | |||
6647 | half_duplex_pipe input; | |||
6648 | half_duplex_pipe output; | |||
6649 | } full_duplex_pipe; | |||
6650 | ||||
6651 | ||||
6652 | ___HIDDENstatic int open_half_duplex_pipe | |||
6653 | ___P((half_duplex_pipe *hdp),(half_duplex_pipe *hdp) | |||
6654 | (hdp)(half_duplex_pipe *hdp) | |||
6655 | half_duplex_pipe *hdp;)(half_duplex_pipe *hdp) | |||
6656 | { | |||
6657 | int fds[2]; | |||
6658 | ||||
6659 | #ifdef USE_pipe | |||
6660 | if (pipe (fds) < 0) | |||
6661 | return -1; | |||
6662 | #endif | |||
6663 | ||||
6664 | #ifdef USE_socketpair | |||
6665 | if (socketpair (AF_UNIX1, SOCK_STREAMSOCK_STREAM, 0, fds) < 0) | |||
6666 | return -1; | |||
6667 | #endif | |||
6668 | ||||
6669 | hdp->reading_fd = fds[0]; | |||
6670 | hdp->writing_fd = fds[1]; | |||
6671 | ||||
6672 | return 0; | |||
6673 | } | |||
6674 | ||||
6675 | ___HIDDENstatic void close_half_duplex_pipe | |||
6676 | ___P((half_duplex_pipe *hdp,(half_duplex_pipe *hdp, int end) | |||
6677 | int end),(half_duplex_pipe *hdp, int end) | |||
6678 | (hdp,(half_duplex_pipe *hdp, int end) | |||
6679 | end)(half_duplex_pipe *hdp, int end) | |||
6680 | half_duplex_pipe *hdp;(half_duplex_pipe *hdp, int end) | |||
6681 | int end;)(half_duplex_pipe *hdp, int end) | |||
6682 | { | |||
6683 | if (end != 1 && hdp->reading_fd >= 0) | |||
| ||||
6684 | { | |||
6685 | close_no_EINTR (hdp->reading_fd); /* ignore error */ | |||
6686 | hdp->reading_fd = -1; | |||
6687 | } | |||
6688 | ||||
6689 | if (end != 0 && hdp->writing_fd >= 0) | |||
6690 | { | |||
6691 | close_no_EINTR (hdp->writing_fd); /* ignore error */ | |||
6692 | hdp->writing_fd = -1; | |||
6693 | } | |||
6694 | } | |||
6695 | ||||
6696 | ___HIDDENstatic int open_pseudo_terminal_master | |||
6697 | ___P((int *master_fd_ptr,(int *master_fd_ptr, int *slave_fd_ptr) | |||
6698 | int *slave_fd_ptr),(int *master_fd_ptr, int *slave_fd_ptr) | |||
6699 | (master_fd_ptr,(int *master_fd_ptr, int *slave_fd_ptr) | |||
6700 | slave_fd_ptr)(int *master_fd_ptr, int *slave_fd_ptr) | |||
6701 | int *master_fd_ptr;(int *master_fd_ptr, int *slave_fd_ptr) | |||
6702 | int *slave_fd_ptr;)(int *master_fd_ptr, int *slave_fd_ptr) | |||
6703 | { | |||
6704 | #ifdef USE_openpty | |||
6705 | ||||
6706 | return openpty (master_fd_ptr, slave_fd_ptr, NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
6707 | ||||
6708 | #else | |||
6709 | #ifdef USE_getpt | |||
6710 | ||||
6711 | *slave_fd_ptr = -1; | |||
6712 | return *master_fd_ptr = getpt (); | |||
6713 | ||||
6714 | #else | |||
6715 | ||||
6716 | *slave_fd_ptr = -1; | |||
6717 | return *master_fd_ptr = open ("/dev/ptmx", O_RDWR02 | O_NOCTTY0400); | |||
6718 | ||||
6719 | #endif | |||
6720 | #endif | |||
6721 | } | |||
6722 | ||||
6723 | ||||
6724 | #if 0 | |||
6725 | #ifndef USE_openpty | |||
6726 | /***************************/ | |||
6727 | #define __USE_XOPEN | |||
6728 | #define __USE_GNU | |||
6729 | #include <stdlib.h> | |||
6730 | #include <stropts.h> | |||
6731 | extern char *ptsname (int __fd); | |||
6732 | #endif | |||
6733 | #endif | |||
6734 | ||||
6735 | ___HIDDENstatic int setup_terminal_slave | |||
6736 | ___P((int slave_fd),(int slave_fd) | |||
6737 | (slave_fd)(int slave_fd) | |||
6738 | int slave_fd;)(int slave_fd) | |||
6739 | { | |||
6740 | struct termios tios; | |||
6741 | ||||
6742 | if (tcgetattr (slave_fd, &tios) >= 0) | |||
6743 | { | |||
6744 | tios.c_lflag &= ~(ECHO0000010 | ECHOCTL0001000 | ICANON0000002 | IEXTEN0100000 | ISIG0000001); | |||
6745 | tios.c_iflag &= ~(BRKINT0000002 | INLCR0000100 | ICRNL0000400 | INPCK0000020 | ISTRIP0000040 | IXON0002000 | IXOFF0010000); | |||
6746 | tios.c_cflag &= ~(CSIZE0000060 | PARENB0000400 | CLOCAL0004000); | |||
6747 | tios.c_cflag |= (CS80000060 | HUPCL0002000); | |||
6748 | #ifndef OCRNL0000010 | |||
6749 | #define OCRNL0000010 0 | |||
6750 | #endif | |||
6751 | tios.c_oflag &= ~(OPOST0000001 | ONLCR0000004 | OCRNL0000010); | |||
6752 | ||||
6753 | if (tcsetattr (slave_fd, TCSANOW0, &tios) >= 0) | |||
6754 | return 0; | |||
6755 | } | |||
6756 | ||||
6757 | return -1; | |||
6758 | } | |||
6759 | ||||
6760 | ||||
6761 | ___HIDDENstatic int open_pseudo_terminal_slave | |||
6762 | ___P((int master_fd,(int master_fd, int *slave_fd) | |||
6763 | int *slave_fd),(int master_fd, int *slave_fd) | |||
6764 | (master_fd,(int master_fd, int *slave_fd) | |||
6765 | slave_fd)(int master_fd, int *slave_fd) | |||
6766 | int master_fd;(int master_fd, int *slave_fd) | |||
6767 | int *slave_fd;)(int master_fd, int *slave_fd) | |||
6768 | { | |||
6769 | #ifndef USE_openpty | |||
6770 | #ifndef USE_ptsname | |||
6771 | ||||
6772 | errno(*__errno_location ()) = xxx;/********************/ | |||
6773 | return -1; | |||
6774 | ||||
6775 | #endif | |||
6776 | #endif | |||
6777 | ||||
6778 | #ifdef USE_openpty | |||
6779 | ||||
6780 | return 0; | |||
6781 | ||||
6782 | #endif | |||
6783 | ||||
6784 | #ifdef USE_ptsname | |||
6785 | ||||
6786 | int fd; | |||
6787 | char *name; | |||
6788 | ||||
6789 | if (grantpt (master_fd) >= 0 && | |||
6790 | unlockpt (master_fd) >= 0 && | |||
6791 | (name = ptsname (master_fd)) != NULL((void*)0) && | |||
6792 | (fd = open (name, O_RDWR02)) >= 0) | |||
6793 | { | |||
6794 | int tmp; | |||
6795 | ||||
6796 | if ( | |||
6797 | #ifndef HAVE_isastream | |||
6798 | 1 | |||
6799 | #else | |||
6800 | !isastream (fd) | |||
6801 | #ifdef I_PUSH | |||
6802 | || (ioctl (fd, I_PUSH, "ptem") >= 0 && | |||
6803 | ioctl (fd, I_PUSH, "ldterm") >= 0) | |||
6804 | #endif | |||
6805 | #endif | |||
6806 | ) | |||
6807 | { | |||
6808 | *slave_fd = fd; | |||
6809 | return 0; | |||
6810 | } | |||
6811 | ||||
6812 | tmp = errno(*__errno_location ()); | |||
6813 | close_no_EINTR (fd); /* ignore error */ | |||
6814 | errno(*__errno_location ()) = tmp; | |||
6815 | } | |||
6816 | ||||
6817 | return -1; | |||
6818 | ||||
6819 | #endif | |||
6820 | } | |||
6821 | ||||
6822 | ||||
6823 | ___HIDDENstatic int open_full_duplex_pipe1 | |||
6824 | ___P((full_duplex_pipe *fdp,(full_duplex_pipe *fdp, int use_pty) | |||
6825 | ___BOOL use_pty),(full_duplex_pipe *fdp, int use_pty) | |||
6826 | (fdp,(full_duplex_pipe *fdp, int use_pty) | |||
6827 | use_pty)(full_duplex_pipe *fdp, int use_pty) | |||
6828 | full_duplex_pipe *fdp;(full_duplex_pipe *fdp, int use_pty) | |||
6829 | ___BOOL use_pty;)(full_duplex_pipe *fdp, int use_pty) | |||
6830 | { | |||
6831 | fdp->input.reading_fd = -1; | |||
6832 | fdp->input.writing_fd = -1; | |||
6833 | fdp->output.reading_fd = -1; | |||
6834 | fdp->output.writing_fd = -1; | |||
6835 | ||||
6836 | if (use_pty) | |||
6837 | { | |||
6838 | int master_fd; | |||
6839 | int slave_fd; | |||
6840 | if (open_pseudo_terminal_master (&master_fd, &slave_fd) >= 0) | |||
6841 | { | |||
6842 | int master_fd_dup; | |||
6843 | int tmp; | |||
6844 | if ((master_fd_dup = dup_no_EINTR (master_fd)) >= 0) | |||
6845 | { | |||
6846 | fdp->input.writing_fd = master_fd; | |||
6847 | fdp->output.reading_fd = master_fd_dup; | |||
6848 | fdp->input.reading_fd = slave_fd; | |||
6849 | return 0; | |||
6850 | } | |||
6851 | tmp = errno(*__errno_location ()); | |||
6852 | close_no_EINTR (master_fd); /* ignore error */ | |||
6853 | if (slave_fd >= 0) | |||
6854 | close_no_EINTR (slave_fd); /* ignore error */ | |||
6855 | errno(*__errno_location ()) = tmp; | |||
6856 | } | |||
6857 | } | |||
6858 | else | |||
6859 | { | |||
6860 | if (open_half_duplex_pipe (&fdp->input) >= 0) | |||
6861 | { | |||
6862 | if (open_half_duplex_pipe (&fdp->output) >= 0) | |||
6863 | return 0; | |||
6864 | close_half_duplex_pipe (&fdp->input, 2); | |||
6865 | } | |||
6866 | } | |||
6867 | ||||
6868 | return -1; | |||
6869 | } | |||
6870 | ||||
6871 | ||||
6872 | ___HIDDENstatic int open_full_duplex_pipe2 | |||
6873 | ___P((full_duplex_pipe *fdp,(full_duplex_pipe *fdp, int use_pty) | |||
6874 | ___BOOL use_pty),(full_duplex_pipe *fdp, int use_pty) | |||
6875 | (fdp,(full_duplex_pipe *fdp, int use_pty) | |||
6876 | use_pty)(full_duplex_pipe *fdp, int use_pty) | |||
6877 | full_duplex_pipe *fdp;(full_duplex_pipe *fdp, int use_pty) | |||
6878 | ___BOOL use_pty;)(full_duplex_pipe *fdp, int use_pty) | |||
6879 | { | |||
6880 | if (use_pty) | |||
6881 | { | |||
6882 | if (setsid () >= 0 && | |||
6883 | #ifdef TIOCSCTTY0x540E | |||
6884 | ioctl (fdp->input.reading_fd, TIOCSCTTY0x540E, 0) >= 0 && | |||
6885 | #endif | |||
6886 | open_pseudo_terminal_slave (fdp->input.writing_fd, | |||
6887 | &fdp->input.reading_fd) >= 0) | |||
6888 | { | |||
6889 | int tmp; | |||
6890 | if (setup_terminal_slave (fdp->input.reading_fd) >= 0 && | |||
6891 | (fdp->output.writing_fd = dup_no_EINTR (fdp->input.reading_fd)) >= 0) | |||
6892 | return 0; | |||
6893 | tmp = errno(*__errno_location ()); | |||
6894 | close_no_EINTR (fdp->input.reading_fd); /* ignore error */ | |||
6895 | errno(*__errno_location ()) = tmp; | |||
6896 | } | |||
6897 | } | |||
6898 | else | |||
6899 | return 0; | |||
6900 | ||||
6901 | return -1; | |||
6902 | } | |||
6903 | ||||
6904 | #endif | |||
6905 | ||||
6906 | ||||
6907 | #ifdef USE_CreateProcess | |||
6908 | ||||
6909 | #define ___ESCAPE_PROCESS_ARGS | |||
6910 | ||||
6911 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char* argv_to_ccmd | |||
6912 | ___P((___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT) *argv),(char* *argv) | |||
6913 | (argv)(char* *argv) | |||
6914 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT) *argv;)(char* *argv) | |||
6915 | { | |||
6916 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char* ccmd; | |||
6917 | int ccmd_len = 0; | |||
6918 | int i = 0; | |||
6919 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char* arg; | |||
6920 | ||||
6921 | while ((arg = argv[i]) != NULL((void*)0)) | |||
6922 | { | |||
6923 | int j = 0; | |||
6924 | ||||
6925 | while (arg[j] != ___UNICODE_NUL0) | |||
6926 | j++; | |||
6927 | ||||
6928 | ccmd_len += j + 1; | |||
6929 | ||||
6930 | #ifdef ___ESCAPE_PROCESS_ARGS | |||
6931 | ||||
6932 | { | |||
6933 | ___BOOLint double_backslash = TRUE; | |||
6934 | ||||
6935 | while (--j >= 0) | |||
6936 | { | |||
6937 | ___CHAR_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char c = arg[j]; | |||
6938 | if (c == ___UNICODE_DOUBLEQUOTE34 || | |||
6939 | (double_backslash && c == ___UNICODE_BACKSLASH92)) | |||
6940 | { | |||
6941 | double_backslash = TRUE; | |||
6942 | ccmd_len++; | |||
6943 | } | |||
6944 | else | |||
6945 | double_backslash = FALSE; | |||
6946 | } | |||
6947 | ||||
6948 | ccmd_len += 2; | |||
6949 | } | |||
6950 | ||||
6951 | #endif | |||
6952 | ||||
6953 | i++; | |||
6954 | } | |||
6955 | ||||
6956 | ccmd = ___CAST(___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT),((char*)(___alloc_mem (ccmd_len * sizeof (*ccmd)))) | |||
6957 | ___alloc_mem (ccmd_len * sizeof (*ccmd)))((char*)(___alloc_mem (ccmd_len * sizeof (*ccmd)))); | |||
6958 | ||||
6959 | if (ccmd != NULL((void*)0)) | |||
6960 | { | |||
6961 | ccmd[--ccmd_len] = ___UNICODE_NUL0; | |||
6962 | ||||
6963 | while (--i >= 0) | |||
6964 | { | |||
6965 | int j = 0; | |||
6966 | ||||
6967 | arg = argv[i]; | |||
6968 | ||||
6969 | while (arg[j] != ___UNICODE_NUL0) | |||
6970 | j++; | |||
6971 | ||||
6972 | #ifdef ___ESCAPE_PROCESS_ARGS | |||
6973 | ||||
6974 | { | |||
6975 | ___BOOLint double_backslash = TRUE; | |||
6976 | ||||
6977 | ccmd[--ccmd_len] = ___UNICODE_DOUBLEQUOTE34; | |||
6978 | ||||
6979 | while (--j >= 0) | |||
6980 | { | |||
6981 | ___CHAR_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char c = arg[j]; | |||
6982 | ccmd[--ccmd_len] = c; | |||
6983 | if (c == ___UNICODE_DOUBLEQUOTE34 || | |||
6984 | (double_backslash && c == ___UNICODE_BACKSLASH92)) | |||
6985 | { | |||
6986 | ccmd[--ccmd_len] = ___UNICODE_BACKSLASH92; | |||
6987 | double_backslash = TRUE; | |||
6988 | } | |||
6989 | else | |||
6990 | double_backslash = FALSE; | |||
6991 | } | |||
6992 | ||||
6993 | ccmd[--ccmd_len] = ___UNICODE_DOUBLEQUOTE34; | |||
6994 | } | |||
6995 | ||||
6996 | #else | |||
6997 | ||||
6998 | while (--j >= 0) | |||
6999 | { | |||
7000 | ___CHAR_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char c = arg[j]; | |||
7001 | ccmd[--ccmd_len] = c; | |||
7002 | } | |||
7003 | ||||
7004 | #endif | |||
7005 | ||||
7006 | if (i > 0) | |||
7007 | ccmd[--ccmd_len] = ___UNICODE_SPACE32; | |||
7008 | } | |||
7009 | } | |||
7010 | ||||
7011 | return ccmd; | |||
7012 | } | |||
7013 | ||||
7014 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char* env_to_cenv | |||
7015 | ___P((___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT) *env),(char* *env) | |||
7016 | (env)(char* *env) | |||
7017 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT) *env;)(char* *env) | |||
7018 | { | |||
7019 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char* cenv; | |||
7020 | int cenv_len = 0; | |||
7021 | int i = 0; | |||
7022 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char* varval; | |||
7023 | ||||
7024 | while ((varval = env[i++]) != NULL((void*)0)) | |||
7025 | { | |||
7026 | int j = 0; | |||
7027 | while (varval[j++] != ___UNICODE_NUL0) | |||
7028 | ; | |||
7029 | cenv_len += j; | |||
7030 | } | |||
7031 | ||||
7032 | cenv_len++; | |||
7033 | ||||
7034 | cenv = ___CAST(___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT),((char*)(___alloc_mem (cenv_len * sizeof (*cenv)))) | |||
7035 | ___alloc_mem (cenv_len * sizeof (*cenv)))((char*)(___alloc_mem (cenv_len * sizeof (*cenv)))); | |||
7036 | ||||
7037 | if (cenv != NULL((void*)0)) | |||
7038 | { | |||
7039 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char* p = cenv; | |||
7040 | i = 0; | |||
7041 | ||||
7042 | while ((varval = env[i++]) != NULL((void*)0)) | |||
7043 | { | |||
7044 | int j = 0; | |||
7045 | while ((*p++ = varval[j++]) != ___UNICODE_NUL0) | |||
7046 | ; | |||
7047 | } | |||
7048 | ||||
7049 | *p++ = ___UNICODE_NUL0; | |||
7050 | } | |||
7051 | ||||
7052 | return cenv; | |||
7053 | } | |||
7054 | ||||
7055 | #endif | |||
7056 | ||||
7057 | ||||
7058 | ___SCMOBJlong ___device_stream_setup_from_process | |||
7059 | ___P((___device_stream **dev,(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7060 | ___device_group *dgroup,(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7061 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT) *argv,(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7062 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT) *env,(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7063 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT) dir,(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7064 | int options),(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7065 | (dev,(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7066 | dgroup,(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7067 | argv,(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7068 | env,(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7069 | dir,(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7070 | options)(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7071 | ___device_stream **dev;(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7072 | ___device_group *dgroup;(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7073 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT) *argv;(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7074 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT) *env;(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7075 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT) dir;(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7076 | int options;)(___device_stream **dev, ___device_group *dgroup, char* *argv , char* *env, char* dir, int options) | |||
7077 | { | |||
7078 | #define STDIN_REDIR1 1 | |||
7079 | #define STDOUT_REDIR2 2 | |||
7080 | #define STDERR_REDIR4 4 | |||
7081 | #define PSEUDO_TERM8 8 | |||
7082 | #define SHOW_CONSOLE16 16 | |||
7083 | ||||
7084 | #ifdef USE_execvp | |||
7085 | ||||
7086 | ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
7087 | int direction; | |||
7088 | ___device_process *d; | |||
7089 | pid_t pid = 0; | |||
7090 | half_duplex_pipe hdp_errno; | |||
7091 | full_duplex_pipe fdp; | |||
7092 | int execvp_errno; | |||
7093 | int n; | |||
7094 | ||||
7095 | /* | |||
7096 | * Block SIGCHLD so that if the process is created the | |||
7097 | * sigchld_signal_handler will find it in the device group. | |||
7098 | */ | |||
7099 | ||||
7100 | sigset_type oldmask = block_signal (SIGCHLD17); | |||
7101 | ||||
7102 | fdp.input.writing_fd = -1; | |||
7103 | fdp.output.reading_fd = -1; | |||
7104 | ||||
7105 | if (open_half_duplex_pipe (&hdp_errno) < 0) | |||
| ||||
7106 | e = err_code_from_errno ()___err_code_from_errno(); | |||
7107 | else | |||
7108 | { | |||
7109 | if ((options & (STDIN_REDIR1 | STDOUT_REDIR2 | STDERR_REDIR4)) && | |||
7110 | open_full_duplex_pipe1 (&fdp, options & PSEUDO_TERM8) < 0) | |||
7111 | e = err_code_from_errno ()___err_code_from_errno(); | |||
7112 | else | |||
7113 | { | |||
7114 | ___disable_os_interrupts (); | |||
7115 | ||||
7116 | if ((pid = fork ()) < 0) | |||
7117 | { | |||
7118 | e = err_code_from_errno ()___err_code_from_errno(); | |||
7119 | if (options & (STDIN_REDIR1 | STDOUT_REDIR2 | STDERR_REDIR4)) | |||
7120 | { | |||
7121 | close_half_duplex_pipe (&fdp.input, 2); | |||
7122 | close_half_duplex_pipe (&fdp.output, 2); | |||
7123 | } | |||
7124 | } | |||
7125 | ||||
7126 | if (pid > 0) | |||
7127 | ___enable_os_interrupts (); | |||
7128 | } | |||
7129 | ||||
7130 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7131 | close_half_duplex_pipe (&hdp_errno, 2); | |||
7132 | } | |||
7133 | ||||
7134 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7135 | { | |||
7136 | if (pid == 0) | |||
7137 | { | |||
7138 | /* child process */ | |||
7139 | ||||
7140 | restore_sigmask (oldmask); | |||
7141 | ||||
7142 | ___cleanup_os_interrupt_handling (); | |||
7143 | ||||
7144 | if (options & (STDIN_REDIR1 | STDOUT_REDIR2 | STDERR_REDIR4)) | |||
7145 | { | |||
7146 | if (open_full_duplex_pipe2 (&fdp, options & PSEUDO_TERM8) < 0 || | |||
7147 | ((options & STDIN_REDIR1) && | |||
7148 | dup2_no_EINTR (fdp.input.reading_fd, STDIN_FILENO0) < 0) || | |||
7149 | ((options & STDOUT_REDIR2) && | |||
7150 | dup2_no_EINTR (fdp.output.writing_fd, STDOUT_FILENO1) < 0) || | |||
7151 | ((options & (STDERR_REDIR4 | PSEUDO_TERM8)) && | |||
7152 | dup2_no_EINTR (fdp.output.writing_fd, STDERR_FILENO2) < 0)) | |||
7153 | goto return_errno; | |||
7154 | } | |||
7155 | ||||
7156 | #ifdef USE_fcntl | |||
7157 | #ifdef FD_CLOEXEC1 | |||
7158 | ||||
7159 | if (fcntl (hdp_errno.writing_fd, F_SETFD2, FD_CLOEXEC1) < 0) | |||
7160 | goto return_errno; | |||
7161 | ||||
7162 | #endif | |||
7163 | #endif | |||
7164 | ||||
7165 | close_half_duplex_pipe (&fdp.input, 1); | |||
7166 | close_half_duplex_pipe (&fdp.output, 0); | |||
7167 | close_half_duplex_pipe (&hdp_errno, 0); | |||
7168 | ||||
7169 | { | |||
7170 | /* Close all file descriptors that aren't used. */ | |||
7171 | ||||
7172 | int fd = sysconf (_SC_OPEN_MAX_SC_OPEN_MAX) - 1; | |||
7173 | ||||
7174 | while (fd >= 0) | |||
7175 | { | |||
7176 | if (fd != STDIN_FILENO0 && | |||
7177 | fd != STDOUT_FILENO1 && | |||
7178 | fd != STDERR_FILENO2 && | |||
7179 | fd != hdp_errno.writing_fd) | |||
7180 | close_no_EINTR (fd); /* ignore error */ | |||
7181 | fd--; | |||
7182 | } | |||
7183 | } | |||
7184 | ||||
7185 | if (dir == NULL((void*)0) || chdir (dir) == 0) | |||
7186 | { | |||
7187 | #ifdef USE_environ | |||
7188 | if (env != NULL((void*)0)) | |||
7189 | environ = env; | |||
7190 | #endif | |||
7191 | execvp (argv[0], argv); | |||
7192 | /* the exec failed, errno will be returned to parent */ | |||
7193 | } | |||
7194 | ||||
7195 | return_errno: | |||
7196 | ||||
7197 | /* return the errno to the parent process */ | |||
7198 | ||||
7199 | execvp_errno = errno(*__errno_location ()); | |||
7200 | ||||
7201 | write (hdp_errno.writing_fd, &execvp_errno, sizeof (execvp_errno)); | |||
7202 | ||||
7203 | close_half_duplex_pipe (&fdp.input, 0); | |||
7204 | close_half_duplex_pipe (&fdp.output, 1); | |||
7205 | close_half_duplex_pipe (&hdp_errno, 1); | |||
7206 | ||||
7207 | _exit (1); | |||
7208 | } | |||
7209 | ||||
7210 | /* parent process */ | |||
7211 | ||||
7212 | if (options & (STDIN_REDIR1 | STDOUT_REDIR2 | STDERR_REDIR4)) | |||
7213 | { | |||
7214 | close_half_duplex_pipe (&fdp.input, 0); | |||
7215 | close_half_duplex_pipe (&fdp.output, 1); | |||
7216 | } | |||
7217 | ||||
7218 | close_half_duplex_pipe (&hdp_errno, 1); | |||
7219 | ||||
7220 | /* | |||
7221 | * The following call to read has been known to fail with EINTR, | |||
7222 | * in particular on OpenBSD 4.5. This is probably because the | |||
7223 | * child process that is started terminates before the parent | |||
7224 | * process doing the read has time to wakeup. So the parent | |||
7225 | * process receives a SIGCHLD signal which interrupts the read. | |||
7226 | */ | |||
7227 | ||||
7228 | n = read_no_EINTR (hdp_errno.reading_fd, | |||
7229 | &execvp_errno, | |||
7230 | sizeof (execvp_errno)); | |||
7231 | ||||
7232 | if (n < 0) | |||
7233 | e = err_code_from_errno ()___err_code_from_errno(); | |||
7234 | else if (n == sizeof (execvp_errno)) | |||
7235 | { | |||
7236 | errno(*__errno_location ()) = execvp_errno; | |||
7237 | e = err_code_from_errno ()___err_code_from_errno(); | |||
7238 | } | |||
7239 | else if (n != 0) | |||
7240 | e = ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
7241 | else | |||
7242 | { | |||
7243 | direction = ___DIRECTION_RD1|___DIRECTION_WR2; | |||
7244 | ||||
7245 | e = ___device_process_setup_from_pid | |||
7246 | (&d, | |||
7247 | dgroup, | |||
7248 | pid, | |||
7249 | fdp.input.writing_fd, | |||
7250 | fdp.output.reading_fd, | |||
7251 | direction); | |||
7252 | ||||
7253 | *dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
7254 | ||||
7255 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7256 | device_transfer_close_responsibility (___CAST(___device*,d)((___device*)(d))); | |||
7257 | } | |||
7258 | ||||
7259 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7260 | if (options & (STDIN_REDIR1 | STDOUT_REDIR2 | STDERR_REDIR4)) | |||
7261 | { | |||
7262 | close_half_duplex_pipe (&fdp.input, 1); | |||
7263 | close_half_duplex_pipe (&fdp.output, 0); | |||
7264 | } | |||
7265 | ||||
7266 | close_half_duplex_pipe (&hdp_errno, 0); | |||
7267 | } | |||
7268 | ||||
7269 | restore_sigmask (oldmask); | |||
7270 | ||||
7271 | return e; | |||
7272 | ||||
7273 | #endif | |||
7274 | ||||
7275 | #ifdef USE_CreateProcess | |||
7276 | ||||
7277 | ___SCMOBJlong e; | |||
7278 | int direction; | |||
7279 | ___device_process *d; | |||
7280 | ||||
7281 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char* ccmd; | |||
7282 | ___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)char* cenv = NULL((void*)0); | |||
7283 | ||||
7284 | HANDLE hstdin_rd = NULL((void*)0); | |||
7285 | HANDLE hstdin_wr = NULL((void*)0); | |||
7286 | HANDLE hstdout_rd = NULL((void*)0); | |||
7287 | HANDLE hstdout_wr = NULL((void*)0); | |||
7288 | ||||
7289 | SECURITY_ATTRIBUTES sa; | |||
7290 | PROCESS_INFORMATION pi; | |||
7291 | STARTUPINFO si; | |||
7292 | ||||
7293 | sa.nLength = sizeof (SECURITY_ATTRIBUTES); | |||
7294 | sa.bInheritHandle = TRUE; | |||
7295 | sa.lpSecurityDescriptor = NULL((void*)0); | |||
7296 | ||||
7297 | if ((ccmd = argv_to_ccmd (argv)) == NULL((void*)0) || | |||
7298 | (env != NULL((void*)0) && (cenv = env_to_cenv (env)) == NULL((void*)0))) | |||
7299 | e = ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+5)))<<2); | |||
7300 | else | |||
7301 | { | |||
7302 | ZeroMemory (&pi, sizeof (pi)); | |||
7303 | ||||
7304 | ZeroMemory (&si, sizeof (si)); | |||
7305 | si.cb = sizeof (si); | |||
7306 | ||||
7307 | si.hStdInput = GetStdHandle (STD_INPUT_HANDLE); | |||
7308 | si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); | |||
7309 | si.hStdError = GetStdHandle (STD_ERROR_HANDLE); | |||
7310 | ||||
7311 | if (options & STDIN_REDIR1) | |||
7312 | { | |||
7313 | if (!CreatePipe (&hstdin_rd, &hstdin_wr, &sa, 0)) | |||
7314 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
7315 | else | |||
7316 | { | |||
7317 | SetHandleInformation (hstdin_wr, HANDLE_FLAG_INHERIT, 0); | |||
7318 | si.hStdInput = hstdin_rd; | |||
7319 | } | |||
7320 | } | |||
7321 | ||||
7322 | if (options & (STDOUT_REDIR2 | STDERR_REDIR4)) | |||
7323 | { | |||
7324 | if (!CreatePipe (&hstdout_rd, &hstdout_wr, &sa, 0)) | |||
7325 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
7326 | else | |||
7327 | { | |||
7328 | SetHandleInformation (hstdout_rd, HANDLE_FLAG_INHERIT, 0); | |||
7329 | if (options & STDOUT_REDIR2) | |||
7330 | si.hStdOutput = hstdout_wr; | |||
7331 | if (options & STDERR_REDIR4) | |||
7332 | si.hStdError = hstdout_wr; | |||
7333 | } | |||
7334 | } | |||
7335 | ||||
7336 | si.dwFlags |= STARTF_USESTDHANDLES; | |||
7337 | ||||
7338 | #if 0 | |||
7339 | if (hstdin_wr != NULL((void*)0)) | |||
7340 | { | |||
7341 | HANDLE h_wr; | |||
7342 | if (DuplicateHandle (GetCurrentProcess (), | |||
7343 | hstdin_wr, | |||
7344 | GetCurrentProcess (), | |||
7345 | &h_wr, | |||
7346 | 0, | |||
7347 | FALSE, | |||
7348 | DUPLICATE_SAME_ACCESS)) | |||
7349 | { | |||
7350 | CloseHandle (hstdin_wr); | |||
7351 | hstdin_wr = h_wr; | |||
7352 | } | |||
7353 | } | |||
7354 | ||||
7355 | if (hstdout_rd != NULL((void*)0)) | |||
7356 | { | |||
7357 | HANDLE h_rd; | |||
7358 | if (DuplicateHandle (GetCurrentProcess (), | |||
7359 | hstdout_rd, | |||
7360 | GetCurrentProcess (), | |||
7361 | &h_rd, | |||
7362 | 0, | |||
7363 | FALSE, | |||
7364 | DUPLICATE_SAME_ACCESS)) | |||
7365 | { | |||
7366 | CloseHandle (hstdout_rd); | |||
7367 | hstdout_rd = h_rd; | |||
7368 | } | |||
7369 | } | |||
7370 | #endif | |||
7371 | ||||
7372 | if (si.hStdError == INVALID_HANDLE_VALUE || | |||
7373 | !CreateProcess | |||
7374 | (NULL((void*)0), /* module name */ | |||
7375 | ccmd, /* command line */ | |||
7376 | NULL((void*)0), /* process handle not inheritable */ | |||
7377 | NULL((void*)0), /* thread handle not inheritable */ | |||
7378 | TRUE, /* set handle inheritance to TRUE */ | |||
7379 | (CP_ENV_FLAGS | ((options & SHOW_CONSOLE16) ? 0 : CREATE_NO_WINDOW)), /* creation flags */ | |||
7380 | cenv, /* child's environment */ | |||
7381 | dir, /* child's starting directory */ | |||
7382 | &si, /* pointer to STARTUPINFO structure */ | |||
7383 | &pi)) /* pointer to PROCESS_INFORMATION structure */ | |||
7384 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
7385 | else | |||
7386 | { | |||
7387 | direction = ___DIRECTION_RD1|___DIRECTION_WR2; | |||
7388 | ||||
7389 | e = ___device_process_setup_from_process | |||
7390 | (&d, | |||
7391 | dgroup, | |||
7392 | pi, | |||
7393 | hstdin_wr, | |||
7394 | hstdout_rd, | |||
7395 | direction); | |||
7396 | ||||
7397 | *dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
7398 | ||||
7399 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7400 | device_transfer_close_responsibility (___CAST(___device*,d)((___device*)(d))); | |||
7401 | } | |||
7402 | } | |||
7403 | ||||
7404 | if (hstdout_rd != NULL((void*)0)) | |||
7405 | CloseHandle (hstdout_wr); /* ignore error */ | |||
7406 | ||||
7407 | if (hstdin_rd != NULL((void*)0)) | |||
7408 | CloseHandle (hstdin_rd); /* ignore error */ | |||
7409 | ||||
7410 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7411 | { | |||
7412 | if (hstdout_rd != NULL((void*)0)) | |||
7413 | CloseHandle (hstdout_rd); /* ignore error */ | |||
7414 | ||||
7415 | if (hstdin_rd != NULL((void*)0)) | |||
7416 | CloseHandle (hstdin_wr); /* ignore error */ | |||
7417 | } | |||
7418 | ||||
7419 | if (cenv != NULL((void*)0)) | |||
7420 | ___free_mem (cenv); | |||
7421 | ||||
7422 | if (ccmd != NULL((void*)0)) | |||
7423 | ___free_mem (ccmd); | |||
7424 | ||||
7425 | return e; | |||
7426 | ||||
7427 | #endif | |||
7428 | } | |||
7429 | ||||
7430 | #endif | |||
7431 | ||||
7432 | ||||
7433 | ___SCMOBJlong ___os_device_process_pid | |||
7434 | ___P((___SCMOBJ dev),(long dev) | |||
7435 | (dev)(long dev) | |||
7436 | ___SCMOBJ dev;)(long dev) | |||
7437 | { | |||
7438 | ___device_process *d = | |||
7439 | ___CAST(___device_process*,___FIELD(dev,___FOREIGN_PTR))((___device_process*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7440 | ||||
7441 | #ifndef USE_POSIX | |||
7442 | #ifndef USE_WIN32 | |||
7443 | ||||
7444 | return ___FIX(0)(((long)(0))<<2); | |||
7445 | ||||
7446 | #endif | |||
7447 | #endif | |||
7448 | ||||
7449 | #ifdef USE_POSIX | |||
7450 | ||||
7451 | return ___FIX(d->pid)(((long)(d->pid))<<2); | |||
7452 | ||||
7453 | #endif | |||
7454 | ||||
7455 | #ifdef USE_WIN32 | |||
7456 | ||||
7457 | return ___FIX(d->pi.dwProcessId)(((long)(d->pi.dwProcessId))<<2); | |||
7458 | ||||
7459 | #endif | |||
7460 | } | |||
7461 | ||||
7462 | ||||
7463 | ___SCMOBJlong ___os_device_process_status | |||
7464 | ___P((___SCMOBJ dev),(long dev) | |||
7465 | (dev)(long dev) | |||
7466 | ___SCMOBJ dev;)(long dev) | |||
7467 | { | |||
7468 | ___device_process *d = | |||
7469 | ___CAST(___device_process*,___FIELD(dev,___FOREIGN_PTR))((___device_process*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7470 | ___SCMOBJlong e; | |||
7471 | ||||
7472 | if ((e = ___device_process_status_poll (d)) != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7473 | return e; | |||
7474 | ||||
7475 | if (!d->got_status) | |||
7476 | return ___FAL((((long)(-1))<<2)+2); | |||
7477 | ||||
7478 | return ___FIX(d->status)(((long)(d->status))<<2); | |||
7479 | } | |||
7480 | ||||
7481 | ||||
7482 | /*---------------------------------------------------------------------------*/ | |||
7483 | ||||
7484 | #ifndef USE_POSIX | |||
7485 | #ifndef USE_WIN32 | |||
7486 | #define ___STREAM_OPEN_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native)native native | |||
7487 | #endif | |||
7488 | #endif | |||
7489 | ||||
7490 | #ifdef USE_POSIX | |||
7491 | #define ___STREAM_OPEN_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native)native native | |||
7492 | #endif | |||
7493 | ||||
7494 | #ifdef USE_WIN32 | |||
7495 | #ifdef _UNICODE | |||
7496 | #define ___STREAM_OPEN_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native)native ucs2 | |||
7497 | #else | |||
7498 | #define ___STREAM_OPEN_PATH_CE_SELECT(latin1,utf8,ucs2,ucs4,wchar,native)native native | |||
7499 | #endif | |||
7500 | #endif | |||
7501 | ||||
7502 | ||||
7503 | #ifdef ___STREAM_OPEN_PATH_CE_SELECT | |||
7504 | ||||
7505 | ___SCMOBJlong ___device_stream_setup_from_path | |||
7506 | ___P((___device_stream **dev,(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7507 | ___device_group *dgroup,(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7508 | ___STRING_TYPE(___STREAM_OPEN_PATH_CE_SELECT) path,(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7509 | int flags,(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7510 | int mode),(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7511 | (dev,(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7512 | dgroup,(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7513 | path,(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7514 | flags,(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7515 | mode)(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7516 | ___device_stream **dev;(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7517 | ___device_group *dgroup;(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7518 | ___STRING_TYPE(___STREAM_OPEN_PATH_CE_SELECT) path;(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7519 | int flags;(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7520 | int mode;)(___device_stream **dev, ___device_group *dgroup, char* path, int flags, int mode) | |||
7521 | { | |||
7522 | ___SCMOBJlong e; | |||
7523 | ||||
7524 | #ifndef USE_POSIX | |||
7525 | #ifndef USE_WIN32 | |||
7526 | ||||
7527 | char *mod; | |||
7528 | int direction; | |||
7529 | ___FILE *stream; | |||
7530 | ||||
7531 | device_translate_flags (flags, | |||
7532 | &mod, | |||
7533 | &direction); | |||
7534 | ||||
7535 | #ifdef ___DEBUG | |||
7536 | ___printf ("path=\"%s\" mode=%s\n", path, mod); | |||
7537 | #endif | |||
7538 | ||||
7539 | if ((stream = ___fopen (path, mod)) == 0) | |||
7540 | return fnf_or_err_code_from_errno ()___err_code_from_errno(); | |||
7541 | ||||
7542 | if ((e = ___device_stream_setup_from_stream | |||
7543 | (dev, | |||
7544 | dgroup, | |||
7545 | stream, | |||
7546 | ___NONE_KIND0, | |||
7547 | direction)) | |||
7548 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7549 | ___fclose (stream); /* ignore error */ | |||
7550 | ||||
7551 | #endif | |||
7552 | #endif | |||
7553 | ||||
7554 | #ifdef USE_POSIX | |||
7555 | ||||
7556 | int fl; | |||
7557 | int direction; | |||
7558 | int fd; | |||
7559 | ||||
7560 | device_translate_flags (flags, | |||
7561 | &fl, | |||
7562 | &direction); | |||
7563 | ||||
7564 | #ifdef ___DEBUG | |||
7565 | ___printf ("path=\"%s\" fl=%d\n", path, fl); | |||
7566 | #endif | |||
7567 | ||||
7568 | if ((fd = open (path, | |||
7569 | fl, | |||
7570 | #ifdef O_BINARY | |||
7571 | O_BINARY| | |||
7572 | #endif | |||
7573 | mode)) | |||
7574 | < 0) | |||
7575 | return fnf_or_err_code_from_errno ()___err_code_from_errno(); | |||
7576 | ||||
7577 | if ((e = ___device_stream_setup_from_fd | |||
7578 | (dev, | |||
7579 | dgroup, | |||
7580 | fd, | |||
7581 | ___NONE_KIND0, | |||
7582 | direction)) | |||
7583 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7584 | close_no_EINTR (fd); /* ignore error */ | |||
7585 | ||||
7586 | #endif | |||
7587 | ||||
7588 | #ifdef USE_WIN32 | |||
7589 | ||||
7590 | DWORD access_mode; | |||
7591 | DWORD share_mode; | |||
7592 | DWORD creation_mode; | |||
7593 | DWORD attributes; | |||
7594 | int direction; | |||
7595 | HANDLE h; | |||
7596 | ||||
7597 | device_translate_flags (flags, | |||
7598 | &access_mode, | |||
7599 | &share_mode, | |||
7600 | &creation_mode, | |||
7601 | &attributes, | |||
7602 | &direction); | |||
7603 | ||||
7604 | h = CreateFile (path, | |||
7605 | access_mode, | |||
7606 | share_mode, | |||
7607 | NULL((void*)0), | |||
7608 | creation_mode, | |||
7609 | attributes, | |||
7610 | NULL((void*)0)); | |||
7611 | ||||
7612 | if (h == INVALID_HANDLE_VALUE) | |||
7613 | return fnf_or_err_code_from_GetLastError ()___fnf_or_err_code_from_GetLastError(); | |||
7614 | ||||
7615 | if ((e = ___device_stream_setup_from_handle | |||
7616 | (dev, | |||
7617 | dgroup, | |||
7618 | h, | |||
7619 | flags, | |||
7620 | ___NONE_KIND0, | |||
7621 | direction)) | |||
7622 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7623 | CloseHandle (h); /* ignore error */ | |||
7624 | ||||
7625 | #endif | |||
7626 | ||||
7627 | if (e == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7628 | device_transfer_close_responsibility (___CAST(___device*,*dev)((___device*)(*dev))); | |||
7629 | ||||
7630 | return e; | |||
7631 | } | |||
7632 | ||||
7633 | #endif | |||
7634 | ||||
7635 | ||||
7636 | /*---------------------------------------------------------------------------*/ | |||
7637 | ||||
7638 | /* Device operations. */ | |||
7639 | ||||
7640 | ___SCMOBJlong ___os_device_kind | |||
7641 | ___P((___SCMOBJ dev),(long dev) | |||
7642 | (dev)(long dev) | |||
7643 | ___SCMOBJ dev;)(long dev) | |||
7644 | { | |||
7645 | ___device *d = ___CAST(___device*,___FIELD(dev,___FOREIGN_PTR))((___device*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7646 | ||||
7647 | return ___FIX(___device_kind (d))(((long)(((___device_vtbl*)((d)->vtbl))->kind(d)))<< 2); | |||
7648 | } | |||
7649 | ||||
7650 | ||||
7651 | ___SCMOBJlong ___os_device_force_output | |||
7652 | ___P((___SCMOBJ dev,(long dev, long level) | |||
7653 | ___SCMOBJ level),(long dev, long level) | |||
7654 | (dev,(long dev, long level) | |||
7655 | level)(long dev, long level) | |||
7656 | ___SCMOBJ dev;(long dev, long level) | |||
7657 | ___SCMOBJ level;)(long dev, long level) | |||
7658 | { | |||
7659 | ___device *d = ___CAST(___device*,___FIELD(dev,___FOREIGN_PTR))((___device*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7660 | ||||
7661 | return ___device_force_output (d, ___INT(level)((level)>>2)); | |||
7662 | } | |||
7663 | ||||
7664 | ||||
7665 | ___SCMOBJlong ___os_device_close | |||
7666 | ___P((___SCMOBJ dev,(long dev, long direction) | |||
7667 | ___SCMOBJ direction),(long dev, long direction) | |||
7668 | (dev,(long dev, long direction) | |||
7669 | direction)(long dev, long direction) | |||
7670 | ___SCMOBJ dev;(long dev, long direction) | |||
7671 | ___SCMOBJ direction;)(long dev, long direction) | |||
7672 | { | |||
7673 | ___device *d = ___CAST(___device*,___FIELD(dev,___FOREIGN_PTR))((___device*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7674 | ||||
7675 | return ___device_close (d, ___INT(direction)((direction)>>2)); | |||
7676 | } | |||
7677 | ||||
7678 | ||||
7679 | /* - - - - - - - - - - - - - - - - - - */ | |||
7680 | ||||
7681 | /* Stream device operations. */ | |||
7682 | ||||
7683 | ___SCMOBJlong ___os_device_stream_seek | |||
7684 | ___P((___SCMOBJ dev,(long dev, long pos, long whence) | |||
7685 | ___SCMOBJ pos,(long dev, long pos, long whence) | |||
7686 | ___SCMOBJ whence),(long dev, long pos, long whence) | |||
7687 | (dev,(long dev, long pos, long whence) | |||
7688 | pos,(long dev, long pos, long whence) | |||
7689 | whence)(long dev, long pos, long whence) | |||
7690 | ___SCMOBJ dev;(long dev, long pos, long whence) | |||
7691 | ___SCMOBJ pos;(long dev, long pos, long whence) | |||
7692 | ___SCMOBJ whence;)(long dev, long pos, long whence) | |||
7693 | { | |||
7694 | ___device_stream *d = | |||
7695 | ___CAST(___device_stream*,___FIELD(dev,___FOREIGN_PTR))((___device_stream*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7696 | ___S32int p; | |||
7697 | ___SCMOBJlong e; | |||
7698 | ___SCMOBJlong result; | |||
7699 | ||||
7700 | if ((e = ___SCMOBJ_to_S32 (pos, &p, 2)) == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7701 | e = ___device_stream_seek (d, &p, ___INT(whence)((whence)>>2)); | |||
7702 | ||||
7703 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2) || | |||
7704 | (e = ___S32_to_SCMOBJ (p, &result, ___RETURN_POS127)) != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7705 | result = e; | |||
7706 | ||||
7707 | return result; | |||
7708 | } | |||
7709 | ||||
7710 | ||||
7711 | ___SCMOBJlong ___os_device_stream_read | |||
7712 | ___P((___SCMOBJ dev,(long dev, long buffer, long lo, long hi) | |||
7713 | ___SCMOBJ buffer,(long dev, long buffer, long lo, long hi) | |||
7714 | ___SCMOBJ lo,(long dev, long buffer, long lo, long hi) | |||
7715 | ___SCMOBJ hi),(long dev, long buffer, long lo, long hi) | |||
7716 | (dev,(long dev, long buffer, long lo, long hi) | |||
7717 | buffer,(long dev, long buffer, long lo, long hi) | |||
7718 | lo,(long dev, long buffer, long lo, long hi) | |||
7719 | hi)(long dev, long buffer, long lo, long hi) | |||
7720 | ___SCMOBJ dev;(long dev, long buffer, long lo, long hi) | |||
7721 | ___SCMOBJ buffer;(long dev, long buffer, long lo, long hi) | |||
7722 | ___SCMOBJ lo;(long dev, long buffer, long lo, long hi) | |||
7723 | ___SCMOBJ hi;)(long dev, long buffer, long lo, long hi) | |||
7724 | { | |||
7725 | ___device_stream *d = | |||
7726 | ___CAST(___device_stream*,___FIELD(dev,___FOREIGN_PTR))((___device_stream*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7727 | ___stream_index len_done; | |||
7728 | ___SCMOBJlong e; | |||
7729 | ||||
7730 | if ((e = ___device_stream_read | |||
7731 | (d, | |||
7732 | ___CAST(___U8*,___BODY_AS(buffer,___tSUBTYPED))((unsigned char*)((((long*)((buffer)-(1)))+1))) + ___INT(lo)((lo)>>2), | |||
7733 | ___INT(hi)((hi)>>2) - ___INT(lo)((lo)>>2), | |||
7734 | &len_done)) | |||
7735 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7736 | return ___FIX(len_done)(((long)(len_done))<<2); | |||
7737 | ||||
7738 | return e; | |||
7739 | } | |||
7740 | ||||
7741 | ||||
7742 | ___SCMOBJlong ___os_device_stream_write | |||
7743 | ___P((___SCMOBJ dev,(long dev, long buffer, long lo, long hi) | |||
7744 | ___SCMOBJ buffer,(long dev, long buffer, long lo, long hi) | |||
7745 | ___SCMOBJ lo,(long dev, long buffer, long lo, long hi) | |||
7746 | ___SCMOBJ hi),(long dev, long buffer, long lo, long hi) | |||
7747 | (dev,(long dev, long buffer, long lo, long hi) | |||
7748 | buffer,(long dev, long buffer, long lo, long hi) | |||
7749 | lo,(long dev, long buffer, long lo, long hi) | |||
7750 | hi)(long dev, long buffer, long lo, long hi) | |||
7751 | ___SCMOBJ dev;(long dev, long buffer, long lo, long hi) | |||
7752 | ___SCMOBJ buffer;(long dev, long buffer, long lo, long hi) | |||
7753 | ___SCMOBJ lo;(long dev, long buffer, long lo, long hi) | |||
7754 | ___SCMOBJ hi;)(long dev, long buffer, long lo, long hi) | |||
7755 | { | |||
7756 | ___device_stream *d = | |||
7757 | ___CAST(___device_stream*,___FIELD(dev,___FOREIGN_PTR))((___device_stream*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7758 | ___stream_index len_done; | |||
7759 | ___SCMOBJlong e; | |||
7760 | ||||
7761 | if ((e = ___device_stream_write | |||
7762 | (d, | |||
7763 | ___CAST(___U8*,___BODY_AS(buffer,___tSUBTYPED))((unsigned char*)((((long*)((buffer)-(1)))+1))) + ___INT(lo)((lo)>>2), | |||
7764 | ___INT(hi)((hi)>>2) - ___INT(lo)((lo)>>2), | |||
7765 | &len_done)) | |||
7766 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7767 | return ___FIX(len_done)(((long)(len_done))<<2); | |||
7768 | ||||
7769 | return e; | |||
7770 | } | |||
7771 | ||||
7772 | ||||
7773 | ___SCMOBJlong ___os_device_stream_width | |||
7774 | ___P((___SCMOBJ dev),(long dev) | |||
7775 | (dev)(long dev) | |||
7776 | ___SCMOBJ dev;)(long dev) | |||
7777 | { | |||
7778 | ___device_stream *d = | |||
7779 | ___CAST(___device_stream*,___FIELD(dev,___FOREIGN_PTR))((___device_stream*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7780 | ||||
7781 | return ___device_stream_width (d)((___device_stream_vtbl*)((d)->base.vtbl))->width(d); | |||
7782 | } | |||
7783 | ||||
7784 | ||||
7785 | ___SCMOBJlong ___os_device_stream_default_options | |||
7786 | ___P((___SCMOBJ dev),(long dev) | |||
7787 | (dev)(long dev) | |||
7788 | ___SCMOBJ dev;)(long dev) | |||
7789 | { | |||
7790 | ___device_stream *d = | |||
7791 | ___CAST(___device_stream*,___FIELD(dev,___FOREIGN_PTR))((___device_stream*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7792 | ||||
7793 | return ___device_stream_default_options (d)((___device_stream_vtbl*)((d)->base.vtbl))->default_options (d); | |||
7794 | } | |||
7795 | ||||
7796 | ||||
7797 | ___SCMOBJlong ___os_device_stream_options_set | |||
7798 | ___P((___SCMOBJ dev,(long dev, long options) | |||
7799 | ___SCMOBJ options),(long dev, long options) | |||
7800 | (dev,(long dev, long options) | |||
7801 | options)(long dev, long options) | |||
7802 | ___SCMOBJ dev;(long dev, long options) | |||
7803 | ___SCMOBJ options;)(long dev, long options) | |||
7804 | { | |||
7805 | ___device_stream *d = | |||
7806 | ___CAST(___device_stream*,___FIELD(dev,___FOREIGN_PTR))((___device_stream*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
7807 | ||||
7808 | return ___device_stream_options_set (d, options)((___device_stream_vtbl*)((d)->base.vtbl))->options_set (d,options); | |||
7809 | } | |||
7810 | ||||
7811 | ||||
7812 | /* - - - - - - - - - - - - - - - - - - */ | |||
7813 | ||||
7814 | /* Opening a predefined device (stdin, stdout, stderr, console, etc). */ | |||
7815 | ||||
7816 | ___SCMOBJlong ___os_device_stream_open_predefined | |||
7817 | ___P((___SCMOBJ index,(long index, long flags) | |||
7818 | ___SCMOBJ flags),(long index, long flags) | |||
7819 | (index,(long index, long flags) | |||
7820 | flags)(long index, long flags) | |||
7821 | ___SCMOBJ index;(long index, long flags) | |||
7822 | ___SCMOBJ flags;)(long index, long flags) | |||
7823 | { | |||
7824 | /* | |||
7825 | * The parameter "index" identifies the stream which is to be | |||
7826 | * associated with the returned device. The stream must be | |||
7827 | * currently open. The responsibility for closing the stream is not | |||
7828 | * transferred to the runtime system because the client may have to | |||
7829 | * do I/O on the stream after the runtime system terminates (for | |||
7830 | * example output on stdout). | |||
7831 | */ | |||
7832 | ||||
7833 | ___SCMOBJlong e; | |||
7834 | ___device_stream *dev; | |||
7835 | ___SCMOBJlong result; | |||
7836 | ||||
7837 | #ifndef USE_POSIX | |||
7838 | #ifndef USE_WIN32 | |||
7839 | ||||
7840 | char *mode; | |||
7841 | int direction; | |||
7842 | ___FILE *stream; | |||
7843 | ||||
7844 | device_translate_flags (___INT(flags)((flags)>>2), | |||
7845 | &mode, | |||
7846 | &direction); | |||
7847 | ||||
7848 | switch (___INT(index)((index)>>2)) | |||
7849 | { | |||
7850 | default: | |||
7851 | { | |||
7852 | switch (___INT(index)((index)>>2)) | |||
7853 | { | |||
7854 | case -1: | |||
7855 | stream = ___stdinstdin; | |||
7856 | break; | |||
7857 | case -2: | |||
7858 | stream = ___stdoutstdout; | |||
7859 | break; | |||
7860 | case -3: | |||
7861 | stream = ___stderrstderr; | |||
7862 | break; | |||
7863 | case -4: | |||
7864 | stream = 0; | |||
7865 | break; | |||
7866 | default: | |||
7867 | stream = fdopen (___INT(index)((index)>>2), mode); | |||
7868 | break; | |||
7869 | } | |||
7870 | ||||
7871 | if ((e = ___device_stream_setup_from_stream | |||
7872 | (&dev, | |||
7873 | ___global_device_group (), | |||
7874 | stream, | |||
7875 | ___NONE_KIND0, | |||
7876 | direction)) | |||
7877 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7878 | return e; | |||
7879 | ||||
7880 | break; | |||
7881 | } | |||
7882 | } | |||
7883 | ||||
7884 | #endif | |||
7885 | #endif | |||
7886 | ||||
7887 | #ifdef USE_POSIX | |||
7888 | ||||
7889 | int fl; | |||
7890 | int direction; | |||
7891 | int fd; | |||
7892 | ||||
7893 | device_translate_flags (___INT(flags)((flags)>>2), | |||
7894 | &fl, | |||
7895 | &direction); | |||
7896 | ||||
7897 | switch (___INT(index)((index)>>2)) | |||
7898 | { | |||
7899 | case -4: | |||
7900 | { | |||
7901 | ___device_tty *d; | |||
7902 | ||||
7903 | if ((e = ___device_tty_setup_console | |||
7904 | (&d, | |||
7905 | ___global_device_group (), | |||
7906 | direction)) | |||
7907 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7908 | return e; | |||
7909 | ||||
7910 | dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
7911 | ||||
7912 | break; | |||
7913 | } | |||
7914 | ||||
7915 | default: | |||
7916 | { | |||
7917 | switch (___INT(index)((index)>>2)) | |||
7918 | { | |||
7919 | case -1: | |||
7920 | fd = STDIN_FILENO0; | |||
7921 | break; | |||
7922 | case -2: | |||
7923 | fd = STDOUT_FILENO1; | |||
7924 | break; | |||
7925 | case -3: | |||
7926 | fd = STDERR_FILENO2; | |||
7927 | break; | |||
7928 | default: | |||
7929 | fd = ___INT(index)((index)>>2); | |||
7930 | break; | |||
7931 | } | |||
7932 | ||||
7933 | if ((e = ___device_stream_setup_from_fd | |||
7934 | (&dev, | |||
7935 | ___global_device_group (), | |||
7936 | fd, | |||
7937 | ___NONE_KIND0, | |||
7938 | direction)) | |||
7939 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7940 | return e; | |||
7941 | ||||
7942 | break; | |||
7943 | } | |||
7944 | } | |||
7945 | ||||
7946 | #endif | |||
7947 | ||||
7948 | #ifdef USE_WIN32 | |||
7949 | ||||
7950 | DWORD access_mode; | |||
7951 | DWORD share_mode; | |||
7952 | DWORD creation_mode; | |||
7953 | DWORD attributes; | |||
7954 | int direction; | |||
7955 | HANDLE h; | |||
7956 | ||||
7957 | device_translate_flags (___INT(flags)((flags)>>2), | |||
7958 | &access_mode, | |||
7959 | &share_mode, | |||
7960 | &creation_mode, | |||
7961 | &attributes, | |||
7962 | &direction); | |||
7963 | ||||
7964 | switch (___INT(index)((index)>>2)) | |||
7965 | { | |||
7966 | case -4: | |||
7967 | open_console: | |||
7968 | { | |||
7969 | ___device_tty *d; | |||
7970 | ||||
7971 | if ((e = ___device_tty_setup_console | |||
7972 | (&d, | |||
7973 | ___global_device_group (), | |||
7974 | direction)) | |||
7975 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
7976 | return e; | |||
7977 | ||||
7978 | dev = ___CAST(___device_stream*,d)((___device_stream*)(d)); | |||
7979 | ||||
7980 | break; | |||
7981 | } | |||
7982 | ||||
7983 | default: | |||
7984 | { | |||
7985 | switch (___INT(index)((index)>>2)) | |||
7986 | { | |||
7987 | default: | |||
7988 | case -1: | |||
7989 | h = GetStdHandle (STD_INPUT_HANDLE); | |||
7990 | break; | |||
7991 | case -2: | |||
7992 | h = GetStdHandle (STD_OUTPUT_HANDLE); | |||
7993 | break; | |||
7994 | case -3: | |||
7995 | h = GetStdHandle (STD_ERROR_HANDLE); | |||
7996 | break; | |||
7997 | } | |||
7998 | ||||
7999 | if (h == INVALID_HANDLE_VALUE) | |||
8000 | return err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
8001 | ||||
8002 | if (GetFileType (h) == FILE_TYPE_UNKNOWN) | |||
8003 | goto open_console; | |||
8004 | ||||
8005 | if ((e = ___device_stream_setup_from_handle | |||
8006 | (&dev, | |||
8007 | ___global_device_group (), | |||
8008 | h, | |||
8009 | 0, | |||
8010 | ___NONE_KIND0, | |||
8011 | direction)) | |||
8012 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8013 | return e; | |||
8014 | ||||
8015 | break; | |||
8016 | } | |||
8017 | } | |||
8018 | ||||
8019 | #endif | |||
8020 | ||||
8021 | e = ___NONNULLPOINTER_to_SCMOBJ | |||
8022 | (dev, | |||
8023 | ___FAL((((long)(-1))<<2)+2), | |||
8024 | ___device_cleanup_from_ptr, | |||
8025 | &result, | |||
8026 | ___RETURN_POS127); | |||
8027 | ||||
8028 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8029 | { | |||
8030 | ___device_cleanup (___CAST(___device*,dev)((___device*)(dev))); /* ignore error */ | |||
8031 | return e; | |||
8032 | } | |||
8033 | ||||
8034 | ___release_scmobj (result); | |||
8035 | ||||
8036 | return result; | |||
8037 | } | |||
8038 | ||||
8039 | ||||
8040 | /* - - - - - - - - - - - - - - - - - - */ | |||
8041 | ||||
8042 | /* Opening a path. */ | |||
8043 | ||||
8044 | ___SCMOBJlong ___os_device_stream_open_path | |||
8045 | ___P((___SCMOBJ path,(long path, long flags, long mode) | |||
8046 | ___SCMOBJ flags,(long path, long flags, long mode) | |||
8047 | ___SCMOBJ mode),(long path, long flags, long mode) | |||
8048 | (path,(long path, long flags, long mode) | |||
8049 | flags,(long path, long flags, long mode) | |||
8050 | mode)(long path, long flags, long mode) | |||
8051 | ___SCMOBJ path;(long path, long flags, long mode) | |||
8052 | ___SCMOBJ flags;(long path, long flags, long mode) | |||
8053 | ___SCMOBJ mode;)(long path, long flags, long mode) | |||
8054 | { | |||
8055 | #ifndef ___STREAM_OPEN_PATH_CE_SELECT | |||
8056 | ||||
8057 | return ___FIX(___UNIMPL_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+4)))<<2); | |||
8058 | ||||
8059 | #else | |||
8060 | ||||
8061 | ___SCMOBJlong e; | |||
8062 | ___SCMOBJlong result; | |||
8063 | ___device_stream *dev; | |||
8064 | void *cpath; | |||
8065 | ||||
8066 | if ((e = ___SCMOBJ_to_NONNULLSTRING | |||
8067 | (path, | |||
8068 | &cpath, | |||
8069 | 1, | |||
8070 | ___CE(___STREAM_OPEN_PATH_CE_SELECT)(20<<0), | |||
8071 | 0)) | |||
8072 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8073 | result = e; | |||
8074 | else | |||
8075 | { | |||
8076 | ___STRING_TYPE(___STREAM_OPEN_PATH_CE_SELECT)char* p = | |||
8077 | ___CAST(___STRING_TYPE(___STREAM_OPEN_PATH_CE_SELECT),cpath)((char*)(cpath)); | |||
8078 | ||||
8079 | if ((e = ___device_stream_setup_from_path | |||
8080 | (&dev, | |||
8081 | ___global_device_group (), | |||
8082 | p, | |||
8083 | ___INT(flags)((flags)>>2), | |||
8084 | ___INT(mode)((mode)>>2))) | |||
8085 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8086 | result = e; | |||
8087 | else | |||
8088 | { | |||
8089 | if ((e = ___NONNULLPOINTER_to_SCMOBJ | |||
8090 | (dev, | |||
8091 | ___FAL((((long)(-1))<<2)+2), | |||
8092 | ___device_cleanup_from_ptr, | |||
8093 | &result, | |||
8094 | ___RETURN_POS127)) | |||
8095 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8096 | { | |||
8097 | ___device_cleanup (___CAST(___device*,dev)((___device*)(dev))); /* ignore error */ | |||
8098 | result = e; | |||
8099 | } | |||
8100 | } | |||
8101 | ||||
8102 | ___release_string (cpath); | |||
8103 | } | |||
8104 | ||||
8105 | ___release_scmobj (result); | |||
8106 | ||||
8107 | return result; | |||
8108 | ||||
8109 | #endif | |||
8110 | } | |||
8111 | ||||
8112 | ||||
8113 | /* - - - - - - - - - - - - - - - - - - */ | |||
8114 | ||||
8115 | /* Opening a process. */ | |||
8116 | ||||
8117 | ___SCMOBJlong ___os_device_stream_open_process | |||
8118 | ___P((___SCMOBJ path_and_args,(long path_and_args, long environment, long directory, long options ) | |||
8119 | ___SCMOBJ environment,(long path_and_args, long environment, long directory, long options ) | |||
8120 | ___SCMOBJ directory,(long path_and_args, long environment, long directory, long options ) | |||
8121 | ___SCMOBJ options),(long path_and_args, long environment, long directory, long options ) | |||
8122 | (path_and_args,(long path_and_args, long environment, long directory, long options ) | |||
8123 | environment,(long path_and_args, long environment, long directory, long options ) | |||
8124 | directory,(long path_and_args, long environment, long directory, long options ) | |||
8125 | options)(long path_and_args, long environment, long directory, long options ) | |||
8126 | ___SCMOBJ path_and_args;(long path_and_args, long environment, long directory, long options ) | |||
8127 | ___SCMOBJ environment;(long path_and_args, long environment, long directory, long options ) | |||
8128 | ___SCMOBJ directory;(long path_and_args, long environment, long directory, long options ) | |||
8129 | ___SCMOBJ options;)(long path_and_args, long environment, long directory, long options ) | |||
8130 | { | |||
8131 | #ifndef ___STREAM_OPEN_PROCESS_CE_SELECT | |||
8132 | ||||
8133 | return ___FIX(___UNIMPL_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+4)))<<2); | |||
8134 | ||||
8135 | #else | |||
8136 | ||||
8137 | ___SCMOBJlong e; | |||
8138 | ___device_stream *dev; | |||
8139 | ___SCMOBJlong result; | |||
8140 | void *argv = NULL((void*)0); | |||
8141 | void *env = NULL((void*)0); | |||
8142 | void *dir = NULL((void*)0); | |||
8143 | ||||
8144 | if ((e = ___SCMOBJ_to_NONNULLSTRINGLIST | |||
8145 | (path_and_args, | |||
8146 | &argv, | |||
8147 | 1, | |||
8148 | ___CE(___STREAM_OPEN_PROCESS_CE_SELECT)(20<<0))) | |||
8149 | != ___FIX(___NO_ERR)(((long)(0))<<2) || | |||
8150 | (environment != ___FAL((((long)(-1))<<2)+2) && | |||
8151 | (e = ___SCMOBJ_to_NONNULLSTRINGLIST | |||
8152 | (environment, | |||
8153 | &env, | |||
8154 | 2, | |||
8155 | ___CE(___STREAM_OPEN_PROCESS_CE_SELECT)(20<<0))) | |||
8156 | != ___FIX(___NO_ERR)(((long)(0))<<2)) || | |||
8157 | (directory != ___FAL((((long)(-1))<<2)+2) && | |||
8158 | (e = ___SCMOBJ_to_NONNULLSTRING | |||
8159 | (directory, | |||
8160 | &dir, | |||
8161 | 3, | |||
8162 | ___CE(___STREAM_OPEN_PROCESS_CE_SELECT)(20<<0), | |||
8163 | 0)) | |||
8164 | != ___FIX(___NO_ERR)(((long)(0))<<2)) || | |||
8165 | (e = ___device_stream_setup_from_process | |||
8166 | (&dev, | |||
8167 | ___global_device_group (), | |||
8168 | ___CAST(___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)*,argv)((char**)(argv)), | |||
8169 | ___CAST(___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT)*,env)((char**)(env)), | |||
8170 | ___CAST(___STRING_TYPE(___STREAM_OPEN_PROCESS_CE_SELECT),dir)((char*)(dir)), | |||
8171 | ___INT(options)((options)>>2))) | |||
8172 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8173 | result = e; | |||
8174 | else | |||
8175 | { | |||
8176 | if ((e = ___NONNULLPOINTER_to_SCMOBJ | |||
8177 | (dev, | |||
8178 | ___FAL((((long)(-1))<<2)+2), | |||
8179 | ___device_cleanup_from_ptr, | |||
8180 | &result, | |||
8181 | ___RETURN_POS127)) | |||
8182 | == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8183 | ___release_scmobj (result); | |||
8184 | } | |||
8185 | ||||
8186 | if (argv != NULL((void*)0)) | |||
8187 | ___release_string_list (argv); | |||
8188 | ||||
8189 | if (env != NULL((void*)0)) | |||
8190 | ___release_string_list (env); | |||
8191 | ||||
8192 | if (dir != NULL((void*)0)) | |||
8193 | ___release_string (dir); | |||
8194 | ||||
8195 | return result; | |||
8196 | ||||
8197 | #endif | |||
8198 | } | |||
8199 | ||||
8200 | ||||
8201 | #ifdef USE_POSIX | |||
8202 | ||||
8203 | ___HIDDENstatic void sigchld_signal_handler | |||
8204 | ___P((int sig),(int sig) | |||
8205 | (sig)(int sig) | |||
8206 | int sig;)(int sig) | |||
8207 | { | |||
8208 | #ifdef USE_signal | |||
8209 | ___set_signal_handler (SIGCHLD17, sigchld_signal_handler); | |||
8210 | #endif | |||
8211 | ||||
8212 | /* | |||
8213 | * A SIGCHLD signal indicates that at least one child has changed | |||
8214 | * status. There may be more than one because signals are not | |||
8215 | * queued. For example during a period when the SIGCHLD signal is | |||
8216 | * blocked several child processes can terminate and only one call | |||
8217 | * to the SIGCHLD handler will occur when the SIGCHLD signal is | |||
8218 | * unblocked. For this reason we must call waitpid in a loop, until | |||
8219 | * the last call indicates that no other child process is available. | |||
8220 | */ | |||
8221 | ||||
8222 | for (;;) | |||
8223 | { | |||
8224 | int status; | |||
8225 | ___device *head; | |||
8226 | pid_t pid = waitpid_no_EINTR (-1, &status, WNOHANG1); | |||
8227 | ||||
8228 | if (pid <= 0) | |||
8229 | break; | |||
8230 | ||||
8231 | /* | |||
8232 | * Find the process device structure for the process which | |||
8233 | * terminated, and save the exit status with the process device. | |||
8234 | */ | |||
8235 | ||||
8236 | head = ___global_device_group ()->list; | |||
8237 | ||||
8238 | if (head != NULL((void*)0)) | |||
8239 | { | |||
8240 | ___device *d = head->prev; | |||
8241 | ||||
8242 | do | |||
8243 | { | |||
8244 | if (___device_kind (d)((___device_vtbl*)((d)->vtbl))->kind(d) == ___PROCESS_DEVICE_KIND((15 +32)+65536)) | |||
8245 | { | |||
8246 | ___device_process *dev = ___CAST(___device_process*,d)((___device_process*)(d)); | |||
8247 | ||||
8248 | if (dev->pid == pid) | |||
8249 | { | |||
8250 | if (WIFEXITED(status)((((__extension__ (((union { __typeof(status) __in; int __i; } ) { .__in = (status) }).__i))) & 0x7f) == 0) || WIFSIGNALED(status)(((signed char) ((((__extension__ (((union { __typeof(status) __in; int __i; }) { .__in = (status) }).__i))) & 0x7f) + 1) >> 1) > 0)) | |||
8251 | ___device_process_status_set (dev, status); /* ignore error */ | |||
8252 | break; | |||
8253 | } | |||
8254 | } | |||
8255 | d = d->prev; | |||
8256 | } while (d != head); | |||
8257 | } | |||
8258 | } | |||
8259 | } | |||
8260 | ||||
8261 | #endif | |||
8262 | ||||
8263 | ||||
8264 | /* - - - - - - - - - - - - - - - - - - */ | |||
8265 | ||||
8266 | /* Opening a TCP client. */ | |||
8267 | ||||
8268 | ___SCMOBJlong ___os_device_tcp_client_open | |||
8269 | ___P((___SCMOBJ server_addr,(long server_addr, long port_num, long options) | |||
8270 | ___SCMOBJ port_num,(long server_addr, long port_num, long options) | |||
8271 | ___SCMOBJ options),(long server_addr, long port_num, long options) | |||
8272 | (server_addr,(long server_addr, long port_num, long options) | |||
8273 | port_num,(long server_addr, long port_num, long options) | |||
8274 | options)(long server_addr, long port_num, long options) | |||
8275 | ___SCMOBJ server_addr;(long server_addr, long port_num, long options) | |||
8276 | ___SCMOBJ port_num;(long server_addr, long port_num, long options) | |||
8277 | ___SCMOBJ options;)(long server_addr, long port_num, long options) | |||
8278 | { | |||
8279 | #ifndef USE_NETWORKING | |||
8280 | ||||
8281 | return ___FIX(___UNIMPL_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+4)))<<2); | |||
8282 | ||||
8283 | #else | |||
8284 | ||||
8285 | ___SCMOBJlong e; | |||
8286 | ___device_tcp_client *dev; | |||
8287 | ___SCMOBJlong result; | |||
8288 | struct sockaddr sa; | |||
8289 | int salen; | |||
8290 | ||||
8291 | if ((e = ___SCMOBJ_to_sockaddr (server_addr, port_num, &sa, &salen, 1)) | |||
8292 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8293 | return e; | |||
8294 | ||||
8295 | if ((e = ___device_tcp_client_setup_from_sockaddr | |||
8296 | (&dev, | |||
8297 | ___global_device_group (), | |||
8298 | &sa, | |||
8299 | salen, | |||
8300 | ___INT(options)((options)>>2), | |||
8301 | ___DIRECTION_RD1|___DIRECTION_WR2)) | |||
8302 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8303 | return e; | |||
8304 | ||||
8305 | if ((e = ___NONNULLPOINTER_to_SCMOBJ | |||
8306 | (dev, | |||
8307 | ___FAL((((long)(-1))<<2)+2), | |||
8308 | ___device_cleanup_from_ptr, | |||
8309 | &result, | |||
8310 | ___RETURN_POS127)) | |||
8311 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8312 | { | |||
8313 | ___device_cleanup (___CAST(___device*,dev)((___device*)(dev))); /* ignore error */ | |||
8314 | return e; | |||
8315 | } | |||
8316 | ||||
8317 | ___release_scmobj (result); | |||
8318 | ||||
8319 | return result; | |||
8320 | ||||
8321 | #endif | |||
8322 | } | |||
8323 | ||||
8324 | ||||
8325 | ___SCMOBJlong ___os_device_tcp_client_socket_info | |||
8326 | ___P((___SCMOBJ dev,(long dev, long peer) | |||
8327 | ___SCMOBJ peer),(long dev, long peer) | |||
8328 | (dev,(long dev, long peer) | |||
8329 | peer)(long dev, long peer) | |||
8330 | ___SCMOBJ dev;(long dev, long peer) | |||
8331 | ___SCMOBJ peer;)(long dev, long peer) | |||
8332 | { | |||
8333 | #ifndef USE_NETWORKING | |||
8334 | ||||
8335 | return ___FIX(___UNIMPL_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+4)))<<2); | |||
8336 | ||||
8337 | #else | |||
8338 | ||||
8339 | ___device_tcp_client *d = | |||
8340 | ___CAST(___device_tcp_client*,___FIELD(dev,___FOREIGN_PTR))((___device_tcp_client*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
8341 | struct sockaddr sa; | |||
8342 | SOCKET_LEN_TYPEsocklen_t salen; | |||
8343 | ||||
8344 | if (d->try_connect_again != 0) | |||
8345 | { | |||
8346 | if (try_connect (d) == 0) | |||
8347 | { | |||
8348 | if (d->try_connect_again != 0) | |||
8349 | return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
8350 | } | |||
8351 | else | |||
8352 | return ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
8353 | } | |||
8354 | ||||
8355 | salen = sizeof (sa); | |||
8356 | ||||
8357 | if (((peer == ___FAL((((long)(-1))<<2)+2)) | |||
8358 | ? getsockname (d->s, &sa, &salen) | |||
8359 | : getpeername (d->s, &sa, &salen)) < 0) | |||
8360 | { | |||
8361 | ___SCMOBJlong e = ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
8362 | if (NOT_CONNECTED(e)((e) == (((long)(((107)==0?0:((((int)(-1))<<29)+(((int) (320))<<16)+(107)))))<<2)) && !d->connect_done) | |||
8363 | e = ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<< 16)+(11)))))<<2); | |||
8364 | return e; | |||
8365 | } | |||
8366 | ||||
8367 | return ___sockaddr_to_SCMOBJ (&sa, salen, ___RETURN_POS127); | |||
8368 | ||||
8369 | #endif | |||
8370 | } | |||
8371 | ||||
8372 | ||||
8373 | /* - - - - - - - - - - - - - - - - - - */ | |||
8374 | ||||
8375 | /* Opening and reading a TCP server. */ | |||
8376 | ||||
8377 | ___SCMOBJlong ___os_device_tcp_server_open | |||
8378 | ___P((___SCMOBJ server_addr,(long server_addr, long port_num, long backlog, long options) | |||
8379 | ___SCMOBJ port_num,(long server_addr, long port_num, long backlog, long options) | |||
8380 | ___SCMOBJ backlog,(long server_addr, long port_num, long backlog, long options) | |||
8381 | ___SCMOBJ options),(long server_addr, long port_num, long backlog, long options) | |||
8382 | (server_addr,(long server_addr, long port_num, long backlog, long options) | |||
8383 | port_num,(long server_addr, long port_num, long backlog, long options) | |||
8384 | backlog,(long server_addr, long port_num, long backlog, long options) | |||
8385 | options)(long server_addr, long port_num, long backlog, long options) | |||
8386 | ___SCMOBJ server_addr;(long server_addr, long port_num, long backlog, long options) | |||
8387 | ___SCMOBJ port_num;(long server_addr, long port_num, long backlog, long options) | |||
8388 | ___SCMOBJ backlog;(long server_addr, long port_num, long backlog, long options) | |||
8389 | ___SCMOBJ options;)(long server_addr, long port_num, long backlog, long options) | |||
8390 | { | |||
8391 | #ifndef USE_NETWORKING | |||
8392 | ||||
8393 | return ___FIX(___UNIMPL_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+4)))<<2); | |||
8394 | ||||
8395 | #else | |||
8396 | ||||
8397 | ___SCMOBJlong e; | |||
8398 | ___device_tcp_server *dev; | |||
8399 | ___SCMOBJlong result; | |||
8400 | struct sockaddr sa; | |||
8401 | int salen; | |||
8402 | ||||
8403 | if ((e = ___SCMOBJ_to_sockaddr (server_addr, port_num, &sa, &salen, 1)) | |||
8404 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8405 | return e; | |||
8406 | ||||
8407 | e = ___device_tcp_server_setup | |||
8408 | (&dev, | |||
8409 | ___global_device_group (), | |||
8410 | &sa, | |||
8411 | salen, | |||
8412 | ___INT(backlog)((backlog)>>2), | |||
8413 | ___INT(options)((options)>>2)); | |||
8414 | ||||
8415 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8416 | return e; | |||
8417 | ||||
8418 | e = ___NONNULLPOINTER_to_SCMOBJ | |||
8419 | (dev, | |||
8420 | ___FAL((((long)(-1))<<2)+2), | |||
8421 | ___device_cleanup_from_ptr, | |||
8422 | &result, | |||
8423 | ___RETURN_POS127); | |||
8424 | ||||
8425 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8426 | { | |||
8427 | ___device_cleanup (___CAST(___device*,dev)((___device*)(dev))); /* ignore error */ | |||
8428 | return e; | |||
8429 | } | |||
8430 | ||||
8431 | ___release_scmobj (result); | |||
8432 | ||||
8433 | return result; | |||
8434 | ||||
8435 | #endif | |||
8436 | } | |||
8437 | ||||
8438 | ||||
8439 | ___SCMOBJlong ___os_device_tcp_server_read | |||
8440 | ___P((___SCMOBJ dev),(long dev) | |||
8441 | (dev)(long dev) | |||
8442 | ___SCMOBJ dev;)(long dev) | |||
8443 | { | |||
8444 | #ifndef USE_NETWORKING | |||
8445 | ||||
8446 | return ___FIX(___UNIMPL_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+4)))<<2); | |||
8447 | ||||
8448 | #else | |||
8449 | ||||
8450 | ___device_tcp_server *d = | |||
8451 | ___CAST(___device_tcp_server*,___FIELD(dev,___FOREIGN_PTR))((___device_tcp_server*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
8452 | ___SCMOBJlong e; | |||
8453 | ___device_tcp_client *client; | |||
8454 | ___SCMOBJlong result; | |||
8455 | ||||
8456 | if ((e = ___device_tcp_server_read (d, ___global_device_group (), &client)) | |||
8457 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8458 | return e; | |||
8459 | ||||
8460 | e = ___NONNULLPOINTER_to_SCMOBJ | |||
8461 | (client, | |||
8462 | ___FAL((((long)(-1))<<2)+2), | |||
8463 | ___device_cleanup_from_ptr, | |||
8464 | &result, | |||
8465 | ___RETURN_POS127); | |||
8466 | ||||
8467 | if (e != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8468 | { | |||
8469 | ___device_cleanup (___CAST(___device*,d)((___device*)(d))); /* ignore error */ | |||
8470 | return e; | |||
8471 | } | |||
8472 | ||||
8473 | ___release_scmobj (result); | |||
8474 | ||||
8475 | return result; | |||
8476 | ||||
8477 | #endif | |||
8478 | } | |||
8479 | ||||
8480 | ||||
8481 | ___SCMOBJlong ___os_device_tcp_server_socket_info | |||
8482 | ___P((___SCMOBJ dev),(long dev) | |||
8483 | (dev)(long dev) | |||
8484 | ___SCMOBJ dev;)(long dev) | |||
8485 | { | |||
8486 | #ifndef USE_NETWORKING | |||
8487 | ||||
8488 | return ___FIX(___UNIMPL_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+4)))<<2); | |||
8489 | ||||
8490 | #else | |||
8491 | ||||
8492 | ___device_tcp_server *d = | |||
8493 | ___CAST(___device_tcp_server*,___FIELD(dev,___FOREIGN_PTR))((___device_tcp_server*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
8494 | struct sockaddr sa; | |||
8495 | SOCKET_LEN_TYPEsocklen_t salen; | |||
8496 | ||||
8497 | salen = sizeof (sa); | |||
8498 | ||||
8499 | if (getsockname (d->s, &sa, &salen) < 0) | |||
8500 | return ERR_CODE_FROM_SOCKET_CALL___err_code_from_errno(); | |||
8501 | ||||
8502 | return ___sockaddr_to_SCMOBJ (&sa, salen, ___RETURN_POS127); | |||
8503 | ||||
8504 | #endif | |||
8505 | } | |||
8506 | ||||
8507 | ||||
8508 | /* - - - - - - - - - - - - - - - - - - */ | |||
8509 | ||||
8510 | /* Opening and reading a directory. */ | |||
8511 | ||||
8512 | ___SCMOBJlong ___os_device_directory_open_path | |||
8513 | ___P((___SCMOBJ path,(long path, long ignore_hidden) | |||
8514 | ___SCMOBJ ignore_hidden),(long path, long ignore_hidden) | |||
8515 | (path,(long path, long ignore_hidden) | |||
8516 | ignore_hidden)(long path, long ignore_hidden) | |||
8517 | ___SCMOBJ path;(long path, long ignore_hidden) | |||
8518 | ___SCMOBJ ignore_hidden;)(long path, long ignore_hidden) | |||
8519 | { | |||
8520 | #ifndef ___DIR_OPEN_PATH_CE_SELECT | |||
8521 | ||||
8522 | return ___FIX(___UNIMPL_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+4)))<<2); | |||
8523 | ||||
8524 | #else | |||
8525 | ||||
8526 | ___SCMOBJlong e; | |||
8527 | ___SCMOBJlong result; | |||
8528 | ___device_directory *dev; | |||
8529 | void *cpath; | |||
8530 | ||||
8531 | if ((e = ___SCMOBJ_to_NONNULLSTRING | |||
8532 | (path, | |||
8533 | &cpath, | |||
8534 | 1, | |||
8535 | ___CE(___DIR_OPEN_PATH_CE_SELECT)(20<<0), | |||
8536 | 0)) | |||
8537 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8538 | result = e; | |||
8539 | else | |||
8540 | { | |||
8541 | ___STRING_TYPE(___DIR_OPEN_PATH_CE_SELECT)char* p = | |||
8542 | ___CAST(___STRING_TYPE(___DIR_OPEN_PATH_CE_SELECT),cpath)((char*)(cpath)); | |||
8543 | ||||
8544 | if ((e = ___device_directory_setup | |||
8545 | (&dev, | |||
8546 | ___global_device_group (), | |||
8547 | p, | |||
8548 | ___INT(ignore_hidden)((ignore_hidden)>>2))) | |||
8549 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8550 | result = e; | |||
8551 | else | |||
8552 | { | |||
8553 | if ((e = ___NONNULLPOINTER_to_SCMOBJ | |||
8554 | (dev, | |||
8555 | ___FAL((((long)(-1))<<2)+2), | |||
8556 | ___device_cleanup_from_ptr, | |||
8557 | &result, | |||
8558 | ___RETURN_POS127)) | |||
8559 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8560 | { | |||
8561 | ___device_cleanup (___CAST(___device*,dev)((___device*)(dev))); /* ignore error */ | |||
8562 | result = e; | |||
8563 | } | |||
8564 | } | |||
8565 | ||||
8566 | ___release_string (cpath); | |||
8567 | } | |||
8568 | ||||
8569 | ___release_scmobj (result); | |||
8570 | ||||
8571 | return result; | |||
8572 | ||||
8573 | #endif | |||
8574 | } | |||
8575 | ||||
8576 | ||||
8577 | ___SCMOBJlong ___os_device_directory_read | |||
8578 | ___P((___SCMOBJ dev),(long dev) | |||
8579 | (dev)(long dev) | |||
8580 | ___SCMOBJ dev;)(long dev) | |||
8581 | { | |||
8582 | #ifndef ___DIR_OPEN_PATH_CE_SELECT | |||
8583 | ||||
8584 | return ___FIX(___UNIMPL_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+4)))<<2); | |||
8585 | ||||
8586 | #else | |||
8587 | ||||
8588 | ___device_directory *d = | |||
8589 | ___CAST(___device_directory*,___FIELD(dev,___FOREIGN_PTR))((___device_directory*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
8590 | ___SCMOBJlong e; | |||
8591 | ___STRING_TYPE(___DIR_OPEN_PATH_CE_SELECT)char* name; | |||
8592 | ___SCMOBJlong result; | |||
8593 | ||||
8594 | if ((e = ___device_directory_read (d, &name)) != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8595 | return e; | |||
8596 | ||||
8597 | if (name == NULL((void*)0)) | |||
8598 | return ___EOF((((long)(-4))<<2)+2); | |||
8599 | ||||
8600 | if ((e = ___STRING_to_SCMOBJ (name, &result, ___RETURN_POS127, ___CE(___DIR_OPEN_PATH_CE_SELECT)(20<<0) )) | |||
8601 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8602 | return e; | |||
8603 | ||||
8604 | ___release_scmobj (result); | |||
8605 | ||||
8606 | return result; | |||
8607 | ||||
8608 | #endif | |||
8609 | } | |||
8610 | ||||
8611 | ||||
8612 | /* - - - - - - - - - - - - - - - - - - */ | |||
8613 | ||||
8614 | /* Opening an event-queue. */ | |||
8615 | ||||
8616 | ___SCMOBJlong ___os_device_event_queue_open | |||
8617 | ___P((___SCMOBJ selector),(long selector) | |||
8618 | (selector)(long selector) | |||
8619 | ___SCMOBJ selector;)(long selector) | |||
8620 | { | |||
8621 | ___SCMOBJlong e; | |||
8622 | ___SCMOBJlong result; | |||
8623 | ___device_event_queue *dev; | |||
8624 | ||||
8625 | if ((e = ___device_event_queue_setup | |||
8626 | (&dev, | |||
8627 | ___global_device_group (), | |||
8628 | selector)) | |||
8629 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8630 | result = e; | |||
8631 | else | |||
8632 | { | |||
8633 | if ((e = ___NONNULLPOINTER_to_SCMOBJ | |||
8634 | (dev, | |||
8635 | ___FAL((((long)(-1))<<2)+2), | |||
8636 | ___device_cleanup_from_ptr, | |||
8637 | &result, | |||
8638 | ___RETURN_POS127)) | |||
8639 | != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8640 | { | |||
8641 | ___device_cleanup (___CAST(___device*,dev)((___device*)(dev))); /* ignore error */ | |||
8642 | result = e; | |||
8643 | } | |||
8644 | } | |||
8645 | ||||
8646 | ___release_scmobj (result); | |||
8647 | ||||
8648 | return result; | |||
8649 | } | |||
8650 | ||||
8651 | ||||
8652 | ___SCMOBJlong ___os_device_event_queue_read | |||
8653 | ___P((___SCMOBJ dev),(long dev) | |||
8654 | (dev)(long dev) | |||
8655 | ___SCMOBJ dev;)(long dev) | |||
8656 | { | |||
8657 | ___device_event_queue *d = | |||
8658 | ___CAST(___device_event_queue*,___FIELD(dev,___FOREIGN_PTR))((___device_event_queue*)((*((((long*)((dev)-(1)))+1)+2)))); | |||
8659 | ___SCMOBJlong e; | |||
8660 | ___SCMOBJlong result; | |||
8661 | ||||
8662 | if ((e = ___device_event_queue_read (d, &result)) != ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
8663 | return e; | |||
8664 | ||||
8665 | ___release_scmobj (result); | |||
8666 | ||||
8667 | return result; | |||
8668 | } | |||
8669 | ||||
8670 | ||||
8671 | /* - - - - - - - - - - - - - - - - - - */ | |||
8672 | ||||
8673 | /* Waiting for I/O to become possible on a set of devices. */ | |||
8674 | ||||
8675 | ___SCMOBJlong ___os_condvar_select | |||
8676 | ___P((___SCMOBJ run_queue,(long run_queue, long timeout) | |||
8677 | ___SCMOBJ timeout),(long run_queue, long timeout) | |||
8678 | (run_queue,(long run_queue, long timeout) | |||
8679 | timeout)(long run_queue, long timeout) | |||
8680 | ___SCMOBJ run_queue;(long run_queue, long timeout) | |||
8681 | ___SCMOBJ timeout;)(long run_queue, long timeout) | |||
8682 | { | |||
8683 | /******************/ | |||
8684 | #define ___BTQ_DEQ_NEXT1 1 | |||
8685 | #define ___BTQ_DEQ_PREV2 2 | |||
8686 | #define ___BTQ_COLOR3 3 | |||
8687 | #define ___BTQ_PARENT4 4 | |||
8688 | #define ___BTQ_LEFT5 5 | |||
8689 | #define ___BTQ_RIGHT6 6 | |||
8690 | #define ___BTQ_LEFTMOST6 6 | |||
8691 | #define ___BTQ_OWNER7 7 | |||
8692 | #define ___CONDVAR_NAME8 8 | |||
8693 | ||||
8694 | ___SCMOBJlong e; | |||
8695 | ___time to; | |||
8696 | ___device *devs[MAX_CONDVARS8192]; | |||
8697 | ___SCMOBJlong condvars[MAX_CONDVARS8192]; | |||
8698 | int read_pos; | |||
8699 | int write_pos; | |||
8700 | ___SCMOBJlong condvar; | |||
8701 | int i; | |||
8702 | int j; | |||
8703 | ||||
8704 | if (timeout == ___FAL((((long)(-1))<<2)+2)) | |||
8705 | to = ___time_mod.time_neg_infinity; | |||
8706 | else if (timeout == ___TRU((((long)(-2))<<2)+2)) | |||
8707 | to = ___time_mod.time_pos_infinity; | |||
8708 | else | |||
8709 | ___time_from_seconds (&to, ___F64VECTORREF(timeout,___FIX(0))*(double*)(((long)(((long*)((timeout)-(1)))+1))+(((((long)(0) )<<2))<<(3-2)))); | |||
8710 | ||||
8711 | read_pos = 0; | |||
8712 | write_pos = MAX_CONDVARS8192; | |||
8713 | condvar = ___FIELD(run_queue,___BTQ_DEQ_NEXT)(*((((long*)((run_queue)-(1)))+1)+1)); | |||
8714 | ||||
8715 | while (condvar != run_queue) | |||
8716 | { | |||
8717 | ___SCMOBJlong owner = ___FIELD(condvar,___BTQ_OWNER)(*((((long*)((condvar)-(1)))+1)+7)); | |||
8718 | if (read_pos < write_pos) | |||
8719 | { | |||
8720 | if (owner & ___FIX(2)(((long)(2))<<2)) | |||
8721 | condvars[--write_pos] = condvar; | |||
8722 | else | |||
8723 | condvars[read_pos++] = condvar; | |||
8724 | ___FIELD(condvar,___BTQ_OWNER)(*((((long*)((condvar)-(1)))+1)+7)) = owner & ~___FIX(1)(((long)(1))<<2); | |||
8725 | } | |||
8726 | else | |||
8727 | { | |||
8728 | to = ___time_mod.time_neg_infinity; | |||
8729 | ___FIELD(condvar,___BTQ_OWNER)(*((((long*)((condvar)-(1)))+1)+7)) = owner | ___FIX(1)(((long)(1))<<2); | |||
8730 | } | |||
8731 | condvar = ___FIELD(condvar,___BTQ_DEQ_NEXT)(*((((long*)((condvar)-(1)))+1)+1)); | |||
8732 | } | |||
8733 | ||||
8734 | i = 0; | |||
8735 | ||||
8736 | while (i < read_pos) | |||
8737 | { | |||
8738 | devs[i] = ___CAST(___device*,((___device*)((*((((long*)(((*((((long*)((condvars[i])-(1)))+ 1)+8)))-(1)))+1)+2)))) | |||
8739 | ___FIELD(___FIELD(condvars[i],___CONDVAR_NAME),((___device*)((*((((long*)(((*((((long*)((condvars[i])-(1)))+ 1)+8)))-(1)))+1)+2)))) | |||
8740 | ___FOREIGN_PTR))((___device*)((*((((long*)(((*((((long*)((condvars[i])-(1)))+ 1)+8)))-(1)))+1)+2)))); | |||
8741 | i++; | |||
8742 | } | |||
8743 | ||||
8744 | j = MAX_CONDVARS8192; | |||
8745 | ||||
8746 | while (j > write_pos) | |||
8747 | { | |||
8748 | j--; | |||
8749 | devs[i] = ___CAST(___device*,((___device*)((*((((long*)(((*((((long*)((condvars[j])-(1)))+ 1)+8)))-(1)))+1)+2)))) | |||
8750 | ___FIELD(___FIELD(condvars[j],___CONDVAR_NAME),((___device*)((*((((long*)(((*((((long*)((condvars[j])-(1)))+ 1)+8)))-(1)))+1)+2)))) | |||
8751 | ___FOREIGN_PTR))((___device*)((*((((long*)(((*((((long*)((condvars[j])-(1)))+ 1)+8)))-(1)))+1)+2)))); | |||
8752 | i++; | |||
8753 | } | |||
8754 | ||||
8755 | e = ___device_select (devs, read_pos, MAX_CONDVARS8192-write_pos, to); | |||
8756 | ||||
8757 | i = 0; | |||
8758 | ||||
8759 | while (i < read_pos) | |||
8760 | { | |||
8761 | if (devs[i] == NULL((void*)0)) | |||
8762 | { | |||
8763 | condvar = condvars[i]; | |||
8764 | ___FIELD(condvar,___BTQ_OWNER)(*((((long*)((condvar)-(1)))+1)+7)) |= ___FIX(1)(((long)(1))<<2); | |||
8765 | } | |||
8766 | i++; | |||
8767 | } | |||
8768 | ||||
8769 | j = MAX_CONDVARS8192; | |||
8770 | ||||
8771 | while (j > write_pos) | |||
8772 | { | |||
8773 | j--; | |||
8774 | if (devs[i] == NULL((void*)0)) | |||
8775 | { | |||
8776 | condvar = condvars[j]; | |||
8777 | ___FIELD(condvar,___BTQ_OWNER)(*((((long*)((condvar)-(1)))+1)+7)) |= ___FIX(1)(((long)(1))<<2); | |||
8778 | } | |||
8779 | i++; | |||
8780 | } | |||
8781 | ||||
8782 | return e; | |||
8783 | } | |||
8784 | ||||
8785 | ||||
8786 | /* - - - - - - - - - - - - - - - - - - */ | |||
8787 | ||||
8788 | /* | |||
8789 | * Decoding and encoding of a buffer of Scheme characters to a buffer | |||
8790 | * of bytes. | |||
8791 | */ | |||
8792 | ||||
8793 | /* | |||
8794 | * The following definitions must match the structure of ports defined | |||
8795 | * in _io#.scm . | |||
8796 | */ | |||
8797 | ||||
8798 | #define ___PORT_MUTEX1 1 | |||
8799 | #define ___PORT_RKIND2 2 | |||
8800 | #define ___PORT_WKIND3 3 | |||
8801 | #define ___PORT_NAME4 4 | |||
8802 | #define ___PORT_READ_DATUM5 5 | |||
8803 | #define ___PORT_WRITE_DATUM6 6 | |||
8804 | #define ___PORT_NEWLINE7 7 | |||
8805 | #define ___PORT_FORCE_OUTPUT8 8 | |||
8806 | #define ___PORT_CLOSE9 9 | |||
8807 | #define ___PORT_ROPTIONS10 10 | |||
8808 | #define ___PORT_RTIMEOUT11 11 | |||
8809 | #define ___PORT_RTIMEOUT_THUNK12 12 | |||
8810 | #define ___PORT_SET_RTIMEOUT13 13 | |||
8811 | #define ___PORT_WOPTIONS14 14 | |||
8812 | #define ___PORT_WTIMEOUT15 15 | |||
8813 | #define ___PORT_WTIMEOUT_THUNK16 16 | |||
8814 | #define ___PORT_SET_WTIMEOUT17 17 | |||
8815 | #define ___PORT_IO_EXCEPTION_HANDLER18 18 | |||
8816 | ||||
8817 | #define ___PORT_OBJECT_OTHER119 19 | |||
8818 | #define ___PORT_OBJECT_OTHER220 20 | |||
8819 | #define ___PORT_OBJECT_OTHER321 21 | |||
8820 | ||||
8821 | #define ___PORT_CHAR_RBUF19 19 | |||
8822 | #define ___PORT_CHAR_RLO20 20 | |||
8823 | #define ___PORT_CHAR_RHI21 21 | |||
8824 | #define ___PORT_CHAR_RCHARS22 22 | |||
8825 | #define ___PORT_CHAR_RLINES23 23 | |||
8826 | #define ___PORT_CHAR_RCURLINE24 24 | |||
8827 | #define ___PORT_CHAR_RBUF_FILL25 25 | |||
8828 | #define ___PORT_CHAR_PEEK_EOFP26 26 | |||
8829 | ||||
8830 | #define ___PORT_CHAR_WBUF27 27 | |||
8831 | #define ___PORT_CHAR_WLO28 28 | |||
8832 | #define ___PORT_CHAR_WHI29 29 | |||
8833 | #define ___PORT_CHAR_WCHARS30 30 | |||
8834 | #define ___PORT_CHAR_WLINES31 31 | |||
8835 | #define ___PORT_CHAR_WCURLINE32 32 | |||
8836 | #define ___PORT_CHAR_WBUF_DRAIN33 33 | |||
8837 | #define ___PORT_INPUT_READTABLE34 34 | |||
8838 | #define ___PORT_OUTPUT_READTABLE35 35 | |||
8839 | #define ___PORT_OUTPUT_WIDTH36 36 | |||
8840 | ||||
8841 | #define ___PORT_CHAR_OTHER137 37 | |||
8842 | #define ___PORT_CHAR_OTHER238 38 | |||
8843 | #define ___PORT_CHAR_OTHER339 39 | |||
8844 | #define ___PORT_CHAR_OTHER440 40 | |||
8845 | #define ___PORT_CHAR_OTHER541 41 | |||
8846 | ||||
8847 | #define ___PORT_BYTE_RBUF37 37 | |||
8848 | #define ___PORT_BYTE_RLO38 38 | |||
8849 | #define ___PORT_BYTE_RHI39 39 | |||
8850 | #define ___PORT_BYTE_RBUF_FILL40 40 | |||
8851 | ||||
8852 | #define ___PORT_BYTE_WBUF41 41 | |||
8853 | #define ___PORT_BYTE_WLO42 42 | |||
8854 | #define ___PORT_BYTE_WHI43 43 | |||
8855 | #define ___PORT_BYTE_WBUF_DRAIN44 44 | |||
8856 | ||||
8857 | #define ___PORT_BYTE_OTHER145 45 | |||
8858 | #define ___PORT_BYTE_OTHER246 46 | |||
8859 | ||||
8860 | #define ___PORT_RDEVICE_CONDVAR45 45 | |||
8861 | #define ___PORT_WDEVICE_CONDVAR46 46 | |||
8862 | ||||
8863 | #define ___PORT_DEVICE_OTHER147 47 | |||
8864 | #define ___PORT_DEVICE_OTHER248 48 | |||
8865 | ||||
8866 | #define ___Cunsigned int ___CS_SELECT(___U8,___U16,___U32)unsigned int | |||
8867 | ||||
8868 | ___SCMOBJlong ___os_port_decode_chars | |||
8869 | ___P((___SCMOBJ port,(long port, long want, long eof) | |||
8870 | ___SCMOBJ want,(long port, long want, long eof) | |||
8871 | ___SCMOBJ eof),(long port, long want, long eof) | |||
8872 | (port,(long port, long want, long eof) | |||
8873 | want,(long port, long want, long eof) | |||
8874 | eof)(long port, long want, long eof) | |||
8875 | ___SCMOBJ port;(long port, long want, long eof) | |||
8876 | ___SCMOBJ want;(long port, long want, long eof) | |||
8877 | ___SCMOBJ eof;)(long port, long want, long eof) | |||
8878 | { | |||
8879 | ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
8880 | ___SCMOBJlong cbuf = ___FIELD(port,___PORT_CHAR_RBUF)(*((((long*)((port)-(1)))+1)+19)); | |||
8881 | int chi = ___INT(___FIELD(port,___PORT_CHAR_RHI))(((*((((long*)((port)-(1)))+1)+21)))>>2); | |||
8882 | int cend = ___INT(___STRINGLENGTH(cbuf))(((((long)(((((unsigned long)((*((long*)((cbuf)-(1))))))>> (3 +5))>>2)))<<2))>>2); | |||
8883 | ___SCMOBJlong bbuf = ___FIELD(port,___PORT_BYTE_RBUF)(*((((long*)((port)-(1)))+1)+37)); | |||
8884 | int blo = ___INT(___FIELD(port,___PORT_BYTE_RLO))(((*((((long*)((port)-(1)))+1)+38)))>>2); | |||
8885 | int bhi = ___INT(___FIELD(port,___PORT_BYTE_RHI))(((*((((long*)((port)-(1)))+1)+39)))>>2); | |||
8886 | int options = ___INT(___FIELD(port,___PORT_ROPTIONS))(((*((((long*)((port)-(1)))+1)+10)))>>2); | |||
8887 | ___Cunsigned int *cbuf_ptr = ___CAST(___C*,___BODY_AS(cbuf,___tSUBTYPED))((unsigned int*)((((long*)((cbuf)-(1)))+1))); | |||
8888 | ___U8unsigned char *bbuf_ptr = ___CAST(___U8*,___BODY_AS(bbuf,___tSUBTYPED))((unsigned char*)((((long*)((bbuf)-(1)))+1))); | |||
8889 | int cbuf_avail; | |||
8890 | int bbuf_avail; | |||
8891 | int code; | |||
8892 | ||||
8893 | if (want != ___FAL((((long)(-1))<<2)+2)) | |||
8894 | { | |||
8895 | int w = ___INT(want)((want)>>2); | |||
8896 | if (chi+w < cend) | |||
8897 | cend = chi+w; | |||
8898 | } | |||
8899 | ||||
8900 | cbuf_avail = cend - chi; | |||
8901 | bbuf_avail = bhi - blo; | |||
8902 | ||||
8903 | code = chars_from_bytes (cbuf_ptr + chi, | |||
8904 | &cbuf_avail, | |||
8905 | bbuf_ptr + blo, | |||
8906 | &bbuf_avail, | |||
8907 | &options); | |||
8908 | ||||
8909 | /* | |||
8910 | * either the character buffer is full (cbuf_avail == 0) or no more | |||
8911 | * characters can be extracted from the byte buffer either because | |||
8912 | * the remaining bytes are not long enough to form a character or | |||
8913 | * don't form a valid character. | |||
8914 | */ | |||
8915 | ||||
8916 | if (cbuf_avail == cend - chi) | |||
8917 | { | |||
8918 | if (code == ___INCOMPLETE_CHAR1 && eof != ___FAL((((long)(-1))<<2)+2)) | |||
8919 | { | |||
8920 | bbuf_avail = 0; /* skip bytes up to end-of-file */ | |||
8921 | code = ___ILLEGAL_CHAR2; | |||
8922 | } | |||
8923 | ||||
8924 | if (code == ___ILLEGAL_CHAR2) | |||
8925 | { | |||
8926 | if (___CHAR_ENCODING_ERRORS(options)((options)&(3<<5)) != ___CHAR_ENCODING_ERRORS_OFF(2<<5)) | |||
8927 | e = err_code_from_char_encoding (___CHAR_ENCODING(options)((options)&(31<<0)), 1, 0, 0); | |||
8928 | else | |||
8929 | { | |||
8930 | if (___CHAR_ENCODING_SUPPORTS_BMP(___CHAR_ENCODING(options))((((options)&(31<<0))) >= (3<<0) && (((options)&(31<<0))) <= (18<<0))) | |||
8931 | cbuf_ptr[chi] = ___UNICODE_REPLACEMENT0xfffd; | |||
8932 | else | |||
8933 | cbuf_ptr[chi] = ___UNICODE_QUESTION63; | |||
8934 | ||||
8935 | cbuf_avail--; | |||
8936 | } | |||
8937 | } | |||
8938 | } | |||
8939 | ||||
8940 | ___FIELD(port,___PORT_CHAR_RHI)(*((((long*)((port)-(1)))+1)+21)) = ___FIX(cend - cbuf_avail)(((long)(cend - cbuf_avail))<<2); | |||
8941 | ___FIELD(port,___PORT_BYTE_RLO)(*((((long*)((port)-(1)))+1)+38)) = ___FIX(bhi - bbuf_avail)(((long)(bhi - bbuf_avail))<<2); | |||
8942 | ___FIELD(port,___PORT_ROPTIONS)(*((((long*)((port)-(1)))+1)+10)) = ___FIX(options)(((long)(options))<<2); | |||
8943 | ||||
8944 | return e; | |||
8945 | } | |||
8946 | ||||
8947 | ||||
8948 | ___SCMOBJlong ___os_port_encode_chars | |||
8949 | ___P((___SCMOBJ port),(long port) | |||
8950 | (port)(long port) | |||
8951 | ___SCMOBJ port;)(long port) | |||
8952 | { | |||
8953 | ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
8954 | ___SCMOBJlong cbuf = ___FIELD(port,___PORT_CHAR_WBUF)(*((((long*)((port)-(1)))+1)+27)); | |||
8955 | int clo = ___INT(___FIELD(port,___PORT_CHAR_WLO))(((*((((long*)((port)-(1)))+1)+28)))>>2); | |||
8956 | int chi = ___INT(___FIELD(port,___PORT_CHAR_WHI))(((*((((long*)((port)-(1)))+1)+29)))>>2); | |||
8957 | ___SCMOBJlong bbuf = ___FIELD(port,___PORT_BYTE_WBUF)(*((((long*)((port)-(1)))+1)+41)); | |||
8958 | int bhi = ___INT(___FIELD(port,___PORT_BYTE_WHI))(((*((((long*)((port)-(1)))+1)+43)))>>2); | |||
8959 | int bend = ___INT(___U8VECTORLENGTH(bbuf))(((((long)((((unsigned long)((*((long*)((bbuf)-(1))))))>> (3 +5))))<<2))>>2); | |||
8960 | int options = ___INT(___FIELD(port,___PORT_WOPTIONS))(((*((((long*)((port)-(1)))+1)+14)))>>2); | |||
8961 | ___Cunsigned int *cbuf_ptr = ___CAST(___C*,___BODY_AS(cbuf,___tSUBTYPED))((unsigned int*)((((long*)((cbuf)-(1)))+1))); | |||
8962 | ___U8unsigned char *bbuf_ptr = ___CAST(___U8*,___BODY_AS(bbuf,___tSUBTYPED))((unsigned char*)((((long*)((bbuf)-(1)))+1))); | |||
8963 | int cbuf_avail; | |||
8964 | int bbuf_avail; | |||
8965 | int code; | |||
8966 | ||||
8967 | cbuf_avail = chi - clo; | |||
8968 | bbuf_avail = bend - bhi; | |||
8969 | ||||
8970 | code = chars_to_bytes (cbuf_ptr + clo, | |||
8971 | &cbuf_avail, | |||
8972 | bbuf_ptr + bhi, | |||
8973 | &bbuf_avail, | |||
8974 | &options); | |||
8975 | ||||
8976 | /* | |||
8977 | * either the character buffer is empty (cbuf_avail == 0) or there | |||
8978 | * is not enough space left in the byte buffer for encoding the next | |||
8979 | * character, or the next character is illegal for the given | |||
8980 | * encoding. | |||
8981 | */ | |||
8982 | ||||
8983 | if (cbuf_avail == chi - clo) | |||
8984 | if (code == ___ILLEGAL_CHAR2) | |||
8985 | { | |||
8986 | if (___CHAR_ENCODING_ERRORS(options)((options)&(3<<5)) != ___CHAR_ENCODING_ERRORS_OFF(2<<5)) | |||
8987 | { | |||
8988 | cbuf_avail--; /* skip illegal char */ | |||
8989 | e = err_code_from_char_encoding (___CHAR_ENCODING(options)((options)&(31<<0)), 0, 0, 0); | |||
8990 | } | |||
8991 | else | |||
8992 | { | |||
8993 | ___Cunsigned int replacement_cbuf[1]; | |||
8994 | int replacement_cbuf_avail = 1; | |||
8995 | ||||
8996 | if (___CHAR_ENCODING_SUPPORTS_BMP(___CHAR_ENCODING(options))((((options)&(31<<0))) >= (3<<0) && (((options)&(31<<0))) <= (18<<0))) | |||
8997 | replacement_cbuf[0] = ___UNICODE_REPLACEMENT0xfffd; | |||
8998 | else | |||
8999 | replacement_cbuf[0] = ___UNICODE_QUESTION63; | |||
9000 | ||||
9001 | code = chars_to_bytes (replacement_cbuf, | |||
9002 | &replacement_cbuf_avail, | |||
9003 | bbuf_ptr + bend - bbuf_avail, | |||
9004 | &bbuf_avail, | |||
9005 | &options); | |||
9006 | ||||
9007 | /* | |||
9008 | * skip over the illegal character if the replacement | |||
9009 | * character was encoded | |||
9010 | */ | |||
9011 | ||||
9012 | cbuf_avail = cbuf_avail - 1 + replacement_cbuf_avail; | |||
9013 | } | |||
9014 | } | |||
9015 | ||||
9016 | ___FIELD(port,___PORT_CHAR_WLO)(*((((long*)((port)-(1)))+1)+28)) = ___FIX(chi - cbuf_avail)(((long)(chi - cbuf_avail))<<2); | |||
9017 | ___FIELD(port,___PORT_BYTE_WHI)(*((((long*)((port)-(1)))+1)+43)) = ___FIX(bend - bbuf_avail)(((long)(bend - bbuf_avail))<<2); | |||
9018 | ___FIELD(port,___PORT_WOPTIONS)(*((((long*)((port)-(1)))+1)+14)) = ___FIX(options)(((long)(options))<<2); | |||
9019 | ||||
9020 | return e; | |||
9021 | } | |||
9022 | ||||
9023 | ||||
9024 | /*---------------------------------------------------------------------------*/ | |||
9025 | ||||
9026 | /* I/O module initialization/finalization. */ | |||
9027 | ||||
9028 | ||||
9029 | ___HIDDENstatic ___SCMOBJlong io_module_setup ___PVOID(void) | |||
9030 | { | |||
9031 | ___SCMOBJlong e; | |||
9032 | ||||
9033 | if ((e = ___device_group_setup (&___io_mod.dgroup)) == ___FIX(___NO_ERR)(((long)(0))<<2)) | |||
9034 | { | |||
9035 | #ifdef USE_POSIX | |||
9036 | ||||
9037 | ___set_signal_handler (SIGCHLD17, sigchld_signal_handler); | |||
9038 | ||||
9039 | #endif | |||
9040 | ||||
9041 | #ifdef USE_WIN32 | |||
9042 | ||||
9043 | #define WINSOCK_MAJOR 1 | |||
9044 | #define WINSOCK_MINOR 1 | |||
9045 | ||||
9046 | WSADATA winsock_data; | |||
9047 | ||||
9048 | if (!WSAStartup (MAKEWORD(WINSOCK_MAJOR, WINSOCK_MINOR), &winsock_data)) | |||
9049 | { | |||
9050 | if (LOBYTE(winsock_data.wVersion) == WINSOCK_MINOR && | |||
9051 | HIBYTE(winsock_data.wVersion) == WINSOCK_MAJOR) | |||
9052 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
9053 | WSACleanup (); /* ignore error */ | |||
9054 | } | |||
9055 | ||||
9056 | e = ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
9057 | ||||
9058 | ___device_group_cleanup (___io_mod.dgroup); | |||
9059 | ||||
9060 | #endif | |||
9061 | } | |||
9062 | ||||
9063 | return e; | |||
9064 | } | |||
9065 | ||||
9066 | ||||
9067 | ___HIDDENstatic void io_module_cleanup ___PVOID(void) | |||
9068 | { | |||
9069 | #ifdef USE_POSIX | |||
9070 | ||||
9071 | ___set_signal_handler (SIGCHLD17, SIG_DFL((__sighandler_t) 0)); | |||
9072 | ||||
9073 | #endif | |||
9074 | ||||
9075 | #ifdef USE_WIN32 | |||
9076 | ||||
9077 | WSACleanup (); /* ignore error */ | |||
9078 | ||||
9079 | #endif | |||
9080 | ||||
9081 | ___device_group_cleanup (___io_mod.dgroup); | |||
9082 | } | |||
9083 | ||||
9084 | ||||
9085 | ||||
9086 | ___SCMOBJlong ___setup_io_module ___PVOID(void) | |||
9087 | { | |||
9088 | if (!___io_mod.setup) | |||
9089 | { | |||
9090 | #ifdef USE_WIN32 | |||
9091 | ||||
9092 | ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2); | |||
9093 | ||||
9094 | ___io_mod.always_signaled = NULL((void*)0); | |||
9095 | ___io_mod.abort_select = NULL((void*)0); | |||
9096 | ||||
9097 | ___io_mod.always_signaled = | |||
9098 | CreateEvent (NULL((void*)0), /* can't inherit */ | |||
9099 | TRUE, /* manual reset */ | |||
9100 | TRUE, /* signaled */ | |||
9101 | NULL((void*)0)); /* no name */ | |||
9102 | ||||
9103 | if (___io_mod.always_signaled == NULL((void*)0)) | |||
9104 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
9105 | else | |||
9106 | { | |||
9107 | ___io_mod.abort_select = | |||
9108 | CreateEvent (NULL((void*)0), /* can't inherit */ | |||
9109 | TRUE, /* manual reset */ | |||
9110 | FALSE, /* not signaled */ | |||
9111 | NULL((void*)0)); /* no name */ | |||
9112 | ||||
9113 | if (___io_mod.abort_select == NULL((void*)0)) | |||
9114 | { | |||
9115 | CloseHandle (___io_mod.always_signaled); /* ignore error */ | |||
9116 | e = err_code_from_GetLastError ()___err_code_from_GetLastError(); | |||
9117 | } | |||
9118 | } | |||
9119 | ||||
9120 | #endif | |||
9121 | ||||
9122 | io_module_setup ();/*****************************/ | |||
9123 | ___io_mod.setup = 1; | |||
9124 | return ___FIX(___NO_ERR)(((long)(0))<<2); | |||
9125 | } | |||
9126 | ||||
9127 | return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+( 0))+3)))<<2); | |||
9128 | } | |||
9129 | ||||
9130 | ||||
9131 | void ___cleanup_io_module ___PVOID(void) | |||
9132 | { | |||
9133 | if (___io_mod.setup) | |||
9134 | { | |||
9135 | io_module_cleanup ();/*****************************/ | |||
9136 | #ifdef USE_WIN32 | |||
9137 | CloseHandle (___io_mod.abort_select); /* ignore error */ | |||
9138 | CloseHandle (___io_mod.always_signaled); /* ignore error */ | |||
9139 | #endif | |||
9140 | ___io_mod.setup = 0; | |||
9141 | } | |||
9142 | } | |||
9143 | ||||
9144 | ||||
9145 | /*---------------------------------------------------------------------------*/ |