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 */
48 /* Mask of bits indicating the descriptors that we wait for input on.
49 These work as follows:
51 input_wait_mask == mask of all file descriptors we select() on,
52 including TTY/stream console descriptors,
53 process descriptors, and the signal event pipe.
54 Only used in event-tty.c; event-Xt.c uses
55 XtAppAddInput(), and the call to select() is down in
58 non_fake_input_wait_mask == same as input_wait_mask but minus the
59 signal event pipe. Also only used in
62 process_only_mask == only the process descriptors.
64 tty_only_mask == only the TTY/stream console descriptors.
66 SELECT_TYPE input_wait_mask, non_fake_input_wait_mask;
67 SELECT_TYPE process_only_mask, tty_only_mask;
69 /* This is used to terminate the select(), when an event came in
70 through a signal (e.g. window-change or C-g on controlling TTY). */
71 int signal_event_pipe[2];
73 int signal_event_pipe_initialized;
75 int fake_event_occurred;
78 read_event_from_tty_or_stream_desc (struct Lisp_Event *event,
79 struct console *con, int fd)
85 XSETCONSOLE (console, con);
88 if (fd == CONSOLE_TTY_MOUSE_FD (con)) {
89 return handle_gpm_read (event,con,fd);
93 nread = read (fd, &ch, 1);
96 /* deleting the console might not be safe right now ... */
97 enqueue_magic_eval_event (io_error_delete_console, console);
98 /* but we definitely need to unselect it to avoid infinite
99 loops reading EOF's */
100 Fconsole_disable_input (console);
104 character_to_event (ch, event, con, 1, 1);
105 event->channel = console;
112 signal_fake_event (void)
115 /* We do the write always. Formerly I tried to "optimize" this
116 by setting a flag indicating whether we're blocking and only
117 doing the write in that case, but there is a race condition
118 if the signal occurs after we've checked for the signal
119 occurrence (which could occur in many places throughout
120 an iteration of the command loop, e.g. in status_notify()),
121 but before we set the blocking flag.
123 This should be OK as long as write() is reentrant, which
124 I'm fairly sure it is since it's a system call. */
126 if (signal_event_pipe_initialized)
127 /* In case a signal comes through while we're dumping */
129 int old_errno = errno;
130 write (signal_event_pipe[1], &byte, 1);
136 drain_signal_event_pipe (void)
139 /* The input end of the pipe has been set to non-blocking. */
140 while (read (signal_event_pipe[0], chars, sizeof (chars)) > 0)
145 event_stream_unixoid_select_console (struct console *con)
149 if (CONSOLE_STREAM_P (con))
150 infd = fileno (CONSOLE_STREAM_DATA (con)->in);
153 assert (CONSOLE_TTY_P (con));
154 infd = CONSOLE_TTY_DATA (con)->infd;
159 FD_SET (infd, &input_wait_mask);
160 FD_SET (infd, &non_fake_input_wait_mask);
161 FD_SET (infd, &tty_only_mask);
166 event_stream_unixoid_unselect_console (struct console *con)
170 if (CONSOLE_STREAM_P (con))
171 infd = fileno (CONSOLE_STREAM_DATA (con)->in);
174 assert (CONSOLE_TTY_P (con));
175 infd = CONSOLE_TTY_DATA (con)->infd;
180 FD_CLR (infd, &input_wait_mask);
181 FD_CLR (infd, &non_fake_input_wait_mask);
182 FD_CLR (infd, &tty_only_mask);
187 get_process_infd (struct Lisp_Process *p)
189 Lisp_Object instr, outstr;
190 get_process_streams (p, &instr, &outstr);
191 assert (!NILP (instr));
192 return filedesc_stream_fd (XLSTREAM (instr));
196 event_stream_unixoid_select_process (struct Lisp_Process *proc)
198 int infd = get_process_infd (proc);
200 FD_SET (infd, &input_wait_mask);
201 FD_SET (infd, &non_fake_input_wait_mask);
202 FD_SET (infd, &process_only_mask);
207 event_stream_unixoid_unselect_process (struct Lisp_Process *proc)
209 int infd = get_process_infd (proc);
211 FD_CLR (infd, &input_wait_mask);
212 FD_CLR (infd, &non_fake_input_wait_mask);
213 FD_CLR (infd, &process_only_mask);
218 poll_fds_for_input (SELECT_TYPE mask)
221 EMACS_SELECT_TIME select_time;
222 SELECT_TYPE temp_mask;
227 EMACS_SET_SECS_USECS (sometime, 0, 0);
228 EMACS_TIME_TO_SELECT_TIME (sometime, select_time);
230 /* To effect a poll, tell select() to block for zero seconds. */
231 retval = select (MAXDESC, &temp_mask, 0, 0, &select_time);
236 /* Something went seriously wrong; don't abort since maybe
237 the TTY just died at the wrong time. */
238 fprintf (stderr, "xemacs: select failed: errno = %d\n", errno);
241 /* else, we got interrupted by a signal, so try again. */
244 RETURN_NOT_REACHED(0) /* not reached */
247 /****************************************************************************/
248 /* Unixoid (file descriptors based) process I/O streams routines */
249 /****************************************************************************/
252 event_stream_unixoid_create_stream_pair (void* inhandle, void* outhandle,
253 Lisp_Object* instream,
254 Lisp_Object* outstream,
258 /* Decode inhandle and outhandle. Their meaning depends on
259 the process implementation being used. */
260 #if defined (HAVE_WIN32_PROCESSES)
261 /* We're passed in Windows handles. Open new fds for them */
262 if ((HANDLE)inhandle != INVALID_HANDLE_VALUE)
264 infd = open_osfhandle ((HANDLE)inhandle, 0);
271 if ((HANDLE)outhandle != INVALID_HANDLE_VALUE)
273 outfd = open_osfhandle ((HANDLE)outhandle, 0);
285 #elif defined (HAVE_UNIX_PROCESSES)
286 /* We are passed plain old file descs */
287 infd = (int)inhandle;
288 outfd = (int)outhandle;
290 # error Which processes do you have?
293 *instream = (infd >= 0
294 ? make_filedesc_input_stream (infd, 0, -1, 0)
297 *outstream = (outfd >= 0
298 ? make_filedesc_output_stream (outfd, 0, -1, LSTR_BLOCKED_OK)
301 #if defined(HAVE_UNIX_PROCESSES) && defined(HAVE_PTYS)
302 /* FLAGS is process->pty_flag for UNIX_PROCESSES */
303 if ((flags & STREAM_PTY_FLUSHING) && outfd >= 0)
305 Bufbyte eof_char = get_eof_char (outfd);
306 int pty_max_bytes = get_pty_max_bytes (outfd);
307 filedesc_stream_set_pty_flushing (XLSTREAM(*outstream), pty_max_bytes, eof_char);
311 return FD_TO_USID (infd);
315 event_stream_unixoid_delete_stream_pair (Lisp_Object instream,
316 Lisp_Object outstream)
318 int in = (NILP(instream) ? -1
319 : filedesc_stream_fd (XLSTREAM (instream)));
320 int out = (NILP(outstream) ? -1
321 : filedesc_stream_fd (XLSTREAM (outstream)));
325 if (out != in && out >= 0)
328 return FD_TO_USID (in);
333 init_event_unixoid (void)
335 /* Do this first; the init_event_*_late() functions
336 pay attention to it. */
337 if (pipe (signal_event_pipe) < 0)
339 perror ("XEmacs: can't open pipe");
342 signal_event_pipe_initialized = 1;
344 /* Set it non-blocking so we can drain its output. */
345 set_descriptor_non_blocking (signal_event_pipe[0]);
347 /* Also set the write descriptor non-blocking so we don't
348 hang in case a long time passes between times when
349 we drain the pipe. */
350 set_descriptor_non_blocking (signal_event_pipe[1]);
352 /* WARNING: In order for the signal-event pipe to work correctly
353 and not cause lockups, the following need to be followed:
355 1) event_pending_p() must ignore input on the signal-event pipe.
356 2) As soon as next_event() notices input on the signal-event
357 pipe, it must drain it. */
358 FD_ZERO (&input_wait_mask);
359 FD_ZERO (&non_fake_input_wait_mask);
360 FD_ZERO (&process_only_mask);
361 FD_ZERO (&tty_only_mask);
363 FD_SET (signal_event_pipe[0], &input_wait_mask);