Mercurial > hg > xemacs-beta
annotate src/event-unixoid.c @ 5724:ede80ef92a74
Make soft links in src for module source files, if built in to the executable.
This ensures that those files are built with the same compiler flags as all
other source files.
See these xemacs-beta messages:
<CAHCOHQn+q=Xuwq+y68dvqi7afAP9f-TdB7=8YiZ8VYO816sjHg@mail.gmail.com>
<f5by5ejqiyk.fsf@calexico.inf.ed.ac.uk>
author | Jerry James <james@xemacs.org> |
---|---|
date | Sat, 02 Mar 2013 14:32:37 -0700 |
parents | 308d34e9f07d |
children | a216b3c2b09e |
rev | line source |
---|---|
428 | 1 /* Code shared between all event loops that use select() and have a |
2 different input descriptor for each device. | |
3 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. | |
4 Copyright (C) 1995 Board of Trustees, University of Illinois. | |
5 Copyright (C) 1995 Sun Microsystems, Inc. | |
1268 | 6 Copyright (C) 1995, 1996, 2001, 2002, 2003 Ben Wing. |
428 | 7 |
8 This file is part of XEmacs. | |
9 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5016
diff
changeset
|
10 XEmacs is free software: you can redistribute it and/or modify it |
428 | 11 under the terms of the GNU General Public License as published by the |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5016
diff
changeset
|
12 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5016
diff
changeset
|
13 option) any later version. |
428 | 14 |
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5016
diff
changeset
|
21 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 22 |
23 /* Synched up with: Not in FSF. */ | |
24 | |
25 /* This file has been Mule-ized. */ | |
26 | |
27 #include <config.h> | |
28 #include "lisp.h" | |
29 | |
872 | 30 #include "console-stream-impl.h" |
31 #include "console-tty-impl.h" | |
1204 | 32 #include "device-impl.h" |
428 | 33 #include "events.h" |
34 #include "lstream.h" | |
35 #include "process.h" | |
36 | |
37 #include "sysdep.h" | |
38 #include "sysfile.h" | |
39 #include "sysproc.h" /* select stuff */ | |
40 #include "systime.h" | |
41 | |
42 /* Mask of bits indicating the descriptors that we wait for input on. | |
43 These work as follows: | |
44 | |
1268 | 45 In event-tty.c we call select() directly on this |
46 to retrieve an event. In event-Xt.c we use | |
47 XtAppAddInput() and the call to select() is down in | |
48 the guts of Xt, but we still use the masks when checking for pending input, even in event-Xt.c. (We can't use XtAppPending() because of the presence of the signal event pipe.) | |
49 | |
428 | 50 input_wait_mask == mask of all file descriptors we select() on, |
51 including TTY/stream console descriptors, | |
52 process descriptors, and the signal event pipe. | |
53 | |
54 non_fake_input_wait_mask == same as input_wait_mask but minus the | |
55 signal event pipe. Also only used in | |
56 event-tty.c. | |
57 | |
58 process_only_mask == only the process descriptors. | |
59 | |
60 tty_only_mask == only the TTY/stream console descriptors. | |
61 */ | |
62 SELECT_TYPE input_wait_mask, non_fake_input_wait_mask; | |
63 SELECT_TYPE process_only_mask, tty_only_mask; | |
64 | |
65 /* This is used to terminate the select(), when an event came in | |
66 through a signal (e.g. window-change or C-g on controlling TTY). */ | |
67 int signal_event_pipe[2]; | |
68 | |
69 int signal_event_pipe_initialized; | |
70 | |
71 int fake_event_occurred; | |
72 | |
1204 | 73 struct console * |
74 find_tty_or_stream_console_from_fd (int fd) | |
75 { | |
76 Lisp_Object concons; | |
77 | |
78 CONSOLE_LOOP (concons) | |
79 { | |
80 struct console *c; | |
81 | |
82 c = XCONSOLE (XCAR (concons)); | |
83 if ((CONSOLE_TTY_P (c) && CONSOLE_TTY_DATA (c)->infd == fd) || | |
84 (CONSOLE_STREAM_P (c) && fileno (CONSOLE_STREAM_DATA (c)->in) == fd)) | |
85 return c; | |
86 } | |
87 | |
88 return 0; | |
89 } | |
90 | |
428 | 91 int |
771 | 92 read_event_from_tty_or_stream_desc (Lisp_Event *event, struct console *con) |
428 | 93 { |
867 | 94 Ichar ch; |
793 | 95 Lisp_Object console = wrap_console (con); |
428 | 96 |
771 | 97 if (CONSOLE_TTY_P (con)) |
867 | 98 ch = Lstream_get_ichar (XLSTREAM (CONSOLE_TTY_DATA (con)->instream)); |
771 | 99 else |
100 { | |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
101 Ibyte ibyte; |
771 | 102 /* #### Definitely something strange here. We should be setting |
103 the stdio handle unbuffered and reading from it instead of mixing | |
104 stdio and raw io calls. */ | |
4954
70e8a00896e9
fix an obscure crash reading from stream devices
Ben Wing <ben@xemacs.org>
parents:
4780
diff
changeset
|
105 int nread = retry_read (fileno (CONSOLE_STREAM_DATA (con)->in), |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
106 &ibyte, 1); |
771 | 107 if (nread <= 0) |
108 ch = -1; | |
4954
70e8a00896e9
fix an obscure crash reading from stream devices
Ben Wing <ben@xemacs.org>
parents:
4780
diff
changeset
|
109 else |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
110 ch = ibyte; |
771 | 111 } |
112 | |
113 if (ch < 0) | |
428 | 114 { |
115 /* deleting the console might not be safe right now ... */ | |
116 enqueue_magic_eval_event (io_error_delete_console, console); | |
117 /* but we definitely need to unselect it to avoid infinite | |
118 loops reading EOF's */ | |
119 Fconsole_disable_input (console); | |
120 } | |
121 else | |
122 { | |
4780
2fd201d73a92
Call character_to_event on characters received from XIM, event-Xt.c
Aidan Kehoe <kehoea@parhasard.net>
parents:
4031
diff
changeset
|
123 character_to_event (ch, event, con, use_console_meta_flag, 1); |
428 | 124 event->channel = console; |
125 return 1; | |
126 } | |
127 return 0; | |
128 } | |
129 | |
130 void | |
131 signal_fake_event (void) | |
132 { | |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
133 Rawbyte rbyte = 0; |
428 | 134 /* We do the write always. Formerly I tried to "optimize" this |
135 by setting a flag indicating whether we're blocking and only | |
136 doing the write in that case, but there is a race condition | |
137 if the signal occurs after we've checked for the signal | |
138 occurrence (which could occur in many places throughout | |
139 an iteration of the command loop, e.g. in status_notify()), | |
140 but before we set the blocking flag. | |
141 | |
771 | 142 This should be OK as long as write() is reentrant, which I'm fairly |
143 sure it is since it's a system call. */ | |
428 | 144 |
145 if (signal_event_pipe_initialized) | |
146 /* In case a signal comes through while we're dumping */ | |
147 { | |
148 int old_errno = errno; | |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
149 retry_write (signal_event_pipe[1], &rbyte, 1); |
428 | 150 errno = old_errno; |
151 } | |
152 } | |
153 | |
154 void | |
155 drain_signal_event_pipe (void) | |
156 { | |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
157 Rawbyte chars[128]; |
428 | 158 /* The input end of the pipe has been set to non-blocking. */ |
771 | 159 while (retry_read (signal_event_pipe[0], chars, sizeof (chars)) > 0) |
428 | 160 ; |
161 } | |
162 | |
1204 | 163 void |
164 drain_tty_devices (void) | |
165 { | |
166 Lisp_Object devcons, concons; | |
167 CONSOLE_LOOP (concons) | |
168 { | |
169 struct console *con = XCONSOLE (XCAR (concons)); | |
170 if (!con->input_enabled) | |
171 continue; | |
172 | |
173 CONSOLE_DEVICE_LOOP (devcons, con) | |
174 { | |
175 struct device *d = XDEVICE (XCAR (devcons)); | |
176 if (DEVICE_TTY_P (d)) | |
177 { | |
178 SELECT_TYPE temp_mask; | |
179 int infd = DEVICE_INFD (d); | |
180 | |
181 FD_ZERO (&temp_mask); | |
182 FD_SET (infd, &temp_mask); | |
183 | |
184 while (1) | |
185 { | |
186 Lisp_Object event; | |
187 | |
188 if (!poll_fds_for_input (temp_mask)) | |
189 break; | |
190 | |
191 event = Fmake_event (Qnil, Qnil); | |
192 if (!read_event_from_tty_or_stream_desc (XEVENT (event), | |
193 con)) | |
194 /* EOF, or something ... */ | |
195 break; | |
196 | |
197 /* queue the read event to be read for real later. */ | |
198 enqueue_dispatch_event (event); | |
199 } | |
200 } | |
201 } | |
202 } | |
203 } | |
204 | |
428 | 205 int |
206 event_stream_unixoid_select_console (struct console *con) | |
207 { | |
208 int infd; | |
209 | |
210 if (CONSOLE_STREAM_P (con)) | |
211 infd = fileno (CONSOLE_STREAM_DATA (con)->in); | |
212 else | |
213 { | |
214 assert (CONSOLE_TTY_P (con)); | |
215 infd = CONSOLE_TTY_DATA (con)->infd; | |
216 } | |
217 | |
218 assert (infd >= 0); | |
219 | |
220 FD_SET (infd, &input_wait_mask); | |
221 FD_SET (infd, &non_fake_input_wait_mask); | |
222 FD_SET (infd, &tty_only_mask); | |
223 return infd; | |
224 } | |
225 | |
226 int | |
227 event_stream_unixoid_unselect_console (struct console *con) | |
228 { | |
229 int infd; | |
230 | |
231 if (CONSOLE_STREAM_P (con)) | |
232 infd = fileno (CONSOLE_STREAM_DATA (con)->in); | |
233 else | |
234 { | |
235 assert (CONSOLE_TTY_P (con)); | |
236 infd = CONSOLE_TTY_DATA (con)->infd; | |
237 } | |
238 | |
239 assert (infd >= 0); | |
240 | |
241 FD_CLR (infd, &input_wait_mask); | |
242 FD_CLR (infd, &non_fake_input_wait_mask); | |
243 FD_CLR (infd, &tty_only_mask); | |
244 return infd; | |
245 } | |
246 | |
247 static int | |
440 | 248 get_process_infd (Lisp_Process *p) |
428 | 249 { |
853 | 250 Lisp_Object instr, outstr, errstr; |
251 get_process_streams (p, &instr, &outstr, &errstr); | |
428 | 252 assert (!NILP (instr)); |
253 return filedesc_stream_fd (XLSTREAM (instr)); | |
254 } | |
255 | |
853 | 256 static int |
257 get_process_errfd (Lisp_Process *p) | |
428 | 258 { |
853 | 259 Lisp_Object instr, outstr, errstr; |
260 get_process_streams (p, &instr, &outstr, &errstr); | |
261 if (!NILP (errstr)) | |
262 return filedesc_stream_fd (XLSTREAM (errstr)); | |
263 else | |
264 return -1; | |
428 | 265 } |
266 | |
853 | 267 void |
268 event_stream_unixoid_select_process (Lisp_Process *proc, int doin, int doerr, | |
269 int *infd, int *errfd) | |
428 | 270 { |
853 | 271 if (doin) |
272 { | |
273 *infd = get_process_infd (proc); | |
274 FD_SET (*infd, &input_wait_mask); | |
275 FD_SET (*infd, &non_fake_input_wait_mask); | |
276 FD_SET (*infd, &process_only_mask); | |
277 } | |
278 | |
279 if (doerr) | |
280 { | |
281 *errfd = get_process_errfd (proc); | |
428 | 282 |
853 | 283 if (*errfd >= 0) |
284 { | |
285 FD_SET (*errfd, &input_wait_mask); | |
286 FD_SET (*errfd, &non_fake_input_wait_mask); | |
287 FD_SET (*errfd, &process_only_mask); | |
288 } | |
289 } | |
290 } | |
291 | |
292 void | |
293 event_stream_unixoid_unselect_process (Lisp_Process *proc, int doin, int doerr, | |
294 int *infd, int *errfd) | |
295 { | |
296 if (doin) | |
297 { | |
298 *infd = get_process_infd (proc); | |
299 FD_CLR (*infd, &input_wait_mask); | |
300 FD_CLR (*infd, &non_fake_input_wait_mask); | |
301 FD_CLR (*infd, &process_only_mask); | |
302 } | |
303 | |
304 if (doerr) | |
305 { | |
306 *errfd = get_process_errfd (proc); | |
307 | |
308 if (*errfd >= 0) | |
309 { | |
310 FD_CLR (*errfd, &input_wait_mask); | |
311 FD_CLR (*errfd, &non_fake_input_wait_mask); | |
312 FD_CLR (*errfd, &process_only_mask); | |
313 } | |
314 } | |
428 | 315 } |
316 | |
317 int | |
318 poll_fds_for_input (SELECT_TYPE mask) | |
319 { | |
320 EMACS_TIME sometime; | |
321 EMACS_SELECT_TIME select_time; | |
322 SELECT_TYPE temp_mask; | |
323 int retval; | |
324 | |
325 while (1) | |
326 { | |
327 EMACS_SET_SECS_USECS (sometime, 0, 0); | |
328 EMACS_TIME_TO_SELECT_TIME (sometime, select_time); | |
329 temp_mask = mask; | |
330 /* To effect a poll, tell select() to block for zero seconds. */ | |
331 retval = select (MAXDESC, &temp_mask, 0, 0, &select_time); | |
332 if (retval >= 0) | |
333 return retval; | |
334 if (errno != EINTR) | |
335 { | |
336 /* Something went seriously wrong; don't abort since maybe | |
337 the TTY just died at the wrong time. */ | |
442 | 338 stderr_out ("xemacs: select failed: errno = %d\n", errno); |
428 | 339 return 0; |
340 } | |
341 /* else, we got interrupted by a signal, so try again. */ | |
342 } | |
343 | |
1204 | 344 RETURN_NOT_REACHED (0); |
428 | 345 } |
346 | |
347 /****************************************************************************/ | |
348 /* Unixoid (file descriptors based) process I/O streams routines */ | |
349 /****************************************************************************/ | |
350 | |
853 | 351 void |
352 event_stream_unixoid_create_io_streams (void* inhandle, void* outhandle, | |
353 void *errhandle, Lisp_Object* instream, | |
354 Lisp_Object* outstream, | |
355 Lisp_Object* errstream, | |
356 USID* in_usid, | |
357 USID* err_usid, | |
358 int flags) | |
428 | 359 { |
853 | 360 int infd, outfd, errfd; |
428 | 361 /* Decode inhandle and outhandle. Their meaning depends on |
362 the process implementation being used. */ | |
4031 | 363 /* We are passed plain old file descs, which are ints, so */ |
364 /* if sizeof(EMACS_INT) > sizeof(int) it's OK. */ | |
365 infd = (EMACS_INT) inhandle; | |
366 outfd = (EMACS_INT) outhandle; | |
367 errfd = (EMACS_INT) errhandle; | |
428 | 368 |
369 *instream = (infd >= 0 | |
370 ? make_filedesc_input_stream (infd, 0, -1, 0) | |
371 : Qnil); | |
372 | |
373 *outstream = (outfd >= 0 | |
374 ? make_filedesc_output_stream (outfd, 0, -1, LSTR_BLOCKED_OK) | |
375 : Qnil); | |
376 | |
853 | 377 *errstream = (errfd >= 0 |
378 ? make_filedesc_input_stream (errfd, 0, -1, 0) | |
379 : Qnil); | |
380 | |
428 | 381 /* FLAGS is process->pty_flag for UNIX_PROCESSES */ |
382 if ((flags & STREAM_PTY_FLUSHING) && outfd >= 0) | |
383 { | |
867 | 384 Ibyte eof_char = get_eof_char (outfd); |
428 | 385 int pty_max_bytes = get_pty_max_bytes (outfd); |
853 | 386 filedesc_stream_set_pty_flushing (XLSTREAM (*outstream), pty_max_bytes, |
387 eof_char); | |
428 | 388 } |
389 | |
853 | 390 *in_usid = FD_TO_USID (infd); |
391 *err_usid = FD_TO_USID (errfd); | |
428 | 392 } |
393 | |
853 | 394 void |
395 event_stream_unixoid_delete_io_streams (Lisp_Object instream, | |
396 Lisp_Object outstream, | |
397 Lisp_Object errstream, | |
398 USID *in_usid, | |
399 USID *err_usid) | |
428 | 400 { |
853 | 401 int in = (NILP (instream) ? -1 |
428 | 402 : filedesc_stream_fd (XLSTREAM (instream))); |
853 | 403 int out = (NILP (outstream) ? -1 |
428 | 404 : filedesc_stream_fd (XLSTREAM (outstream))); |
853 | 405 int err = (NILP (errstream) ? -1 |
406 : filedesc_stream_fd (XLSTREAM (errstream))); | |
428 | 407 |
408 if (in >= 0) | |
771 | 409 retry_close (in); |
428 | 410 if (out != in && out >= 0) |
771 | 411 retry_close (out); |
853 | 412 if (err != in && err != out && err >= 0) |
413 retry_close (err); | |
428 | 414 |
853 | 415 *in_usid = FD_TO_USID (in); |
416 *err_usid = FD_TO_USID (err); | |
428 | 417 } |
418 | |
419 | |
420 void | |
421 init_event_unixoid (void) | |
422 { | |
423 /* Do this first; the init_event_*_late() functions | |
424 pay attention to it. */ | |
425 if (pipe (signal_event_pipe) < 0) | |
426 { | |
427 perror ("XEmacs: can't open pipe"); | |
428 exit (-1); | |
429 } | |
430 signal_event_pipe_initialized = 1; | |
431 | |
432 /* Set it non-blocking so we can drain its output. */ | |
433 set_descriptor_non_blocking (signal_event_pipe[0]); | |
434 | |
435 /* Also set the write descriptor non-blocking so we don't | |
436 hang in case a long time passes between times when | |
437 we drain the pipe. */ | |
438 set_descriptor_non_blocking (signal_event_pipe[1]); | |
439 | |
440 /* WARNING: In order for the signal-event pipe to work correctly | |
441 and not cause lockups, the following need to be followed: | |
442 | |
443 1) event_pending_p() must ignore input on the signal-event pipe. | |
444 2) As soon as next_event() notices input on the signal-event | |
445 pipe, it must drain it. */ | |
446 FD_ZERO (&input_wait_mask); | |
447 FD_ZERO (&non_fake_input_wait_mask); | |
448 FD_ZERO (&process_only_mask); | |
449 FD_ZERO (&tty_only_mask); | |
450 | |
451 FD_SET (signal_event_pipe[0], &input_wait_mask); | |
452 } |