/* Asynchronous subprocess control for GNU Emacs.
- Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 96, 98, 1999,
- 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
+ 1996, 1998, 1999, 2001, 2002, 2003, 2004,
+ 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
#include <sys/types.h> /* some typedefs are used in sys/file.h */
#include <sys/file.h>
#include <sys/stat.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/wait.h>
#endif
+/* Disable IPv6 support for w32 until someone figures out how to do it
+ properly. */
+#ifdef WINDOWSNT
+# ifdef AF_INET6
+# undef AF_INET6
+# endif
+#endif
+
+#include "lisp.h"
#include "systime.h"
#include "systty.h"
-#include "lisp.h"
#include "window.h"
#include "buffer.h"
#include "charset.h"
Lisp_Object Qprocessp;
Lisp_Object Qrun, Qstop, Qsignal;
Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
-Lisp_Object Qlocal, Qdatagram;
+Lisp_Object Qlocal, Qipv4, Qdatagram;
+#ifdef AF_INET6
+Lisp_Object Qipv6;
+#endif
Lisp_Object QCname, QCbuffer, QChost, QCservice, QCtype;
Lisp_Object QClocal, QCremote, QCcoding;
Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
#include "syswait.h"
-extern void set_waiting_for_input P_ ((EMACS_TIME *));
+extern char *get_operating_system_release ();
#ifndef USE_CRT_DLL
extern int errno;
#define READ_OUTPUT_DELAY_MAX (READ_OUTPUT_DELAY_INCREMENT * 5)
#define READ_OUTPUT_DELAY_MAX_MAX (READ_OUTPUT_DELAY_INCREMENT * 7)
-/* Number of processes which might be delayed. */
+/* Number of processes which have a non-zero read_output_delay,
+ and therefore might be delayed for adaptive read buffering. */
static int process_output_delay_count;
-/* Non-zero if any process has non-nil process_output_skip. */
+/* Non-zero if any process has non-nil read_output_skip. */
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. */
+ 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
#include "sysselect.h"
-extern int keyboard_bit_set P_ ((SELECT_TYPE *));
+static int keyboard_bit_set P_ ((SELECT_TYPE *));
+static void deactivate_process P_ ((Lisp_Object));
+static void status_notify P_ ((struct Lisp_Process *));
+static int read_process_output P_ ((Lisp_Object, int));
/* If we support a window system, turn on the code to poll periodically
to detect C-g. It isn't actually used when doing interrupt input. */
static SELECT_TYPE non_process_wait_mask;
+#ifdef NON_BLOCKING_CONNECT
/* Mask of bits indicating the descriptors that we wait for connect to
complete on. Once they complete, they are removed from this mask
and added to the input_wait_mask and non_keyboard_wait_mask. */
/* Number of bits set in connect_wait_mask. */
static int num_pending_connects;
+#define IF_NON_BLOCKING_CONNECT(s) s
+#else
+#define IF_NON_BLOCKING_CONNECT(s)
+#endif
+
/* The largest descriptor currently in use for a process object. */
static int max_process_desc;
/* Maximum number of bytes to send to a pty without an eof. */
static int pty_max_bytes;
-extern Lisp_Object Vfile_name_coding_system, Vdefault_file_name_coding_system;
-
#ifdef HAVE_PTYS
#ifdef HAVE_PTY_H
#include <pty.h>
/* Compute the Lisp form of the process status, p->status, from
the numeric status that was returned by `wait'. */
-Lisp_Object status_convert ();
+static Lisp_Object status_convert ();
-void
+static void
update_status (p)
struct Lisp_Process *p;
{
union { int i; WAITTYPE wt; } u;
- u.i = XFASTINT (p->raw_status_low) + (XFASTINT (p->raw_status_high) << 16);
+ eassert (p->raw_status_new);
+ u.i = p->raw_status;
p->status = status_convert (u.wt);
- p->raw_status_low = Qnil;
- p->raw_status_high = Qnil;
+ p->raw_status_new = 0;
}
/* Convert a process status word in Unix format to
the list that we use internally. */
-Lisp_Object
+static Lisp_Object
status_convert (w)
WAITTYPE w;
{
/* Given a status-list, extract the three pieces of information
and store them individually through the three pointers. */
-void
+static void
decode_status (l, symbol, code, coredump)
Lisp_Object l;
Lisp_Object *symbol;
The file name of the terminal corresponding to the pty
is left in the variable pty_name. */
-int
+static int
allocate_pty ()
{
register int c, i;
}
#endif /* HAVE_PTYS */
\f
-Lisp_Object
+static Lisp_Object
make_process (name)
Lisp_Object name;
{
XSETINT (p->infd, -1);
XSETINT (p->outfd, -1);
- XSETFASTINT (p->pid, 0);
XSETFASTINT (p->tick, 0);
XSETFASTINT (p->update_tick, 0);
- p->raw_status_low = Qnil;
- p->raw_status_high = Qnil;
+ p->pid = 0;
+ p->raw_status_new = 0;
p->status = Qrun;
p->mark = Fmake_marker ();
return val;
}
-void
+static void
remove_process (proc)
register Lisp_Object proc;
{
= (struct coding_system *) xmalloc (sizeof (struct coding_system));
setup_coding_system (p->encode_coding_system,
proc_encode_coding_system[outch]);
+ if (proc_encode_coding_system[outch]->eol_type == CODING_EOL_UNDECIDED)
+ proc_encode_coding_system[outch]->eol_type = system_eol_type;
}
\f
DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0,
return proc;
}
+
+#ifdef SIGCHLD
+/* Fdelete_process promises to immediately forget about the process, but in
+ reality, Emacs needs to remember those processes until they have been
+ treated by sigchld_handler; otherwise this handler would consider the
+ process as being synchronous and say that the synchronous process is
+ dead. */
+static Lisp_Object deleted_pid_list;
+#endif
+
DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
doc: /* Delete PROCESS: kill it and forget about it immediately.
PROCESS may be a process, a buffer, the name of a process or buffer, or
(process)
register Lisp_Object process;
{
+ register struct Lisp_Process *p;
+
process = get_process (process);
- XPROCESS (process)->raw_status_low = Qnil;
- XPROCESS (process)->raw_status_high = Qnil;
- if (NETCONN_P (process))
+ p = XPROCESS (process);
+
+ p->raw_status_new = 0;
+ if (NETCONN1_P (p))
{
- XPROCESS (process)->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
- XSETINT (XPROCESS (process)->tick, ++process_tick);
- status_notify ();
+ p->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
+ XSETINT (p->tick, ++process_tick);
+ status_notify (p);
}
- else if (XINT (XPROCESS (process)->infd) >= 0)
+ else if (XINT (p->infd) >= 0)
{
- Fkill_process (process, Qnil);
- /* Do this now, since remove_process will make sigchld_handler do nothing. */
- XPROCESS (process)->status
- = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
- XSETINT (XPROCESS (process)->tick, ++process_tick);
- status_notify ();
+#ifdef SIGCHLD
+ Lisp_Object symbol;
+
+ /* No problem storing the pid here, as it is still in Vprocess_alist. */
+ deleted_pid_list = Fcons (make_fixnum_or_float (p->pid),
+ /* GC treated elements set to nil. */
+ Fdelq (Qnil, deleted_pid_list));
+ /* If the process has already signaled, remove it from the list. */
+ if (p->raw_status_new)
+ update_status (p);
+ symbol = p->status;
+ if (CONSP (p->status))
+ symbol = XCAR (p->status);
+ if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
+ Fdelete (make_fixnum_or_float (p->pid), deleted_pid_list);
+ else
+#endif
+ {
+ Fkill_process (process, Qnil);
+ /* Do this now, since remove_process will make sigchld_handler do nothing. */
+ p->status
+ = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
+ XSETINT (p->tick, ++process_tick);
+ status_notify (p);
+ }
}
remove_process (process);
return Qnil;
return process;
p = XPROCESS (process);
- if (!NILP (p->raw_status_low))
+ if (p->raw_status_new)
update_status (p);
status = p->status;
if (CONSP (status))
register Lisp_Object process;
{
CHECK_PROCESS (process);
- if (!NILP (XPROCESS (process)->raw_status_low))
+ if (XPROCESS (process)->raw_status_new)
update_status (XPROCESS (process));
if (CONSP (XPROCESS (process)->status))
return XCAR (XCDR (XPROCESS (process)->status));
register Lisp_Object process;
{
CHECK_PROCESS (process);
- return XPROCESS (process)->pid;
+ return (XPROCESS (process)->pid
+ ? make_fixnum_or_float (XPROCESS (process)->pid)
+ : Qnil);
}
DEFUN ("process-name", Fprocess_name, Sprocess_name, 1, 1, 0,
DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address,
1, 2, 0,
doc: /* Convert network ADDRESS from internal format to a string.
+A 4 or 5 element vector represents an IPv4 address (with port number).
+An 8 or 9 element vector represents an IPv6 address (with port number).
If optional second argument OMIT-PORT is non-nil, don't include a port
-number in the string; in this case, interpret a 4 element vector as an
-IP address. Returns nil if format of ADDRESS is invalid. */)
+number in the string, even when present in ADDRESS.
+Returns nil if format of ADDRESS is invalid. */)
(address, omit_port)
Lisp_Object address, omit_port;
{
if (STRINGP (address)) /* AF_LOCAL */
return address;
- if (VECTORP (address)) /* AF_INET */
+ if (VECTORP (address)) /* AF_INET or AF_INET6 */
{
register struct Lisp_Vector *p = XVECTOR (address);
Lisp_Object args[6];
int nargs, i;
- if (!NILP (omit_port) && (p->size == 4 || p->size == 5))
+ if (p->size == 4 || (p->size == 5 && !NILP (omit_port)))
{
args[0] = build_string ("%d.%d.%d.%d");
nargs = 4;
args[0] = build_string ("%d.%d.%d.%d:%d");
nargs = 5;
}
+ else if (p->size == 8 || (p->size == 9 && !NILP (omit_port)))
+ {
+ args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
+ nargs = 8;
+ }
+ else if (p->size == 9)
+ {
+ args[0] = build_string ("[%x:%x:%x:%x:%x:%x:%x:%x]:%d");
+ nargs = 9;
+ }
else
return Qnil;
}
#endif
\f
-Lisp_Object
+static Lisp_Object
list_processes_1 (query_only)
Lisp_Object query_only;
{
XSETFASTINT (minspace, 1);
set_buffer_internal (XBUFFER (Vstandard_output));
- Fbuffer_disable_undo (Vstandard_output);
+ current_buffer->undo_list = Qt;
current_buffer->truncate_lines = Qt;
Finsert (1, &p->name);
Findent_to (i_status, minspace);
- if (!NILP (p->raw_status_low))
+ if (p->raw_status_new)
update_status (p);
symbol = p->status;
if (CONSP (p->status))
XPROCESS (proc)->childp = Qt;
XPROCESS (proc)->plist = Qnil;
- XPROCESS (proc)->command_channel_p = Qnil;
XPROCESS (proc)->buffer = buffer;
XPROCESS (proc)->sentinel = Qnil;
XPROCESS (proc)->filter = Qnil;
#endif
/* Make the process marker point into the process buffer (if any). */
- if (!NILP (buffer))
+ if (BUFFERP (buffer))
set_marker_both (XPROCESS (proc)->mark, buffer,
BUF_ZV (XBUFFER (buffer)),
BUF_ZV_BYTE (XBUFFER (buffer)));
abort ();
/* Was PROC started successfully? */
- if (XINT (XPROCESS (proc)->pid) <= 0)
+ if (XPROCESS (proc)->pid <= 0)
remove_process (proc);
return Qnil;
}
-void
+static void
create_process_1 (timer)
struct atimer *timer;
{
#endif
if (forkin < 0)
report_file_error ("Opening pty", Qnil);
+#if defined (RTU) || defined (UNIPLUS) || defined (DONT_REOPEN_PTY)
+ /* In the case that vfork is defined as fork, the parent process
+ (Emacs) may send some data before the child process completes
+ tty options setup. So we setup tty before forking. */
+ child_setup_tty (forkout);
+#endif /* RTU or UNIPLUS or DONT_REOPEN_PTY */
#else
forkin = forkout = -1;
#endif /* not USG, or USG_SUBTTY_WORKS */
in the table after this function has returned; if it does
it might cause call-process to hang and subsequent asynchronous
processes to get their return values scrambled. */
- XSETINT (XPROCESS (process)->pid, -1);
+ XPROCESS (process)->pid = -1;
BLOCK_INPUT;
#endif /* SIGCHLD */
#endif /* !POSIX_SIGNALS */
+#if !defined (RTU) && !defined (UNIPLUS) && !defined (DONT_REOPEN_PTY)
if (pty_flag)
child_setup_tty (xforkout);
+#endif /* not RTU and not UNIPLUS and not DONT_REOPEN_PTY */
#ifdef WINDOWSNT
pid = child_setup (xforkin, xforkout, xforkout,
new_argv, 1, current_dir);
else
{
/* vfork succeeded. */
- XSETFASTINT (XPROCESS (process)->pid, pid);
+ XPROCESS (process)->pid = pid;
#ifdef WINDOWSNT
register_child (pid, inchannel);
cp = (unsigned char *)&sin->sin_addr;
break;
}
+#ifdef AF_INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr;
+ len = sizeof (sin6->sin6_addr)/2 + 1;
+ address = Fmake_vector (make_number (len), Qnil);
+ p = XVECTOR (address);
+ p->contents[--len] = make_number (ntohs (sin6->sin6_port));
+ for (i = 0; i < len; i++)
+ p->contents[i] = make_number (ntohs (ip6[i]));
+ return address;
+ }
+#endif
#ifdef HAVE_LOCAL_SOCKETS
case AF_LOCAL:
{
*familyp = AF_INET;
return sizeof (struct sockaddr_in);
}
+#ifdef AF_INET6
+ else if (p->size == 9)
+ {
+ *familyp = AF_INET6;
+ return sizeof (struct sockaddr_in6);
+ }
+#endif
}
#ifdef HAVE_LOCAL_SOCKETS
else if (STRINGP (address))
}
/* Convert an address object (vector or string) to an internal sockaddr.
- Format of address has already been validated by size_lisp_to_sockaddr. */
+
+ The address format has been basically validated by
+ get_lisp_to_sockaddr_size, but this does not mean FAMILY is valid;
+ it could have come from user data. So if FAMILY is not valid,
+ we return after zeroing *SA. */
static void
conv_lisp_to_sockaddr (family, address, sa, len)
register int i;
bzero (sa, len);
- sa->sa_family = family;
if (VECTORP (address))
{
i = XINT (p->contents[--len]);
sin->sin_port = htons (i);
cp = (unsigned char *)&sin->sin_addr;
+ sa->sa_family = family;
+ }
+#ifdef AF_INET6
+ else if (family == AF_INET6)
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr;
+ len = sizeof (sin6->sin6_addr) + 1;
+ i = XINT (p->contents[--len]);
+ sin6->sin6_port = htons (i);
+ for (i = 0; i < len; i++)
+ if (INTEGERP (p->contents[i]))
+ {
+ int j = XFASTINT (p->contents[i]) & 0xffff;
+ ip6[i] = ntohs (j);
+ }
+ sa->sa_family = family;
}
+#endif
+ return;
}
else if (STRINGP (address))
{
cp = SDATA (address);
for (i = 0; i < sizeof (sockun->sun_path) && *cp; i++)
sockun->sun_path[i] = *cp++;
+ sa->sa_family = family;
}
#endif
return;
\f
/* A version of request_sigio suitable for a record_unwind_protect. */
-Lisp_Object
+static Lisp_Object
unwind_request_sigio (dummy)
Lisp_Object dummy;
{
In Emacs, network connections are represented by process objects, so
input and output work as for subprocesses and `delete-process' closes
a network connection. However, a network process has no process id,
-it cannot be signalled, and the status codes are different from normal
+it cannot be signaled, and the status codes are different from normal
processes.
Arguments are specified as keyword/argument pairs. The following
stream type connection, `datagram' creates a datagram type connection.
:family FAMILY -- FAMILY is the address (and protocol) family for the
-service specified by HOST and SERVICE. The default address family is
-Inet (or IPv4) for the host and port number specified by HOST and
-SERVICE. Other address families supported are:
+service specified by HOST and SERVICE. The default (nil) is to use
+whatever address family (IPv4 or IPv6) that is defined for the host
+and port number specified by HOST and SERVICE. Other address families
+supported are:
local -- for a local (i.e. UNIX) address specified by SERVICE.
+ ipv4 -- use IPv4 address family only.
+ ipv6 -- use IPv6 address family only.
:local ADDRESS -- ADDRESS is the local address used for the connection.
This parameter is ignored when opening a client process. When specified
struct Lisp_Process *p;
#ifdef HAVE_GETADDRINFO
struct addrinfo ai, *res, *lres;
- struct addrinfo hints;
- char *portstring, portbuf[128];
+ struct addrinfo hints;
+ char *portstring, portbuf[128];
#else /* HAVE_GETADDRINFO */
struct _emacs_addrinfo
{
int xerrno = 0;
int s = -1, outch, inch;
struct gcpro gcpro1;
- int retry = 0;
int count = SPECPDL_INDEX ();
int count1;
Lisp_Object QCaddress; /* one of QClocal or QCremote */
/* :family FAMILY -- nil (for Inet), local, or integer. */
tem = Fplist_get (contact, QCfamily);
- if (INTEGERP (tem))
- family = XINT (tem);
- else
+ if (NILP (tem))
{
- if (NILP (tem))
- family = AF_INET;
-#ifdef HAVE_LOCAL_SOCKETS
- else if (EQ (tem, Qlocal))
- family = AF_LOCAL;
+#if defined(HAVE_GETADDRINFO) && defined(AF_INET6)
+ family = AF_UNSPEC;
+#else
+ family = AF_INET;
#endif
}
- if (family < 0)
+#ifdef HAVE_LOCAL_SOCKETS
+ else if (EQ (tem, Qlocal))
+ family = AF_LOCAL;
+#endif
+#ifdef AF_INET6
+ else if (EQ (tem, Qipv6))
+ family = AF_INET6;
+#endif
+ else if (EQ (tem, Qipv4))
+ family = AF_INET;
+ else if (INTEGERP (tem))
+ family = XINT (tem);
+ else
error ("Unknown address family");
+
ai.ai_family = family;
/* :service SERVICE -- string, integer (port number), or t (random port). */
QUIT;
memset (&hints, 0, sizeof (hints));
hints.ai_flags = 0;
- hints.ai_family = NILP (Fplist_member (contact, QCfamily)) ? AF_UNSPEC : family;
+ hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_protocol = 0;
ret = getaddrinfo (SDATA (host), portstring, &hints, &res);
{
int optn, optbits;
+ retry_connect:
+
s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol);
if (s < 0)
{
break;
}
- retry_connect:
-
immediate_quit = 1;
QUIT;
immediate_quit = 0;
- if (xerrno == EINTR)
- goto retry_connect;
- if (xerrno == EADDRINUSE && retry < 20)
- {
- /* A delay here is needed on some FreeBSD systems,
- and it is harmless, since this retrying takes time anyway
- and should be infrequent. */
- Fsleep_for (make_number (1), Qnil);
- retry++;
- goto retry_connect;
- }
-
/* Discard the unwind protect closing S. */
specpdl_ptr = specpdl + count1;
emacs_close (s);
s = -1;
+
+ if (xerrno == EINTR)
+ goto retry_connect;
}
if (s >= 0)
p->kill_without_query = Qt;
if ((tem = Fplist_get (contact, QCstop), !NILP (tem)))
p->command = Qt;
- p->pid = Qnil;
+ p->pid = 0;
XSETINT (p->infd, inch);
XSETINT (p->outfd, outch);
if (is_server && socktype == SOCK_STREAM)
p->status = Qlisten;
+ /* Make the process marker point into the process buffer (if any). */
+ if (BUFFERP (buffer))
+ set_marker_both (p->mark, buffer,
+ BUF_ZV (XBUFFER (buffer)),
+ BUF_ZV_BYTE (XBUFFER (buffer)));
+
#ifdef NON_BLOCKING_CONNECT
if (is_non_blocking_client)
{
#endif
#ifdef IFF_DYNAMIC
{ IFF_DYNAMIC, "dynamic" },
+#endif
+#ifdef IFF_OACTIVE
+ { IFF_OACTIVE, "oactive" }, /* OpenBSD: transmission in progress */
+#endif
+#ifdef IFF_SIMPLEX
+ { IFF_SIMPLEX, "simplex" }, /* OpenBSD: can't hear own transmissions */
+#endif
+#ifdef IFF_LINK0
+ { IFF_LINK0, "link0" }, /* OpenBSD: per link layer defined bit */
+#endif
+#ifdef IFF_LINK1
+ { IFF_LINK1, "link1" }, /* OpenBSD: per link layer defined bit */
+#endif
+#ifdef IFF_LINK2
+ { IFF_LINK2, "link2" }, /* OpenBSD: per link layer defined bit */
#endif
{ 0, 0 }
};
int fnum;
any++;
- for (fp = ifflag_table; flags != 0 && fp; fp++)
+ for (fp = ifflag_table; flags != 0 && fp->flag_sym; fp++)
{
if (flags & fp->flag_bit)
{
res = Fcons (elt, res);
elt = Qnil;
-#if defined(SIOCGIFNETMASK) && defined(ifr_netmask)
+#if defined(SIOCGIFNETMASK) && (defined(HAVE_STRUCT_IFREQ_IFR_NETMASK) || defined(HAVE_STRUCT_IFREQ_IFR_ADDR))
if (ioctl (s, SIOCGIFNETMASK, &rq) == 0)
{
any++;
+#ifdef HAVE_STRUCT_IFREQ_IFR_NETMASK
elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask));
+#else
+ elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr));
+#endif
}
#endif
res = Fcons (elt, res);
chan_process[inchannel] = Qnil;
FD_CLR (inchannel, &input_wait_mask);
FD_CLR (inchannel, &non_keyboard_wait_mask);
+#ifdef NON_BLOCKING_CONNECT
if (FD_ISSET (inchannel, &connect_wait_mask))
{
FD_CLR (inchannel, &connect_wait_mask);
if (--num_pending_connects < 0)
abort ();
}
+#endif
if (inchannel == max_process_desc)
{
int i;
}
\f
DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
- 0, 3, 0,
+ 0, 4, 0,
doc: /* Allow any pending output from subprocesses to be read by Emacs.
It is read into the process' buffers or given to their filter functions.
Non-nil arg PROCESS means do not return until some output has been received
from PROCESS.
-Non-nil second arg TIMEOUT and third arg TIMEOUT-MSECS are number of
-seconds and microseconds to wait; return after that much time whether
-or not there is input.
+
+Non-nil second arg SECONDS and third arg MILLISEC are number of
+seconds and milliseconds to wait; return after that much time whether
+or not there is input. If SECONDS is a floating point number,
+it specifies a fractional number of seconds to wait.
+
+If optional fourth arg JUST-THIS-ONE is non-nil, only accept output
+from PROCESS, suspending reading output from other processes.
+If JUST-THIS-ONE is an integer, don't run any timers either.
Return non-nil iff we received any output before the timeout expired. */)
- (process, timeout, timeout_msecs)
- register Lisp_Object process, timeout, timeout_msecs;
+ (process, seconds, millisec, just_this_one)
+ register Lisp_Object process, seconds, millisec, just_this_one;
{
- int seconds;
- int useconds;
+ int secs, usecs = 0;
if (! NILP (process))
CHECK_PROCESS (process);
+ else
+ just_this_one = Qnil;
- if (! NILP (timeout_msecs))
+ if (!NILP (seconds))
{
- CHECK_NUMBER (timeout_msecs);
- useconds = XINT (timeout_msecs);
- if (!INTEGERP (timeout))
- XSETINT (timeout, 0);
-
- {
- int carry = useconds / 1000000;
-
- XSETINT (timeout, XINT (timeout) + carry);
- useconds -= carry * 1000000;
+ if (INTEGERP (seconds))
+ secs = XINT (seconds);
+ else if (FLOATP (seconds))
+ {
+ double timeout = XFLOAT_DATA (seconds);
+ secs = (int) timeout;
+ usecs = (int) ((timeout - (double) secs) * 1000000);
+ }
+ else
+ wrong_type_argument (Qnumberp, seconds);
- /* I think this clause is necessary because C doesn't
- guarantee a particular rounding direction for negative
- integers. */
- if (useconds < 0)
- {
- XSETINT (timeout, XINT (timeout) - 1);
- useconds += 1000000;
- }
- }
- }
- else
- useconds = 0;
+ if (INTEGERP (millisec))
+ {
+ int carry;
+ usecs += XINT (millisec) * 1000;
+ carry = usecs / 1000000;
+ secs += carry;
+ if ((usecs -= carry * 1000000) < 0)
+ {
+ secs--;
+ usecs += 1000000;
+ }
+ }
- if (! NILP (timeout))
- {
- CHECK_NUMBER (timeout);
- seconds = XINT (timeout);
- if (seconds < 0 || (seconds == 0 && useconds == 0))
- seconds = -1;
+ if (secs < 0 || (secs == 0 && usecs == 0))
+ secs = -1, usecs = 0;
}
else
- seconds = NILP (process) ? -1 : 0;
-
- if (NILP (process))
- XSETFASTINT (process, 0);
+ secs = NILP (process) ? -1 : 0;
return
- (wait_reading_process_input (seconds, useconds, process, 0)
+ (wait_reading_process_output (secs, usecs, 0, 0,
+ Qnil,
+ !NILP (process) ? XPROCESS (process) : NULL,
+ NILP (just_this_one) ? 0 :
+ !INTEGERP (just_this_one) ? 1 : -1)
? Qt : Qnil);
}
union u_sockaddr {
struct sockaddr sa;
struct sockaddr_in in;
+#ifdef AF_INET6
+ struct sockaddr_in6 in6;
+#endif
#ifdef HAVE_LOCAL_SOCKETS
struct sockaddr_un un;
#endif
}
break;
+#ifdef AF_INET6
+ case AF_INET6:
+ {
+ Lisp_Object args[9];
+ uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr;
+ int i;
+ args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
+ for (i = 0; i < 8; i++)
+ args[i+1] = make_number (ntohs(ip6[i]));
+ host = Fformat (9, args);
+ service = make_number (ntohs (saddr.in.sin_port));
+
+ args[0] = build_string (" <[%s]:%d>");
+ args[1] = host;
+ args[2] = service;
+ caller = Fformat (3, args);
+ }
+ break;
+#endif
+
#ifdef HAVE_LOCAL_SOCKETS
case AF_LOCAL:
#endif
p->sentinel = ps->sentinel;
p->filter = ps->filter;
p->command = Qnil;
- p->pid = Qnil;
+ p->pid = 0;
XSETINT (p->infd, s);
XSETINT (p->outfd, s);
p->status = Qrun;
lisp code is being evalled.
This is also used in record_asynch_buffer_change.
For that purpose, this must be 0
- when not inside wait_reading_process_input. */
+ when not inside wait_reading_process_output. */
static int waiting_for_user_input_p;
/* This is here so breakpoints can be put on it. */
static void
-wait_reading_process_input_1 ()
+wait_reading_process_output_1 ()
{
}
+/* Use a wrapper around select to work around a bug in gdb 5.3.
+ Normally, the wrapper is optimzed away by inlining.
+
+ If emacs is stopped inside select, the gdb backtrace doesn't
+ show the function which called select, so it is practically
+ impossible to step through wait_reading_process_output. */
+
+#ifndef select
+static INLINE int
+select_wrapper (n, rfd, wfd, xfd, tmo)
+ int n;
+ SELECT_TYPE *rfd, *wfd, *xfd;
+ EMACS_TIME *tmo;
+{
+ return select (n, rfd, wfd, xfd, tmo);
+}
+#define select select_wrapper
+#endif
+
/* Read and dispose of subprocess output while waiting for timeout to
elapse and/or keyboard input to be available.
1 to return when input is available, or
-1 meaning caller will actually read the input, so don't throw to
the quit handler, or
- a cons cell, meaning wait until its car is non-nil
- (and gobble terminal input into the buffer if any arrives), or
- a process object, meaning wait until something arrives from that
- process. The return value is true iff we read some input from
- that process.
DO_DISPLAY != 0 means redisplay should be done to show subprocess
- output that arrives.
+ output that arrives.
+
+ If WAIT_FOR_CELL is a cons cell, wait until its car is non-nil
+ (and gobble terminal input into the buffer if any arrives).
- If READ_KBD is a pointer to a struct Lisp_Process, then the
- function returns true iff we received input from that process
- before the timeout elapsed.
+ If WAIT_PROC is specified, wait until something arrives from that
+ process. The return value is true iff we read some input from
+ that process.
+
+ If JUST_WAIT_PROC is non-nil, handle only output from WAIT_PROC
+ (suspending output from other processes). A negative value
+ means don't run any timers either.
+
+ If WAIT_PROC is specified, then the function returns true iff we
+ received input from that process before the timeout elapsed.
Otherwise, return true iff we received input from any process. */
int
-wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
- int time_limit, microsecs;
- Lisp_Object read_kbd;
- int do_display;
+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;
{
register int channel, nfds;
SELECT_TYPE Available;
+#ifdef NON_BLOCKING_CONNECT
SELECT_TYPE Connecting;
- int check_connect, check_delay, no_avail;
+ int check_connect;
+#endif
+ int check_delay, no_avail;
int xerrno;
Lisp_Object proc;
EMACS_TIME timeout, end_time;
int wait_channel = -1;
- struct Lisp_Process *wait_proc = 0;
int got_some_input = 0;
/* Either nil or a cons cell, the car of which is of interest and
may be changed outside of this routine. */
- Lisp_Object wait_for_cell = Qnil;
int saved_waiting_for_user_input_p = waiting_for_user_input_p;
FD_ZERO (&Available);
+#ifdef NON_BLOCKING_CONNECT
FD_ZERO (&Connecting);
+#endif
- /* If read_kbd is a process to watch, set wait_proc and wait_channel
- accordingly. */
- if (PROCESSP (read_kbd))
- {
- wait_proc = XPROCESS (read_kbd);
- wait_channel = XINT (wait_proc->infd);
- XSETFASTINT (read_kbd, 0);
- }
-
- /* If waiting for non-nil in a cell, record where. */
- if (CONSP (read_kbd))
- {
- wait_for_cell = read_kbd;
- XSETFASTINT (read_kbd, 0);
- }
+ /* If wait_proc is a process to watch, set wait_channel accordingly. */
+ if (wait_proc != NULL)
+ wait_channel = XINT (wait_proc->infd);
- waiting_for_user_input_p = XINT (read_kbd);
+ waiting_for_user_input_p = read_kbd;
/* Since we may need to wait several times,
compute the absolute time to return at. */
/* If calling from keyboard input, do not quit
since we want to return C-g as an input character.
Otherwise, do pending quit if requested. */
- if (XINT (read_kbd) >= 0)
+ if (read_kbd >= 0)
QUIT;
#ifdef SYNC_INPUT
else if (interrupt_input_pending)
But not if wait_for_cell; in those cases,
the wait is supposed to be short,
and those callers cannot handle running arbitrary Lisp code here. */
- if (NILP (wait_for_cell))
+ if (NILP (wait_for_cell)
+ && just_wait_proc >= 0)
{
EMACS_TIME timer_delay;
while (!detect_input_pending ());
/* If there is unread keyboard input, also return. */
- if (XINT (read_kbd) != 0
+ if (read_kbd != 0
&& requeued_events_pending_p ())
break;
else if (time_limit != -1)
{
/* This is so a breakpoint can be put here. */
- wait_reading_process_input_1 ();
+ wait_reading_process_output_1 ();
}
}
It is important that we do this before checking for process
activity. If we get a SIGCHLD after the explicit checks for
process activity, timeout is the only way we will know. */
- if (XINT (read_kbd) < 0)
+ if (read_kbd < 0)
set_waiting_for_input (&timeout);
/* If status of something has changed, and no input is
timeout to get our attention. */
if (update_tick != process_tick && do_display)
{
- SELECT_TYPE Atemp, Ctemp;
+ SELECT_TYPE Atemp;
+#ifdef NON_BLOCKING_CONNECT
+ SELECT_TYPE Ctemp;
+#endif
Atemp = input_wait_mask;
#if 0
*/
FD_CLR (0, &Atemp);
#endif
- Ctemp = connect_wait_mask;
+ IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask);
+
EMACS_SET_SECS_USECS (timeout, 0, 0);
if ((select (max (max_process_desc, max_keyboard_desc) + 1,
&Atemp,
+#ifdef NON_BLOCKING_CONNECT
(num_pending_connects > 0 ? &Ctemp : (SELECT_TYPE *)0),
+#else
+ (SELECT_TYPE *)0,
+#endif
(SELECT_TYPE *)0, &timeout)
<= 0))
{
/* It's okay for us to do this and then continue with
the loop, since timeout has already been zeroed out. */
clear_waiting_for_input ();
- status_notify ();
+ status_notify (NULL);
}
}
/* Don't wait for output from a non-running process. Just
read whatever data has already been received. */
- if (wait_proc != 0 && !NILP (wait_proc->raw_status_low))
+ if (wait_proc && wait_proc->raw_status_new)
update_status (wait_proc);
- if (wait_proc != 0
+ if (wait_proc
&& ! EQ (wait_proc->status, Qrun)
&& ! EQ (wait_proc->status, Qconnect))
{
/* Wait till there is something to do */
- if (!NILP (wait_for_cell))
+ if (wait_proc && just_wait_proc)
+ {
+ if (XINT (wait_proc->infd) < 0) /* Terminated */
+ break;
+ FD_SET (XINT (wait_proc->infd), &Available);
+ check_delay = 0;
+ IF_NON_BLOCKING_CONNECT (check_connect = 0);
+ }
+ else if (!NILP (wait_for_cell))
{
Available = non_process_wait_mask;
- check_connect = check_delay = 0;
+ check_delay = 0;
+ IF_NON_BLOCKING_CONNECT (check_connect = 0);
}
else
{
- if (! XINT (read_kbd))
+ if (! read_kbd)
Available = non_keyboard_wait_mask;
else
Available = input_wait_mask;
- check_connect = (num_pending_connects > 0);
+ IF_NON_BLOCKING_CONNECT (check_connect = (num_pending_connects > 0));
check_delay = wait_channel >= 0 ? 0 : process_output_delay_count;
}
{
clear_waiting_for_input ();
redisplay_preserve_echo_area (11);
- if (XINT (read_kbd) < 0)
+ if (read_kbd < 0)
set_waiting_for_input (&timeout);
}
no_avail = 0;
- if (XINT (read_kbd) && detect_input_pending ())
+ if (read_kbd && detect_input_pending ())
{
nfds = 0;
no_avail = 1;
}
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
+ process has non-nil read_output_skip and non-zero
+ read_output_delay, and we are not reading output for a
+ specific wait_channel. It is not executed if
+ Vprocess_adaptive_read_buffering is nil. */
if (process_output_skip && check_delay > 0)
{
int usecs = EMACS_USECS (timeout);
proc = chan_process[channel];
if (NILP (proc))
continue;
+ /* Find minimum non-zero read_output_delay among the
+ processes with non-nil read_output_skip. */
if (XINT (XPROCESS (proc)->read_output_delay) > 0)
{
check_delay--;
nfds = select (max (max_process_desc, max_keyboard_desc) + 1,
&Available,
+#ifdef NON_BLOCKING_CONNECT
(check_connect ? &Connecting : (SELECT_TYPE *)0),
+#else
+ (SELECT_TYPE *)0,
+#endif
(SELECT_TYPE *)0, &timeout);
}
if (no_avail)
{
FD_ZERO (&Available);
- check_connect = 0;
+ IF_NON_BLOCKING_CONNECT (check_connect = 0);
}
#if defined(sun) && !defined(USG5_4)
/* If we are using polling for input,
and we see input available, make it get read now.
Otherwise it might not actually get read for a second.
- And on hpux, since we turn off polling in wait_reading_process_input,
+ And on hpux, since we turn off polling in wait_reading_process_output,
it might never get read at all if we don't spend much time
- outside of wait_reading_process_input. */
- if (XINT (read_kbd) && interrupt_input
+ outside of wait_reading_process_output. */
+ if (read_kbd && interrupt_input
&& keyboard_bit_set (&Available)
&& input_polling_used ())
kill (getpid (), SIGALRM);
/* If there is any, return immediately
to give it higher priority than subprocesses */
- if (XINT (read_kbd) != 0)
+ if (read_kbd != 0)
{
int old_timers_run = timers_run;
struct buffer *old_buffer = current_buffer;
}
/* If there is unread keyboard input, also return. */
- if (XINT (read_kbd) != 0
+ if (read_kbd != 0
&& requeued_events_pending_p ())
break;
That would causes delays in pasting selections, for example.
(We used to do this only if wait_for_cell.) */
- if (XINT (read_kbd) == 0 && detect_input_pending ())
+ if (read_kbd == 0 && detect_input_pending ())
{
swallow_events (do_display);
#if 0 /* Exiting when read_kbd doesn't request that seems wrong, though. */
In that case, there really is no input and no SIGIO,
but select says there is input. */
- if (XINT (read_kbd) && interrupt_input
+ if (read_kbd && interrupt_input
&& keyboard_bit_set (&Available) && ! noninteractive)
kill (getpid (), SIGIO);
#endif
/* If checking input just got us a size-change event from X,
obey it now if we should. */
- if (XINT (read_kbd) || ! NILP (wait_for_cell))
+ if (read_kbd || ! NILP (wait_for_cell))
do_pending_window_change (0);
/* Check for data from a process. */
/* Preserve status of processes already terminated. */
XSETINT (XPROCESS (proc)->tick, ++process_tick);
deactivate_process (proc);
- if (!NILP (XPROCESS (proc)->raw_status_low))
+ if (XPROCESS (proc)->raw_status_new)
update_status (XPROCESS (proc));
if (EQ (XPROCESS (proc)->status, Qrun))
XPROCESS (proc)->status
/* If calling from keyboard input, do not quit
since we want to return C-g as an input character.
Otherwise, do pending quit if requested. */
- if (XINT (read_kbd) >= 0)
+ if (read_kbd >= 0)
{
/* Prevent input_pending from remaining set if we quit. */
clear_input_pending ();
The characters read are decoded according to PROC's coding-system
for decoding. */
-int
+static int
read_process_output (proc, channel)
Lisp_Object proc;
register int channel;
{
Lisp_Object tem;
/* Don't clobber the CURRENT match data, either! */
- tem = Fmatch_data (Qnil, Qnil);
- restore_match_data ();
- record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
- Fset_match_data (tem);
+ tem = Fmatch_data (Qnil, Qnil, Qnil);
+ restore_search_regs ();
+ record_unwind_save_match_data ();
+ Fset_match_data (tem, Qt);
}
/* For speed, if a search happens within this code,
p->encode_coding_system = coding->symbol;
setup_coding_system (coding->symbol,
proc_encode_coding_system[XINT (p->outfd)]);
+ if (proc_encode_coding_system[XINT (p->outfd)]->eol_type
+ == CODING_EOL_UNDECIDED)
+ proc_encode_coding_system[XINT (p->outfd)]->eol_type
+ = system_eol_type;
}
}
read_process_output_error_handler);
/* If we saved the match data nonrecursively, restore it now. */
- restore_match_data ();
+ restore_search_regs ();
running_asynch_code = outer_running_asynch_code;
/* Handling the process output should not deactivate the mark. */
p->encode_coding_system = coding->symbol;
setup_coding_system (coding->symbol,
proc_encode_coding_system[XINT (p->outfd)]);
+ if (proc_encode_coding_system[XINT (p->outfd)]->eol_type
+ == CODING_EOL_UNDECIDED)
+ proc_encode_coding_system[XINT (p->outfd)]->eol_type
+ = system_eol_type;
}
}
carryover = nbytes - coding->consumed;
SIGTYPE
send_process_trap ()
{
+ SIGNAL_THREAD_CHECK (SIGPIPE);
#ifdef BSD4_1
sigrelse (SIGPIPE);
sigrelse (SIGALRM);
#endif /* BSD4_1 */
+ sigunblock (sigmask (SIGPIPE));
longjmp (send_process_frame, 1);
}
This function can evaluate Lisp code and can garbage collect. */
-void
+static void
send_process (proc, buf, len, object)
volatile Lisp_Object proc;
unsigned char *volatile buf;
int rv;
struct coding_system *coding;
struct gcpro gcpro1;
+ SIGTYPE (*volatile old_sigpipe) ();
GCPRO1 (object);
VMS_PROC_STUFF *vs, *get_vms_process_pointer();
#endif /* VMS */
- if (! NILP (p->raw_status_low))
+ if (p->raw_status_new)
update_status (p);
if (! EQ (p->status, Qrun))
error ("Process %s not running", SDATA (p->name));
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);
+ if (coding->eol_type == CODING_EOL_UNDECIDED)
+ coding->eol_type = system_eol_type;
/* src_multibyte should be set to 1 _after_ a call to
setup_coding_system, since it resets src_multibyte to
zero. */
object = p->encoding_buf;
encode_coding (coding, (char *) buf, SDATA (object),
len, SBYTES (object));
+ coding_free_composition_data (coding);
len = coding->produced;
buf = SDATA (object);
}
while (len > 0)
{
int this = len;
- SIGTYPE (*old_sigpipe)();
/* Decide how much data we can send in one batch.
Long lines need to be split into multiple batches. */
0, datagram_address[outfd].sa,
datagram_address[outfd].len);
if (rv < 0 && errno == EMSGSIZE)
- report_file_error ("sending datagram", Fcons (proc, Qnil));
+ {
+ signal (SIGPIPE, old_sigpipe);
+ report_file_error ("sending datagram",
+ Fcons (proc, Qnil));
+ }
}
else
#endif
that may allow the program
to finish doing output and read more. */
{
- Lisp_Object zero;
int offset = 0;
#ifdef BROKEN_PTY_READ_AFTER_EAGAIN
else if (STRINGP (object))
offset = buf - SDATA (object);
- XSETFASTINT (zero, 0);
#ifdef EMACS_HAS_USECS
- wait_reading_process_input (0, 20000, zero, 0);
+ wait_reading_process_output (0, 20000, 0, 0, Qnil, NULL, 0);
#else
- wait_reading_process_input (1, 0, zero, 0);
+ wait_reading_process_output (1, 0, 0, 0, Qnil, NULL, 0);
#endif
if (BUFFERP (object))
#endif /* not VMS */
else
{
+ signal (SIGPIPE, old_sigpipe);
#ifndef VMS
proc = process_sent_to;
p = XPROCESS (proc);
#endif
- p->raw_status_low = Qnil;
- p->raw_status_high = Qnil;
+ p->raw_status_new = 0;
p->status = Fcons (Qexit, Fcons (make_number (256), Qnil));
XSETINT (p->tick, ++process_tick);
deactivate_process (proc);
gid = emacs_get_tty_pgrp (p);
- if (gid == XFASTINT (p->pid))
+ if (gid == p->pid)
return Qnil;
return Qt;
}
/* If we are using pgrps, get a pgrp number and make it negative. */
if (NILP (current_group))
/* Send the signal to the shell's process group. */
- gid = XFASTINT (p->pid);
+ gid = p->pid;
else
{
#ifdef SIGNALS_VIA_CHARACTERS
break;
}
- if (sig_char && *sig_char != CVDISABLE)
- send_process (proc, sig_char, 1, Qnil);
- return;
+ if (sig_char && *sig_char != CDISABLE)
+ {
+ send_process (proc, sig_char, 1, Qnil);
+ return;
+ }
+ /* 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
you'd better be using one of the alternatives above! */
#endif /* ! defined (TCGETA) */
#endif /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
-#endif /* ! defined HAVE_TERMIOS */
+ /* In this case, the code above should alway returns. */
abort ();
- /* The code above always returns from the function. */
+#endif /* ! defined HAVE_TERMIOS */
+
+ /* The code above may fall through if it can't
+ handle the signal. */
#endif /* defined (SIGNALS_VIA_CHARACTERS) */
#ifdef TIOCGPGRP
if (gid == -1)
/* If we can't get the information, assume
the shell owns the tty. */
- gid = XFASTINT (p->pid);
+ gid = p->pid;
/* It is not clear whether anything really can set GID to -1.
Perhaps on some system one of those ioctls can or could do so.
#else /* ! defined (TIOCGPGRP ) */
/* Can't select pgrps on this system, so we know that
the child itself heads the pgrp. */
- gid = XFASTINT (p->pid);
+ gid = p->pid;
#endif /* ! defined (TIOCGPGRP ) */
/* If current_group is lambda, and the shell owns the terminal,
don't send any signal. */
- if (EQ (current_group, Qlambda) && gid == XFASTINT (p->pid))
+ if (EQ (current_group, Qlambda) && gid == p->pid)
return;
}
{
#ifdef SIGCONT
case SIGCONT:
- p->raw_status_low = Qnil;
- p->raw_status_high = Qnil;
+ p->raw_status_new = 0;
p->status = Qrun;
XSETINT (p->tick, ++process_tick);
if (!nomsg)
- status_notify ();
+ status_notify (NULL);
break;
#endif /* ! defined (SIGCONT) */
case SIGINT:
#endif
case SIGKILL:
#ifdef VMS
- sys$forcex (&(XFASTINT (p->pid)), 0, 1);
+ sys$forcex (&(p->pid), 0, 1);
whoosh:
#endif
flush_pending_output (XINT (p->infd));
obvious alternative. */
if (no_pgrp)
{
- kill (XFASTINT (p->pid), signo);
+ kill (p->pid, signo);
return;
}
}
else
{
- gid = - XFASTINT (p->pid);
+ gid = - p->pid;
kill (gid, signo);
}
#else /* ! defined (TIOCSIGSEND) */
}
#endif
#ifndef SIGTSTP
- error ("no SIGTSTP support");
+ error ("No SIGTSTP support");
#else
process_send_signal (process, SIGTSTP, current_group, 0);
#endif
#ifdef SIGCONT
process_send_signal (process, SIGCONT, current_group, 0);
#else
- error ("no SIGCONT support");
+ error ("No SIGCONT support");
#endif
return process;
}
(process, sigcode)
Lisp_Object process, sigcode;
{
- Lisp_Object pid;
+ pid_t pid;
if (INTEGERP (process))
{
- pid = process;
+ pid = XINT (process);
+ goto got_it;
+ }
+
+ if (FLOATP (process))
+ {
+ pid = (pid_t) XFLOAT (process);
goto got_it;
}
Lisp_Object tem;
if (tem = Fget_process (process), NILP (tem))
{
- pid = Fstring_to_number (process, make_number (10));
- if (XINT (pid) != 0)
+ pid = XINT (Fstring_to_number (process, make_number (10)));
+ if (pid > 0)
goto got_it;
}
process = tem;
CHECK_PROCESS (process);
pid = XPROCESS (process)->pid;
- if (!INTEGERP (pid) || XINT (pid) <= 0)
+ if (pid <= 0)
error ("Cannot signal process %s", SDATA (XPROCESS (process)->name));
got_it:
CHECK_SYMBOL (sigcode);
name = SDATA (SYMBOL_NAME (sigcode));
+ if (!strncmp(name, "SIG", 3))
+ name += 3;
+
if (0)
;
#ifdef SIGHUP
- handle_signal ("SIGHUP", SIGHUP);
+ handle_signal ("HUP", SIGHUP);
#endif
#ifdef SIGINT
- handle_signal ("SIGINT", SIGINT);
+ handle_signal ("INT", SIGINT);
#endif
#ifdef SIGQUIT
- handle_signal ("SIGQUIT", SIGQUIT);
+ handle_signal ("QUIT", SIGQUIT);
#endif
#ifdef SIGILL
- handle_signal ("SIGILL", SIGILL);
+ handle_signal ("ILL", SIGILL);
#endif
#ifdef SIGABRT
- handle_signal ("SIGABRT", SIGABRT);
+ handle_signal ("ABRT", SIGABRT);
#endif
#ifdef SIGEMT
- handle_signal ("SIGEMT", SIGEMT);
+ handle_signal ("EMT", SIGEMT);
#endif
#ifdef SIGKILL
- handle_signal ("SIGKILL", SIGKILL);
+ handle_signal ("KILL", SIGKILL);
#endif
#ifdef SIGFPE
- handle_signal ("SIGFPE", SIGFPE);
+ handle_signal ("FPE", SIGFPE);
#endif
#ifdef SIGBUS
- handle_signal ("SIGBUS", SIGBUS);
+ handle_signal ("BUS", SIGBUS);
#endif
#ifdef SIGSEGV
- handle_signal ("SIGSEGV", SIGSEGV);
+ handle_signal ("SEGV", SIGSEGV);
#endif
#ifdef SIGSYS
- handle_signal ("SIGSYS", SIGSYS);
+ handle_signal ("SYS", SIGSYS);
#endif
#ifdef SIGPIPE
- handle_signal ("SIGPIPE", SIGPIPE);
+ handle_signal ("PIPE", SIGPIPE);
#endif
#ifdef SIGALRM
- handle_signal ("SIGALRM", SIGALRM);
+ handle_signal ("ALRM", SIGALRM);
#endif
#ifdef SIGTERM
- handle_signal ("SIGTERM", SIGTERM);
+ handle_signal ("TERM", SIGTERM);
#endif
#ifdef SIGURG
- handle_signal ("SIGURG", SIGURG);
+ handle_signal ("URG", SIGURG);
#endif
#ifdef SIGSTOP
- handle_signal ("SIGSTOP", SIGSTOP);
+ handle_signal ("STOP", SIGSTOP);
#endif
#ifdef SIGTSTP
- handle_signal ("SIGTSTP", SIGTSTP);
+ handle_signal ("TSTP", SIGTSTP);
#endif
#ifdef SIGCONT
- handle_signal ("SIGCONT", SIGCONT);
+ handle_signal ("CONT", SIGCONT);
#endif
#ifdef SIGCHLD
- handle_signal ("SIGCHLD", SIGCHLD);
+ handle_signal ("CHLD", SIGCHLD);
#endif
#ifdef SIGTTIN
- handle_signal ("SIGTTIN", SIGTTIN);
+ handle_signal ("TTIN", SIGTTIN);
#endif
#ifdef SIGTTOU
- handle_signal ("SIGTTOU", SIGTTOU);
+ handle_signal ("TTOU", SIGTTOU);
#endif
#ifdef SIGIO
- handle_signal ("SIGIO", SIGIO);
+ handle_signal ("IO", SIGIO);
#endif
#ifdef SIGXCPU
- handle_signal ("SIGXCPU", SIGXCPU);
+ handle_signal ("XCPU", SIGXCPU);
#endif
#ifdef SIGXFSZ
- handle_signal ("SIGXFSZ", SIGXFSZ);
+ handle_signal ("XFSZ", SIGXFSZ);
#endif
#ifdef SIGVTALRM
- handle_signal ("SIGVTALRM", SIGVTALRM);
+ handle_signal ("VTALRM", SIGVTALRM);
#endif
#ifdef SIGPROF
- handle_signal ("SIGPROF", SIGPROF);
+ handle_signal ("PROF", SIGPROF);
#endif
#ifdef SIGWINCH
- handle_signal ("SIGWINCH", SIGWINCH);
+ handle_signal ("WINCH", SIGWINCH);
#endif
#ifdef SIGINFO
- handle_signal ("SIGINFO", SIGINFO);
+ handle_signal ("INFO", SIGINFO);
#endif
#ifdef SIGUSR1
- handle_signal ("SIGUSR1", SIGUSR1);
+ handle_signal ("USR1", SIGUSR1);
#endif
#ifdef SIGUSR2
- handle_signal ("SIGUSR2", SIGUSR2);
+ handle_signal ("USR2", SIGUSR2);
#endif
else
error ("Undefined signal name %s", name);
#undef handle_signal
- return make_number (kill (XINT (pid), XINT (sigcode)));
+ return make_number (kill (pid, XINT (sigcode)));
}
DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0,
coding = proc_encode_coding_system[XINT (XPROCESS (proc)->outfd)];
/* Make sure the process is really alive. */
- if (! NILP (XPROCESS (proc)->raw_status_low))
+ if (XPROCESS (proc)->raw_status_new)
update_status (XPROCESS (proc));
if (! EQ (XPROCESS (proc)->status, Qrun))
error ("Process %s not running", SDATA (XPROCESS (proc)->name));
for communication with the subprocess, call shutdown to cause EOF.
(In some old system, shutdown to socketpair doesn't work.
Then we just can't win.) */
- if (NILP (XPROCESS (proc)->pid)
+ if (XPROCESS (proc)->pid == 0
|| XINT (XPROCESS (proc)->outfd) == XINT (XPROCESS (proc)->infd))
shutdown (XINT (XPROCESS (proc)->outfd), 1);
/* In case of socketpair, outfd == infd, so don't close it. */
emacs_close (XINT (XPROCESS (proc)->outfd));
#endif /* not HAVE_SHUTDOWN */
new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0);
+ if (new_outfd < 0)
+ abort ();
old_outfd = XINT (XPROCESS (proc)->outfd);
if (!proc_encode_coding_system[new_outfd])
** Malloc WARNING: This should never call malloc either directly or
indirectly; if it does, that is a bug */
+#ifdef SIGCHLD
SIGTYPE
sigchld_handler (signo)
int signo;
register struct Lisp_Process *p;
extern EMACS_TIME *input_available_clear_time;
+ SIGNAL_THREAD_CHECK (signo);
+
#ifdef BSD4_1
extern int sigheld;
sigheld |= sigbit (SIGCHLD);
/* Find the process that signaled us, and record its status. */
+ /* The process can have been deleted by Fdelete_process. */
+ tail = Fmember (make_fixnum_or_float (pid), deleted_pid_list);
+ if (!NILP (tail))
+ {
+ Fsetcar (tail, Qnil);
+ goto sigchld_end_of_loop;
+ }
+
+ /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */
p = 0;
for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail))
{
proc = XCDR (XCAR (tail));
p = XPROCESS (proc);
- if (GC_EQ (p->childp, Qt) && XINT (p->pid) == pid)
+ if (GC_EQ (p->childp, Qt) && p->pid == pid)
break;
p = 0;
}
{
proc = XCDR (XCAR (tail));
p = XPROCESS (proc);
- if (GC_INTEGERP (p->pid) && XINT (p->pid) == -1)
+ if (p->pid == -1)
break;
p = 0;
}
XSETINT (p->tick, ++process_tick);
u.wt = w;
- XSETINT (p->raw_status_low, u.i & 0xffff);
- XSETINT (p->raw_status_high, u.i >> 16);
+ p->raw_status = u.i;
+ p->raw_status_new = 1;
/* If process has terminated, stop waiting for its output. */
if ((WIFSIGNALED (w) || WIFEXITED (w))
FD_CLR (XINT (p->infd), &non_keyboard_wait_mask);
}
- /* Tell wait_reading_process_input that it needs to wake up and
+ /* Tell wait_reading_process_output that it needs to wake up and
look around. */
if (input_available_clear_time)
EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
}
- /* There was no asynchronous process found for that id. Check
- if we have a synchronous process. */
+ /* There was no asynchronous process found for that pid: we have
+ a synchronous process. */
else
{
synch_process_alive = 0;
else if (WIFSIGNALED (w))
synch_process_termsig = WTERMSIG (w);
- /* Tell wait_reading_process_input that it needs to wake up and
+ /* Tell wait_reading_process_output that it needs to wake up and
look around. */
if (input_available_clear_time)
EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
}
+ sigchld_end_of_loop:
+ ;
+
/* On some systems, we must return right away.
If any more processes want to signal us, we will
get another signal.
#endif /* USG, but not HPUX with WNOHANG */
}
}
+#endif /* SIGCHLD */
\f
static Lisp_Object
if (outer_running_asynch_code)
{
Lisp_Object tem;
- tem = Fmatch_data (Qnil, Qnil);
- restore_match_data ();
- record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
- Fset_match_data (tem);
+ tem = Fmatch_data (Qnil, Qnil, Qnil);
+ restore_search_regs ();
+ record_unwind_save_match_data ();
+ Fset_match_data (tem, Qt);
}
/* For speed, if a search happens within this code,
exec_sentinel_error_handler);
/* If we saved the match data nonrecursively, restore it now. */
- restore_match_data ();
+ restore_search_regs ();
running_asynch_code = outer_running_asynch_code;
Vdeactivate_mark = odeactivate;
This is usually done while Emacs is waiting for keyboard input
but can be done at other times. */
-void
-status_notify ()
+static void
+status_notify (deleting_process)
+ struct Lisp_Process *deleting_process;
{
register Lisp_Object proc, buffer;
Lisp_Object tail, msg;
&& ! EQ (p->status, Qlisten)
&& ! EQ (p->command, Qt) /* Network process not stopped. */
&& XINT (p->infd) >= 0
+ && p != deleting_process
&& read_process_output (proc, XINT (p->infd)) > 0);
buffer = p->buffer;
/* Get the text to use for the message. */
- if (!NILP (p->raw_status_low))
+ if (p->raw_status_new)
update_status (p);
msg = status_message (p);
/* Return nonzero if *MASK has a bit set
that corresponds to one of the keyboard input descriptors. */
-int
+static int
keyboard_bit_set (mask)
SELECT_TYPE *mask;
{
FD_ZERO (&non_process_wait_mask);
max_process_desc = 0;
+#ifdef NON_BLOCKING_CONNECT
+ FD_ZERO (&connect_wait_mask);
+ num_pending_connects = 0;
+#endif
+
#ifdef ADAPTIVE_READ_BUFFERING
process_output_delay_count = 0;
process_output_skip = 0;
FD_SET (0, &input_wait_mask);
Vprocess_alist = Qnil;
+#ifdef SIGCHLD
+ deleted_pid_list = Qnil;
+#endif
for (i = 0; i < MAXDESC; i++)
{
chan_process[i] = Qnil;
#endif
#ifdef HAVE_LOCAL_SOCKETS
ADD_SUBFEATURE (QCfamily, Qlocal);
+#endif
+ ADD_SUBFEATURE (QCfamily, Qipv4);
+#ifdef AF_INET6
+ ADD_SUBFEATURE (QCfamily, Qipv6);
#endif
#ifdef HAVE_GETSOCKNAME
ADD_SUBFEATURE (QCservice, Qt);
Fprovide (intern ("make-network-process"), subfeatures);
}
#endif /* HAVE_SOCKETS */
+
+#if defined (DARWIN) || defined (MAC_OSX)
+ /* 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();
+ if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
+ && release[1] == '.')) {
+ Vprocess_connection_type = Qnil;
+ }
+ }
+#endif
}
void
staticpro (&Qlisten);
Qlocal = intern ("local");
staticpro (&Qlocal);
+ Qipv4 = intern ("ipv4");
+ staticpro (&Qipv4);
+#ifdef AF_INET6
+ Qipv6 = intern ("ipv6");
+ staticpro (&Qipv6);
+#endif
Qdatagram = intern ("datagram");
staticpro (&Qdatagram);
staticpro (&Qlast_nonmenu_event);
staticpro (&Vprocess_alist);
+#ifdef SIGCHLD
+ staticpro (&deleted_pid_list);
+#endif
DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
doc: /* *Non-nil means delete processes immediately when they exit.
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.
-This behaviour can be remedied to some extent by setting this variable to a
+This behavior can be remedied to some extent by setting this variable to a
non-nil value, as it will automatically delay reading from such processes, to
-allowing them to produce more output before Emacs tries to read it.
+allow them to produce more output before Emacs tries to read it.
If the value is t, the delay is reset after each write to the process; any other
non-nil value means that the delay is not reset on write.
The variable takes effect when `start-process' is called. */);
1 to return when input is available, or
-1 means caller will actually read the input, so don't throw to
the quit handler.
- a cons cell, meaning wait until its car is non-nil
- (and gobble terminal input into the buffer if any arrives), or
- We know that read_kbd will never be a Lisp_Process, since
- `subprocesses' isn't defined.
+
+ see full version for other parameters. We know that wait_proc will
+ always be NULL, since `subprocesses' isn't defined.
do_display != 0 means redisplay should be done to show subprocess
output that arrives.
Return true iff we received input from any process. */
int
-wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
- int time_limit, microsecs;
- Lisp_Object read_kbd;
- int do_display;
+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;
{
register int nfds;
EMACS_TIME end_time, timeout;
SELECT_TYPE waitchannels;
int xerrno;
- /* Either nil or a cons cell, the car of which is of interest and
- may be changed outside of this routine. */
- Lisp_Object wait_for_cell;
-
- wait_for_cell = Qnil;
-
- /* If waiting for non-nil in a cell, record where. */
- if (CONSP (read_kbd))
- {
- wait_for_cell = read_kbd;
- XSETFASTINT (read_kbd, 0);
- }
/* What does time_limit really mean? */
if (time_limit || microsecs)
/* If calling from keyboard input, do not quit
since we want to return C-g as an input character.
Otherwise, do pending quit if requested. */
- if (XINT (read_kbd) >= 0)
+ if (read_kbd >= 0)
QUIT;
/* Exit now if the cell we're waiting for became non-nil. */
while (!detect_input_pending ());
/* If there is unread keyboard input, also return. */
- if (XINT (read_kbd) != 0
+ if (read_kbd != 0
&& requeued_events_pending_p ())
break;
/* Cause C-g and alarm signals to take immediate action,
and cause input available signals to zero out timeout. */
- if (XINT (read_kbd) < 0)
+ if (read_kbd < 0)
set_waiting_for_input (&timeout);
/* Wait till there is something to do. */
- if (! XINT (read_kbd) && NILP (wait_for_cell))
+ if (! read_kbd && NILP (wait_for_cell))
FD_ZERO (&waitchannels);
else
FD_SET (0, &waitchannels);
{
clear_waiting_for_input ();
redisplay_preserve_echo_area (15);
- if (XINT (read_kbd) < 0)
+ if (read_kbd < 0)
set_waiting_for_input (&timeout);
}
- if (XINT (read_kbd) && detect_input_pending ())
+ if (read_kbd && detect_input_pending ())
{
nfds = 0;
FD_ZERO (&waitchannels);
kill (getpid (), SIGIO);
#endif
#ifdef SIGIO
- if (XINT (read_kbd) && interrupt_input && (waitchannels & 1))
+ if (read_kbd && interrupt_input && (waitchannels & 1))
kill (getpid (), SIGIO);
#endif
/* Check for keyboard input */
- if ((XINT (read_kbd) != 0)
+ if (read_kbd
&& detect_input_pending_run_timers (do_display))
{
swallow_events (do_display);
}
/* If there is unread keyboard input, also return. */
- if (XINT (read_kbd) != 0
+ if (read_kbd
&& requeued_events_pending_p ())
break;