/* Asynchronous subprocess control for GNU Emacs.
Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
1996, 1998, 1999, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#endif
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#include <fcntl.h>
/* Only MS-DOS does not define `subprocesses'. */
#endif
#endif
-#if defined(HAVE_SYS_IOCTL_H)
#include <sys/ioctl.h>
-#if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
-#include <fcntl.h>
-#endif /* HAVE_PTYS and no O_NDELAY */
#if defined(HAVE_NET_IF_H)
#include <net/if.h>
#endif /* HAVE_NET_IF_H */
-#endif /* HAVE_SYS_IOCTL_H */
#ifdef NEED_BSDTTY
#include <bsdtty.h>
#endif
-#ifdef HAVE_SYS_WAIT
-#include <sys/wait.h>
-#endif
-
#ifdef HAVE_RES_INIT
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <util.h>
#endif
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
+
#endif /* subprocesses */
#include "lisp.h"
#include "sysselect.h"
#include "syssignal.h"
#include "syswait.h"
+#ifdef HAVE_GNUTLS
+#include "gnutls.h"
+#endif
#if defined (USE_GTK) || defined (HAVE_GCONF)
#include "xgselect.h"
#ifdef HAVE_NS
#include "nsterm.h"
#endif
-extern int timers_run;
Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
static int kbd_is_on_hold;
-/* Nonzero means delete a process right away if it exits. */
-static int delete_exited_processes;
-
/* Nonzero means don't run process sentinels. This is used
when exiting. */
int inhibit_sentinels;
/* Define first descriptor number available for subprocesses. */
#define FIRST_PROC_DESC 3
-/* Define SIGCHLD as an alias for SIGCLD. There are many conditionals
- testing SIGCHLD. */
-
-#if !defined (SIGCHLD) && defined (SIGCLD)
-#define SIGCHLD SIGCLD
-#endif /* SIGCLD */
-
-extern char *get_operating_system_release (void);
+extern const char *get_operating_system_release (void);
-/* Serial processes require termios or Windows. */
-#if defined (HAVE_TERMIOS) || defined (WINDOWSNT)
-#define HAVE_SERIAL
-#endif
-
-#ifdef HAVE_SERIAL
/* From sysdep.c or w32.c */
extern int serial_open (char *port);
extern void serial_configure (struct Lisp_Process *p, Lisp_Object contact);
-#endif
#ifndef HAVE_H_ERRNO
extern int h_errno;
#endif
-/* t means use pty, nil means use a pipe,
- maybe other values to come. */
-static Lisp_Object Vprocess_connection_type;
-
/* These next two vars are non-static since sysdep.c uses them in the
emulation of `select'. */
/* Number of events of change of status of a process. */
/* Define NON_BLOCKING_CONNECT if we can support non-blocking connects. */
+/* Only W32 has this, it really means that select can't take write mask. */
#ifdef BROKEN_NON_BLOCKING_CONNECT
#undef NON_BLOCKING_CONNECT
+#define SELECT_CANT_DO_WRITE_MASK
#else
#ifndef NON_BLOCKING_CONNECT
#ifdef HAVE_SELECT
static int process_output_skip;
-/* Non-nil means to delay reading process output to improve buffering.
- A value of t means that delay is reset after each send, any other
- non-nil value does not reset the delay. A value of nil disables
- adaptive read buffering completely. */
-static Lisp_Object Vprocess_adaptive_read_buffering;
#else
#define process_output_delay_count 0
#endif
static SELECT_TYPE non_process_wait_mask;
-/* Mask for the gpm mouse input descriptor. */
+/* Mask for selecting for write. */
-static SELECT_TYPE gpm_wait_mask;
+static SELECT_TYPE write_mask;
#ifdef NON_BLOCKING_CONNECT
/* Mask of bits indicating the descriptors that we wait for connect to
/* The largest descriptor currently in use for a process object. */
static int max_process_desc;
-/* The largest descriptor currently in use for keyboard input. */
-static int max_keyboard_desc;
-
-/* The largest descriptor currently in use for gpm mouse input. */
-static int max_gpm_desc;
+/* The largest descriptor currently in use for input. */
+static int max_input_desc;
/* Indexed by descriptor, gives the process (if any) for that descriptor */
Lisp_Object chan_process[MAXDESC];
/* Maximum number of bytes to send to a pty without an eof. */
static int pty_max_bytes;
-#ifdef HAVE_PTYS
-#ifdef HAVE_PTY_H
-#include <pty.h>
-#endif
-/* The file name of the pty opened by allocate_pty. */
+\f
+
+struct fd_callback_data
+{
+ fd_callback func;
+ void *data;
+#define FOR_READ 1
+#define FOR_WRITE 2
+ int condition; /* mask of the defines above. */
+} fd_callback_info[MAXDESC];
+
+
+/* Add a file descriptor FD to be monitored for when read is possible.
+ When read is possible, call FUNC with argument DATA. */
+
+void
+add_read_fd (int fd, fd_callback func, void *data)
+{
+ xassert (fd < MAXDESC);
+ add_keyboard_wait_descriptor (fd);
+
+ fd_callback_info[fd].func = func;
+ fd_callback_info[fd].data = data;
+ fd_callback_info[fd].condition |= FOR_READ;
+}
+
+/* Stop monitoring file descriptor FD for when read is possible. */
+
+void
+delete_read_fd (int fd)
+{
+ xassert (fd < MAXDESC);
+ delete_keyboard_wait_descriptor (fd);
+
+ fd_callback_info[fd].condition &= ~FOR_READ;
+ if (fd_callback_info[fd].condition == 0)
+ {
+ fd_callback_info[fd].func = 0;
+ fd_callback_info[fd].data = 0;
+ }
+}
+
+/* Add a file descriptor FD to be monitored for when write is possible.
+ When write is possible, call FUNC with argument DATA. */
+
+void
+add_write_fd (int fd, fd_callback func, void *data)
+{
+ xassert (fd < MAXDESC);
+ FD_SET (fd, &write_mask);
+ if (fd > max_input_desc)
+ max_input_desc = fd;
+
+ fd_callback_info[fd].func = func;
+ fd_callback_info[fd].data = data;
+ fd_callback_info[fd].condition |= FOR_WRITE;
+}
+
+/* Stop monitoring file descriptor FD for when write is possible. */
+
+void
+delete_write_fd (int fd)
+{
+ int lim = max_input_desc;
+
+ xassert (fd < MAXDESC);
+ FD_CLR (fd, &write_mask);
+ fd_callback_info[fd].condition &= ~FOR_WRITE;
+ if (fd_callback_info[fd].condition == 0)
+ {
+ fd_callback_info[fd].func = 0;
+ fd_callback_info[fd].data = 0;
+
+ if (fd == max_input_desc)
+ for (fd = lim; fd >= 0; fd--)
+ if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask))
+ {
+ max_input_desc = fd;
+ break;
+ }
+
+ }
+}
-static char pty_name[24];
-#endif
\f
/* Compute the Lisp form of the process status, p->status, from
the numeric status that was returned by `wait'. */
if (! NILP (Vlocale_coding_system))
string = (code_convert_string_norecord
(string, Vlocale_coding_system, 0));
- c1 = STRING_CHAR ((char *) SDATA (string));
+ c1 = STRING_CHAR (SSDATA (string));
c2 = DOWNCASE (c1);
if (c1 != c2)
Faset (string, make_number (0), make_number (c2));
\f
#ifdef HAVE_PTYS
+/* The file name of the pty opened by allocate_pty. */
+static char pty_name[24];
+
/* Open an available pty, returning a file descriptor.
Return -1 on failure.
The file name of the terminal corresponding to the pty
p->read_output_skip = 0;
#endif
+#ifdef HAVE_GNUTLS
+ p->gnutls_initstage = GNUTLS_STAGE_EMPTY;
+ p->gnutls_log_level = 0;
+ p->gnutls_p = 0;
+#endif
+
/* If name is already in use, modify it until it is unused. */
name1 = name;
port = Fformat_network_address (Fplist_get (p->childp, QClocal), Qnil);
sprintf (tembuf, "(network %s server on %s)\n",
(DATAGRAM_CHAN_P (p->infd) ? "datagram" : "stream"),
- (STRINGP (port) ? (char *)SDATA (port) : "?"));
+ (STRINGP (port) ? SSDATA (port) : "?"));
insert_string (tembuf);
}
else if (NETCONN1_P (p))
host = Fformat_network_address (Fplist_get (p->childp, QCremote), Qnil);
sprintf (tembuf, "(network %s connection to %s)\n",
(DATAGRAM_CHAN_P (p->infd) ? "datagram" : "stream"),
- (STRINGP (host) ? (char *)SDATA (host) : "?"));
+ (STRINGP (host) ? SSDATA (host) : "?"));
insert_string (tembuf);
}
else if (SERIALCONN1_P (p))
XPROCESS (proc)->filter = Qnil;
XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
+#ifdef HAVE_GNUTLS
+ /* AKA GNUTLS_INITSTAGE(proc). */
+ XPROCESS (proc)->gnutls_initstage = GNUTLS_STAGE_EMPTY;
+ XPROCESS (proc)->gnutls_cred_type = Qnil;
+#endif
+
#ifdef ADAPTIVE_READ_BUFFERING
XPROCESS (proc)->adaptive_read_buffering
= (NILP (Vprocess_adaptive_read_buffering) ? 0
val = XCDR (Vdefault_process_coding_system);
}
XPROCESS (proc)->encode_coding_system = val;
+ /* Note: At this momemnt, the above coding system may leave
+ text-conversion or eol-conversion unspecified. They will be
+ decided after we read output from the process and decode it by
+ some coding system, or just before we actually send a text to
+ the process. */
}
tem = Fsubstring (tem, make_number (2), Qnil);
{
+ Lisp_Object arg_encoding = Qnil;
struct gcpro gcpro1;
GCPRO1 (tem);
tem = Fcons (args[i], tem);
CHECK_STRING (XCAR (tem));
if (STRING_MULTIBYTE (XCAR (tem)))
- XSETCAR (tem,
- code_convert_string_norecord
- (XCAR (tem), XPROCESS (proc)->encode_coding_system, 1));
+ {
+ if (NILP (arg_encoding))
+ arg_encoding = (complement_process_encoding_system
+ (XPROCESS (proc)->encode_coding_system));
+ XSETCAR (tem,
+ code_convert_string_norecord
+ (XCAR (tem), arg_encoding, 1));
+ }
}
UNGCPRO;
}
#endif
-#if 0
- /* Replaced by close_process_descs */
- set_exclusive_use (inchannel);
- set_exclusive_use (outchannel);
-#endif
-
#ifdef O_NONBLOCK
fcntl (inchannel, F_SETFL, O_NONBLOCK);
fcntl (outchannel, F_SETFL, O_NONBLOCK);
setpgrp ();
#endif /* USG */
#endif /* not HAVE_SETSID */
-#if defined (HAVE_TERMIOS) && defined (LDISC1)
+#if defined (LDISC1)
if (pty_flag && xforkin >= 0)
{
struct termios t;
CHECK_SYMBOL (opt);
- name = (char *) SDATA (SYMBOL_NAME (opt));
+ name = SSDATA (SYMBOL_NAME (opt));
for (sopt = socket_options; sopt->name; sopt++)
if (strcmp (name, sopt->name) == 0)
break;
memset (devname, 0, sizeof devname);
if (STRINGP (val))
{
- char *arg = (char *) SDATA (val);
+ char *arg = SSDATA (val);
int len = min (strlen (arg), IFNAMSIZ);
memcpy (devname, arg, len);
}
}
\f
-#ifdef HAVE_SERIAL
DEFUN ("serial-process-configure",
Fserial_process_configure,
Sserial_process_configure,
record_unwind_protect (make_serial_process_unwind, proc);
p = XPROCESS (proc);
- fd = serial_open ((char*) SDATA (port));
+ fd = serial_open (SSDATA (port));
p->infd = fd;
p->outfd = fd;
if (fd > max_process_desc)
UNGCPRO;
return proc;
}
-#endif /* HAVE_SERIAL */
/* Create a network stream/datagram client/server process. Treated
exactly like a normal process when reading and writing. Primary
#ifdef HAVE_GETADDRINFO
struct addrinfo ai, *res, *lres;
struct addrinfo hints;
- char *portstring, portbuf[128];
+ const char *portstring;
+ char portbuf[128];
#else /* HAVE_GETADDRINFO */
struct _emacs_addrinfo
{
if (!NILP (host))
{
if (EQ (host, Qlocal))
- host = build_string ("localhost");
+ /* Depending on setup, "localhost" may map to different IPv4 and/or
+ IPv6 addresses, so it's better to be explicit. (Bug#6781) */
+ host = build_string ("127.0.0.1");
CHECK_STRING (host);
}
/* Attempt to interpret host as numeric inet address */
{
unsigned long numeric_addr;
- numeric_addr = inet_addr ((char *) SDATA (host));
+ numeric_addr = inet_addr (SSDATA (host));
if (numeric_addr == -1)
error ("Unknown host \"%s\"", SDATA (host));
if (!FD_ISSET (inch, &connect_wait_mask))
{
FD_SET (inch, &connect_wait_mask);
+ FD_SET (inch, &write_mask);
num_pending_connects++;
}
}
}
\f
-#if defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H)
+#if defined(HAVE_NET_IF_H)
#ifdef SIOCGIFCONF
DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0,
return any ? res : Qnil;
}
#endif
-#endif /* defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H) */
+#endif /* defined(HAVE_NET_IF_H) */
/* Turn off input and output for process PROC. */
if (FD_ISSET (inchannel, &connect_wait_mask))
{
FD_CLR (inchannel, &connect_wait_mask);
+ FD_CLR (inchannel, &write_mask);
if (--num_pending_connects < 0)
abort ();
}
{
register int channel, nfds;
SELECT_TYPE Available;
-#ifdef NON_BLOCKING_CONNECT
- SELECT_TYPE Connecting;
- int check_connect;
-#endif
+ SELECT_TYPE Writeok;
+ int check_write;
int check_delay, no_avail;
int xerrno;
Lisp_Object proc;
int count = SPECPDL_INDEX ();
FD_ZERO (&Available);
-#ifdef NON_BLOCKING_CONNECT
- FD_ZERO (&Connecting);
-#endif
+ FD_ZERO (&Writeok);
- if (time_limit == 0 && wait_proc && !NILP (Vinhibit_quit)
+ if (time_limit == 0 && microsecs == 0 && wait_proc && !NILP (Vinhibit_quit)
&& !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit)))
message ("Blocking call to accept-process-output with quit inhibited!!");
if (update_tick != process_tick)
{
SELECT_TYPE Atemp;
-#ifdef NON_BLOCKING_CONNECT
SELECT_TYPE Ctemp;
-#endif
if (kbd_on_hold_p ())
FD_ZERO (&Atemp);
else
Atemp = input_wait_mask;
- IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask);
+ Ctemp = write_mask;
EMACS_SET_SECS_USECS (timeout, 0, 0);
- if ((select (max (max (max_process_desc, max_keyboard_desc),
- max_gpm_desc) + 1,
+ if ((select (max (max_process_desc, max_input_desc) + 1,
&Atemp,
#ifdef NON_BLOCKING_CONNECT
(num_pending_connects > 0 ? &Ctemp : (SELECT_TYPE *)0),
break;
FD_SET (wait_proc->infd, &Available);
check_delay = 0;
- IF_NON_BLOCKING_CONNECT (check_connect = 0);
+ check_write = 0;
}
else if (!NILP (wait_for_cell))
{
Available = non_process_wait_mask;
check_delay = 0;
- IF_NON_BLOCKING_CONNECT (check_connect = 0);
+ check_write = 0;
}
else
{
Available = non_keyboard_wait_mask;
else
Available = input_wait_mask;
- IF_NON_BLOCKING_CONNECT (check_connect = (num_pending_connects > 0));
+ Writeok = write_mask;
+#ifdef SELECT_CANT_DO_WRITE_MASK
+ check_write = 0;
+#else
+ check_write = 1;
+#endif
check_delay = wait_channel >= 0 ? 0 : process_output_delay_count;
}
}
else
{
-#ifdef NON_BLOCKING_CONNECT
- if (check_connect)
- Connecting = connect_wait_mask;
-#endif
#ifdef ADAPTIVE_READ_BUFFERING
/* Set the timeout for adaptive read buffering if any
#else
nfds = select
#endif
- (max (max (max_process_desc, max_keyboard_desc),
- max_gpm_desc) + 1,
- &Available,
-#ifdef NON_BLOCKING_CONNECT
- (check_connect ? &Connecting : (SELECT_TYPE *)0),
-#else
- (SELECT_TYPE *)0,
-#endif
- (SELECT_TYPE *)0, &timeout);
+ (max (max_process_desc, max_input_desc) + 1,
+ &Available,
+ (check_write ? &Writeok : (SELECT_TYPE *)0),
+ (SELECT_TYPE *)0, &timeout);
}
xerrno = errno;
if (no_avail)
{
FD_ZERO (&Available);
- IF_NON_BLOCKING_CONNECT (check_connect = 0);
+ check_write = 0;
}
#if 0 /* When polling is used, interrupt_input is 0,
if (no_avail || nfds == 0)
continue;
+ for (channel = 0; channel <= max_input_desc; ++channel)
+ {
+ struct fd_callback_data *d = &fd_callback_info[channel];
+ if (FD_ISSET (channel, &Available)
+ && d->func != 0
+ && (d->condition & FOR_READ) != 0)
+ d->func (channel, d->data, 1);
+ if (FD_ISSET (channel, &write_mask)
+ && d->func != 0
+ && (d->condition & FOR_WRITE) != 0)
+ d->func (channel, d->data, 0);
+ }
+
/* Really FIRST_PROC_DESC should be 0 on Unix,
but this is safer in the short run. */
for (channel = 0; channel <= max_process_desc; channel++)
{
if (FD_ISSET (channel, &Available)
- && FD_ISSET (channel, &non_keyboard_wait_mask))
+ && FD_ISSET (channel, &non_keyboard_wait_mask)
+ && !FD_ISSET (channel, &non_process_wait_mask))
{
int nread;
}
}
#ifdef NON_BLOCKING_CONNECT
- if (check_connect && FD_ISSET (channel, &Connecting)
+ if (FD_ISSET (channel, &Writeok)
&& FD_ISSET (channel, &connect_wait_mask))
{
struct Lisp_Process *p;
FD_CLR (channel, &connect_wait_mask);
+ FD_CLR (channel, &write_mask);
if (--num_pending_connects < 0)
abort ();
char *chars;
register Lisp_Object outstream;
register struct Lisp_Process *p = XPROCESS (proc);
- register int opoint;
+ register EMACS_INT opoint;
struct coding_system *coding = proc_decode_coding_system[channel];
int carryover = p->decoding_carryover;
int readmax = 4096;
#endif
if (proc_buffered_char[channel] < 0)
{
- nbytes = emacs_read (channel, chars + carryover, readmax);
+#ifdef HAVE_GNUTLS
+ if (XPROCESS (proc)->gnutls_p)
+ nbytes = emacs_gnutls_read (channel, XPROCESS (proc),
+ chars + carryover, readmax);
+ else
+#endif
+ nbytes = emacs_read (channel, chars + carryover, readmax);
#ifdef ADAPTIVE_READ_BUFFERING
if (nbytes > 0 && p->adaptive_read_buffering)
{
{
chars[carryover] = proc_buffered_char[channel];
proc_buffered_char[channel] = -1;
- nbytes = emacs_read (channel, chars + carryover + 1, readmax - 1);
+#ifdef HAVE_GNUTLS
+ if (XPROCESS (proc)->gnutls_p)
+ nbytes = emacs_gnutls_read (channel, XPROCESS (proc),
+ chars + carryover + 1, readmax - 1);
+ else
+#endif
+ nbytes = emacs_read (channel, chars + carryover + 1, readmax - 1);
if (nbytes < 0)
nbytes = 1;
else
else if (!NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name))
{
Lisp_Object old_read_only;
- int old_begv, old_zv;
- int old_begv_byte, old_zv_byte;
- int before, before_byte;
- int opoint_byte;
+ EMACS_INT old_begv, old_zv;
+ EMACS_INT old_begv_byte, old_zv_byte;
+ EMACS_INT before, before_byte;
+ EMACS_INT opoint_byte;
Lisp_Object text;
struct buffer *b;
This function can evaluate Lisp code and can garbage collect. */
static void
-send_process (volatile Lisp_Object proc, unsigned char *volatile buf,
- volatile int len, volatile Lisp_Object object)
+send_process (volatile Lisp_Object proc, const unsigned char *volatile buf,
+ volatile EMACS_INT len, volatile Lisp_Object object)
{
/* Use volatile to protect variables from being clobbered by longjmp. */
struct Lisp_Process *p = XPROCESS (proc);
- int rv;
+ EMACS_INT rv;
struct coding_system *coding;
struct gcpro gcpro1;
SIGTYPE (*volatile old_sigpipe) (int);
&& !NILP (XBUFFER (object)->enable_multibyte_characters))
|| EQ (object, Qt))
{
+ p->encode_coding_system
+ = complement_process_encoding_system (p->encode_coding_system);
if (!EQ (Vlast_coding_system_used, p->encode_coding_system))
- /* The coding system for encoding was changed to raw-text
- because we sent a unibyte text previously. Now we are
- sending a multibyte text, thus we must encode it by the
- original coding system specified for the current process. */
- setup_coding_system (p->encode_coding_system, coding);
+ {
+ /* The coding system for encoding was changed to raw-text
+ because we sent a unibyte text previously. Now we are
+ sending a multibyte text, thus we must encode it by the
+ original coding system specified for the current process.
+
+ Another reason we comming here is that the coding system
+ was just complemented and new one was returned by
+ complement_process_encoding_system. */
+ setup_coding_system (p->encode_coding_system, coding);
+ Vlast_coding_system_used = p->encode_coding_system;
+ }
coding->src_multibyte = 1;
}
else
coding->dst_object = Qt;
if (BUFFERP (object))
{
- int from_byte, from, to;
- int save_pt, save_pt_byte;
+ EMACS_INT from_byte, from, to;
+ EMACS_INT save_pt, save_pt_byte;
struct buffer *cur = current_buffer;
set_buffer_internal (XBUFFER (object));
process_sent_to = proc;
while (len > 0)
{
- int this = len;
+ EMACS_INT this = len;
/* Send this batch, using one or more write calls. */
while (this > 0)
else
#endif
{
- rv = emacs_write (outfd, (char *) buf, this);
+#ifdef HAVE_GNUTLS
+ if (XPROCESS (proc)->gnutls_p)
+ rv = emacs_gnutls_write (outfd,
+ XPROCESS (proc),
+ (char *) buf, this);
+ else
+#endif
+ rv = emacs_write (outfd, (char *) buf, this);
#ifdef ADAPTIVE_READ_BUFFERING
if (p->read_output_delay > 0
&& p->adaptive_read_buffering == 1)
(Lisp_Object process, Lisp_Object start, Lisp_Object end)
{
Lisp_Object proc;
- int start1, end1;
+ EMACS_INT start1, end1;
proc = get_process (process);
validate_region (&start, &end);
/* If possible, send signals to the entire pgrp
by sending an input character to it. */
- /* TERMIOS is the latest and bestest, and seems most likely to
- work. If the system has it, use it. */
-#ifdef HAVE_TERMIOS
struct termios t;
cc_t *sig_char = NULL;
}
/* If we can't send the signal with a character,
fall through and send it another way. */
-#else /* ! HAVE_TERMIOS */
-
- /* On Berkeley descendants, the following IOCTL's retrieve the
- current control characters. */
-#if defined (TIOCGLTC) && defined (TIOCGETC)
-
- struct tchars c;
- struct ltchars lc;
-
- switch (signo)
- {
- case SIGINT:
- ioctl (p->infd, TIOCGETC, &c);
- send_process (proc, &c.t_intrc, 1, Qnil);
- return;
- case SIGQUIT:
- ioctl (p->infd, TIOCGETC, &c);
- send_process (proc, &c.t_quitc, 1, Qnil);
- return;
-#ifdef SIGTSTP
- case SIGTSTP:
- ioctl (p->infd, TIOCGLTC, &lc);
- send_process (proc, &lc.t_suspc, 1, Qnil);
- return;
-#endif /* ! defined (SIGTSTP) */
- }
-
-#else /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
-
- /* On SYSV descendants, the TCGETA ioctl retrieves the current control
- characters. */
-#ifdef TCGETA
- struct termio t;
- switch (signo)
- {
- case SIGINT:
- ioctl (p->infd, TCGETA, &t);
- send_process (proc, &t.c_cc[VINTR], 1, Qnil);
- return;
- case SIGQUIT:
- ioctl (p->infd, TCGETA, &t);
- send_process (proc, &t.c_cc[VQUIT], 1, Qnil);
- return;
-#ifdef SIGTSTP
- case SIGTSTP:
- ioctl (p->infd, TCGETA, &t);
- send_process (proc, &t.c_cc[VSWTCH], 1, Qnil);
- return;
-#endif /* ! defined (SIGTSTP) */
- }
-#else /* ! defined (TCGETA) */
- Your configuration files are messed up.
- /* If your system configuration files define SIGNALS_VIA_CHARACTERS,
- you'd better be using one of the alternatives above! */
-#endif /* ! defined (TCGETA) */
-#endif /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
- /* In this case, the code above should alway return. */
- abort ();
-#endif /* ! defined HAVE_TERMIOS */
/* The code above may fall through if it can't
handle the signal. */
#ifdef WINDOWSNT
if (fd_info[ p->infd ].flags & FILE_SERIAL)
PurgeComm (fd_info[ p->infd ].hnd, PURGE_RXABORT | PURGE_RXCLEAR);
-#endif
-#ifdef HAVE_TERMIOS
+#else /* not WINDOWSNT */
tcflush (p->infd, TCIFLUSH);
-#endif
+#endif /* not WINDOWSNT */
}
p->command = Qnil;
return process;
send_process (proc, "\004", 1, Qnil);
else if (EQ (XPROCESS (proc)->type, Qserial))
{
-#ifdef HAVE_TERMIOS
+#ifndef WINDOWSNT
if (tcdrain (XPROCESS (proc)->outfd) != 0)
error ("tcdrain() failed: %s", emacs_strerror (errno));
-#endif
+#endif /* not WINDOWSNT */
/* Do nothing on Windows because writes are blocking. */
}
else
{
Lisp_Object tem;
struct buffer *old = current_buffer;
- int opoint, opoint_byte;
- int before, before_byte;
+ EMACS_INT opoint, opoint_byte;
+ EMACS_INT before, before_byte;
/* Avoid error if buffer is deleted
(probably that's why the process is dead, too) */
\f
-static int add_gpm_wait_descriptor_called_flag;
-
void
add_gpm_wait_descriptor (int desc)
{
- if (! add_gpm_wait_descriptor_called_flag)
- FD_CLR (0, &input_wait_mask);
- add_gpm_wait_descriptor_called_flag = 1;
- FD_SET (desc, &input_wait_mask);
- FD_SET (desc, &gpm_wait_mask);
- if (desc > max_gpm_desc)
- max_gpm_desc = desc;
+ add_keyboard_wait_descriptor (desc);
}
void
delete_gpm_wait_descriptor (int desc)
{
- int fd;
- int lim = max_gpm_desc;
-
- FD_CLR (desc, &input_wait_mask);
- FD_CLR (desc, &non_process_wait_mask);
-
- if (desc == max_gpm_desc)
- for (fd = 0; fd < lim; fd++)
- if (FD_ISSET (fd, &input_wait_mask)
- && !FD_ISSET (fd, &non_keyboard_wait_mask)
- && !FD_ISSET (fd, &non_process_wait_mask))
- max_gpm_desc = fd;
+ delete_keyboard_wait_descriptor (desc);
}
/* Return nonzero if *MASK has a bit set
{
int fd;
- for (fd = 0; fd <= max_keyboard_desc; fd++)
+ for (fd = 0; fd <= max_input_desc; fd++)
if (FD_ISSET (fd, mask) && FD_ISSET (fd, &input_wait_mask)
&& !FD_ISSET (fd, &non_keyboard_wait_mask))
return 1;
void
add_keyboard_wait_descriptor (int desc)
{
-#ifdef subprocesses
+#ifdef subprocesses /* actually means "not MSDOS" */
FD_SET (desc, &input_wait_mask);
FD_SET (desc, &non_process_wait_mask);
- if (desc > max_keyboard_desc)
- max_keyboard_desc = desc;
+ if (desc > max_input_desc)
+ max_input_desc = desc;
#endif
}
{
#ifdef subprocesses
int fd;
- int lim = max_keyboard_desc;
+ int lim = max_input_desc;
FD_CLR (desc, &input_wait_mask);
FD_CLR (desc, &non_process_wait_mask);
- if (desc == max_keyboard_desc)
+ if (desc == max_input_desc)
for (fd = 0; fd < lim; fd++)
- if (FD_ISSET (fd, &input_wait_mask)
- && !FD_ISSET (fd, &non_keyboard_wait_mask)
- && !FD_ISSET (fd, &gpm_wait_mask))
- max_keyboard_desc = fd;
-#endif /* subprocesses */
+ if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask))
+ max_input_desc = fd;
+#endif
}
/* Setup coding systems of PROCESS. */
FD_ZERO (&input_wait_mask);
FD_ZERO (&non_keyboard_wait_mask);
FD_ZERO (&non_process_wait_mask);
+ FD_ZERO (&write_mask);
max_process_desc = 0;
+ memset (fd_callback_info, 0, sizeof (fd_callback_info));
#ifdef NON_BLOCKING_CONNECT
FD_ZERO (&connect_wait_mask);
processes. As such, we only change the default value. */
if (initialized)
{
- char *release = get_operating_system_release ();
+ const char *release = get_operating_system_release ();
if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
&& release[1] == '.')) {
Vprocess_connection_type = Qnil;
Qargs = intern_c_string ("args");
staticpro (&Qargs);
- DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
+ DEFVAR_BOOL ("delete-exited-processes", delete_exited_processes,
doc: /* *Non-nil means delete processes immediately when they exit.
A value of nil means don't delete them until `list-processes' is run. */);
delete_exited_processes = 1;
#ifdef subprocesses
- DEFVAR_LISP ("process-connection-type", &Vprocess_connection_type,
+ DEFVAR_LISP ("process-connection-type", Vprocess_connection_type,
doc: /* Control type of device used to communicate with subprocesses.
Values are nil to use a pipe, or t or `pty' to use a pty.
The value has no effect if the system has no ptys or if all ptys are busy:
Vprocess_connection_type = Qt;
#ifdef ADAPTIVE_READ_BUFFERING
- DEFVAR_LISP ("process-adaptive-read-buffering", &Vprocess_adaptive_read_buffering,
+ DEFVAR_LISP ("process-adaptive-read-buffering", Vprocess_adaptive_read_buffering,
doc: /* If non-nil, improve receive buffering by delaying after short reads.
On some systems, when Emacs reads the output from a subprocess, the output data
is read in very small blocks, potentially resulting in very poor performance.
defsubr (&Slist_processes);
defsubr (&Sprocess_list);
defsubr (&Sstart_process);
-#ifdef HAVE_SERIAL
defsubr (&Sserial_process_configure);
defsubr (&Smake_serial_process);
-#endif /* HAVE_SERIAL */
defsubr (&Sset_network_process_option);
defsubr (&Smake_network_process);
defsubr (&Sformat_network_address);
-#if defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H)
+#if defined(HAVE_NET_IF_H)
#ifdef SIOCGIFCONF
defsubr (&Snetwork_interface_list);
#endif
#if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS)
defsubr (&Snetwork_interface_info);
#endif
-#endif /* defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H) */
+#endif /* defined(HAVE_NET_IF_H) */
#ifdef DATAGRAM_SOCKETS
defsubr (&Sprocess_datagram_address);
defsubr (&Sset_process_datagram_address);
defsubr (&Slist_system_processes);
defsubr (&Sprocess_attributes);
}
-
-/* arch-tag: 3706c011-7b9a-4117-bd4f-59e7f701a4c4
- (do not change this comment) */