/* 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-2014
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <config.h>
-#define PROCESS_INLINE EXTERN_INLINE
-
#include <stdio.h>
#include <errno.h>
#include <sys/types.h> /* Some typedefs are used in sys/file.h. */
#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
+
+/* Work around GCC 4.7.0 bug with strict overflow checking; see
+ <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>.
+ These lines can be removed once the GCC bug is fixed. */
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
+# pragma GCC diagnostic ignored "-Wstrict-overflow"
#endif
+Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
+Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
+Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
+Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
+Lisp_Object QCname, QCtype;
+\f
+/* True if keyboard input is on hold, zero otherwise. */
+
+static bool kbd_is_on_hold;
+
+/* Nonzero means don't run process sentinels. This is used
+ when exiting. */
+bool inhibit_sentinels;
+
+#ifdef subprocesses
+
#ifndef SOCK_CLOEXEC
# define SOCK_CLOEXEC 0
#endif
# define socket(domain, type, protocol) process_socket (domain, type, protocol)
#endif
-/* Work around GCC 4.7.0 bug with strict overflow checking; see
- <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>.
- These lines can be removed once the GCC bug is fixed. */
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
-# pragma GCC diagnostic ignored "-Wstrict-overflow"
-#endif
-
-Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
-Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
-Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
-Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
-Lisp_Object QCname, QCtype;
-\f
-/* True if keyboard input is on hold, zero otherwise. */
-
-static bool kbd_is_on_hold;
-
-/* Nonzero means don't run process sentinels. This is used
- when exiting. */
-bool inhibit_sentinels;
-
-#ifdef subprocesses
-
Lisp_Object Qprocessp;
static Lisp_Object Qrun, Qstop, Qsignal;
static Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
#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)
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 *);
/* 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;
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;
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)
+#define DATAGRAM_CONN_P(proc) \
+ (PROCESSP (proc) && \
+ XPROCESS (proc)->infd >= 0 && \
+ datagram_address[XPROCESS (proc)->infd].sa != 0)
#else
#define DATAGRAM_CHAN_P(chan) (0)
#define DATAGRAM_CONN_P(proc) (0)
#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.
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;
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;
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;
void
delete_write_fd (int fd)
{
- 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)
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
{
DEFUN ("process-buffer", Fprocess_buffer, Sprocess_buffer,
1, 1, 0,
doc: /* Return the buffer PROCESS is associated with.
-Output from PROCESS is inserted in this buffer unless PROCESS has a filter. */)
+The default process filter inserts output from PROCESS into this buffer. */)
(register Lisp_Object process)
{
CHECK_PROCESS (process);
The filter gets two arguments: the process and the string of output.
The string argument is normally a multibyte string, except:
-- if the process' input coding system is no-conversion or raw-text,
+- if the process's input coding system is no-conversion or raw-text,
it is a unibyte string (the non-converted input), or else
- if `default-enable-multibyte-characters' is nil, it is a unibyte
string (the result of converting the decoded input multibyte
CHECK_PROCESS (process);
p = XPROCESS (process);
- /* Don't signal an error if the process' input file descriptor
+ /* Don't signal an error if the process's input file descriptor
is closed. This could make debugging Lisp more difficult,
for example when doing something like
tem = Qnil;
GCPRO4 (name, program, buffer, current_dir);
- openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK));
+ openp (Vexec_path, program, Vexec_suffixes, &tem,
+ make_number (X_OK), false);
UNGCPRO;
if (NILP (tem))
report_file_error ("Searching for program", program);
bool pty_flag = 0;
char pty_name[PTY_NAME_SIZE];
Lisp_Object lisp_pty_name = Qnil;
+ sigset_t oldset;
inchannel = outchannel = -1;
setup_process_coding_systems (process);
block_input ();
- block_child_signal ();
+ block_child_signal (&oldset);
#ifndef WINDOWSNT
/* vfork, and prevent local vars from being clobbered by the vfork. */
signal (SIGINT, SIG_DFL);
signal (SIGQUIT, SIG_DFL);
+#ifdef SIGPROF
+ signal (SIGPROF, SIG_DFL);
+#endif
/* Emacs ignores SIGPIPE, but the child should not. */
signal (SIGPIPE, SIG_DFL);
/* Stop blocking SIGCHLD in the child. */
- unblock_child_signal ();
+ unblock_child_signal (&oldset);
if (pty_flag)
child_setup_tty (xforkout);
p->alive = 1;
/* Stop blocking in the parent. */
- unblock_child_signal ();
+ unblock_child_signal (&oldset);
unblock_input ();
if (pid < 0)
/* 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;
case AF_LOCAL:
{
struct sockaddr_un *sockun = (struct sockaddr_un *) sa;
- for (i = 0; i < sizeof (sockun->sun_path); i++)
- if (sockun->sun_path[i] == 0)
- break;
- return make_unibyte_string (sockun->sun_path, i);
+ ptrdiff_t name_length = len - offsetof (struct sockaddr_un, sun_path);
+ /* If the first byte is NUL, the name is a Linux abstract
+ socket name, and the name can contain embedded NULs. If
+ it's not, we have a NUL-terminated string. Be careful not
+ to walk past the end of the object looking for the name
+ terminator, however. */
+ if (name_length > 0 && sockun->sun_path[0] != '\0')
+ {
+ const char *terminator
+ = memchr (sockun->sun_path, '\0', name_length);
+
+ if (terminator)
+ name_length = terminator - (const char *) sockun->sun_path;
+ }
+
+ return make_unibyte_string (sockun->sun_path, name_length);
}
#endif
default:
is the server process, CLIENT is the new process for the connection,
and MESSAGE is a string.
-:plist PLIST -- Install PLIST as the new process' initial plist.
+:plist PLIST -- Install PLIST as the new process's initial plist.
:server QLEN -- if QLEN is non-nil, create a server process for the
specified FAMILY, SERVICE, and connection type (stream or datagram).
for the connection with the following parameters:
- The client's process name is constructed by concatenating the server
-process' NAME and a client identification string.
+process's NAME and a client identification string.
- If the FILTER argument is non-nil, the client process will not get a
separate process buffer; otherwise, the client's process buffer is a newly
-created buffer named after the server process' BUFFER name or process
+created buffer named after the server process's BUFFER name or process
NAME concatenated with the client identification string.
- The connection type and the process filter and sentinel parameters are
-inherited from the server process' TYPE, FILTER and SENTINEL.
-- The client process' contact info is set according to the client's
+inherited from the server process's TYPE, FILTER and SENTINEL.
+- The client process's contact info is set according to the client's
addressing information (typically an IP address and a port number).
-- The client process' plist is initialized from the server's plist.
+- The client process's plist is initialized from the server's plist.
Notice that the FILTER and SENTINEL args are never used directly by
the server process. Also, the BUFFER argument is not used directly by
the server process, but via the optional :log function, accepted (and
-failed) connections may be logged in the server process' buffer.
+failed) connections may be logged in the server process's buffer.
The original argument list, modified with the actual connection
information, is available via the `process-contact' function.
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);
}
\f
-#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;
{ 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;
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)
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
DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
0, 4, 0,
doc: /* Allow any pending output from subprocesses to be read by Emacs.
-It is read into the process' buffers or given to their filter functions.
+It is given to their filter functions.
Non-nil arg PROCESS means do not return until some output has been received
from PROCESS.
{
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
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 ();
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)
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.
if (NILP (wait_for_cell)
&& just_wait_proc >= 0)
{
- EMACS_TIME timer_delay;
+ struct timespec timer_delay;
do
{
/* 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;
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);
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
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++)
{
nsecs = XPROCESS (proc)->read_output_delay;
}
}
- timeout = make_emacs_time (0, nsecs);
+ timeout = make_timespec (0, nsecs);
process_output_skip = 0;
}
#endif
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))
{
/* 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))
#else
{
struct sockaddr pname;
- int pnamelen = sizeof (pname);
+ socklen_t pnamelen = sizeof (pname);
/* If connection failed, getpeername will fail. */
xerrno = 0;
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
DEFUN ("internal-default-process-filter", Finternal_default_process_filter,
Sinternal_default_process_filter, 2, 2, 0,
- doc: /* Function used as default process filter. */)
+ doc: /* Function used as default process filter.
+This inserts the process's output into its buffer, if there is one.
+Otherwise it discards the output. */)
(Lisp_Object proc, Lisp_Object text)
{
struct Lisp_Process *p;
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;
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. */
#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
(Lisp_Object process)
{
Lisp_Object proc;
- struct coding_system *coding;
+ struct coding_system *coding = NULL;
+ int outfd;
if (DATAGRAM_CONN_P (process))
return process;
proc = get_process (process);
- coding = proc_encode_coding_system[XPROCESS (proc)->outfd];
+ outfd = XPROCESS (proc)->outfd;
+ if (outfd >= 0)
+ coding = proc_encode_coding_system[outfd];
/* Make sure the process is really alive. */
if (XPROCESS (proc)->raw_status_new)
if (! EQ (XPROCESS (proc)->status, Qrun))
error ("Process %s not running", SDATA (XPROCESS (proc)->name));
- if (CODING_REQUIRE_FLUSHING (coding))
+ if (coding && CODING_REQUIRE_FLUSHING (coding))
{
coding->mode |= CODING_MODE_LAST_BLOCK;
send_process (proc, "", 0, Qnil);
}
else
{
- int old_outfd = XPROCESS (proc)->outfd;
+ struct Lisp_Process *p = XPROCESS (proc);
+ int old_outfd = p->outfd;
int new_outfd;
#ifdef HAVE_SHUTDOWN
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 (EQ (XPROCESS (proc)->type, Qnetwork)
- || XPROCESS (proc)->infd == old_outfd)
+ if (EQ (p->type, Qnetwork)
+ || p->infd == old_outfd)
shutdown (old_outfd, 1);
#endif
- close_process_fd (&XPROCESS (proc)->open_fd[WRITE_TO_SUBPROCESS]);
+ close_process_fd (&p->open_fd[WRITE_TO_SUBPROCESS]);
new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0);
if (new_outfd < 0)
report_file_error ("Opening null device", Qnil);
- XPROCESS (proc)->open_fd[WRITE_TO_SUBPROCESS] = new_outfd;
- XPROCESS (proc)->outfd = new_outfd;
+ p->open_fd[WRITE_TO_SUBPROCESS] = new_outfd;
+ p->outfd = new_outfd;
if (!proc_encode_coding_system[new_outfd])
proc_encode_coding_system[new_outfd]
= xmalloc (sizeof (struct coding_system));
- *proc_encode_coding_system[new_outfd]
- = *proc_encode_coding_system[old_outfd];
- memset (proc_encode_coding_system[old_outfd], 0,
- sizeof (struct coding_system));
+ if (old_outfd >= 0)
+ {
+ *proc_encode_coding_system[new_outfd]
+ = *proc_encode_coding_system[old_outfd];
+ memset (proc_encode_coding_system[old_outfd], 0,
+ sizeof (struct coding_system));
+ }
+ else
+ setup_coding_system (p->encode_coding_system,
+ proc_encode_coding_system[new_outfd]);
}
return process;
}
lib_child_handler (sig);
#ifdef NS_IMPL_GNUSTEP
- /* NSTask in GNUStep sets its child handler each time it is called.
+ /* NSTask in GNUstep sets its child handler each time it is called.
So we must re-set ours. */
catch_child_signal();
#endif
}
} /* 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;
}
DEFUN ("internal-default-process-sentinel", Finternal_default_process_sentinel,
Sinternal_default_process_sentinel, 2, 2, 0,
- doc: /* Function used as default sentinel for processes. */)
+ doc: /* Function used as default sentinel for processes.
+This inserts a status message into the process's buffer, if there is one. */)
(Lisp_Object proc, Lisp_Object msg)
{
Lisp_Object buffer, symbol;
#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.
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)
{
/* 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)
while (1)
{
bool timeout_reduced_for_timers = 0;
- SELECT_TYPE waitchannels;
+ fd_set waitchannels;
int xerrno;
/* If calling from keyboard input, do not quit
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,
call timer_delay on their own.) */
if (NILP (wait_for_cell))
{
- EMACS_TIME timer_delay;
+ struct timespec timer_delay;
do
{
&& 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;
return system_process_attributes (pid);
}
+#ifdef subprocesses
/* Arrange to catch SIGCHLD if this hasn't already been arranged.
Invoke this after init_process_emacs, and after glib and/or GNUstep
futz with the SIGCHLD handler, but before Emacs forks any children.
catch_child_signal (void)
{
struct sigaction action, old_action;
+ sigset_t oldset;
emacs_sigaction_init (&action, deliver_child_signal);
- block_child_signal ();
+ block_child_signal (&oldset);
sigaction (SIGCHLD, &action, &old_action);
eassert (! (old_action.sa_flags & SA_SIGINFO));
= (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN
? dummy_handler
: old_action.sa_handler);
- unblock_child_signal ();
+ unblock_child_signal (&oldset);
}
+#endif /* subprocesses */
\f
/* This is not called "init_process" because that is the name of a
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;
DEFSYM (Qcutime, "cutime");
DEFSYM (Qcstime, "cstime");
DEFSYM (Qctime, "ctime");
+#ifdef subprocesses
DEFSYM (Qinternal_default_process_sentinel,
"internal-default-process-sentinel");
DEFSYM (Qinternal_default_process_filter,
"internal-default-process-filter");
+#endif
DEFSYM (Qpri, "pri");
DEFSYM (Qnice, "nice");
DEFSYM (Qthcount, "thcount");
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);