X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/edceb51cbc80e88ca6c53837daf1e6a0c4d5de26..0cf79a3ba2bd3047e875a51edc6358955c0c3a49:/src/process.c diff --git a/src/process.c b/src/process.c index db13406606..ebe8ef56ff 100644 --- a/src/process.c +++ b/src/process.c @@ -1,6 +1,7 @@ /* 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 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,6 @@ 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 @@ -272,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 @@ -291,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. */ @@ -299,6 +318,12 @@ extern int keyboard_bit_set P_ ((SELECT_TYPE *)); #define POLL_FOR_INPUT #endif +static Lisp_Object get_process (); +static void exec_sentinel (); + +extern EMACS_TIME timer_check (); +extern int timers_run; + /* Mask of bits indicating the descriptors that we wait for input on. */ static SELECT_TYPE input_wait_mask; @@ -367,15 +392,13 @@ struct sockaddr_and_len { #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 @@ -388,23 +411,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; { @@ -423,7 +446,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; @@ -502,7 +525,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; @@ -587,7 +610,7 @@ allocate_pty () } #endif /* HAVE_PTYS */ -Lisp_Object +static Lisp_Object make_process (name) Lisp_Object name; { @@ -600,11 +623,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 (); @@ -631,7 +653,7 @@ make_process (name) return val; } -void +static void remove_process (proc) register Lisp_Object proc; { @@ -677,6 +699,8 @@ setup_process_coding_systems (process) = (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; } DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0, @@ -758,6 +782,16 @@ get_process (name) 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 @@ -765,23 +799,45 @@ 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 - = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil)); - XSETINT (XPROCESS (process)->tick, ++process_tick); - status_notify (); +#ifdef SIGCHLD + Lisp_Object symbol; + + /* No problem storing the pid here, as it is still in Vprocess_alist. */ + deleted_pid_list = Fcons (make_fixnum_or_float (p->pid), + /* GC treated elements set to nil. */ + Fdelq (Qnil, deleted_pid_list)); + /* If the process has already signaled, remove it from the list. */ + if (p->raw_status_new) + update_status (p); + symbol = p->status; + if (CONSP (p->status)) + symbol = XCAR (p->status); + if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)) + Fdelete (make_fixnum_or_float (p->pid), deleted_pid_list); + else +#endif + { + Fkill_process (process, Qnil); + /* Do this now, since remove_process will make sigchld_handler do nothing. */ + p->status + = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil)); + XSETINT (p->tick, ++process_tick); + status_notify (p); + } } remove_process (process); return Qnil; @@ -817,7 +873,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)) @@ -842,7 +898,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)); @@ -857,7 +913,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, @@ -1186,9 +1244,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; { @@ -1198,13 +1258,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; @@ -1214,6 +1274,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; @@ -1235,7 +1305,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; { @@ -1244,6 +1314,7 @@ list_processes_1 (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 */ @@ -1327,7 +1398,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)) @@ -1370,8 +1441,8 @@ list_processes_1 (query_only) } } - 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)) @@ -1435,6 +1506,8 @@ list_processes_1 (query_only) insert_string ("\n"); } } + if (exited) + status_notify (NULL); return Qnil; } @@ -1535,7 +1608,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; @@ -1548,7 +1620,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))); @@ -1700,13 +1772,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; { @@ -1784,6 +1856,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 */ @@ -1905,7 +1983,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; @@ -2068,8 +2146,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); @@ -2094,7 +2174,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); @@ -2196,6 +2276,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: { @@ -2240,6 +2334,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)) @@ -2259,7 +2360,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) @@ -2273,7 +2378,6 @@ conv_lisp_to_sockaddr (family, address, sa, len) register int i; bzero (sa, len); - sa->sa_family = family; if (VECTORP (address)) { @@ -2285,7 +2389,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)) { @@ -2296,6 +2419,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; @@ -2529,7 +2653,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; { @@ -2551,7 +2675,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 @@ -2579,10 +2703,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 @@ -2699,8 +2826,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 { @@ -2839,19 +2966,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). */ @@ -2917,7 +3054,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); @@ -3256,12 +3393,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) { @@ -3505,6 +3648,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 } }; @@ -3542,7 +3700,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) { @@ -3578,11 +3736,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); @@ -3720,62 +3882,60 @@ DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output, 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 : @@ -3800,6 +3960,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 @@ -3856,6 +4019,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 @@ -3926,7 +4109,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; @@ -3982,12 +4165,39 @@ server_accept_connection (server, channel) 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. @@ -4045,9 +4255,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, 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 @@ -4058,6 +4266,8 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, 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, @@ -4220,15 +4430,15 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, /* 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)) { @@ -4319,6 +4529,11 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, #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); @@ -4329,6 +4544,8 @@ wait_reading_process_output (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--; @@ -4605,7 +4822,7 @@ wait_reading_process_output (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 @@ -4677,7 +4894,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, } /* 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. @@ -4731,7 +4948,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; @@ -4879,10 +5096,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, @@ -4914,6 +5131,10 @@ read_process_output (proc, channel) 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; } } @@ -4936,7 +5157,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. */ @@ -4954,7 +5175,7 @@ read_process_output (proc, channel) #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 (); @@ -5021,6 +5242,10 @@ read_process_output (proc, channel) 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; @@ -5122,7 +5347,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; @@ -5134,7 +5359,7 @@ send_process (proc, buf, len, object) int rv; struct coding_system *coding; struct gcpro gcpro1; - SIGTYPE (*old_sigpipe) (); + SIGTYPE (*volatile old_sigpipe) (); GCPRO1 (object); @@ -5142,7 +5367,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)); @@ -5163,6 +5388,8 @@ send_process (proc, buf, len, object) 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. */ @@ -5406,8 +5633,7 @@ send_process (proc, buf, len, object) 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); @@ -5522,7 +5748,7 @@ return t unconditionally. */) gid = emacs_get_tty_pgrp (p); - if (gid == XFASTINT (p->pid)) + if (gid == p->pid) return Qnil; return Qt; } @@ -5569,7 +5795,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 @@ -5688,7 +5914,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. @@ -5698,12 +5924,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; } @@ -5711,12 +5937,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: @@ -5731,7 +5956,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)); @@ -5743,7 +5968,7 @@ process_send_signal (process, signo, current_group, nomsg) obvious alternative. */ if (no_pgrp) { - kill (XFASTINT (p->pid), signo); + kill (p->pid, signo); return; } @@ -5756,7 +5981,7 @@ process_send_signal (process, signo, current_group, nomsg) } else { - gid = - XFASTINT (p->pid); + gid = - p->pid; kill (gid, signo); } #else /* ! defined (TIOCSIGSEND) */ @@ -5827,7 +6052,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 @@ -5861,7 +6086,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; } @@ -5876,11 +6101,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; } @@ -5889,8 +6120,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; @@ -5903,7 +6134,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: @@ -5921,97 +6152,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); @@ -6019,7 +6253,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, @@ -6043,7 +6277,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)); @@ -6068,7 +6302,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. */ @@ -6078,6 +6312,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]) @@ -6143,6 +6379,7 @@ kill_buffer_processes (buffer) ** 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; @@ -6200,12 +6437,21 @@ sigchld_handler (signo) /* Find the process that signaled us, and record its status. */ + /* The process can have been deleted by Fdelete_process. */ + tail = Fmember (make_fixnum_or_float (pid), deleted_pid_list); + if (!NILP (tail)) + { + Fsetcar (tail, Qnil); + goto sigchld_end_of_loop; + } + + /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ p = 0; for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail)) { proc = XCDR (XCAR (tail)); p = XPROCESS (proc); - if (GC_EQ (p->childp, Qt) && XINT (p->pid) == pid) + if (GC_EQ (p->childp, Qt) && p->pid == pid) break; p = 0; } @@ -6217,7 +6463,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; } @@ -6230,8 +6476,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)) @@ -6251,8 +6497,8 @@ sigchld_handler (signo) 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; @@ -6269,6 +6515,9 @@ sigchld_handler (signo) 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. @@ -6285,6 +6534,7 @@ sigchld_handler (signo) #endif /* USG, but not HPUX with WNOHANG */ } } +#endif /* SIGCHLD */ static Lisp_Object @@ -6316,6 +6566,9 @@ exec_sentinel (proc, reason) 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; @@ -6340,10 +6593,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, @@ -6357,7 +6610,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; @@ -6372,7 +6625,7 @@ exec_sentinel (proc, reason) #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 (); @@ -6384,8 +6637,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; @@ -6421,12 +6675,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); @@ -6624,7 +6879,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; { @@ -6643,6 +6898,8 @@ init_process () { register int i; + inhibit_sentinels = 0; + #ifdef SIGCHLD #ifndef CANNOT_DUMP if (! noninteractive || initialized) @@ -6668,6 +6925,9 @@ init_process () 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; @@ -6695,6 +6955,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); @@ -6711,7 +6975,7 @@ init_process () #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) { @@ -6754,6 +7018,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); @@ -6796,6 +7066,9 @@ syms_of_process () 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. @@ -6816,9 +7089,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. */);