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.
6 Copyright (C) 1995, 1996 Ben Wing.
8 This file is part of XEmacs.
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
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
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
25 /* Synched up with: Not in FSF. */
27 /* This file has been Mule-ized. */
32 #include "console-stream.h"
33 #include "console-tty.h"
41 #include "sysproc.h" /* select stuff */
44 /* Mask of bits indicating the descriptors that we wait for input on.
45 These work as follows:
47 input_wait_mask == mask of all file descriptors we select() on,
48 including TTY/stream console descriptors,
49 process descriptors, and the signal event pipe.
50 Only used in event-tty.c; event-Xt.c uses
51 XtAppAddInput(), and the call to select() is down in
54 non_fake_input_wait_mask == same as input_wait_mask but minus the
55 signal event pipe. Also only used in
58 process_only_mask == only the process descriptors.
60 tty_only_mask == only the TTY/stream console descriptors.
62 SELECT_TYPE input_wait_mask, non_fake_input_wait_mask;
63 SELECT_TYPE process_only_mask, tty_only_mask;
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];
69 int signal_event_pipe_initialized;
71 int fake_event_occurred;
74 read_event_from_tty_or_stream_desc (Lisp_Event *event,
75 struct console *con, int fd)
81 XSETCONSOLE (console, con);
83 nread = read (fd, &ch, 1);
86 /* deleting the console might not be safe right now ... */
87 enqueue_magic_eval_event (io_error_delete_console, console);
88 /* but we definitely need to unselect it to avoid infinite
89 loops reading EOF's */
90 Fconsole_disable_input (console);
94 character_to_event (ch, event, con, 1, 1);
95 event->channel = console;
102 signal_fake_event (void)
105 /* We do the write always. Formerly I tried to "optimize" this
106 by setting a flag indicating whether we're blocking and only
107 doing the write in that case, but there is a race condition
108 if the signal occurs after we've checked for the signal
109 occurrence (which could occur in many places throughout
110 an iteration of the command loop, e.g. in status_notify()),
111 but before we set the blocking flag.
113 This should be OK as long as write() is reentrant, which
114 I'm fairly sure it is since it's a system call. */
116 if (signal_event_pipe_initialized)
117 /* In case a signal comes through while we're dumping */
119 int old_errno = errno;
120 write (signal_event_pipe[1], &byte, 1);
126 drain_signal_event_pipe (void)
129 /* The input end of the pipe has been set to non-blocking. */
130 while (read (signal_event_pipe[0], chars, sizeof (chars)) > 0)
135 event_stream_unixoid_select_console (struct console *con)
139 if (CONSOLE_STREAM_P (con))
140 infd = fileno (CONSOLE_STREAM_DATA (con)->in);
143 assert (CONSOLE_TTY_P (con));
144 infd = CONSOLE_TTY_DATA (con)->infd;
149 FD_SET (infd, &input_wait_mask);
150 FD_SET (infd, &non_fake_input_wait_mask);
151 FD_SET (infd, &tty_only_mask);
156 event_stream_unixoid_unselect_console (struct console *con)
160 if (CONSOLE_STREAM_P (con))
161 infd = fileno (CONSOLE_STREAM_DATA (con)->in);
164 assert (CONSOLE_TTY_P (con));
165 infd = CONSOLE_TTY_DATA (con)->infd;
170 FD_CLR (infd, &input_wait_mask);
171 FD_CLR (infd, &non_fake_input_wait_mask);
172 FD_CLR (infd, &tty_only_mask);
177 get_process_infd (Lisp_Process *p)
179 Lisp_Object instr, outstr;
180 get_process_streams (p, &instr, &outstr);
181 assert (!NILP (instr));
182 return filedesc_stream_fd (XLSTREAM (instr));
186 event_stream_unixoid_select_process (Lisp_Process *proc)
188 int infd = get_process_infd (proc);
190 FD_SET (infd, &input_wait_mask);
191 FD_SET (infd, &non_fake_input_wait_mask);
192 FD_SET (infd, &process_only_mask);
197 event_stream_unixoid_unselect_process (Lisp_Process *proc)
199 int infd = get_process_infd (proc);
201 FD_CLR (infd, &input_wait_mask);
202 FD_CLR (infd, &non_fake_input_wait_mask);
203 FD_CLR (infd, &process_only_mask);
208 poll_fds_for_input (SELECT_TYPE mask)
211 EMACS_SELECT_TIME select_time;
212 SELECT_TYPE temp_mask;
217 EMACS_SET_SECS_USECS (sometime, 0, 0);
218 EMACS_TIME_TO_SELECT_TIME (sometime, select_time);
220 /* To effect a poll, tell select() to block for zero seconds. */
221 retval = select (MAXDESC, &temp_mask, 0, 0, &select_time);
226 /* Something went seriously wrong; don't ABORT since maybe
227 the TTY just died at the wrong time. */
228 stderr_out ("xemacs: select failed: errno = %d\n", errno);
231 /* else, we got interrupted by a signal, so try again. */
234 RETURN_NOT_REACHED(0) /* not reached */
237 /****************************************************************************/
238 /* Unixoid (file descriptors based) process I/O streams routines */
239 /****************************************************************************/
242 event_stream_unixoid_create_stream_pair (void* inhandle, void* outhandle,
243 Lisp_Object* instream,
244 Lisp_Object* outstream,
248 /* Decode inhandle and outhandle. Their meaning depends on
249 the process implementation being used. */
250 #if defined (HAVE_WIN32_PROCESSES)
251 /* We're passed in Windows handles. Open new fds for them */
252 if ((HANDLE)inhandle != INVALID_HANDLE_VALUE)
254 infd = open_osfhandle ((HANDLE)inhandle, 0);
261 if ((HANDLE)outhandle != INVALID_HANDLE_VALUE)
263 outfd = open_osfhandle ((HANDLE)outhandle, 0);
275 #elif defined (HAVE_UNIX_PROCESSES)
276 /* We are passed plain old file descs */
277 infd = (int)inhandle;
278 outfd = (int)outhandle;
280 # error Which processes do you have?
283 *instream = (infd >= 0
284 ? make_filedesc_input_stream (infd, 0, -1, 0)
287 *outstream = (outfd >= 0
288 ? make_filedesc_output_stream (outfd, 0, -1, LSTR_BLOCKED_OK)
291 #if defined(HAVE_UNIX_PROCESSES) && defined(HAVE_PTYS)
292 /* FLAGS is process->pty_flag for UNIX_PROCESSES */
293 if ((flags & STREAM_PTY_FLUSHING) && outfd >= 0)
295 Bufbyte eof_char = get_eof_char (outfd);
296 int pty_max_bytes = get_pty_max_bytes (outfd);
297 filedesc_stream_set_pty_flushing (XLSTREAM(*outstream), pty_max_bytes, eof_char);
301 return FD_TO_USID (infd);
305 event_stream_unixoid_delete_stream_pair (Lisp_Object instream,
306 Lisp_Object outstream)
308 int in = (NILP(instream) ? -1
309 : filedesc_stream_fd (XLSTREAM (instream)));
310 int out = (NILP(outstream) ? -1
311 : filedesc_stream_fd (XLSTREAM (outstream)));
315 if (out != in && out >= 0)
318 return FD_TO_USID (in);
323 init_event_unixoid (void)
325 /* Do this first; the init_event_*_late() functions
326 pay attention to it. */
327 if (pipe (signal_event_pipe) < 0)
329 perror ("XEmacs: can't open pipe");
332 signal_event_pipe_initialized = 1;
334 /* Set it non-blocking so we can drain its output. */
335 set_descriptor_non_blocking (signal_event_pipe[0]);
337 /* Also set the write descriptor non-blocking so we don't
338 hang in case a long time passes between times when
339 we drain the pipe. */
340 set_descriptor_non_blocking (signal_event_pipe[1]);
342 /* WARNING: In order for the signal-event pipe to work correctly
343 and not cause lockups, the following need to be followed:
345 1) event_pending_p() must ignore input on the signal-event pipe.
346 2) As soon as next_event() notices input on the signal-event
347 pipe, it must drain it. */
348 FD_ZERO (&input_wait_mask);
349 FD_ZERO (&non_fake_input_wait_mask);
350 FD_ZERO (&process_only_mask);
351 FD_ZERO (&tty_only_mask);
353 FD_SET (signal_event_pipe[0], &input_wait_mask);