/* Asynchronous subprocess control for GNU Emacs.
- Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1998, 1999,
- 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
+ 1996, 1998, 1999, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007 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
#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. */
#define POLL_FOR_INPUT
#endif
+static Lisp_Object get_process ();
+static void exec_sentinel ();
+
+extern EMACS_TIME timer_check ();
+extern int timers_run;
+\f
/* Mask of bits indicating the descriptors that we wait for input on. */
static SELECT_TYPE input_wait_mask;
#define DATAGRAM_CONN_P(proc) (0)
#endif
-static Lisp_Object get_process ();
-static void exec_sentinel ();
-
-extern EMACS_TIME timer_check ();
-extern int timers_run;
-
/* 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;
+
#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;
+ /* Assignment to EMACS_INT stops GCC whining about limited range
+ of data type. */
+ EMACS_INT pid = p->pid;
+
+ /* No problem storing the pid here, as it is still in Vprocess_alist. */
+ deleted_pid_list = Fcons (make_fixnum_or_float (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))
+ deleted_pid_list
+ = Fdelete (make_fixnum_or_float (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));
(process)
register Lisp_Object process;
{
+ /* Assignment to EMACS_INT stops GCC whining about limited range of
+ data type. */
+ EMACS_INT pid;
+
CHECK_PROCESS (process);
- return XPROCESS (process)->pid;
+ pid = XPROCESS (process)->pid;
+ return (pid ? make_fixnum_or_float (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];
+ Lisp_Object args[10];
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;
args[0] = build_string ("<Family %d>");
args[1] = Fcar (address);
return Fformat (2, args);
-
}
return Qnil;
}
#endif
\f
-Lisp_Object
+static Lisp_Object
list_processes_1 (query_only)
Lisp_Object query_only;
{
register struct Lisp_Process *p;
char tembuf[300];
int w_proc, w_buffer, w_tty;
+ int exited = 0;
Lisp_Object i_status, i_buffer, i_tty, i_command;
w_proc = 4; /* Proc */
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))
}
}
- if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
- remove_process (proc);
+ if (EQ (symbol, Qsignal) || EQ (symbol, Qexit) || EQ (symbol, Qclosed))
+ exited++;
Findent_to (i_buffer, minspace);
if (NILP (p->buffer))
insert_string ("\n");
}
}
+ if (exited)
+ status_notify (NULL);
return Qnil;
}
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;
{
char **new_argv;
Lisp_Object current_dir;
{
- int pid, inchannel, outchannel;
+ int inchannel, outchannel;
+ pid_t pid;
int sv[2];
#ifdef POSIX_SIGNALS
sigset_t procmask;
#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
{
/* Make QCaddress an alias for :local (server) or :remote (client). */
QCaddress = is_server ? QClocal : QCremote;
- /* :wait BOOL */
+ /* :nowait BOOL */
if (!is_server && socktype == SOCK_STREAM
&& (tem = Fplist_get (contact, QCnowait), !NILP (tem)))
{
/* :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);
#endif
}
+ immediate_quit = 0;
+
#ifdef HAVE_GETADDRINFO
if (res != &ai)
- freeaddrinfo (res);
+ {
+ BLOCK_INPUT;
+ freeaddrinfo (res);
+ UNBLOCK_INPUT;
+ }
#endif
- immediate_quit = 0;
-
/* Discard the unwind protect for closing S, if any. */
specpdl_ptr = specpdl + count1;
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);
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, just_this_one)
- register Lisp_Object process, timeout, timeout_msecs, just_this_one;
+ (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;
+ secs = NILP (process) ? -1 : 0;
return
- (wait_reading_process_output (seconds, useconds, 0, 0,
+ (wait_reading_process_output (secs, usecs, 0, 0,
Qnil,
!NILP (process) ? XPROCESS (process) : NULL,
NILP (just_this_one) ? 0 :
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;
when not inside wait_reading_process_output. */
static int waiting_for_user_input_p;
+static Lisp_Object
+wait_reading_process_output_unwind (data)
+ Lisp_Object data;
+{
+ waiting_for_user_input_p = XINT (data);
+ return Qnil;
+}
+
/* This is here so breakpoints can be put on it. */
static void
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.
EMACS_TIME timeout, end_time;
int wait_channel = -1;
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. */
- int saved_waiting_for_user_input_p = waiting_for_user_input_p;
+ int count = SPECPDL_INDEX ();
FD_ZERO (&Available);
#ifdef NON_BLOCKING_CONNECT
if (wait_proc != NULL)
wait_channel = XINT (wait_proc->infd);
+ record_unwind_protect (wait_reading_process_output_unwind,
+ make_number (waiting_for_user_input_p));
waiting_for_user_input_p = read_kbd;
/* Since we may need to wait several times,
/* 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))
{
#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--;
/* 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
} /* end for each file descriptor */
} /* end while exit conditions not met */
- waiting_for_user_input_p = saved_waiting_for_user_input_p;
+ unbind_to (count, Qnil);
/* If calling from keyboard input, do not quit
since we want to return C-g as an input character.
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;
}
}
carryover = nbytes - coding->consumed;
+ if (carryover < 0)
+ abort ();
+
if (SCHARS (p->decoding_buf) < carryover)
p->decoding_buf = make_uninit_string (carryover);
bcopy (chars + coding->consumed, SDATA (p->decoding_buf),
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. */
#endif
/* But do it only if the caller is actually going to read events.
Otherwise there's no need to make him wake up, and it could
- cause trouble (for example it would make Fsit_for return). */
+ cause trouble (for example it would make sit_for return). */
if (waiting_for_user_input_p == -1)
record_asynch_buffer_change ();
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;
+ if (carryover < 0)
+ abort ();
+
if (SCHARS (p->decoding_buf) < carryover)
p->decoding_buf = make_uninit_string (carryover);
bcopy (chars + coding->consumed, SDATA (p->decoding_buf),
carryover);
XSETINT (p->decoding_carryover, carryover);
+
/* Adjust the multibyteness of TEXT to that of the buffer. */
if (NILP (current_buffer->enable_multibyte_characters)
!= ! STRING_MULTIBYTE (text))
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. */
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. */
#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);
UNGCPRO;
}
+static Lisp_Object
+send_process_object_unwind (buf)
+ Lisp_Object buf;
+{
+ Lisp_Object tembuf;
+
+ if (XBUFFER (buf) == current_buffer)
+ return Qnil;
+ tembuf = Fcurrent_buffer ();
+ Fset_buffer (buf);
+ Fkill_buffer (tembuf);
+ return Qnil;
+}
+
+/* Send current contents of region between START and END to PROC.
+ If START is a string, send it instead.
+ This function can evaluate Lisp code and can garbage collect. */
+
+static void
+send_process_object (proc, start, end)
+ Lisp_Object proc, start, end;
+{
+ int count = SPECPDL_INDEX ();
+ Lisp_Object object = STRINGP (start) ? start : Fcurrent_buffer ();
+ struct buffer *given_buffer = current_buffer;
+ unsigned char *buf;
+ int len;
+
+ record_unwind_protect (send_process_object_unwind, Fcurrent_buffer ());
+
+ if (STRINGP (object) ? STRING_MULTIBYTE (object)
+ : ! NILP (XBUFFER (object)->enable_multibyte_characters))
+ {
+ struct Lisp_Process *p = XPROCESS (proc);
+ struct coding_system *coding;
+
+ if (p->raw_status_new)
+ update_status (p);
+ if (! EQ (p->status, Qrun))
+ error ("Process %s not running", SDATA (p->name));
+ if (XINT (p->outfd) < 0)
+ error ("Output file descriptor of %s is closed", SDATA (p->name));
+
+ coding = proc_encode_coding_system[XINT (p->outfd)];
+ if (! EQ (coding->symbol, 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);
+ if (! NILP (coding->pre_write_conversion))
+ {
+ struct gcpro gcpro1, gcpro2;
+
+ GCPRO2 (proc, object);
+ call2 (coding->pre_write_conversion, start, end);
+ UNGCPRO;
+ if (given_buffer != current_buffer)
+ {
+ start = make_number (BEGV), end = make_number (ZV);
+ object = Fcurrent_buffer ();
+ }
+ }
+ }
+
+ if (BUFFERP (object))
+ {
+ EMACS_INT start_byte;
+
+ if (XINT (start) < GPT && XINT (end) > GPT)
+ move_gap (XINT (end));
+ start_byte = CHAR_TO_BYTE (XINT (start));
+ buf = BYTE_POS_ADDR (start_byte);
+ len = CHAR_TO_BYTE (XINT (end)) - start_byte;
+ }
+ else
+ {
+ buf = SDATA (object);
+ len = SBYTES (object);
+ }
+ send_process (proc, buf, len, object);
+
+ unbind_to (count, Qnil);
+}
+
DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
3, 3, 0,
doc: /* Send current contents of region as input to PROCESS.
Lisp_Object process, start, end;
{
Lisp_Object proc;
- int start1, end1;
proc = get_process (process);
validate_region (&start, &end);
-
- if (XINT (start) < GPT && XINT (end) > GPT)
- move_gap (XINT (start));
-
- start1 = CHAR_TO_BYTE (XINT (start));
- end1 = CHAR_TO_BYTE (XINT (end));
- send_process (proc, BYTE_POS_ADDR (start1), end1 - start1,
- Fcurrent_buffer ());
-
+ send_process_object (proc, start, end);
return Qnil;
}
Lisp_Object proc;
CHECK_STRING (string);
proc = get_process (process);
- send_process (proc, SDATA (string),
- SBYTES (string), string);
+ send_process_object (proc, string, Qnil);
return Qnil;
}
\f
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
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;
}
DEFUN ("signal-process", Fsignal_process, Ssignal_process,
2, 2, "sProcess (name or number): \nnSignal code: ",
doc: /* Send PROCESS the signal with code SIGCODE.
-PROCESS may also be an integer specifying the process id of the
+PROCESS may also be a number specifying the process id of the
process to signal; in this case, the process need not be a child of
this Emacs.
SIGCODE may be an integer, or a symbol whose name is a signal name. */)
(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_DATA (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:
-#define handle_signal(NAME, VALUE) \
- else if (!strcmp (name, NAME)) \
+#define parse_signal(NAME, VALUE) \
+ else if (!xstricmp (name, NAME)) \
XSETINT (sigcode, VALUE)
if (INTEGERP (sigcode))
CHECK_SYMBOL (sigcode);
name = SDATA (SYMBOL_NAME (sigcode));
+ if (!strncmp(name, "SIG", 3) || !strncmp(name, "sig", 3))
+ name += 3;
+
if (0)
;
+#ifdef SIGUSR1
+ parse_signal ("usr1", SIGUSR1);
+#endif
+#ifdef SIGUSR2
+ parse_signal ("usr2", SIGUSR2);
+#endif
+#ifdef SIGTERM
+ parse_signal ("term", SIGTERM);
+#endif
#ifdef SIGHUP
- handle_signal ("SIGHUP", SIGHUP);
+ parse_signal ("hup", SIGHUP);
#endif
#ifdef SIGINT
- handle_signal ("SIGINT", SIGINT);
+ parse_signal ("int", SIGINT);
#endif
#ifdef SIGQUIT
- handle_signal ("SIGQUIT", SIGQUIT);
+ parse_signal ("quit", SIGQUIT);
#endif
#ifdef SIGILL
- handle_signal ("SIGILL", SIGILL);
+ parse_signal ("ill", SIGILL);
#endif
#ifdef SIGABRT
- handle_signal ("SIGABRT", SIGABRT);
+ parse_signal ("abrt", SIGABRT);
#endif
#ifdef SIGEMT
- handle_signal ("SIGEMT", SIGEMT);
+ parse_signal ("emt", SIGEMT);
#endif
#ifdef SIGKILL
- handle_signal ("SIGKILL", SIGKILL);
+ parse_signal ("kill", SIGKILL);
#endif
#ifdef SIGFPE
- handle_signal ("SIGFPE", SIGFPE);
+ parse_signal ("fpe", SIGFPE);
#endif
#ifdef SIGBUS
- handle_signal ("SIGBUS", SIGBUS);
+ parse_signal ("bus", SIGBUS);
#endif
#ifdef SIGSEGV
- handle_signal ("SIGSEGV", SIGSEGV);
+ parse_signal ("segv", SIGSEGV);
#endif
#ifdef SIGSYS
- handle_signal ("SIGSYS", SIGSYS);
+ parse_signal ("sys", SIGSYS);
#endif
#ifdef SIGPIPE
- handle_signal ("SIGPIPE", SIGPIPE);
+ parse_signal ("pipe", SIGPIPE);
#endif
#ifdef SIGALRM
- handle_signal ("SIGALRM", SIGALRM);
-#endif
-#ifdef SIGTERM
- handle_signal ("SIGTERM", SIGTERM);
+ parse_signal ("alrm", SIGALRM);
#endif
#ifdef SIGURG
- handle_signal ("SIGURG", SIGURG);
+ parse_signal ("urg", SIGURG);
#endif
#ifdef SIGSTOP
- handle_signal ("SIGSTOP", SIGSTOP);
+ parse_signal ("stop", SIGSTOP);
#endif
#ifdef SIGTSTP
- handle_signal ("SIGTSTP", SIGTSTP);
+ parse_signal ("tstp", SIGTSTP);
#endif
#ifdef SIGCONT
- handle_signal ("SIGCONT", SIGCONT);
+ parse_signal ("cont", SIGCONT);
#endif
#ifdef SIGCHLD
- handle_signal ("SIGCHLD", SIGCHLD);
+ parse_signal ("chld", SIGCHLD);
#endif
#ifdef SIGTTIN
- handle_signal ("SIGTTIN", SIGTTIN);
+ parse_signal ("ttin", SIGTTIN);
#endif
#ifdef SIGTTOU
- handle_signal ("SIGTTOU", SIGTTOU);
+ parse_signal ("ttou", SIGTTOU);
#endif
#ifdef SIGIO
- handle_signal ("SIGIO", SIGIO);
+ parse_signal ("io", SIGIO);
#endif
#ifdef SIGXCPU
- handle_signal ("SIGXCPU", SIGXCPU);
+ parse_signal ("xcpu", SIGXCPU);
#endif
#ifdef SIGXFSZ
- handle_signal ("SIGXFSZ", SIGXFSZ);
+ parse_signal ("xfsz", SIGXFSZ);
#endif
#ifdef SIGVTALRM
- handle_signal ("SIGVTALRM", SIGVTALRM);
+ parse_signal ("vtalrm", SIGVTALRM);
#endif
#ifdef SIGPROF
- handle_signal ("SIGPROF", SIGPROF);
+ parse_signal ("prof", SIGPROF);
#endif
#ifdef SIGWINCH
- handle_signal ("SIGWINCH", SIGWINCH);
+ parse_signal ("winch", SIGWINCH);
#endif
#ifdef SIGINFO
- handle_signal ("SIGINFO", SIGINFO);
-#endif
-#ifdef SIGUSR1
- handle_signal ("SIGUSR1", SIGUSR1);
-#endif
-#ifdef SIGUSR2
- handle_signal ("SIGUSR2", SIGUSR2);
+ parse_signal ("info", SIGINFO);
#endif
else
error ("Undefined signal name %s", name);
}
-#undef handle_signal
+#undef parse_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;
while (1)
{
- register int pid;
+ pid_t pid;
WAITTYPE w;
Lisp_Object tail;
#endif /* no WUNTRACED */
/* Keep trying to get a status until we get a definitive result. */
do
- {
+ {
+ /* For some reason, this sleep() prevents Emacs from sending
+ loadavg to 5-8(!) for ~10 seconds.
+ See http://thread.gmane.org/gmane.emacs.devel/67722 or
+ http://www.google.com/search?q=busyloop+in+sigchld_handler */
+ usleep (1000);
errno = 0;
pid = wait3 (&w, WNOHANG | WUNTRACED, 0);
}
/* Find the process that signaled us, and record its status. */
+ /* The process can have been deleted by Fdelete_process. */
+ for (tail = deleted_pid_list; GC_CONSP (tail); tail = XCDR (tail))
+ {
+ Lisp_Object xpid = XCAR (tail);
+ if ((GC_INTEGERP (xpid) && pid == (pid_t) XINT (xpid))
+ || (GC_FLOATP (xpid) && pid == (pid_t) XFLOAT_DATA (xpid)))
+ {
+ XSETCAR (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))
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;
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
int outer_running_asynch_code = running_asynch_code;
int waiting = waiting_for_user_input_p;
+ if (inhibit_sentinels)
+ return;
+
/* No need to gcpro these, because all we do with them later
is test them for EQness, and none of them should be a string. */
odeactivate = Vdeactivate_mark;
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;
#endif
/* But do it only if the caller is actually going to read events.
Otherwise there's no need to make him wake up, and it could
- cause trouble (for example it would make Fsit_for return). */
+ cause trouble (for example it would make sit_for return). */
if (waiting_for_user_input_p == -1)
record_asynch_buffer_change ();
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;
{
{
register int i;
+ inhibit_sentinels = 0;
+
#ifdef SIGCHLD
#ifndef CANNOT_DUMP
if (! noninteractive || initialized)
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);
#endif /* HAVE_SOCKETS */
#if defined (DARWIN) || defined (MAC_OSX)
- /* PTYs are broken on Darwin < 6, but are sometimes useful for interactive
+ /* PTYs are broken on Darwin < 6, but are sometimes useful for interactive
processes. As such, we only change the default value. */
if (initialized)
{
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.
-nil means don't delete them until `list-processes' is run. */);
+A value of nil means don't delete them until `list-processes' is run. */);
delete_exited_processes = 1;
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. */);