/* 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'. */
#ifdef subprocesses
-#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/un.h>
#endif
#endif
-#endif /* HAVE_SOCKETS */
-#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 */
-#endif /* HAVE_SYS_IOCTL_H */
+#if defined(HAVE_NET_IF_H)
+#include <net/if.h>
+#endif /* HAVE_NET_IF_H */
#ifdef NEED_BSDTTY
#include <bsdtty.h>
#endif
-/* Can we use SIOCGIFCONF and/or SIOCGIFADDR */
-#ifdef HAVE_SOCKETS
-#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H)
-/* sys/ioctl.h may have been included already */
-#ifndef SIOCGIFADDR
-#include <sys/ioctl.h>
-#endif
-#include <net/if.h>
-#endif
-#endif
-
-#ifdef HAVE_SYS_WAIT
-#include <sys/wait.h>
-#endif
-
#ifdef HAVE_RES_INIT
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#endif
+#ifdef HAVE_UTIL_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"
#endif /* defined (USE_GTK) || defined (HAVE_GCONF) */
+#ifdef HAVE_NS
+#include "nsterm.h"
+#endif
+
+Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
+Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
+Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
+Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
+Lisp_Object QCname, QCtype;
+\f
+/* Non-zero if keyboard input is on hold, zero otherwise. */
+
+static int kbd_is_on_hold;
+
+/* Nonzero means don't run process sentinels. This is used
+ when exiting. */
+int inhibit_sentinels;
#ifdef subprocesses
/* QCfilter is defined in keyboard.c. */
extern Lisp_Object QCfilter;
-#ifdef HAVE_SOCKETS
#define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork))
#define NETCONN1_P(p) (EQ ((p)->type, Qnetwork))
#define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial))
#define SERIALCONN1_P(p) (EQ ((p)->type, Qserial))
-#else
-#define NETCONN_P(p) 0
-#define NETCONN1_P(p) 0
-#define SERIALCONN_P(p) 0
-#define SERIALCONN1_P(p) 0
-#endif /* HAVE_SOCKETS */
/* 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 const char *get_operating_system_release (void);
-extern 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_SOCKETS
#ifdef HAVE_SELECT
#if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX)
#if defined (O_NONBLOCK) || defined (O_NDELAY)
#endif /* O_NONBLOCK || O_NDELAY */
#endif /* HAVE_GETPEERNAME || GNU_LINUX */
#endif /* HAVE_SELECT */
-#endif /* HAVE_SOCKETS */
#endif /* NON_BLOCKING_CONNECT */
#endif /* BROKEN_NON_BLOCKING_CONNECT */
#undef DATAGRAM_SOCKETS
#else
#ifndef DATAGRAM_SOCKETS
-#ifdef HAVE_SOCKETS
#if defined (HAVE_SELECT) || defined (FIONREAD)
#if defined (HAVE_SENDTO) && defined (HAVE_RECVFROM) && defined (EMSGSIZE)
#define DATAGRAM_SOCKETS
#endif /* HAVE_SENDTO && HAVE_RECVFROM && EMSGSIZE */
#endif /* HAVE_SELECT || FIONREAD */
-#endif /* HAVE_SOCKETS */
#endif /* DATAGRAM_SOCKETS */
#endif /* BROKEN_DATAGRAM_SOCKETS */
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 Lisp_Object get_process (register Lisp_Object name);
static void exec_sentinel (Lisp_Object proc, Lisp_Object reason);
-#endif /* subprocesses */
-
-extern int timers_run;
-
-Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
-Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
-Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
-Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
-Lisp_Object QCname, QCtype;
-\f
-/* Non-zero if keyboard input is on hold, zero otherwise. */
-
-static int kbd_is_on_hold;
-
-/* Nonzero means delete a process right away if it exits. */
-static int delete_exited_processes;
-
-#ifdef subprocesses
-
/* Mask of bits indicating the descriptors that we wait for input on. */
static SELECT_TYPE input_wait_mask;
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;
-/* Nonzero means don't run process sentinels. This is used
- when exiting. */
-int inhibit_sentinels;
+\f
-#ifdef HAVE_PTYS
-#ifdef HAVE_PTY_H
-#include <pty.h>
-#endif
-/* The file name of the pty opened by allocate_pty. */
+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;
return XPROCESS (proc)->type;
}
-#ifdef HAVE_SOCKETS
DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address,
1, 2, 0,
doc: /* Convert network ADDRESS from internal format to a string.
return Qnil;
}
-#endif
\f
static Lisp_Object
list_processes_1 (Lisp_Object query_only)
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;
}
-#if 0 /* This doesn't work; see the note before sigchld_handler. */
-#ifdef USG
-#ifdef SIGCHLD
-/* Mimic blocking of signals on system V, which doesn't really have it. */
-
-/* Nonzero means we got a SIGCHLD when it was supposed to be blocked. */
-int sigchld_deferred;
-
-SIGTYPE
-create_process_sigchld ()
-{
- signal (SIGCHLD, create_process_sigchld);
-
- sigchld_deferred = 1;
-}
-#endif
-#endif
-#endif
-
void
create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
{
}
#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;
}
\f
-#ifdef HAVE_SOCKETS
-
/* Convert an internal struct sockaddr to a lisp object (vector or string).
The address family of sa is not included in the result. */
static const struct socket_options {
/* The name of this option. Should be lowercase version of option
name without SO_ prefix. */
- char *name;
+ const char *name;
/* Option level SOL_... */
int optlevel;
/* Option number SO_... */
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++;
}
}
UNGCPRO;
return proc;
}
-#endif /* HAVE_SOCKETS */
\f
-#if defined(HAVE_SOCKETS) && 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 /* HAVE_SOCKETS */
+#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 ();
}
Otherwise, return true if we received input from any process. */
int
-wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
- wait_for_cell, wait_proc, just_wait_proc)
- int time_limit, microsecs, read_kbd, do_display;
- Lisp_Object wait_for_cell;
- struct Lisp_Process *wait_proc;
- int just_wait_proc;
+wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+ int do_display,
+ Lisp_Object wait_for_cell,
+ struct Lisp_Process *wait_proc, int just_wait_proc)
{
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;
unbind_to (count, Qnil);
return nbytes;
}
-
-DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, Swaiting_for_user_input_p,
- 0, 0, 0,
- doc: /* Returns non-nil if Emacs is waiting for input from the user.
-This is intended for use by asynchronous process output filters and sentinels. */)
- (void)
-{
- return (waiting_for_user_input_p ? Qt : Qnil);
-}
\f
/* Sending data to subprocess */
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. */
traffic. */)
(Lisp_Object process, Lisp_Object current_group)
{
-#ifdef HAVE_SOCKETS
if (PROCESSP (process) && (NETCONN_P (process) || SERIALCONN_P (process)))
{
struct Lisp_Process *p;
p->command = Qt;
return process;
}
-#endif
#ifndef SIGTSTP
error ("No SIGTSTP support");
#else
traffic. */)
(Lisp_Object process, Lisp_Object current_group)
{
-#ifdef HAVE_SOCKETS
if (PROCESSP (process) && (NETCONN_P (process) || SERIALCONN_P (process)))
{
struct Lisp_Process *p;
#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;
}
-#endif
#ifdef SIGCONT
process_send_signal (process, SIGCONT, current_group, 0);
#else
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
{
int old_errno = errno;
Lisp_Object proc;
- register struct Lisp_Process *p;
- extern EMACS_TIME *input_available_clear_time;
+ struct Lisp_Process *p;
SIGNAL_THREAD_CHECK (signo);
{
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
-/* Add DESC to the set of keyboard input descriptors. */
-
-void
-add_keyboard_wait_descriptor (int desc)
-{
- FD_SET (desc, &input_wait_mask);
- FD_SET (desc, &non_process_wait_mask);
- if (desc > max_keyboard_desc)
- max_keyboard_desc = desc;
-}
-
-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;
-}
-
-/* From now on, do not expect DESC to give keyboard input. */
-
-void
-delete_keyboard_wait_descriptor (int desc)
-{
- int fd;
- int lim = max_keyboard_desc;
-
- FD_CLR (desc, &input_wait_mask);
- FD_CLR (desc, &non_process_wait_mask);
-
- if (desc == max_keyboard_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;
+ 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;
Return true if we received input from any process. */
int
-wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
- wait_for_cell, wait_proc, just_wait_proc)
- int time_limit, microsecs, read_kbd, do_display;
- Lisp_Object wait_for_cell;
- struct Lisp_Process *wait_proc;
- int just_wait_proc;
+wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+ int do_display,
+ Lisp_Object wait_for_cell,
+ struct Lisp_Process *wait_proc, int just_wait_proc)
{
register int nfds;
EMACS_TIME end_time, timeout;
/* The following functions are needed even if async subprocesses are
not supported. Some of them are no-op stubs in that case. */
+/* Add DESC to the set of keyboard input descriptors. */
+
+void
+add_keyboard_wait_descriptor (int desc)
+{
+#ifdef subprocesses /* actually means "not MSDOS" */
+ FD_SET (desc, &input_wait_mask);
+ FD_SET (desc, &non_process_wait_mask);
+ if (desc > max_input_desc)
+ max_input_desc = desc;
+#endif
+}
+
+/* From now on, do not expect DESC to give keyboard input. */
+
+void
+delete_keyboard_wait_descriptor (int desc)
+{
+#ifdef subprocesses
+ int fd;
+ int lim = max_input_desc;
+
+ FD_CLR (desc, &input_wait_mask);
+ FD_CLR (desc, &non_process_wait_mask);
+
+ if (desc == max_input_desc)
+ for (fd = 0; fd < lim; fd++)
+ if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask))
+ max_input_desc = fd;
+#endif
+}
+
/* Setup coding systems of PROCESS. */
void
#endif /* subprocesses */
}
+DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, Swaiting_for_user_input_p,
+ 0, 0, 0,
+ doc: /* Returns non-nil if Emacs is waiting for input from the user.
+This is intended for use by asynchronous process output filters and sentinels. */)
+ (void)
+{
+#ifdef subprocesses
+ return (waiting_for_user_input_p ? Qt : Qnil);
+#else
+ return Qnil;
+#endif
+}
+
/* Stop reading input from keyboard sources. */
void
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);
memset (datagram_address, 0, sizeof datagram_address);
#endif
-#ifdef HAVE_SOCKETS
{
Lisp_Object subfeatures = Qnil;
const struct socket_options *sopt;
Fprovide (intern_c_string ("make-network-process"), subfeatures);
}
-#endif /* HAVE_SOCKETS */
#if defined (DARWIN_OS)
/* PTYs are broken on Darwin < 6, but are sometimes useful for interactive
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 */
-#ifdef HAVE_SOCKETS
defsubr (&Sset_network_process_option);
defsubr (&Smake_network_process);
defsubr (&Sformat_network_address);
-#endif /* HAVE_SOCKETS */
-#if defined(HAVE_SOCKETS) && 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 /* HAVE_SOCKETS ... */
+#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) */