X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/fec9206062b420aca84f53d05a72c3ee43244022..4e36a6a6e2ce2367d0c049c45c91a7ae48ae1e77:/src/process.c diff --git a/src/process.c b/src/process.c index d87a1803fe..7050bf9822 100644 --- a/src/process.c +++ b/src/process.c @@ -1,7 +1,7 @@ /* Asynchronous subprocess control for GNU Emacs. -Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2013 Free Software -Foundation, Inc. +Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2013 + Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -21,8 +21,6 @@ along with GNU Emacs. If not, see . */ #include -#define PROCESS_INLINE EXTERN_INLINE - #include #include #include /* Some typedefs are used in sys/file.h. */ @@ -92,6 +90,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #endif /* subprocesses */ @@ -131,8 +130,8 @@ along with GNU Emacs. If not, see . */ #endif #ifdef WINDOWSNT -extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, - EMACS_TIME *, void *); +extern int sys_select (int, fd_set *, fd_set *, fd_set *, + struct timespec *, void *); #endif #ifndef SOCK_CLOEXEC @@ -260,7 +259,7 @@ static EMACS_INT update_tick; #endif #ifdef ADAPTIVE_READ_BUFFERING -#define READ_OUTPUT_DELAY_INCREMENT (EMACS_TIME_RESOLUTION / 100) +#define READ_OUTPUT_DELAY_INCREMENT (TIMESPEC_RESOLUTION / 100) #define READ_OUTPUT_DELAY_MAX (READ_OUTPUT_DELAY_INCREMENT * 5) #define READ_OUTPUT_DELAY_MAX_MAX (READ_OUTPUT_DELAY_INCREMENT * 7) @@ -279,7 +278,7 @@ static bool process_output_skip; static void create_process (Lisp_Object, char **, Lisp_Object); #ifdef USABLE_SIGIO -static bool keyboard_bit_set (SELECT_TYPE *); +static bool keyboard_bit_set (fd_set *); #endif static void deactivate_process (Lisp_Object); static void status_notify (struct Lisp_Process *); @@ -298,39 +297,39 @@ static void exec_sentinel (Lisp_Object proc, Lisp_Object reason); /* Mask of bits indicating the descriptors that we wait for input on. */ -static SELECT_TYPE input_wait_mask; +static fd_set input_wait_mask; /* Mask that excludes keyboard input descriptor(s). */ -static SELECT_TYPE non_keyboard_wait_mask; +static fd_set non_keyboard_wait_mask; /* Mask that excludes process input descriptor(s). */ -static SELECT_TYPE non_process_wait_mask; +static fd_set non_process_wait_mask; /* Mask for selecting for write. */ -static SELECT_TYPE write_mask; +static fd_set write_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. */ -static SELECT_TYPE connect_wait_mask; +static fd_set connect_wait_mask; /* Number of bits set in connect_wait_mask. */ static int num_pending_connects; #endif /* NON_BLOCKING_CONNECT */ -/* The largest descriptor currently in use for a process object. */ +/* The largest descriptor currently in use for a process object; -1 if none. */ static int max_process_desc; -/* The largest descriptor currently in use for input. */ +/* The largest descriptor currently in use for input; -1 if none. */ static int max_input_desc; /* Indexed by descriptor, gives the process (if any) for that descriptor */ -static Lisp_Object chan_process[MAXDESC]; +static Lisp_Object chan_process[FD_SETSIZE]; /* Alist of elements (NAME . PROCESS) */ static Lisp_Object Vprocess_alist; @@ -341,18 +340,18 @@ static Lisp_Object Vprocess_alist; output from the process is to read at least one char. Always -1 on systems that support FIONREAD. */ -static int proc_buffered_char[MAXDESC]; +static int proc_buffered_char[FD_SETSIZE]; /* Table of `struct coding-system' for each process. */ -static struct coding_system *proc_decode_coding_system[MAXDESC]; -static struct coding_system *proc_encode_coding_system[MAXDESC]; +static struct coding_system *proc_decode_coding_system[FD_SETSIZE]; +static struct coding_system *proc_encode_coding_system[FD_SETSIZE]; #ifdef DATAGRAM_SOCKETS /* Table of `partner address' for datagram sockets. */ static struct sockaddr_and_len { struct sockaddr *sa; int len; -} datagram_address[MAXDESC]; +} datagram_address[FD_SETSIZE]; #define DATAGRAM_CHAN_P(chan) (datagram_address[chan].sa != 0) #define DATAGRAM_CONN_P(proc) (PROCESSP (proc) && datagram_address[XPROCESS (proc)->infd].sa != 0) #else @@ -360,6 +359,12 @@ static struct sockaddr_and_len { #define DATAGRAM_CONN_P(proc) (0) #endif +/* FOR_EACH_PROCESS (LIST_VAR, PROC_VAR) followed by a statement is + a `for' loop which iterates over processes from Vprocess_alist. */ + +#define FOR_EACH_PROCESS(list_var, proc_var) \ + FOR_EACH_ALIST_VALUE (Vprocess_alist, list_var, proc_var) + /* These setters are used only in this file, so they can be private. */ static void pset_buffer (struct Lisp_Process *p, Lisp_Object val) @@ -451,7 +456,7 @@ static struct fd_callback_data #define FOR_READ 1 #define FOR_WRITE 2 int condition; /* mask of the defines above. */ -} fd_callback_info[MAXDESC]; +} fd_callback_info[FD_SETSIZE]; /* Add a file descriptor FD to be monitored for when read is possible. @@ -460,7 +465,7 @@ static struct fd_callback_data void add_read_fd (int fd, fd_callback func, void *data) { - eassert (fd < MAXDESC); + eassert (fd < FD_SETSIZE); add_keyboard_wait_descriptor (fd); fd_callback_info[fd].func = func; @@ -473,7 +478,7 @@ add_read_fd (int fd, fd_callback func, void *data) void delete_read_fd (int fd) { - eassert (fd < MAXDESC); + eassert (fd < FD_SETSIZE); delete_keyboard_wait_descriptor (fd); fd_callback_info[fd].condition &= ~FOR_READ; @@ -490,7 +495,7 @@ delete_read_fd (int fd) void add_write_fd (int fd, fd_callback func, void *data) { - eassert (fd < MAXDESC); + eassert (fd < FD_SETSIZE); FD_SET (fd, &write_mask); if (fd > max_input_desc) max_input_desc = fd; @@ -500,29 +505,35 @@ add_write_fd (int fd, fd_callback func, void *data) fd_callback_info[fd].condition |= FOR_WRITE; } +/* FD is no longer an input descriptor; update max_input_desc accordingly. */ + +static void +delete_input_desc (int fd) +{ + if (fd == max_input_desc) + { + do + fd--; + while (0 <= fd && ! (FD_ISSET (fd, &input_wait_mask) + || FD_ISSET (fd, &write_mask))); + + max_input_desc = fd; + } +} + /* Stop monitoring file descriptor FD for when write is possible. */ void delete_write_fd (int fd) { - int lim = max_input_desc; - - eassert (fd < MAXDESC); + eassert (fd < FD_SETSIZE); FD_CLR (fd, &write_mask); fd_callback_info[fd].condition &= ~FOR_WRITE; if (fd_callback_info[fd].condition == 0) { fd_callback_info[fd].func = 0; fd_callback_info[fd].data = 0; - - if (fd == max_input_desc) - for (fd = lim; fd >= 0; fd--) - if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask)) - { - max_input_desc = fd; - break; - } - + delete_input_desc (fd); } } @@ -674,6 +685,15 @@ allocate_pty (char pty_name[PTY_NAME_SIZE]) if (fd >= 0) { +#ifdef PTY_OPEN + /* Set FD's close-on-exec flag. This is needed even if + PT_OPEN calls posix_openpt with O_CLOEXEC, since POSIX + doesn't require support for that combination. + Multithreaded platforms where posix_openpt ignores + O_CLOEXEC (or where PTY_OPEN doesn't call posix_openpt) + have a race condition between the PTY_OPEN and here. */ + fcntl (fd, F_SETFD, FD_CLOEXEC); +#endif /* check to make certain that both sides are available this avoids a nasty yet stupid bug in rlogins */ #ifdef PTY_TTY_NAME_SPRINTF @@ -716,6 +736,8 @@ make_process (Lisp_Object name) non-Lisp data, so do it only for slots which should not be zero. */ p->infd = -1; p->outfd = -1; + for (i = 0; i < PROCESS_OPEN_FDS; i++) + p->open_fd[i] = -1; #ifdef HAVE_GNUTLS p->gnutls_initstage = GNUTLS_STAGE_EMPTY; @@ -790,13 +812,14 @@ get_process (register Lisp_Object name) else obj = name; - /* Now obj should be either a buffer object or a process object. - */ + /* Now obj should be either a buffer object or a process object. */ if (BUFFERP (obj)) { + if (NILP (BVAR (XBUFFER (obj), name))) + error ("Attempt to get process for a dead buffer"); proc = Fget_buffer_process (obj); if (NILP (proc)) - error ("Buffer %s has no process", SDATA (BVAR (XBUFFER (obj), name))); + error ("Buffer %s has no process", SDATA (BVAR (XBUFFER (obj), name))); } else { @@ -812,13 +835,17 @@ get_process (register Lisp_Object name) treated by the SIGCHLD handler and waitpid has been invoked on them; otherwise they might fill up the kernel's process table. - Some processes created by call-process are also put onto this list. */ + Some processes created by call-process are also put onto this list. + + Members of this list are (process-ID . filename) pairs. The + process-ID is a number; the filename, if a string, is a file that + needs to be removed after the process exits. */ static Lisp_Object deleted_pid_list; void -record_deleted_pid (pid_t pid) +record_deleted_pid (pid_t pid, Lisp_Object filename) { - deleted_pid_list = Fcons (make_fixnum_or_float (pid), + deleted_pid_list = Fcons (Fcons (make_fixnum_or_float (pid), filename), /* GC treated elements set to nil. */ Fdelq (Qnil, deleted_pid_list)); @@ -846,7 +873,7 @@ nil, indicating the current buffer's process. */) else { if (p->alive) - record_kill_process (p); + record_kill_process (p, Qnil); if (p->infd >= 0) { @@ -1112,15 +1139,18 @@ See `set-process-sentinel' for more info on sentinels. */) DEFUN ("set-process-window-size", Fset_process_window_size, Sset_process_window_size, 3, 3, 0, doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH. */) - (register Lisp_Object process, Lisp_Object height, Lisp_Object width) + (Lisp_Object process, Lisp_Object height, Lisp_Object width) { CHECK_PROCESS (process); - CHECK_RANGED_INTEGER (height, 0, INT_MAX); - CHECK_RANGED_INTEGER (width, 0, INT_MAX); + + /* All known platforms store window sizes as 'unsigned short'. */ + CHECK_RANGED_INTEGER (height, 0, USHRT_MAX); + CHECK_RANGED_INTEGER (width, 0, USHRT_MAX); if (XPROCESS (process)->infd < 0 - || set_window_size (XPROCESS (process)->infd, - XINT (height), XINT (width)) <= 0) + || (set_window_size (XPROCESS (process)->infd, + XINT (height), XINT (width)) + < 0)) return Qnil; else return Qt; @@ -1380,22 +1410,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) function. The argument list is protected by the caller, so all we really have to worry about is buffer. */ { - struct gcpro gcpro1, gcpro2; - - current_dir = BVAR (current_buffer, directory); - - GCPRO2 (buffer, current_dir); - - current_dir = Funhandled_file_name_directory (current_dir); - if (NILP (current_dir)) - /* If the file name handler says that current_dir is unreachable, use - a sensible default. */ - current_dir = build_string ("~/"); - current_dir = expand_and_dir_to_file (current_dir, Qnil); - if (NILP (Ffile_accessible_directory_p (current_dir))) - report_file_error ("Setting current directory", - BVAR (current_buffer, directory)); - + struct gcpro gcpro1; + GCPRO1 (buffer); + current_dir = encode_current_directory (); UNGCPRO; } @@ -1599,22 +1616,49 @@ start_process_unwind (Lisp_Object proc) remove_process (proc); } +/* If *FD_ADDR is nonnegative, close it, and mark it as closed. */ + +static void +close_process_fd (int *fd_addr) +{ + int fd = *fd_addr; + if (0 <= fd) + { + *fd_addr = -1; + emacs_close (fd); + } +} + +/* Indexes of file descriptors in open_fds. */ +enum + { + /* The pipe from Emacs to its subprocess. */ + SUBPROCESS_STDIN, + WRITE_TO_SUBPROCESS, + + /* The main pipe from the subprocess to Emacs. */ + READ_FROM_SUBPROCESS, + SUBPROCESS_STDOUT, + + /* The pipe from the subprocess to Emacs that is closed when the + subprocess execs. */ + READ_FROM_EXEC_MONITOR, + EXEC_MONITOR_OUTPUT + }; + +verify (PROCESS_OPEN_FDS == EXEC_MONITOR_OUTPUT + 1); static void create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) { + struct Lisp_Process *p = XPROCESS (process); int inchannel, outchannel; pid_t pid; int vfork_errno; - int sv[2]; -#ifndef WINDOWSNT - int wait_child_setup[2]; -#endif int forkin, forkout; bool pty_flag = 0; char pty_name[PTY_NAME_SIZE]; Lisp_Object lisp_pty_name = Qnil; - Lisp_Object encoded_current_dir; inchannel = outchannel = -1; @@ -1623,6 +1667,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) if (inchannel >= 0) { + p->open_fd[READ_FROM_SUBPROCESS] = inchannel; #if ! defined (USG) || defined (USG_SUBTTY_WORKS) /* On most USG systems it does not work to open the pty's tty here, then close it and reopen it in the child. */ @@ -1631,6 +1676,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); if (forkin < 0) report_file_error ("Opening pty", Qnil); + p->open_fd[SUBPROCESS_STDIN] = forkin; #else forkin = forkout = -1; #endif /* not USG, or USG_SUBTTY_WORKS */ @@ -1639,23 +1685,17 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) } else { - if (emacs_pipe (sv) != 0) + if (emacs_pipe (p->open_fd + SUBPROCESS_STDIN) != 0 + || emacs_pipe (p->open_fd + READ_FROM_SUBPROCESS) != 0) report_file_error ("Creating pipe", Qnil); - inchannel = sv[0]; - forkout = sv[1]; - if (emacs_pipe (sv) != 0) - { - int pipe_errno = errno; - emacs_close (inchannel); - emacs_close (forkout); - report_file_errno ("Creating pipe", Qnil, pipe_errno); - } - outchannel = sv[1]; - forkin = sv[0]; + forkin = p->open_fd[SUBPROCESS_STDIN]; + outchannel = p->open_fd[WRITE_TO_SUBPROCESS]; + inchannel = p->open_fd[READ_FROM_SUBPROCESS]; + forkout = p->open_fd[SUBPROCESS_STDOUT]; } #ifndef WINDOWSNT - if (emacs_pipe (wait_child_setup) != 0) + if (emacs_pipe (p->open_fd + READ_FROM_EXEC_MONITOR) != 0) report_file_error ("Creating pipe", Qnil); #endif @@ -1664,16 +1704,16 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) /* Record this as an active process, with its channels. */ chan_process[inchannel] = process; - XPROCESS (process)->infd = inchannel; - XPROCESS (process)->outfd = outchannel; + p->infd = inchannel; + p->outfd = outchannel; /* Previously we recorded the tty descriptor used in the subprocess. It was only used for getting the foreground tty process, so now we just reopen the device (see emacs_get_tty_pgrp) as this is more portable (see USG_SUBTTY_WORKS above). */ - XPROCESS (process)->pty_flag = pty_flag; - pset_status (XPROCESS (process), Qrun); + p->pty_flag = pty_flag; + pset_status (p, Qrun); FD_SET (inchannel, &input_wait_mask); FD_SET (inchannel, &non_keyboard_wait_mask); @@ -1683,35 +1723,29 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) /* This may signal an error. */ setup_process_coding_systems (process); - encoded_current_dir = ENCODE_FILE (current_dir); - block_input (); block_child_signal (); #ifndef WINDOWSNT /* vfork, and prevent local vars from being clobbered by the vfork. */ { - Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; + Lisp_Object volatile current_dir_volatile = current_dir; Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; - Lisp_Object volatile process_volatile = process; char **volatile new_argv_volatile = new_argv; int volatile forkin_volatile = forkin; int volatile forkout_volatile = forkout; - int volatile wait_child_setup_0_volatile = wait_child_setup[0]; - int volatile wait_child_setup_1_volatile = wait_child_setup[1]; + struct Lisp_Process *p_volatile = p; pid = vfork (); - encoded_current_dir = encoded_current_dir_volatile; + current_dir = current_dir_volatile; lisp_pty_name = lisp_pty_name_volatile; - process = process_volatile; new_argv = new_argv_volatile; forkin = forkin_volatile; forkout = forkout_volatile; - wait_child_setup[0] = wait_child_setup_0_volatile; - wait_child_setup[1] = wait_child_setup_1_volatile; + p = p_volatile; - pty_flag = XPROCESS (process)->pty_flag; + pty_flag = p->pty_flag; } if (pid == 0) @@ -1816,53 +1850,51 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) if (pty_flag) child_setup_tty (xforkout); #ifdef WINDOWSNT - pid = child_setup (xforkin, xforkout, xforkout, - new_argv, 1, encoded_current_dir); + pid = child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir); #else /* not WINDOWSNT */ - child_setup (xforkin, xforkout, xforkout, - new_argv, 1, encoded_current_dir); + child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir); #endif /* not WINDOWSNT */ } /* Back in the parent process. */ vfork_errno = errno; - XPROCESS (process)->pid = pid; + p->pid = pid; if (pid >= 0) - XPROCESS (process)->alive = 1; + p->alive = 1; /* Stop blocking in the parent. */ unblock_child_signal (); unblock_input (); - if (forkin >= 0) - emacs_close (forkin); - if (forkin != forkout && forkout >= 0) - emacs_close (forkout); - if (pid < 0) report_file_errno ("Doing vfork", Qnil, vfork_errno); else { /* vfork succeeded. */ + /* Close the pipe ends that the child uses, or the child's pty. */ + close_process_fd (&p->open_fd[SUBPROCESS_STDIN]); + close_process_fd (&p->open_fd[SUBPROCESS_STDOUT]); + #ifdef WINDOWSNT register_child (pid, inchannel); #endif /* WINDOWSNT */ - pset_tty_name (XPROCESS (process), lisp_pty_name); + pset_tty_name (p, lisp_pty_name); #ifndef WINDOWSNT /* Wait for child_setup to complete in case that vfork is - actually defined as fork. The descriptor wait_child_setup[1] + actually defined as fork. The descriptor + XPROCESS (proc)->open_fd[EXEC_MONITOR_OUTPUT] of a pipe is closed at the child side either by close-on-exec on successful execve or the _exit call in child_setup. */ { char dummy; - emacs_close (wait_child_setup[1]); - emacs_read (wait_child_setup[0], &dummy, 1); - emacs_close (wait_child_setup[0]); + close_process_fd (&p->open_fd[EXEC_MONITOR_OUTPUT]); + emacs_read (p->open_fd[READ_FROM_EXEC_MONITOR], &dummy, 1); + close_process_fd (&p->open_fd[READ_FROM_EXEC_MONITOR]); } #endif } @@ -1871,16 +1903,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) static void create_pty (Lisp_Object process) { + struct Lisp_Process *p = XPROCESS (process); char pty_name[PTY_NAME_SIZE]; - int inchannel, outchannel; - - inchannel = outchannel = -1; + int pty_fd = NILP (Vprocess_connection_type) ? -1 : allocate_pty (pty_name); - if (!NILP (Vprocess_connection_type)) - outchannel = inchannel = allocate_pty (pty_name); - - if (inchannel >= 0) + if (pty_fd >= 0) { + p->open_fd[SUBPROCESS_STDIN] = pty_fd; #if ! defined (USG) || defined (USG_SUBTTY_WORKS) /* On most USG systems it does not work to open the pty's tty here, then close it and reopen it in the child. */ @@ -1889,6 +1918,7 @@ create_pty (Lisp_Object process) int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); if (forkout < 0) report_file_error ("Opening pty", Qnil); + p->open_fd[WRITE_TO_SUBPROCESS] = forkout; #if 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 @@ -1897,40 +1927,42 @@ create_pty (Lisp_Object process) #endif /* DONT_REOPEN_PTY */ #endif /* not USG, or USG_SUBTTY_WORKS */ - fcntl (inchannel, F_SETFL, O_NONBLOCK); - fcntl (outchannel, F_SETFL, O_NONBLOCK); + fcntl (pty_fd, F_SETFL, O_NONBLOCK); /* Record this as an active process, with its channels. As a result, child_setup will close Emacs's side of the pipes. */ - chan_process[inchannel] = process; - XPROCESS (process)->infd = inchannel; - XPROCESS (process)->outfd = outchannel; + chan_process[pty_fd] = process; + p->infd = pty_fd; + p->outfd = pty_fd; /* Previously we recorded the tty descriptor used in the subprocess. It was only used for getting the foreground tty process, so now we just reopen the device (see emacs_get_tty_pgrp) as this is more portable (see USG_SUBTTY_WORKS above). */ - XPROCESS (process)->pty_flag = 1; - pset_status (XPROCESS (process), Qrun); + p->pty_flag = 1; + pset_status (p, Qrun); setup_process_coding_systems (process); - FD_SET (inchannel, &input_wait_mask); - FD_SET (inchannel, &non_keyboard_wait_mask); - if (inchannel > max_process_desc) - max_process_desc = inchannel; + FD_SET (pty_fd, &input_wait_mask); + FD_SET (pty_fd, &non_keyboard_wait_mask); + if (pty_fd > max_process_desc) + max_process_desc = pty_fd; - pset_tty_name (XPROCESS (process), build_string (pty_name)); + pset_tty_name (p, build_string (pty_name)); } - XPROCESS (process)->pid = -2; + p->pid = -2; } /* Convert an internal struct sockaddr to a lisp object (vector or string). The address family of sa is not included in the result. */ -static Lisp_Object +#ifndef WINDOWSNT +static +#endif +Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *sa, int len) { Lisp_Object address; @@ -2529,6 +2561,7 @@ usage: (make-serial-process &rest ARGS) */) p = XPROCESS (proc); fd = serial_open (port); + p->open_fd[SUBPROCESS_STDIN] = fd; p->infd = fd; p->outfd = fd; if (fd > max_process_desc) @@ -3201,7 +3234,7 @@ usage: (make-network-process &rest ARGS) */) wait for completion is pselect(). */ int sc; socklen_t len; - SELECT_TYPE fdset; + fd_set fdset; retry_select: FD_ZERO (&fdset); FD_SET (s, &fdset); @@ -3291,12 +3324,6 @@ usage: (make-network-process &rest ARGS) */) } #endif - /* Discard the unwind protect for closing S, if any. */ - specpdl_ptr = specpdl + count1; - - /* Unwind bind_polling_period and request_sigio. */ - unbind_to (count, Qnil); - if (s < 0) { /* If non-blocking got this far - and failed - assume non-blocking is @@ -3338,8 +3365,17 @@ usage: (make-network-process &rest ARGS) */) if ((tem = Fplist_get (contact, QCstop), !NILP (tem))) pset_command (p, Qt); p->pid = 0; + + p->open_fd[SUBPROCESS_STDIN] = inch; p->infd = inch; p->outfd = outch; + + /* Discard the unwind protect for closing S, if any. */ + specpdl_ptr = specpdl + count1; + + /* Unwind bind_polling_period and request_sigio. */ + unbind_to (count, Qnil); + if (is_server && socktype != SOCK_DGRAM) pset_status (p, Qlisten); @@ -3472,15 +3508,11 @@ usage: (make-network-process &rest ARGS) */) } -#if defined (HAVE_NET_IF_H) +#ifdef HAVE_NET_IF_H #ifdef SIOCGIFCONF -DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0, - doc: /* Return an alist of all network interfaces and their network address. -Each element is a cons, the car of which is a string containing the -interface name, and the cdr is the network address in internal -format; see the description of ADDRESS in `make-network-process'. */) - (void) +static Lisp_Object +network_interface_list (void) { struct ifconf ifconf; struct ifreq *ifreq; @@ -3622,13 +3654,8 @@ static const struct ifflag_def ifflag_table[] = { { 0, 0 } }; -DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_info, 1, 1, 0, - doc: /* Return information about network interface named IFNAME. -The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS), -where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address, -NETMASK is the layer 3 network mask, HWADDR is the layer 2 address, and -FLAGS is the current flags of the interface. */) - (Lisp_Object ifname) +static Lisp_Object +network_interface_info (Lisp_Object ifname) { struct ifreq rq; Lisp_Object res = Qnil; @@ -3697,7 +3724,9 @@ FLAGS is the current flags of the interface. */) any = 1; for (n = 0; n < 6; n++) - p->contents[n] = make_number (((unsigned char *)&rq.ifr_hwaddr.sa_data[0])[n]); + p->contents[n] = make_number (((unsigned char *) + &rq.ifr_hwaddr.sa_data[0]) + [n]); elt = Fcons (make_number (rq.ifr_hwaddr.sa_family), hwaddr); } #elif defined (HAVE_GETIFADDRS) && defined (LLADDR) @@ -3770,25 +3799,62 @@ FLAGS is the current flags of the interface. */) return unbind_to (count, any ? res : Qnil); } -#endif +#endif /* !SIOCGIFADDR && !SIOCGIFHWADDR && !SIOCGIFFLAGS */ #endif /* defined (HAVE_NET_IF_H) */ +DEFUN ("network-interface-list", Fnetwork_interface_list, + Snetwork_interface_list, 0, 0, 0, + doc: /* Return an alist of all network interfaces and their network address. +Each element is a cons, the car of which is a string containing the +interface name, and the cdr is the network address in internal +format; see the description of ADDRESS in `make-network-process'. + +If the information is not available, return nil. */) + (void) +{ +#if (defined HAVE_NET_IF_H && defined SIOCGIFCONF) || defined WINDOWSNT + return network_interface_list (); +#else + return Qnil; +#endif +} + +DEFUN ("network-interface-info", Fnetwork_interface_info, + Snetwork_interface_info, 1, 1, 0, + doc: /* Return information about network interface named IFNAME. +The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS), +where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address, +NETMASK is the layer 3 network mask, HWADDR is the layer 2 address, and +FLAGS is the current flags of the interface. + +Data that is unavailable is returned as nil. */) + (Lisp_Object ifname) +{ +#if ((defined HAVE_NET_IF_H \ + && (defined SIOCGIFADDR || defined SIOCGIFHWADDR \ + || defined SIOCGIFFLAGS)) \ + || defined WINDOWSNT) + return network_interface_info (ifname); +#else + return Qnil; +#endif +} + + /* Turn off input and output for process PROC. */ static void deactivate_process (Lisp_Object proc) { - register int inchannel, outchannel; - register struct Lisp_Process *p = XPROCESS (proc); + int inchannel; + struct Lisp_Process *p = XPROCESS (proc); + int i; #ifdef HAVE_GNUTLS /* Delete GnuTLS structures in PROC, if any. */ emacs_gnutls_deinit (proc); #endif /* HAVE_GNUTLS */ - inchannel = p->infd; - outchannel = p->outfd; - #ifdef ADAPTIVE_READ_BUFFERING if (p->read_output_delay > 0) { @@ -3799,14 +3865,14 @@ deactivate_process (Lisp_Object proc) } #endif + /* Beware SIGCHLD hereabouts. */ + + for (i = 0; i < PROCESS_OPEN_FDS; i++) + close_process_fd (&p->open_fd[i]); + + inchannel = p->infd; if (inchannel >= 0) { - /* Beware SIGCHLD hereabouts. */ - flush_pending_output (inchannel); - emacs_close (inchannel); - if (outchannel >= 0 && outchannel != inchannel) - emacs_close (outchannel); - p->infd = -1; p->outfd = -1; #ifdef DATAGRAM_SOCKETS @@ -3831,13 +3897,14 @@ deactivate_process (Lisp_Object proc) #endif if (inchannel == max_process_desc) { - int i; /* We just closed the highest-numbered process input descriptor, so recompute the highest-numbered one now. */ - max_process_desc = 0; - for (i = 0; i < MAXDESC; i++) - if (!NILP (chan_process[i])) - max_process_desc = i; + int i = inchannel; + do + i--; + while (0 <= i && NILP (chan_process[i])); + + max_process_desc = i; } } } @@ -3899,9 +3966,9 @@ Return non-nil if we received any output before the timeout expired. */) { if (XFLOAT_DATA (seconds) > 0) { - EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (seconds)); - secs = min (EMACS_SECS (t), WAIT_READING_MAX); - nsecs = EMACS_NSECS (t); + struct timespec t = dtotimespec (XFLOAT_DATA (seconds)); + secs = min (t.tv_sec, WAIT_READING_MAX); + nsecs = t.tv_nsec; } } else @@ -4088,6 +4155,7 @@ server_accept_connection (Lisp_Object server, int channel) /* Discard the unwind protect for closing S. */ specpdl_ptr = specpdl + count; + p->open_fd[SUBPROCESS_STDIN] = s; p->infd = s; p->outfd = s; pset_status (p, Qrun); @@ -4198,14 +4266,14 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, struct Lisp_Process *wait_proc, int just_wait_proc) { int channel, nfds; - SELECT_TYPE Available; - SELECT_TYPE Writeok; + fd_set Available; + fd_set Writeok; bool check_write; int check_delay; bool no_avail; int xerrno; Lisp_Object proc; - EMACS_TIME timeout, end_time; + struct timespec timeout, end_time; int wait_channel = -1; bool got_some_input = 0; ptrdiff_t count = SPECPDL_INDEX (); @@ -4238,8 +4306,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, compute the absolute time to return at. */ if (time_limit || nsecs > 0) { - timeout = make_emacs_time (time_limit, nsecs); - end_time = add_emacs_time (current_emacs_time (), timeout); + timeout = make_timespec (time_limit, nsecs); + end_time = timespec_add (current_timespec (), timeout); } while (1) @@ -4266,18 +4334,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, gobble output available now but don't wait at all. */ - timeout = make_emacs_time (0, 0); + timeout = make_timespec (0, 0); } else if (time_limit || nsecs > 0) { - EMACS_TIME now = current_emacs_time (); - if (EMACS_TIME_LE (end_time, now)) + struct timespec now = current_timespec (); + if (timespec_cmp (end_time, now) <= 0) break; - timeout = sub_emacs_time (end_time, now); + timeout = timespec_sub (end_time, now); } else { - timeout = make_emacs_time (100000, 0); + timeout = make_timespec (100000, 0); } /* Normally we run timers here. @@ -4287,7 +4355,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (NILP (wait_for_cell) && just_wait_proc >= 0) { - EMACS_TIME timer_delay; + struct timespec timer_delay; do { @@ -4322,9 +4390,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* A negative timeout means do not wait at all. */ if (nsecs >= 0) { - if (EMACS_TIME_VALID_P (timer_delay)) + if (timespec_valid_p (timer_delay)) { - if (EMACS_TIME_LT (timer_delay, timeout)) + if (timespec_cmp (timer_delay, timeout) < 0) { timeout = timer_delay; timeout_reduced_for_timers = 1; @@ -4353,8 +4421,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, timeout to get our attention. */ if (update_tick != process_tick) { - SELECT_TYPE Atemp; - SELECT_TYPE Ctemp; + fd_set Atemp; + fd_set Ctemp; if (kbd_on_hold_p ()) FD_ZERO (&Atemp); @@ -4362,7 +4430,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, Atemp = input_wait_mask; Ctemp = write_mask; - timeout = make_emacs_time (0, 0); + timeout = make_timespec (0, 0); if ((pselect (max (max_process_desc, max_input_desc) + 1, &Atemp, #ifdef NON_BLOCKING_CONNECT @@ -4484,8 +4552,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, Vprocess_adaptive_read_buffering is nil. */ if (process_output_skip && check_delay > 0) { - int nsecs = EMACS_NSECS (timeout); - if (EMACS_SECS (timeout) > 0 || nsecs > READ_OUTPUT_DELAY_MAX) + int nsecs = timeout.tv_nsec; + if (timeout.tv_sec > 0 || nsecs > READ_OUTPUT_DELAY_MAX) nsecs = READ_OUTPUT_DELAY_MAX; for (channel = 0; check_delay > 0 && channel <= max_process_desc; channel++) { @@ -4505,7 +4573,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, nsecs = XPROCESS (proc)->read_output_delay; } } - timeout = make_emacs_time (0, nsecs); + timeout = make_timespec (0, nsecs); process_output_skip = 0; } #endif @@ -4519,7 +4587,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, #endif (max (max_process_desc, max_input_desc) + 1, &Available, - (check_write ? &Writeok : (SELECT_TYPE *)0), + (check_write ? &Writeok : 0), NULL, &timeout, NULL); #ifdef HAVE_GNUTLS @@ -4537,12 +4605,12 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, the gnutls library -- 2.12.14 has been confirmed to need it. See http://comments.gmane.org/gmane.emacs.devel/145074 */ - for (channel = 0; channel < MAXDESC; ++channel) + for (channel = 0; channel < FD_SETSIZE; ++channel) if (! NILP (chan_process[channel])) { struct Lisp_Process *p = XPROCESS (chan_process[channel]); - if (p && p->gnutls_p && p->infd + if (p && p->gnutls_p && p->gnutls_state && p->infd && ((emacs_gnutls_record_check_pending (p->gnutls_state)) > 0)) @@ -4556,6 +4624,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, { /* Check this specific channel. */ if (wait_proc->gnutls_p /* Check for valid process. */ + && wait_proc->gnutls_state /* Do we have pending data? */ && ((emacs_gnutls_record_check_pending (wait_proc->gnutls_state)) @@ -4815,7 +4884,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, #else { struct sockaddr pname; - int pnamelen = sizeof (pname); + socklen_t pnamelen = sizeof (pname); /* If connection failed, getpeername will fail. */ xerrno = 0; @@ -4937,7 +5006,7 @@ read_process_output (Lisp_Object proc, register int channel) proc_buffered_char[channel] = -1; } #ifdef HAVE_GNUTLS - if (p->gnutls_p) + if (p->gnutls_p && p->gnutls_state) nbytes = emacs_gnutls_read (p, chars + carryover + buffered, readmax - buffered); else @@ -5144,15 +5213,10 @@ DEFUN ("internal-default-process-filter", Finternal_default_process_filter, bset_read_only (current_buffer, Qnil); - /* Insert new output into buffer - at the current end-of-output marker, - thus preserving logical ordering of input and output. */ + /* Insert new output into buffer at the current end-of-output + marker, thus preserving logical ordering of input and output. */ if (XMARKER (p->mark)->buffer) - SET_PT_BOTH (clip_to_bounds (BEGV, - marker_position (p->mark), ZV), - clip_to_bounds (BEGV_BYTE, - marker_byte_position (p->mark), - ZV_BYTE)); + set_point_from_marker (p->mark); else SET_PT_BOTH (ZV, ZV_BYTE); before = PT; @@ -5183,7 +5247,7 @@ DEFUN ("internal-default-process-filter", Finternal_default_process_filter, else set_marker_both (p->mark, p->buffer, PT, PT_BYTE); - update_mode_lines++; + update_mode_lines = 23; /* Make sure opoint and the old restrictions float ahead of any new text just as point would. */ @@ -5436,7 +5500,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len, #endif { #ifdef HAVE_GNUTLS - if (p->gnutls_p) + if (p->gnutls_p && p->gnutls_state) written = emacs_gnutls_write (p, cur_buf, cur_len); else #endif @@ -5733,10 +5797,9 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, return; } - switch (signo) - { #ifdef SIGCONT - case SIGCONT: + if (signo == SIGCONT) + { p->raw_status_new = 0; pset_status (p, Qrun); p->tick = ++process_tick; @@ -5745,14 +5808,8 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, status_notify (NULL); redisplay_preserve_echo_area (13); } - break; -#endif /* ! defined (SIGCONT) */ - case SIGINT: - case SIGQUIT: - case SIGKILL: - flush_pending_output (p->infd); - break; } +#endif /* If we don't have process groups, send the signal to the immediate subprocess. That isn't really right, but it's better than any @@ -6007,7 +6064,8 @@ process has been transmitted to the serial port. */) } else { - int old_outfd, new_outfd; + int old_outfd = XPROCESS (proc)->outfd; + int new_outfd; #ifdef HAVE_SHUTDOWN /* If this is a network connection, or socketpair is used @@ -6015,18 +6073,15 @@ process has been transmitted to the serial port. */) (In some old system, shutdown to socketpair doesn't work. Then we just can't win.) */ if (EQ (XPROCESS (proc)->type, Qnetwork) - || XPROCESS (proc)->outfd == XPROCESS (proc)->infd) - shutdown (XPROCESS (proc)->outfd, 1); - /* In case of socketpair, outfd == infd, so don't close it. */ - if (XPROCESS (proc)->outfd != XPROCESS (proc)->infd) - emacs_close (XPROCESS (proc)->outfd); -#else /* not HAVE_SHUTDOWN */ - emacs_close (XPROCESS (proc)->outfd); -#endif /* not HAVE_SHUTDOWN */ + || XPROCESS (proc)->infd == old_outfd) + shutdown (old_outfd, 1); +#endif + close_process_fd (&XPROCESS (proc)->open_fd[WRITE_TO_SUBPROCESS]); new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0); if (new_outfd < 0) - emacs_abort (); - old_outfd = XPROCESS (proc)->outfd; + report_file_error ("Opening null device", Qnil); + XPROCESS (proc)->open_fd[WRITE_TO_SUBPROCESS] = new_outfd; + XPROCESS (proc)->outfd = new_outfd; if (!proc_encode_coding_system[new_outfd]) proc_encode_coding_system[new_outfd] @@ -6035,8 +6090,6 @@ process has been transmitted to the serial port. */) = *proc_encode_coding_system[old_outfd]; memset (proc_encode_coding_system[old_outfd], 0, sizeof (struct coding_system)); - - XPROCESS (proc)->outfd = new_outfd; } return process; } @@ -6102,7 +6155,7 @@ static signal_handler_t volatile lib_child_handler; static void handle_child_signal (int sig) { - Lisp_Object tail; + Lisp_Object tail, proc; /* Find the process that signaled us, and record its status. */ @@ -6113,7 +6166,11 @@ handle_child_signal (int sig) bool all_pids_are_fixnums = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t) && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM); - Lisp_Object xpid = XCAR (tail); + Lisp_Object head = XCAR (tail); + Lisp_Object xpid; + if (! CONSP (head)) + continue; + xpid = XCAR (head); if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid)) { pid_t deleted_pid; @@ -6122,14 +6179,17 @@ handle_child_signal (int sig) else deleted_pid = XFLOAT_DATA (xpid); if (child_status_changed (deleted_pid, 0, 0)) - XSETCAR (tail, Qnil); + { + if (STRINGP (XCDR (head))) + unlink (SSDATA (XCDR (head))); + XSETCAR (tail, Qnil); + } } } /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ - for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) + FOR_EACH_PROCESS (tail, proc) { - Lisp_Object proc = XCDR (XCAR (tail)); struct Lisp_Process *p = XPROCESS (proc); int status; @@ -6284,13 +6344,10 @@ status_notify (struct Lisp_Process *deleting_process) that we run, we get called again to handle their status changes. */ update_tick = process_tick; - for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) + FOR_EACH_PROCESS (tail, proc) { Lisp_Object symbol; - register struct Lisp_Process *p; - - proc = Fcdr (XCAR (tail)); - p = XPROCESS (proc); + register struct Lisp_Process *p = XPROCESS (proc); if (p->tick != p->update_tick) { @@ -6334,7 +6391,7 @@ status_notify (struct Lisp_Process *deleting_process) } } /* end for */ - update_mode_lines++; /* In case buffers use %s in mode-line-format. */ + update_mode_lines = 24; /* In case buffers use %s in mode-line-format. */ UNGCPRO; } @@ -6515,8 +6572,8 @@ keyboard_bit_set (fd_set *mask) #else /* not subprocesses */ /* Defined on msdos.c. */ -extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, - EMACS_TIME *, void *); +extern int sys_select (int, fd_set *, fd_set *, fd_set *, + struct timespec *, void *); /* Implementation of wait_reading_process_output, assuming that there are no subprocesses. Used only by the MS-DOS build. @@ -6555,7 +6612,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, struct Lisp_Process *wait_proc, int just_wait_proc) { register int nfds; - EMACS_TIME end_time, timeout; + struct timespec end_time, timeout; if (time_limit < 0) { @@ -6568,8 +6625,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* What does time_limit really mean? */ if (time_limit || nsecs > 0) { - timeout = make_emacs_time (time_limit, nsecs); - end_time = add_emacs_time (current_emacs_time (), timeout); + timeout = make_timespec (time_limit, nsecs); + end_time = timespec_add (current_timespec (), timeout); } /* Turn off periodic alarms (in case they are in use) @@ -6581,7 +6638,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, while (1) { bool timeout_reduced_for_timers = 0; - SELECT_TYPE waitchannels; + fd_set waitchannels; int xerrno; /* If calling from keyboard input, do not quit @@ -6602,18 +6659,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, gobble output available now but don't wait at all. */ - timeout = make_emacs_time (0, 0); + timeout = make_timespec (0, 0); } else if (time_limit || nsecs > 0) { - EMACS_TIME now = current_emacs_time (); - if (EMACS_TIME_LE (end_time, now)) + struct timespec now = current_timespec (); + if (timespec_cmp (end_time, now) <= 0) break; - timeout = sub_emacs_time (end_time, now); + timeout = timespec_sub (end_time, now); } else { - timeout = make_emacs_time (100000, 0); + timeout = make_timespec (100000, 0); } /* If our caller will not immediately handle keyboard events, @@ -6622,7 +6679,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, call timer_delay on their own.) */ if (NILP (wait_for_cell)) { - EMACS_TIME timer_delay; + struct timespec timer_delay; do { @@ -6642,9 +6699,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, && requeued_events_pending_p ()) break; - if (EMACS_TIME_VALID_P (timer_delay) && nsecs >= 0) + if (timespec_valid_p (timer_delay) && nsecs >= 0) { - if (EMACS_TIME_LT (timer_delay, timeout)) + if (timespec_cmp (timer_delay, timeout) < 0) { timeout = timer_delay; timeout_reduced_for_timers = 1; @@ -6763,16 +6820,9 @@ void delete_keyboard_wait_descriptor (int desc) { #ifdef subprocesses - int fd; - int lim = max_input_desc; - FD_CLR (desc, &input_wait_mask); FD_CLR (desc, &non_process_wait_mask); - - if (desc == max_input_desc) - for (fd = 0; fd < lim; fd++) - if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask)) - max_input_desc = fd; + delete_input_desc (desc); #endif } @@ -6820,12 +6870,9 @@ BUFFER may be a buffer or the name of one. */) buf = Fget_buffer (buffer); if (NILP (buf)) return Qnil; - for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) - { - proc = Fcdr (XCAR (tail)); - if (PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf)) - return proc; - } + FOR_EACH_PROCESS (tail, proc) + if (EQ (XPROCESS (proc)->buffer, buf)) + return proc; #endif /* subprocesses */ return Qnil; } @@ -6858,18 +6905,14 @@ kill_buffer_processes (Lisp_Object buffer) #ifdef subprocesses Lisp_Object tail, proc; - for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) - { - proc = XCDR (XCAR (tail)); - if (PROCESSP (proc) - && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer))) - { - if (NETCONN_P (proc) || SERIALCONN_P (proc)) - Fdelete_process (proc); - else if (XPROCESS (proc)->infd >= 0) - process_send_signal (proc, SIGHUP, Qnil, 1); - } - } + FOR_EACH_PROCESS (tail, proc) + if (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)) + { + if (NETCONN_P (proc) || SERIALCONN_P (proc)) + Fdelete_process (proc); + else if (XPROCESS (proc)->infd >= 0) + process_send_signal (proc, SIGHUP, Qnil, 1); + } #else /* subprocesses */ /* Since we have no subprocesses, this does nothing. */ #endif /* subprocesses */ @@ -7037,7 +7080,7 @@ init_process_emacs (void) FD_ZERO (&non_keyboard_wait_mask); FD_ZERO (&non_process_wait_mask); FD_ZERO (&write_mask); - max_process_desc = 0; + max_process_desc = max_input_desc = -1; memset (fd_callback_info, 0, sizeof (fd_callback_info)); #ifdef NON_BLOCKING_CONNECT @@ -7059,7 +7102,7 @@ init_process_emacs (void) Vprocess_alist = Qnil; deleted_pid_list = Qnil; - for (i = 0; i < MAXDESC; i++) + for (i = 0; i < FD_SETSIZE; i++) { chan_process[i] = Qnil; proc_buffered_char[i] = -1; @@ -7287,14 +7330,8 @@ The variable takes effect when `start-process' is called. */); defsubr (&Sset_network_process_option); defsubr (&Smake_network_process); defsubr (&Sformat_network_address); -#if defined (HAVE_NET_IF_H) -#ifdef SIOCGIFCONF defsubr (&Snetwork_interface_list); -#endif -#if defined (SIOCGIFADDR) || defined (SIOCGIFHWADDR) || defined (SIOCGIFFLAGS) defsubr (&Snetwork_interface_info); -#endif -#endif /* defined (HAVE_NET_IF_H) */ #ifdef DATAGRAM_SOCKETS defsubr (&Sprocess_datagram_address); defsubr (&Sset_process_datagram_address);