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 SXEmacs
10 SXEmacs is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 SXEmacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 /* Synched up with: Not in FSF. */
26 /* This file has been Mule-ized. */
31 #include "ui/console-stream.h"
32 #include "ui/TTY/console-tty.h" /* for stuff in
33 event_stream_unixoid_select_console. Needs
35 #include "ui/device.h"
36 #define INCLUDE_EVENTS_H_PRIVATE_SPHERE
43 #include "sysproc.h" /* select stuff */
46 /* Mask of bits indicating the descriptors that we wait for input on.
47 These work as follows:
49 input_wait_mask == mask of all file descriptors we select() on,
50 including TTY/stream console descriptors,
51 process descriptors, and the signal event pipe.
52 Only used in event-tty.c; event-Xt.c uses
53 XtAppAddInput(), and the call to select() is down in
56 non_fake_input_wait_mask == same as input_wait_mask but minus the
57 signal event pipe. Also only used in
60 process_only_mask == only the process descriptors.
62 tty_only_mask == only the TTY/stream console descriptors.
64 SELECT_TYPE input_wait_mask, non_fake_input_wait_mask;
65 SELECT_TYPE process_only_mask, tty_only_mask;
67 /* This is used to terminate the select(), when an event came in
68 through a signal (e.g. window-change or C-g on controlling TTY). */
69 int signal_event_pipe[2];
71 int signal_event_pipe_initialized;
73 int fake_event_occurred;
76 read_event_from_tty_or_stream_desc(Lisp_Event * event,
77 struct console *con, int fd)
83 XSETCONSOLE(console, con);
85 nread = read(fd, &ch, 1);
87 /* deleting the console might not be safe right now ... */
88 enqueue_magic_eval_event(io_error_delete_console, console);
89 /* but we definitely need to unselect it to avoid infinite
90 loops reading EOF's */
91 Fconsole_disable_input(console);
93 character_to_event(ch, event, con, 1, 1);
94 event->channel = console;
100 void signal_fake_event(void)
103 /* We do the write always. Formerly I tried to "optimize" this
104 by setting a flag indicating whether we're blocking and only
105 doing the write in that case, but there is a race condition
106 if the signal occurs after we've checked for the signal
107 occurrence (which could occur in many places throughout
108 an iteration of the command loop, e.g. in status_notify()),
109 but before we set the blocking flag.
111 This should be OK as long as write() is reentrant, which
112 I'm fairly sure it is since it's a system call. */
114 if (signal_event_pipe_initialized)
115 /* In case a signal comes through while we're dumping */
117 int old_errno = errno;
118 write(signal_event_pipe[1], &byte, 1);
123 void drain_signal_event_pipe(void)
126 /* The input end of the pipe has been set to non-blocking. */
127 while (read(signal_event_pipe[0], chars, sizeof(chars)) > 0) ;
130 int event_stream_unixoid_select_console(struct console *con)
134 if (CONSOLE_STREAM_P(con))
135 infd = fileno(CONSOLE_STREAM_DATA(con)->in);
137 assert(CONSOLE_TTY_P(con));
138 infd = CONSOLE_TTY_DATA(con)->infd;
143 FD_SET(infd, &input_wait_mask);
144 FD_SET(infd, &non_fake_input_wait_mask);
145 FD_SET(infd, &tty_only_mask);
149 int event_stream_unixoid_unselect_console(struct console *con)
153 if (CONSOLE_STREAM_P(con))
154 infd = fileno(CONSOLE_STREAM_DATA(con)->in);
156 assert(CONSOLE_TTY_P(con));
157 infd = CONSOLE_TTY_DATA(con)->infd;
162 FD_CLR(infd, &input_wait_mask);
163 FD_CLR(infd, &non_fake_input_wait_mask);
164 FD_CLR(infd, &tty_only_mask);
168 static int get_process_infd(Lisp_Process * p)
170 Lisp_Object instr, outstr;
171 get_process_streams(p, &instr, &outstr);
172 assert(!NILP(instr));
174 return Lstream_get_fd(XLSTREAM(instr));
177 int event_stream_unixoid_select_process(Lisp_Process * proc)
179 int infd = get_process_infd(proc);
181 FD_SET(infd, &input_wait_mask);
182 FD_SET(infd, &non_fake_input_wait_mask);
183 FD_SET(infd, &process_only_mask);
187 int event_stream_unixoid_unselect_process(Lisp_Process * proc)
189 int infd = get_process_infd(proc);
191 FD_CLR(infd, &input_wait_mask);
192 FD_CLR(infd, &non_fake_input_wait_mask);
193 FD_CLR(infd, &process_only_mask);
197 int poll_fds_for_input(SELECT_TYPE mask)
200 EMACS_SELECT_TIME select_time;
201 SELECT_TYPE temp_mask;
205 EMACS_SET_SECS_USECS(sometime, 0, 0);
206 EMACS_TIME_TO_SELECT_TIME(sometime, select_time);
208 /* To effect a poll, tell select() to block for zero seconds. */
209 retval = select(MAXDESC, &temp_mask, 0, 0, &select_time);
212 if (errno != EINTR) {
213 /* Something went seriously wrong; don't abort since maybe
214 the TTY just died at the wrong time. */
215 stderr_out("sxemacs: select failed: errno = %d\n",
219 /* else, we got interrupted by a signal, so try again. */
222 RETURN_NOT_REACHED(0) /* not reached */
225 /****************************************************************************/
226 /* Unixoid (file descriptors based) process I/O streams routines */
227 /****************************************************************************/
230 event_stream_unixoid_create_stream_pair(void *inhandle, void *outhandle,
231 Lisp_Object * instream,
232 Lisp_Object * outstream, int flags)
235 /* Decode inhandle and outhandle. Their meaning depends on
236 the process implementation being used. */
237 #if defined (HAVE_UNIX_PROCESSES)
238 /* We are passed plain old file descs */
239 infd = (EMACS_INT)inhandle;
240 outfd = (EMACS_INT)outhandle;
242 # error Which processes do you have?
245 *instream = (infd >= 0 ? make_filedesc_input_stream(infd, 0, -1, 0)
248 *outstream = (outfd >= 0
249 ? make_filedesc_output_stream(outfd, 0, -1,
253 #if defined(HAVE_UNIX_PROCESSES) && defined(HAVE_PTYS)
254 /* FLAGS is process->pty_flag for UNIX_PROCESSES */
255 if ((flags & STREAM_PTY_FLUSHING) && outfd >= 0) {
256 Bufbyte eof_char = get_eof_char(outfd);
257 int pty_max_bytes = get_pty_max_bytes(outfd);
258 filedesc_stream_set_pty_flushing(XLSTREAM(*outstream),
259 pty_max_bytes, eof_char);
263 return FD_TO_USID(infd);
267 event_stream_unixoid_delete_stream_pair(Lisp_Object instream,
268 Lisp_Object outstream)
274 in = Lstream_get_fd(XLSTREAM(instream));
276 if (!NILP(outstream))
277 out = Lstream_get_fd(XLSTREAM(outstream));
281 if (out != in && out >= 0)
284 return FD_TO_USID(in);
287 void init_event_unixoid(void)
289 /* Do this first; the init_event_*_late() functions
290 pay attention to it. */
291 if (pipe(signal_event_pipe) < 0) {
292 perror("SXEmacs: can't open pipe");
295 signal_event_pipe_initialized = 1;
297 /* Set it non-blocking so we can drain its output. */
298 set_descriptor_non_blocking(signal_event_pipe[0]);
300 /* Also set the write descriptor non-blocking so we don't
301 hang in case a long time passes between times when
302 we drain the pipe. */
303 set_descriptor_non_blocking(signal_event_pipe[1]);
305 /* WARNING: In order for the signal-event pipe to work correctly
306 and not cause lockups, the following need to be followed:
308 1) event_pending_p() must ignore input on the signal-event pipe.
309 2) As soon as next_event() notices input on the signal-event
310 pipe, it must drain it. */
311 FD_ZERO(&input_wait_mask);
312 FD_ZERO(&non_fake_input_wait_mask);
313 FD_ZERO(&process_only_mask);
314 FD_ZERO(&tty_only_mask);
316 FD_SET(signal_event_pipe[0], &input_wait_mask);