X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/39b1da208b66d626706391d06715c39bdce7adaa..a12aece30906d6a8b03611262169ba181b37b93b:/src/process.c diff --git a/src/process.c b/src/process.c index 5e83214f4f..dbb431496c 100644 --- a/src/process.c +++ b/src/process.c @@ -1,6 +1,7 @@ /* 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. @@ -16,8 +17,8 @@ GNU General Public License for more details. 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 @@ -39,6 +40,9 @@ Boston, MA 02111-1307, USA. */ #include /* some typedefs are used in sys/file.h */ #include #include +#ifdef HAVE_INTTYPES_H +#include +#endif #ifdef HAVE_UNISTD_H #include #endif @@ -117,10 +121,18 @@ Boston, MA 02111-1307, USA. */ #include #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" @@ -139,7 +151,10 @@ Boston, MA 02111-1307, USA. */ 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; @@ -186,7 +201,7 @@ extern Lisp_Object QCfilter; #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; @@ -271,17 +286,19 @@ int update_tick; #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 @@ -290,7 +307,10 @@ static Lisp_Object Vprocess_adaptive_read_buffering; #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. */ @@ -310,6 +330,7 @@ static SELECT_TYPE non_keyboard_wait_mask; 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. */ @@ -319,6 +340,11 @@ static SELECT_TYPE connect_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; @@ -369,8 +395,6 @@ extern int timers_run; /* 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 @@ -383,23 +407,23 @@ static char pty_name[24]; /* 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; { @@ -418,7 +442,7 @@ status_convert (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; @@ -497,7 +521,7 @@ status_message (p) 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; @@ -582,7 +606,7 @@ allocate_pty () } #endif /* HAVE_PTYS */ -Lisp_Object +static Lisp_Object make_process (name) Lisp_Object name; { @@ -595,11 +619,10 @@ make_process (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 (); @@ -626,7 +649,7 @@ make_process (name) return val; } -void +static void remove_process (proc) register Lisp_Object proc; { @@ -760,23 +783,26 @@ nil, indicating the current buffer's process. */) (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 + p->status = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil)); - XSETINT (XPROCESS (process)->tick, ++process_tick); - status_notify (); + XSETINT (p->tick, ++process_tick); + status_notify (p); } remove_process (process); return Qnil; @@ -812,7 +838,7 @@ nil, indicating the current buffer's process. */) 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)) @@ -837,7 +863,7 @@ If PROCESS has not yet exited or died, return 0. */) 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)); @@ -852,7 +878,9 @@ For a network connection, this value is nil. */) 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, @@ -1181,9 +1209,11 @@ a socket connection. */) 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; { @@ -1193,13 +1223,13 @@ IP address. Returns nil if format of ADDRESS is invalid. */) 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; @@ -1209,6 +1239,16 @@ IP address. Returns nil if format of ADDRESS is invalid. */) 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; @@ -1230,7 +1270,7 @@ IP address. Returns nil if format of ADDRESS is invalid. */) } #endif -Lisp_Object +static Lisp_Object list_processes_1 (query_only) Lisp_Object query_only; { @@ -1284,7 +1324,7 @@ list_processes_1 (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; @@ -1322,7 +1362,7 @@ list_processes_1 (query_only) 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)) @@ -1530,7 +1570,6 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) 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; @@ -1543,7 +1582,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) #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))); @@ -1695,13 +1734,13 @@ start_process_unwind (proc) 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; { @@ -1779,6 +1818,12 @@ create_process (process, new_argv, current_dir) #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 */ @@ -1900,7 +1945,7 @@ create_process (process, new_argv, current_dir) 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; @@ -2063,8 +2108,10 @@ create_process (process, new_argv, current_dir) #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); @@ -2089,7 +2136,7 @@ create_process (process, new_argv, current_dir) else { /* vfork succeeded. */ - XSETFASTINT (XPROCESS (process)->pid, pid); + XPROCESS (process)->pid = pid; #ifdef WINDOWSNT register_child (pid, inchannel); @@ -2191,6 +2238,20 @@ conv_sockaddr_to_lisp (sa, len) 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: { @@ -2235,6 +2296,13 @@ get_lisp_to_sockaddr_size (address, familyp) *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)) @@ -2254,7 +2322,11 @@ get_lisp_to_sockaddr_size (address, familyp) } /* 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) @@ -2268,7 +2340,6 @@ conv_lisp_to_sockaddr (family, address, sa, len) register int i; bzero (sa, len); - sa->sa_family = family; if (VECTORP (address)) { @@ -2280,7 +2351,26 @@ conv_lisp_to_sockaddr (family, address, sa, len) 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)) { @@ -2291,6 +2381,7 @@ conv_lisp_to_sockaddr (family, address, sa, len) cp = SDATA (address); for (i = 0; i < sizeof (sockun->sun_path) && *cp; i++) sockun->sun_path[i] = *cp++; + sa->sa_family = family; } #endif return; @@ -2524,7 +2615,7 @@ OPTION is not a supported option, return nil instead; otherwise return t. */) /* A version of request_sigio suitable for a record_unwind_protect. */ -Lisp_Object +static Lisp_Object unwind_request_sigio (dummy) Lisp_Object dummy; { @@ -2546,7 +2637,7 @@ DEFUN ("make-network-process", Fmake_network_process, Smake_network_process, 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 @@ -2574,10 +2665,13 @@ a random port number is selected for the server. 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 @@ -2694,8 +2788,8 @@ usage: (make-network-process &rest ARGS) */) 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 { @@ -2716,7 +2810,6 @@ usage: (make-network-process &rest ARGS) */) 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 */ @@ -2835,19 +2928,29 @@ usage: (make-network-process &rest ARGS) */) /* :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). */ @@ -2913,7 +3016,7 @@ usage: (make-network-process &rest ARGS) */) 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); @@ -3017,6 +3120,8 @@ usage: (make-network-process &rest ARGS) */) { int optn, optbits; + retry_connect: + s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); if (s < 0) { @@ -3095,8 +3200,6 @@ usage: (make-network-process &rest ARGS) */) break; } - retry_connect: - immediate_quit = 1; QUIT; @@ -3138,22 +3241,13 @@ usage: (make-network-process &rest ARGS) */) 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) @@ -3261,12 +3355,18 @@ usage: (make-network-process &rest ARGS) */) 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) { @@ -3510,6 +3610,21 @@ static struct ifflag_def ifflag_table[] = { #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 } }; @@ -3547,7 +3662,7 @@ FLAGS is the current flags of the interface. */) 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) { @@ -3583,11 +3698,15 @@ FLAGS is the current flags of the interface. */) 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); @@ -3672,12 +3791,14 @@ deactivate_process (proc) 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; @@ -3718,65 +3839,69 @@ close_process_descs () } 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); } @@ -3797,6 +3922,9 @@ server_accept_connection (server, channel) 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 @@ -3853,6 +3981,26 @@ server_accept_connection (server, channel) } 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 @@ -3923,7 +4071,7 @@ server_accept_connection (server, channel) 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; @@ -3976,12 +4124,12 @@ server_accept_connection (server, channel) 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 () { } @@ -4003,61 +4151,59 @@ wait_reading_process_input_1 () 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 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 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, 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. */ @@ -4085,7 +4231,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) /* 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) @@ -4122,7 +4268,8 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) 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; @@ -4150,7 +4297,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) 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; @@ -4168,7 +4315,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) else if (time_limit != -1) { /* This is so a breakpoint can be put here. */ - wait_reading_process_input_1 (); + wait_reading_process_output_1 (); } } @@ -4178,7 +4325,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) 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 @@ -4187,7 +4334,10 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) 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 @@ -4199,26 +4349,31 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) */ 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)) { @@ -4258,18 +4413,27 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) /* 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; } @@ -4282,22 +4446,29 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) { 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); @@ -4308,6 +4479,8 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) 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--; @@ -4326,7 +4499,11 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) 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); } @@ -4382,7 +4559,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) if (no_avail) { FD_ZERO (&Available); - check_connect = 0; + IF_NON_BLOCKING_CONNECT (check_connect = 0); } #if defined(sun) && !defined(USG5_4) @@ -4404,10 +4581,10 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) /* 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); @@ -4417,7 +4594,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) /* 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; @@ -4442,7 +4619,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) } /* If there is unread keyboard input, also return. */ - if (XINT (read_kbd) != 0 + if (read_kbd != 0 && requeued_events_pending_p ()) break; @@ -4453,7 +4630,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) 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. */ @@ -4472,7 +4649,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) 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 @@ -4482,7 +4659,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) /* 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. */ @@ -4580,7 +4757,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) /* 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 @@ -4657,7 +4834,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) /* 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 (); @@ -4706,7 +4883,7 @@ read_process_output_error_handler (error) 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; @@ -4854,10 +5031,10 @@ read_process_output (proc, 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, @@ -4911,7 +5088,7 @@ read_process_output (proc, channel) 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. */ @@ -5078,10 +5255,12 @@ Lisp_Object process_sent_to; 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); } @@ -5095,7 +5274,7 @@ send_process_trap () 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; @@ -5107,6 +5286,7 @@ send_process (proc, buf, len, object) int rv; struct coding_system *coding; struct gcpro gcpro1; + SIGTYPE (*volatile old_sigpipe) (); GCPRO1 (object); @@ -5114,7 +5294,7 @@ send_process (proc, buf, len, 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)); @@ -5196,6 +5376,7 @@ send_process (proc, buf, len, object) 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); } @@ -5230,7 +5411,6 @@ send_process (proc, buf, len, 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. */ @@ -5272,7 +5452,11 @@ send_process (proc, buf, len, object) 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 @@ -5304,7 +5488,6 @@ send_process (proc, buf, len, object) that may allow the program to finish doing output and read more. */ { - Lisp_Object zero; int offset = 0; #ifdef BROKEN_PTY_READ_AFTER_EAGAIN @@ -5339,11 +5522,10 @@ send_process (proc, buf, len, object) 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)) @@ -5371,12 +5553,12 @@ send_process (proc, buf, len, 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); @@ -5491,7 +5673,7 @@ return t unconditionally. */) gid = emacs_get_tty_pgrp (p); - if (gid == XFASTINT (p->pid)) + if (gid == p->pid) return Qnil; return Qt; } @@ -5538,7 +5720,7 @@ process_send_signal (process, signo, current_group, nomsg) /* 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 @@ -5549,29 +5731,36 @@ process_send_signal (process, signo, current_group, nomsg) work. If the system has it, use it. */ #ifdef HAVE_TERMIOS struct termios t; + cc_t *sig_char = NULL; + + tcgetattr (XINT (p->infd), &t); switch (signo) { case SIGINT: - tcgetattr (XINT (p->infd), &t); - send_process (proc, &t.c_cc[VINTR], 1, Qnil); - return; + sig_char = &t.c_cc[VINTR]; + break; case SIGQUIT: - tcgetattr (XINT (p->infd), &t); - send_process (proc, &t.c_cc[VQUIT], 1, Qnil); - return; + sig_char = &t.c_cc[VQUIT]; + break; case SIGTSTP: - tcgetattr (XINT (p->infd), &t); #if defined (VSWTCH) && !defined (PREFER_VSUSP) - send_process (proc, &t.c_cc[VSWTCH], 1, Qnil); + sig_char = &t.c_cc[VSWTCH]; #else - send_process (proc, &t.c_cc[VSUSP], 1, Qnil); + sig_char = &t.c_cc[VSUSP]; #endif - return; + break; } + 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 @@ -5628,9 +5817,12 @@ process_send_signal (process, signo, current_group, nomsg) 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 @@ -5647,7 +5839,7 @@ process_send_signal (process, signo, current_group, nomsg) 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. @@ -5657,12 +5849,12 @@ process_send_signal (process, signo, current_group, nomsg) #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; } @@ -5670,12 +5862,11 @@ process_send_signal (process, signo, current_group, nomsg) { #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: @@ -5690,7 +5881,7 @@ process_send_signal (process, signo, current_group, nomsg) #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)); @@ -5702,7 +5893,7 @@ process_send_signal (process, signo, current_group, nomsg) obvious alternative. */ if (no_pgrp) { - kill (XFASTINT (p->pid), signo); + kill (p->pid, signo); return; } @@ -5715,7 +5906,7 @@ process_send_signal (process, signo, current_group, nomsg) } else { - gid = - XFASTINT (p->pid); + gid = - p->pid; kill (gid, signo); } #else /* ! defined (TIOCSIGSEND) */ @@ -5786,7 +5977,7 @@ If PROCESS is a network process, inhibit handling of incoming traffic. */) } #endif #ifndef SIGTSTP - error ("no SIGTSTP support"); + error ("No SIGTSTP support"); #else process_send_signal (process, SIGTSTP, current_group, 0); #endif @@ -5820,7 +6011,7 @@ If PROCESS is a network process, resume handling of incoming traffic. */) #ifdef SIGCONT process_send_signal (process, SIGCONT, current_group, 0); #else - error ("no SIGCONT support"); + error ("No SIGCONT support"); #endif return process; } @@ -5835,11 +6026,17 @@ 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 (process); goto got_it; } @@ -5848,8 +6045,8 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */) 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; @@ -5862,7 +6059,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */) 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: @@ -5880,97 +6077,100 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */) 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); @@ -5978,7 +6178,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal 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, @@ -6002,7 +6202,7 @@ text to PROCESS after you call this function. */) 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)); @@ -6027,7 +6227,7 @@ text to PROCESS after you call this function. */) 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. */ @@ -6037,6 +6237,8 @@ text to PROCESS after you call this function. */) 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]) @@ -6111,6 +6313,8 @@ sigchld_handler (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); @@ -6162,7 +6366,7 @@ sigchld_handler (signo) { 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; } @@ -6174,7 +6378,7 @@ sigchld_handler (signo) { proc = XCDR (XCAR (tail)); p = XPROCESS (proc); - if (GC_INTEGERP (p->pid) && XINT (p->pid) == -1) + if (p->pid == -1) break; p = 0; } @@ -6187,8 +6391,8 @@ sigchld_handler (signo) 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)) @@ -6202,7 +6406,7 @@ sigchld_handler (signo) 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); @@ -6220,7 +6424,7 @@ sigchld_handler (signo) 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); @@ -6297,10 +6501,10 @@ exec_sentinel (proc, reason) 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, @@ -6314,7 +6518,7 @@ exec_sentinel (proc, reason) 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; @@ -6341,8 +6545,9 @@ exec_sentinel (proc, reason) 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; @@ -6378,12 +6583,13 @@ status_notify () && ! 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); @@ -6581,7 +6787,7 @@ delete_keyboard_wait_descriptor (desc) /* 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; { @@ -6612,6 +6818,11 @@ init_process () 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; @@ -6647,6 +6858,10 @@ init_process () #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); @@ -6661,6 +6876,19 @@ init_process () 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 @@ -6693,6 +6921,12 @@ syms_of_process () 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); @@ -6755,9 +6989,9 @@ The value takes effect when `start-process' is called. */); 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. */); @@ -6862,10 +7096,9 @@ Lisp_Object QCtype; 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. @@ -6873,27 +7106,17 @@ Lisp_Object QCtype; 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) @@ -6916,7 +7139,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) /* 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. */ @@ -6967,7 +7190,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) 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; @@ -6985,12 +7208,12 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) /* 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); @@ -7001,11 +7224,11 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) { 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); @@ -7041,13 +7264,13 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) 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); @@ -7056,7 +7279,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) } /* If there is unread keyboard input, also return. */ - if (XINT (read_kbd) != 0 + if (read_kbd && requeued_events_pending_p ()) break;