#include <config.h>
+
+#define PROCESS_INLINE EXTERN_INLINE
+
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include "systty.h"
#include "window.h"
-#include "buffer.h"
#include "character.h"
+#include "buffer.h"
#include "coding.h"
#include "process.h"
#include "frame.h"
#include "gnutls.h"
#endif
+#ifdef HAVE_WINDOW_SYSTEM
+#include TERM_HEADER
+#endif /* HAVE_WINDOW_SYSTEM */
+
#if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS)
#include "xgselect.h"
#endif
-#ifdef HAVE_NS
-#include "nsterm.h"
-#endif
/* Work around GCC 4.7.0 bug with strict overflow checking; see
<http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>.
extern Lisp_Object QCfilter;
#define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork))
-#define NETCONN1_P(p) (EQ ((p)->type, Qnetwork))
+#define NETCONN1_P(p) (EQ (p->type, Qnetwork))
#define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial))
-#define SERIALCONN1_P(p) (EQ ((p)->type, Qserial))
+#define SERIALCONN1_P(p) (EQ (p->type, Qserial))
#ifndef HAVE_H_ERRNO
extern int h_errno;
#endif
/* Number of events of change of status of a process. */
-static int process_tick;
+static EMACS_INT process_tick;
/* Number of events for which the user or sentinel has been notified. */
-static int update_tick;
+static EMACS_INT update_tick;
/* Define NON_BLOCKING_CONNECT if we can support non-blocking connects. */
#endif
#if !defined (ADAPTIVE_READ_BUFFERING) && !defined (NO_ADAPTIVE_READ_BUFFERING)
-#ifdef EMACS_HAS_USECS
#define ADAPTIVE_READ_BUFFERING
#endif
-#endif
#ifdef ADAPTIVE_READ_BUFFERING
-#define READ_OUTPUT_DELAY_INCREMENT 10000
+#define READ_OUTPUT_DELAY_INCREMENT (EMACS_TIME_RESOLUTION / 100)
#define READ_OUTPUT_DELAY_MAX (READ_OUTPUT_DELAY_INCREMENT * 5)
#define READ_OUTPUT_DELAY_MAX_MAX (READ_OUTPUT_DELAY_INCREMENT * 7)
#define process_output_delay_count 0
#endif
-static Lisp_Object Fget_process (Lisp_Object);
static void create_process (Lisp_Object, char **, Lisp_Object);
#ifdef SIGIO
static int keyboard_bit_set (SELECT_TYPE *);
/* Maximum number of bytes to send to a pty without an eof. */
static int pty_max_bytes;
+/* These setters are used only in this file, so they can be private. */
+static inline void
+pset_buffer (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->buffer = val;
+}
+static inline void
+pset_command (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->command = val;
+}
+static inline void
+pset_decode_coding_system (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->decode_coding_system = val;
+}
+static inline void
+pset_decoding_buf (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->decoding_buf = val;
+}
+static inline void
+pset_encode_coding_system (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->encode_coding_system = val;
+}
+static inline void
+pset_encoding_buf (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->encoding_buf = val;
+}
+static inline void
+pset_filter (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->filter = val;
+}
+static inline void
+pset_log (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->log = val;
+}
+static inline void
+pset_mark (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->mark = val;
+}
+static inline void
+pset_name (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->name = val;
+}
+static inline void
+pset_plist (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->plist = val;
+}
+static inline void
+pset_sentinel (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->sentinel = val;
+}
+static inline void
+pset_status (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->status = val;
+}
+static inline void
+pset_tty_name (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->tty_name = val;
+}
+static inline void
+pset_type (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->type = val;
+}
+static inline void
+pset_write_queue (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->write_queue = val;
+}
+
\f
static struct fd_callback_data
void
add_read_fd (int fd, fd_callback func, void *data)
{
- xassert (fd < MAXDESC);
+ eassert (fd < MAXDESC);
add_keyboard_wait_descriptor (fd);
fd_callback_info[fd].func = func;
void
delete_read_fd (int fd)
{
- xassert (fd < MAXDESC);
+ eassert (fd < MAXDESC);
delete_keyboard_wait_descriptor (fd);
fd_callback_info[fd].condition &= ~FOR_READ;
void
add_write_fd (int fd, fd_callback func, void *data)
{
- xassert (fd < MAXDESC);
+ eassert (fd < MAXDESC);
FD_SET (fd, &write_mask);
if (fd > max_input_desc)
max_input_desc = fd;
{
int lim = max_input_desc;
- xassert (fd < MAXDESC);
+ eassert (fd < MAXDESC);
FD_CLR (fd, &write_mask);
fd_callback_info[fd].condition &= ~FOR_WRITE;
if (fd_callback_info[fd].condition == 0)
update_status (struct Lisp_Process *p)
{
eassert (p->raw_status_new);
- p->status = status_convert (p->raw_status);
+ pset_status (p, status_convert (p->raw_status));
p->raw_status_new = 0;
}
if (WIFSTOPPED (w))
return Fcons (Qstop, Fcons (make_number (WSTOPSIG (w)), Qnil));
else if (WIFEXITED (w))
- return Fcons (Qexit, Fcons (make_number (WRETCODE (w)),
+ return Fcons (Qexit, Fcons (make_number (WEXITSTATUS (w)),
WCOREDUMP (w) ? Qt : Qnil));
else if (WIFSIGNALED (w))
return Fcons (Qsignal, Fcons (make_number (WTERMSIG (w)),
{
int c1, c2;
- string = make_unibyte_string (signame, strlen (signame));
+ string = build_unibyte_string (signame);
if (! NILP (Vlocale_coding_system))
string = (code_convert_string_norecord
(string, Vlocale_coding_system, 0));
printmax_t i;
p = allocate_process ();
+ /* Initialize Lisp data. Note that allocate_process initializes all
+ Lisp data to nil, so do it only for slots which should not be nil. */
+ pset_status (p, Qrun);
+ pset_mark (p, Fmake_marker ());
+ /* Initialize non-Lisp data. Note that allocate_process zeroes out all
+ non-Lisp data, so do it only for slots which should not be zero. */
p->infd = -1;
p->outfd = -1;
- p->tick = 0;
- p->update_tick = 0;
- p->pid = 0;
- p->pty_flag = 0;
- p->raw_status_new = 0;
- p->status = Qrun;
- p->mark = Fmake_marker ();
- p->kill_without_query = 0;
-
-#ifdef ADAPTIVE_READ_BUFFERING
- p->adaptive_read_buffering = 0;
- p->read_output_delay = 0;
- p->read_output_skip = 0;
-#endif
#ifdef HAVE_GNUTLS
p->gnutls_initstage = GNUTLS_STAGE_EMPTY;
- /* Default log level. */
- p->gnutls_log_level = 0;
- /* GnuTLS handshakes attempted for this connection. */
- p->gnutls_handshakes_tried = 0;
- p->gnutls_p = 0;
- p->gnutls_state = NULL;
- p->gnutls_x509_cred = NULL;
- p->gnutls_anon_cred = NULL;
#endif
/* If name is already in use, modify it until it is unused. */
{
tem = Fget_process (name1);
if (NILP (tem)) break;
- sprintf (suffix, "<%"pMd">", i);
- name1 = concat2 (name, build_string (suffix));
+ name1 = concat2 (name, make_formatted_string (suffix, "<%"pMd">", i));
}
name = name1;
- p->name = name;
+ pset_name (p, name);
XSETPROCESS (val, p);
Vprocess_alist = Fcons (Fcons (name, val), Vprocess_alist);
return val;
p->raw_status_new = 0;
if (NETCONN1_P (p) || SERIALCONN1_P (p))
{
- p->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
+ pset_status (p, Fcons (Qexit, Fcons (make_number (0), Qnil)));
p->tick = ++process_tick;
status_notify (p);
redisplay_preserve_echo_area (13);
{
#ifdef SIGCHLD
Lisp_Object symbol;
- /* Assignment to EMACS_INT stops GCC whining about limited range
- of data type. */
- EMACS_INT pid = p->pid;
+ pid_t pid = p->pid;
/* No problem storing the pid here, as it is still in Vprocess_alist. */
deleted_pid_list = Fcons (make_fixnum_or_float (pid),
{
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));
+ pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil)));
p->tick = ++process_tick;
status_notify (p);
redisplay_preserve_echo_area (13);
For a network connection, this value is nil. */)
(register Lisp_Object process)
{
- /* Assignment to EMACS_INT stops GCC whining about limited range of
- data type. */
- EMACS_INT pid;
+ pid_t pid;
CHECK_PROCESS (process);
pid = XPROCESS (process)->pid;
if (!NILP (buffer))
CHECK_BUFFER (buffer);
p = XPROCESS (process);
- p->buffer = buffer;
+ pset_buffer (p, buffer);
if (NETCONN1_P (p) || SERIALCONN1_P (p))
- p->childp = Fplist_put (p->childp, QCbuffer, buffer);
+ pset_childp (p, Fplist_put (p->childp, QCbuffer, buffer));
setup_process_coding_systems (process);
return buffer;
}
}
}
- p->filter = filter;
+ pset_filter (p, filter);
if (NETCONN1_P (p) || SERIALCONN1_P (p))
- p->childp = Fplist_put (p->childp, QCfilter, filter);
+ pset_childp (p, Fplist_put (p->childp, QCfilter, filter));
setup_process_coding_systems (process);
return filter;
}
CHECK_PROCESS (process);
p = XPROCESS (process);
- p->sentinel = sentinel;
+ pset_sentinel (p, sentinel);
if (NETCONN1_P (p) || SERIALCONN1_P (p))
- p->childp = Fplist_put (p->childp, QCsentinel, sentinel);
+ pset_childp (p, Fplist_put (p->childp, QCsentinel, sentinel));
return sentinel;
}
(register Lisp_Object process, Lisp_Object height, Lisp_Object width)
{
CHECK_PROCESS (process);
- CHECK_NATNUM (height);
- CHECK_NATNUM (width);
+ CHECK_RANGED_INTEGER (height, 0, INT_MAX);
+ CHECK_RANGED_INTEGER (width, 0, INT_MAX);
if (XPROCESS (process)->infd < 0
|| set_window_size (XPROCESS (process)->infd,
Binding the variable `inherit-process-coding-system' to non-nil before
starting the process is an alternative way of setting the inherit flag
-for the process which will run. */)
+for the process which will run.
+
+This function returns FLAG. */)
(register Lisp_Object process, Lisp_Object flag)
{
CHECK_PROCESS (process);
2, 2, 0,
doc: /* Specify if query is needed for PROCESS when Emacs is exited.
If the second argument FLAG is non-nil, Emacs will query the user before
-exiting or killing a buffer if PROCESS is running. */)
+exiting or killing a buffer if PROCESS is running. This function
+returns FLAG. */)
(register Lisp_Object process, Lisp_Object flag)
{
CHECK_PROCESS (process);
return (XPROCESS (process)->kill_without_query ? Qnil : Qt);
}
-#ifdef DATAGRAM_SOCKETS
-static Lisp_Object Fprocess_datagram_address (Lisp_Object);
-#endif
-
DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
1, 2, 0,
doc: /* Return the contact info of PROCESS; t for a real child.
CHECK_PROCESS (process);
CHECK_LIST (plist);
- XPROCESS (process)->plist = plist;
+ pset_plist (XPROCESS (process), plist);
return plist;
}
if (VECTORP (address)) /* AF_INET or AF_INET6 */
{
register struct Lisp_Vector *p = XVECTOR (address);
- EMACS_INT size = p->header.size;
+ ptrdiff_t size = p->header.size;
Lisp_Object args[10];
int nargs, i;
for (i = 0; i < nargs; i++)
{
- EMACS_INT element = XINT (p->contents[i]);
-
- if (element < 0 || element > 65535)
+ if (! RANGED_INTEGERP (0, p->contents[i], 65535))
return Qnil;
if (nargs <= 5 /* IPv4 */
&& i < 4 /* host, not port */
- && element > 255)
+ && XINT (p->contents[i]) > 255)
return Qnil;
args[i+1] = p->contents[i];
Lisp_Object buffer, name, program, proc, current_dir, tem;
register unsigned char **new_argv;
ptrdiff_t i;
- int count = SPECPDL_INDEX ();
+ ptrdiff_t count = SPECPDL_INDEX ();
buffer = args[1];
if (!NILP (buffer))
itself; it's all taken care of here. */
record_unwind_protect (start_process_unwind, proc);
- XPROCESS (proc)->childp = Qt;
- XPROCESS (proc)->plist = Qnil;
- XPROCESS (proc)->type = Qreal;
- XPROCESS (proc)->buffer = buffer;
- XPROCESS (proc)->sentinel = Qnil;
- XPROCESS (proc)->filter = Qnil;
- XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
+ pset_childp (XPROCESS (proc), Qt);
+ pset_plist (XPROCESS (proc), Qnil);
+ pset_type (XPROCESS (proc), Qreal);
+ pset_buffer (XPROCESS (proc), buffer);
+ pset_sentinel (XPROCESS (proc), Qnil);
+ pset_filter (XPROCESS (proc), Qnil);
+ pset_command (XPROCESS (proc), Flist (nargs - 2, args + 2));
#ifdef HAVE_GNUTLS
/* AKA GNUTLS_INITSTAGE(proc). */
XPROCESS (proc)->gnutls_initstage = GNUTLS_STAGE_EMPTY;
- XPROCESS (proc)->gnutls_cred_type = Qnil;
+ pset_gnutls_cred_type (XPROCESS (proc), Qnil);
#endif
#ifdef ADAPTIVE_READ_BUFFERING
val = Vcoding_system_for_read;
if (NILP (val))
{
- args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+ args2 = alloca ((nargs + 1) * sizeof *args2);
args2[0] = Qstart_process;
for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
GCPRO2 (proc, current_dir);
else if (CONSP (Vdefault_process_coding_system))
val = XCAR (Vdefault_process_coding_system);
}
- XPROCESS (proc)->decode_coding_system = val;
+ pset_decode_coding_system (XPROCESS (proc), val);
val = Vcoding_system_for_write;
if (NILP (val))
{
if (EQ (coding_systems, Qt))
{
- args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+ args2 = alloca ((nargs + 1) * sizeof *args2);
args2[0] = Qstart_process;
for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
GCPRO2 (proc, current_dir);
else if (CONSP (Vdefault_process_coding_system))
val = XCDR (Vdefault_process_coding_system);
}
- XPROCESS (proc)->encode_coding_system = val;
+ pset_encode_coding_system (XPROCESS (proc), val);
/* Note: At this moment, the above coding system may leave
text-conversion or eol-conversion unspecified. They will be
decided after we read output from the process and decode it by
}
- XPROCESS (proc)->decoding_buf = empty_unibyte_string;
+ pset_decoding_buf (XPROCESS (proc), empty_unibyte_string);
XPROCESS (proc)->decoding_carryover = 0;
- XPROCESS (proc)->encoding_buf = empty_unibyte_string;
+ pset_encoding_buf (XPROCESS (proc), empty_unibyte_string);
XPROCESS (proc)->inherit_coding_system_flag
= !(NILP (buffer) || !inherit_process_coding_system);
/* Now that everything is encoded we can collect the strings into
NEW_ARGV. */
- new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
+ new_argv = alloca ((nargs - 1) * sizeof *new_argv);
new_argv[nargs - 2] = 0;
for (i = nargs - 2; i-- != 0; )
/* Use volatile to protect variables from being clobbered by longjmp. */
volatile int forkin, forkout;
volatile int pty_flag = 0;
-#ifndef USE_CRT_DLL
- extern char **environ;
-#endif
inchannel = outchannel = -1;
more portable (see USG_SUBTTY_WORKS above). */
XPROCESS (process)->pty_flag = pty_flag;
- XPROCESS (process)->status = Qrun;
+ pset_status (XPROCESS (process), Qrun);
/* Delay interrupts until we have a chance to store
the new fork's pid in its process structure */
So have an interrupt jar it loose. */
{
struct atimer *timer;
- EMACS_TIME offset;
+ EMACS_TIME offset = make_emacs_time (1, 0);
stop_polling ();
- EMACS_SET_SECS_USECS (offset, 1, 0);
timer = start_atimer (ATIMER_RELATIVE, offset, create_process_1, 0);
if (forkin >= 0)
#ifdef HAVE_PTYS
if (pty_flag)
- XPROCESS (process)->tty_name = build_string (pty_name);
+ pset_tty_name (XPROCESS (process), build_string (pty_name));
else
#endif
- XPROCESS (process)->tty_name = Qnil;
+ pset_tty_name (XPROCESS (process), Qnil);
#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
/* Wait for child_setup to complete in case that vfork is
more portable (see USG_SUBTTY_WORKS above). */
XPROCESS (process)->pty_flag = pty_flag;
- XPROCESS (process)->status = Qrun;
+ pset_status (XPROCESS (process), Qrun);
setup_process_coding_systems (process);
FD_SET (inchannel, &input_wait_mask);
XPROCESS (process)->pid = -2;
#ifdef HAVE_PTYS
if (pty_flag)
- XPROCESS (process)->tty_name = build_string (pty_name);
+ pset_tty_name (XPROCESS (process), build_string (pty_name));
else
#endif
- XPROCESS (process)->tty_name = Qnil;
+ pset_tty_name (XPROCESS (process), Qnil);
}
\f
return sizeof (struct sockaddr_un);
}
#endif
- else if (CONSP (address) && INTEGERP (XCAR (address)) && VECTORP (XCDR (address)))
+ else if (CONSP (address) && TYPE_RANGED_INTEGERP (int, XCAR (address))
+ && VECTORP (XCDR (address)))
{
struct sockaddr *sa;
*familyp = XINT (XCAR (address));
register struct Lisp_Vector *p;
register unsigned char *cp = NULL;
register int i;
+ EMACS_INT hostport;
memset (sa, 0, len);
{
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
len = sizeof (sin->sin_addr) + 1;
- i = XINT (p->contents[--len]);
- sin->sin_port = htons (i);
+ hostport = XINT (p->contents[--len]);
+ sin->sin_port = htons (hostport);
cp = (unsigned char *)&sin->sin_addr;
sa->sa_family = family;
}
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);
+ hostport = XINT (p->contents[--len]);
+ sin6->sin6_port = htons (hostport);
for (i = 0; i < len; i++)
if (INTEGERP (p->contents[i]))
{
case SOPT_INT:
{
int optval;
- if (INTEGERP (val))
+ if (TYPE_RANGED_INTEGERP (int, val))
optval = XINT (val);
else
error ("Bad option value for %s", name);
linger.l_onoff = 1;
linger.l_linger = 0;
- if (INTEGERP (val))
+ if (TYPE_RANGED_INTEGERP (int, val))
linger.l_linger = XINT (val);
else
linger.l_onoff = NILP (val) ? 0 : 1;
if (set_socket_option (s, option, value))
{
- p->childp = Fplist_put (p->childp, option, value);
+ pset_childp (p, Fplist_put (p->childp, option, value));
return Qt;
}
the backslashes in strings).
:speed SPEED -- (mandatory) is handled by `serial-process-configure',
-which is called by `make-serial-process'.
+which this function calls.
:name NAME -- NAME is the name of the process. If NAME is not given,
the value of PORT is used.
:plist PLIST -- Install PLIST as the initial plist of the process.
-:speed
:bytesize
:parity
:stopbits
:flowcontrol
--- These arguments are handled by `serial-process-configure', which is
-called by `make-serial-process'.
+-- This function calls `serial-process-configure' to handle these
+arguments.
The original argument list, possibly modified by later configuration,
is available via the function `process-contact'.
struct gcpro gcpro1;
Lisp_Object name, buffer;
Lisp_Object tem, val;
- int specpdl_count = -1;
+ ptrdiff_t specpdl_count = -1;
if (nargs == 0)
return Qnil;
if (NILP (buffer))
buffer = name;
buffer = Fget_buffer_create (buffer);
- p->buffer = buffer;
-
- p->childp = contact;
- p->plist = Fcopy_sequence (Fplist_get (contact, QCplist));
- p->type = Qserial;
- p->sentinel = Fplist_get (contact, QCsentinel);
- p->filter = Fplist_get (contact, QCfilter);
- p->log = Qnil;
+ pset_buffer (p, buffer);
+
+ pset_childp (p, contact);
+ pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist)));
+ pset_type (p, Qserial);
+ pset_sentinel (p, Fplist_get (contact, QCsentinel));
+ pset_filter (p, Fplist_get (contact, QCfilter));
+ pset_log (p, Qnil);
if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
p->kill_without_query = 1;
if (tem = Fplist_get (contact, QCstop), !NILP (tem))
- p->command = Qt;
+ pset_command (p, Qt);
p->pty_flag = 0;
if (!EQ (p->command, Qt))
else if ((!NILP (buffer) && NILP (BVAR (XBUFFER (buffer), enable_multibyte_characters)))
|| (NILP (buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters))))
val = Qnil;
- p->decode_coding_system = val;
+ pset_decode_coding_system (p, val);
val = Qnil;
if (!NILP (tem))
else if ((!NILP (buffer) && NILP (BVAR (XBUFFER (buffer), enable_multibyte_characters)))
|| (NILP (buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters))))
val = Qnil;
- p->encode_coding_system = val;
+ pset_encode_coding_system (p, val);
setup_process_coding_systems (proc);
- p->decoding_buf = empty_unibyte_string;
+ pset_decoding_buf (p, empty_unibyte_string);
p->decoding_carryover = 0;
- p->encoding_buf = empty_unibyte_string;
+ pset_encoding_buf (p, empty_unibyte_string);
p->inherit_coding_system_flag
= !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system);
:filter-multibyte BOOL -- If BOOL is non-nil, strings given to the
process filter are multibyte, otherwise they are unibyte.
If this keyword is not specified, the strings are multibyte if
-`default-enable-multibyte-characters' is non-nil.
+the default value of `enable-multibyte-characters' is non-nil.
:sentinel SENTINEL -- Install SENTINEL as the process sentinel.
int xerrno = 0;
int s = -1, outch, inch;
struct gcpro gcpro1;
- int count = SPECPDL_INDEX ();
- int count1;
+ ptrdiff_t count = SPECPDL_INDEX ();
+ ptrdiff_t count1;
Lisp_Object QCaddress; /* one of QClocal or QCremote */
Lisp_Object tem;
Lisp_Object name, buffer, host, service, address;
error ("Network servers not supported");
#else
is_server = 1;
- if (INTEGERP (tem))
+ if (TYPE_RANGED_INTEGERP (int, tem))
backlog = XINT (tem);
#endif
}
#endif
else if (EQ (tem, Qipv4))
family = AF_INET;
- else if (INTEGERP (tem))
+ else if (TYPE_RANGED_INTEGERP (int, tem))
family = XINT (tem);
else
error ("Unknown address family");
CHECK_STRING (service);
memset (&address_un, 0, sizeof address_un);
address_un.sun_family = AF_LOCAL;
- strncpy (address_un.sun_path, SSDATA (service), sizeof address_un.sun_path);
+ if (sizeof address_un.sun_path <= SBYTES (service))
+ error ("Service name too long");
+ strcpy (address_un.sun_path, SSDATA (service));
ai.ai_addr = (struct sockaddr *) &address_un;
ai.ai_addrlen = sizeof address_un;
goto open_socket;
{
/* Unlike most other syscalls connect() cannot be called
again. (That would return EALREADY.) The proper way to
- wait for completion is select(). */
+ wait for completion is pselect(). */
int sc;
socklen_t len;
SELECT_TYPE fdset;
FD_ZERO (&fdset);
FD_SET (s, &fdset);
QUIT;
- sc = select (s + 1, (SELECT_TYPE *)0, &fdset, (SELECT_TYPE *)0,
- (EMACS_TIME *)0);
+ sc = pselect (s + 1, NULL, &fdset, NULL, NULL, NULL);
if (sc == -1)
{
if (errno == EINTR)
{
if (datagram_address[s].sa)
abort ();
- datagram_address[s].sa = (struct sockaddr *) xmalloc (lres->ai_addrlen);
+ datagram_address[s].sa = xmalloc (lres->ai_addrlen);
datagram_address[s].len = lres->ai_addrlen;
if (is_server)
{
p = XPROCESS (proc);
- p->childp = contact;
- p->plist = Fcopy_sequence (Fplist_get (contact, QCplist));
- p->type = Qnetwork;
+ pset_childp (p, contact);
+ pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist)));
+ pset_type (p, Qnetwork);
- p->buffer = buffer;
- p->sentinel = sentinel;
- p->filter = filter;
- p->log = Fplist_get (contact, QClog);
+ pset_buffer (p, buffer);
+ pset_sentinel (p, sentinel);
+ pset_filter (p, filter);
+ pset_log (p, Fplist_get (contact, QClog));
if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
p->kill_without_query = 1;
if ((tem = Fplist_get (contact, QCstop), !NILP (tem)))
- p->command = Qt;
+ pset_command (p, Qt);
p->pid = 0;
p->infd = inch;
p->outfd = outch;
if (is_server && socktype != SOCK_DGRAM)
- p->status = Qlisten;
+ pset_status (p, Qlisten);
/* Make the process marker point into the process buffer (if any). */
if (BUFFERP (buffer))
/* We may get here if connect did succeed immediately. However,
in that case, we still need to signal this like a non-blocking
connection. */
- p->status = Qconnect;
+ pset_status (p, Qconnect);
if (!FD_ISSET (inch, &connect_wait_mask))
{
FD_SET (inch, &connect_wait_mask);
else
val = Qnil;
}
- p->decode_coding_system = val;
+ pset_decode_coding_system (p, val);
if (!NILP (tem))
{
else
val = Qnil;
}
- p->encode_coding_system = val;
+ pset_encode_coding_system (p, val);
}
setup_process_coding_systems (proc);
- p->decoding_buf = empty_unibyte_string;
+ pset_decoding_buf (p, empty_unibyte_string);
p->decoding_carryover = 0;
- p->encoding_buf = empty_unibyte_string;
+ pset_encoding_buf (p, empty_unibyte_string);
p->inherit_coding_system_flag
= !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system);
CHECK_STRING (ifname);
- memset (rq.ifr_name, 0, sizeof rq.ifr_name);
- strncpy (rq.ifr_name, SSDATA (ifname), sizeof (rq.ifr_name));
+ if (sizeof rq.ifr_name <= SBYTES (ifname))
+ error ("interface name too long");
+ strcpy (rq.ifr_name, SSDATA (ifname));
s = socket (AF_INET, SOCK_STREAM, 0);
if (s < 0)
Return non-nil if we received any output before the timeout expired. */)
(register Lisp_Object process, Lisp_Object seconds, Lisp_Object millisec, Lisp_Object just_this_one)
{
- int secs, usecs = 0;
+ intmax_t secs;
+ int nsecs;
if (! NILP (process))
CHECK_PROCESS (process);
}
}
+ secs = 0;
+ nsecs = -1;
+
if (!NILP (seconds))
{
if (INTEGERP (seconds))
- secs = XINT (seconds);
+ {
+ if (0 < XINT (seconds))
+ {
+ secs = XINT (seconds);
+ nsecs = 0;
+ }
+ }
else if (FLOATP (seconds))
{
- double timeout = XFLOAT_DATA (seconds);
- secs = (int) timeout;
- usecs = (int) ((timeout - (double) secs) * 1000000);
+ if (0 < XFLOAT_DATA (seconds))
+ {
+ EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (seconds));
+ secs = min (EMACS_SECS (t), WAIT_READING_MAX);
+ nsecs = EMACS_NSECS (t);
+ }
}
else
wrong_type_argument (Qnumberp, seconds);
-
- if (secs < 0 || (secs == 0 && usecs == 0))
- secs = -1, usecs = 0;
}
- else
- secs = NILP (process) ? -1 : 0;
+ else if (! NILP (process))
+ nsecs = 0;
return
- (wait_reading_process_output (secs, usecs, 0, 0,
+ (wait_reading_process_output (secs, nsecs, 0, 0,
Qnil,
!NILP (process) ? XPROCESS (process) : NULL,
NILP (just_this_one) ? 0 :
conv_sockaddr_to_lisp (&saddr.sa, len));
#endif
- p->childp = contact;
- p->plist = Fcopy_sequence (ps->plist);
- p->type = Qnetwork;
+ pset_childp (p, contact);
+ pset_plist (p, Fcopy_sequence (ps->plist));
+ pset_type (p, Qnetwork);
- p->buffer = buffer;
- p->sentinel = ps->sentinel;
- p->filter = ps->filter;
- p->command = Qnil;
+ pset_buffer (p, buffer);
+ pset_sentinel (p, ps->sentinel);
+ pset_filter (p, ps->filter);
+ pset_command (p, Qnil);
p->pid = 0;
p->infd = s;
p->outfd = s;
- p->status = Qrun;
+ pset_status (p, Qrun);
/* Client processes for accepted connections are not stopped initially. */
if (!EQ (p->filter, Qt))
of the new process should reflect the settings at the time the
server socket was opened; not the current settings. */
- p->decode_coding_system = ps->decode_coding_system;
- p->encode_coding_system = ps->encode_coding_system;
+ pset_decode_coding_system (p, ps->decode_coding_system);
+ pset_encode_coding_system (p, ps->encode_coding_system);
setup_process_coding_systems (proc);
- p->decoding_buf = empty_unibyte_string;
+ pset_decoding_buf (p, empty_unibyte_string);
p->decoding_carryover = 0;
- p->encoding_buf = empty_unibyte_string;
+ pset_encoding_buf (p, empty_unibyte_string);
p->inherit_coding_system_flag
= (NILP (buffer) ? 0 : ps->inherit_coding_system_flag);
{
}
-/* Use a wrapper around select to work around a bug in gdb 5.3.
- Normally, the wrapper is optimized 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 (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *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.
TIME_LIMIT is:
- timeout in seconds, or
- zero for no limit, or
- -1 means gobble data immediately available but don't wait for any.
+ timeout in seconds
+ If negative, gobble data immediately available but don't wait for any.
- MICROSECS is:
- an additional duration to wait, measured in microseconds.
- If this is nonzero and time_limit is 0, then the timeout
- consists of MICROSECS only.
+ NSECS is:
+ an additional duration to wait, measured in nanoseconds
+ If TIME_LIMIT is zero, then:
+ If NSECS == 0, there is no limit.
+ If NSECS > 0, the timeout consists of NSECS only.
+ If NSECS < 0, gobble data immediately, as if TIME_LIMIT were negative.
- READ_KBD is a lisp value:
+ READ_KBD is:
0 to ignore keyboard input, or
1 to return when input is available, or
-1 meaning caller will actually read the input, so don't throw to
Otherwise, return true if we received input from any process. */
int
-wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
int do_display,
Lisp_Object wait_for_cell,
struct Lisp_Process *wait_proc, int just_wait_proc)
EMACS_TIME timeout, end_time;
int wait_channel = -1;
int got_some_input = 0;
- int count = SPECPDL_INDEX ();
+ ptrdiff_t count = SPECPDL_INDEX ();
FD_ZERO (&Available);
FD_ZERO (&Writeok);
- if (time_limit == 0 && microsecs == 0 && wait_proc && !NILP (Vinhibit_quit)
- && !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit)))
+ if (time_limit == 0 && nsecs == 0 && wait_proc && !NILP (Vinhibit_quit)
+ && !(CONSP (wait_proc->status)
+ && EQ (XCAR (wait_proc->status), Qexit)))
message ("Blocking call to accept-process-output with quit inhibited!!");
/* If wait_proc is a process to watch, set wait_channel accordingly. */
make_number (waiting_for_user_input_p));
waiting_for_user_input_p = read_kbd;
+ if (time_limit < 0)
+ {
+ time_limit = 0;
+ nsecs = -1;
+ }
+ else if (TYPE_MAXIMUM (time_t) < time_limit)
+ time_limit = TYPE_MAXIMUM (time_t);
+
/* Since we may need to wait several times,
compute the absolute time to return at. */
- if (time_limit || microsecs)
+ if (time_limit || 0 < nsecs)
{
- EMACS_GET_TIME (end_time);
- EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
- EMACS_ADD_TIME (end_time, end_time, timeout);
+ timeout = make_emacs_time (time_limit, nsecs);
+ end_time = add_emacs_time (current_emacs_time (), timeout);
}
while (1)
/* Compute time from now till when time limit is up */
/* Exit if already run out */
- if (time_limit == -1)
+ if (nsecs < 0)
{
- /* -1 specified for timeout means
+ /* A negative timeout means
gobble output available now
but don't wait at all. */
- EMACS_SET_SECS_USECS (timeout, 0, 0);
+ timeout = make_emacs_time (0, 0);
}
- else if (time_limit || microsecs)
+ else if (time_limit || 0 < nsecs)
{
- EMACS_GET_TIME (timeout);
- EMACS_SUB_TIME (timeout, end_time, timeout);
- if (EMACS_TIME_NEG_P (timeout))
+ EMACS_TIME now = current_emacs_time ();
+ if (EMACS_TIME_LE (end_time, now))
break;
+ timeout = sub_emacs_time (end_time, now);
}
else
{
- EMACS_SET_SECS_USECS (timeout, 100000, 0);
+ timeout = make_emacs_time (100000, 0);
}
/* Normally we run timers here.
&& requeued_events_pending_p ())
break;
- if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
+ /* A negative timeout means do not wait at all. */
+ if (0 <= nsecs)
{
- EMACS_TIME difference;
- EMACS_SUB_TIME (difference, timer_delay, timeout);
- if (EMACS_TIME_NEG_P (difference))
+ if (EMACS_TIME_VALID_P (timer_delay))
{
- timeout = timer_delay;
- timeout_reduced_for_timers = 1;
+ if (EMACS_TIME_LT (timer_delay, timeout))
+ {
+ timeout = timer_delay;
+ timeout_reduced_for_timers = 1;
+ }
+ }
+ else
+ {
+ /* This is so a breakpoint can be put here. */
+ wait_reading_process_output_1 ();
}
- }
- /* If time_limit is -1, we are not going to wait at all. */
- else if (time_limit != -1)
- {
- /* This is so a breakpoint can be put here. */
- wait_reading_process_output_1 ();
}
}
Atemp = input_wait_mask;
Ctemp = write_mask;
- EMACS_SET_SECS_USECS (timeout, 0, 0);
- if ((select (max (max_process_desc, max_input_desc) + 1,
- &Atemp,
+ timeout = make_emacs_time (0, 0);
+ if ((pselect (max (max_process_desc, max_input_desc) + 1,
+ &Atemp,
#ifdef NON_BLOCKING_CONNECT
- (num_pending_connects > 0 ? &Ctemp : (SELECT_TYPE *)0),
+ (num_pending_connects > 0 ? &Ctemp : NULL),
#else
- (SELECT_TYPE *)0,
+ NULL,
#endif
- (SELECT_TYPE *)0, &timeout)
+ NULL, &timeout, NULL)
<= 0))
{
/* It's okay for us to do this and then continue with
Vprocess_adaptive_read_buffering is nil. */
if (process_output_skip && check_delay > 0)
{
- int usecs = EMACS_USECS (timeout);
- if (EMACS_SECS (timeout) > 0 || usecs > READ_OUTPUT_DELAY_MAX)
- usecs = READ_OUTPUT_DELAY_MAX;
+ int nsecs = EMACS_NSECS (timeout);
+ if (EMACS_SECS (timeout) > 0 || nsecs > READ_OUTPUT_DELAY_MAX)
+ nsecs = READ_OUTPUT_DELAY_MAX;
for (channel = 0; check_delay > 0 && channel <= max_process_desc; channel++)
{
proc = chan_process[channel];
continue;
FD_CLR (channel, &Available);
XPROCESS (proc)->read_output_skip = 0;
- if (XPROCESS (proc)->read_output_delay < usecs)
- usecs = XPROCESS (proc)->read_output_delay;
+ if (XPROCESS (proc)->read_output_delay < nsecs)
+ nsecs = XPROCESS (proc)->read_output_delay;
}
}
- EMACS_SET_SECS_USECS (timeout, 0, usecs);
+ timeout = make_emacs_time (0, nsecs);
process_output_skip = 0;
}
#endif
#elif defined (HAVE_NS)
nfds = ns_select
#else
- nfds = select
+ nfds = pselect
#endif
(max (max_process_desc, max_input_desc) + 1,
&Available,
(check_write ? &Writeok : (SELECT_TYPE *)0),
- (SELECT_TYPE *)0, &timeout);
+ NULL, &timeout, NULL);
#ifdef HAVE_GNUTLS
/* GnuTLS buffers data internally. In lowat mode it leaves
/* If we woke up due to SIGWINCH, actually change size now. */
do_pending_window_change (0);
- if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
- /* We wanted the full specified time, so return now. */
+ if ((time_limit || nsecs) && nfds == 0 && ! timeout_reduced_for_timers)
+ /* We waited the full specified time, so return now. */
break;
if (nfds < 0)
{
for (channel = 0; channel <= max_input_desc; ++channel)
{
struct fd_callback_data *d = &fd_callback_info[channel];
- if (FD_ISSET (channel, &Available)
- && d->func != 0
- && (d->condition & FOR_READ) != 0)
- d->func (channel, d->data, 1);
- if (FD_ISSET (channel, &write_mask)
- && d->func != 0
- && (d->condition & FOR_WRITE) != 0)
- d->func (channel, d->data, 0);
- }
+ if (d->func
+ && ((d->condition & FOR_READ
+ && FD_ISSET (channel, &Available))
+ || (d->condition & FOR_WRITE
+ && FD_ISSET (channel, &write_mask))))
+ d->func (channel, d->data);
+ }
for (channel = 0; channel <= max_process_desc; channel++)
{
if (wait_channel == channel)
{
wait_channel = -1;
- time_limit = -1;
+ nsecs = -1;
got_some_input = 1;
}
proc = chan_process[channel];
It can't hurt. */
else if (nread == -1 && errno == EIO)
{
- /* Don't do anything if only a pty, with no associated
- process (bug#10933). */
- if (XPROCESS (proc)->pid != -2) {
- /* Clear the descriptor now, so we only raise the signal
- once. */
- FD_CLR (channel, &input_wait_mask);
- FD_CLR (channel, &non_keyboard_wait_mask);
-
- kill (getpid (), SIGCHLD);
- }
+ struct Lisp_Process *p = XPROCESS (proc);
+
+ /* Clear the descriptor now, so we only raise the
+ signal once. */
+ FD_CLR (channel, &input_wait_mask);
+ FD_CLR (channel, &non_keyboard_wait_mask);
+
+ if (p->pid == -2)
+ {
+ /* If the EIO occurs on a pty, sigchld_handler's
+ waitpid() will not find the process object to
+ delete. Do it here. */
+ p->tick = ++process_tick;
+ pset_status (p, Qfailed);
+ }
+ else
+ kill (getpid (), SIGCHLD);
}
#endif /* HAVE_PTYS */
/* If we can detect process termination, don't consider the
if (XPROCESS (proc)->raw_status_new)
update_status (XPROCESS (proc));
if (EQ (XPROCESS (proc)->status, Qrun))
- XPROCESS (proc)->status
- = Fcons (Qexit, Fcons (make_number (256), Qnil));
+ pset_status (XPROCESS (proc),
+ list2 (Qexit, make_number (256)));
}
}
#ifdef NON_BLOCKING_CONNECT
if (xerrno)
{
p->tick = ++process_tick;
- p->status = Fcons (Qfailed, Fcons (make_number (xerrno), Qnil));
+ pset_status (p, list2 (Qfailed, make_number (xerrno)));
deactivate_process (proc);
}
else
{
- p->status = Qrun;
+ pset_status (p, Qrun);
/* Execute the sentinel here. If we had relied on
status_notify to do it later, it will read input
from the process before calling the sentinel. */
char *chars;
register Lisp_Object outstream;
register struct Lisp_Process *p = XPROCESS (proc);
- register EMACS_INT opoint;
+ register ptrdiff_t opoint;
struct coding_system *coding = proc_decode_coding_system[channel];
int carryover = p->decoding_carryover;
int readmax = 4096;
- int count = SPECPDL_INDEX ();
+ ptrdiff_t count = SPECPDL_INDEX ();
Lisp_Object odeactivate;
- chars = (char *) alloca (carryover + readmax);
+ chars = alloca (carryover + readmax);
if (carryover)
/* See the comment above. */
memcpy (chars, SDATA (p->decoding_buf), carryover);
/* There's no good reason to let process filters change the current
buffer, and many callers of accept-process-output, sit-for, and
friends don't expect current-buffer to be changed from under them. */
- record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
+ record_unwind_current_buffer ();
/* Read and dispose of the process output. */
outstream = p->filter;
/* A new coding system might be found. */
if (!EQ (p->decode_coding_system, Vlast_coding_system_used))
{
- p->decode_coding_system = Vlast_coding_system_used;
+ pset_decode_coding_system (p, Vlast_coding_system_used);
/* Don't call setup_coding_system for
proc_decode_coding_system[channel] here. It is done in
if (NILP (p->encode_coding_system)
&& proc_encode_coding_system[p->outfd])
{
- p->encode_coding_system
- = coding_inherit_eol_type (Vlast_coding_system_used, Qnil);
+ pset_encode_coding_system
+ (p, coding_inherit_eol_type (Vlast_coding_system_used, Qnil));
setup_coding_system (p->encode_coding_system,
proc_encode_coding_system[p->outfd]);
}
if (coding->carryover_bytes > 0)
{
if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
- p->decoding_buf = make_uninit_string (coding->carryover_bytes);
+ pset_decoding_buf (p, make_uninit_string (coding->carryover_bytes));
memcpy (SDATA (p->decoding_buf), coding->carryover,
coding->carryover_bytes);
p->decoding_carryover = coding->carryover_bytes;
else if (!NILP (p->buffer) && !NILP (BVAR (XBUFFER (p->buffer), name)))
{
Lisp_Object old_read_only;
- EMACS_INT old_begv, old_zv;
- EMACS_INT old_begv_byte, old_zv_byte;
- EMACS_INT before, before_byte;
- EMACS_INT opoint_byte;
+ ptrdiff_t old_begv, old_zv;
+ ptrdiff_t old_begv_byte, old_zv_byte;
+ ptrdiff_t before, before_byte;
+ ptrdiff_t opoint_byte;
Lisp_Object text;
struct buffer *b;
old_begv_byte = BEGV_BYTE;
old_zv_byte = ZV_BYTE;
- BVAR (current_buffer, read_only) = Qnil;
+ 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. */
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),
+ SET_PT_BOTH (clip_to_bounds (BEGV,
+ marker_position (p->mark), ZV),
+ clip_to_bounds (BEGV_BYTE,
+ marker_byte_position (p->mark),
ZV_BYTE));
else
SET_PT_BOTH (ZV, ZV_BYTE);
similar code in the previous `if' block. */
if (!EQ (p->decode_coding_system, Vlast_coding_system_used))
{
- p->decode_coding_system = Vlast_coding_system_used;
+ pset_decode_coding_system (p, Vlast_coding_system_used);
if (NILP (p->encode_coding_system)
&& proc_encode_coding_system[p->outfd])
{
- p->encode_coding_system
- = coding_inherit_eol_type (Vlast_coding_system_used, Qnil);
+ pset_encode_coding_system
+ (p, coding_inherit_eol_type (Vlast_coding_system_used, Qnil));
setup_coding_system (p->encode_coding_system,
proc_encode_coding_system[p->outfd]);
}
if (coding->carryover_bytes > 0)
{
if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
- p->decoding_buf = make_uninit_string (coding->carryover_bytes);
+ pset_decoding_buf (p, make_uninit_string (coding->carryover_bytes));
memcpy (SDATA (p->decoding_buf), coding->carryover,
coding->carryover_bytes);
p->decoding_carryover = coding->carryover_bytes;
Fnarrow_to_region (make_number (old_begv), make_number (old_zv));
- BVAR (current_buffer, read_only) = old_read_only;
+ bset_read_only (current_buffer, old_read_only);
SET_PT_BOTH (opoint, opoint_byte);
}
/* Handling the process output should not deactivate the mark. */
static Lisp_Object process_sent_to;
#ifndef FORWARD_SIGNAL_TO_MAIN_THREAD
-static void send_process_trap (int) NO_RETURN;
+static _Noreturn void send_process_trap (int);
#endif
static void
longjmp (send_process_frame, 1);
}
+/* In send_process, when a write fails temporarily,
+ wait_reading_process_output is called. It may execute user code,
+ e.g. timers, that attempts to write new data to the same process.
+ We must ensure that data is sent in the right order, and not
+ interspersed half-completed with other writes (Bug#10815). This is
+ handled by the write_queue element of struct process. It is a list
+ with each entry having the form
+
+ (string . (offset . length))
+
+ where STRING is a lisp string, OFFSET is the offset into the
+ string's byte sequence from which we should begin to send, and
+ LENGTH is the number of bytes left to send. */
+
+/* Create a new entry in write_queue.
+ INPUT_OBJ should be a buffer, string Qt, or Qnil.
+ BUF is a pointer to the string sequence of the input_obj or a C
+ string in case of Qt or Qnil. */
+
+static void
+write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj,
+ const char *buf, ptrdiff_t len, int front)
+{
+ ptrdiff_t offset;
+ Lisp_Object entry, obj;
+
+ if (STRINGP (input_obj))
+ {
+ offset = buf - SSDATA (input_obj);
+ obj = input_obj;
+ }
+ else
+ {
+ offset = 0;
+ obj = make_unibyte_string (buf, len);
+ }
+
+ entry = Fcons (obj, Fcons (make_number (offset), make_number (len)));
+
+ if (front)
+ pset_write_queue (p, Fcons (entry, p->write_queue));
+ else
+ pset_write_queue (p, nconc2 (p->write_queue, Fcons (entry, Qnil)));
+}
+
+/* Remove the first element in the write_queue of process P, put its
+ contents in OBJ, BUF and LEN, and return non-zero. If the
+ write_queue is empty, return zero. */
+
+static int
+write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj,
+ const char **buf, ptrdiff_t *len)
+{
+ Lisp_Object entry, offset_length;
+ ptrdiff_t offset;
+
+ if (NILP (p->write_queue))
+ return 0;
+
+ entry = XCAR (p->write_queue);
+ pset_write_queue (p, XCDR (p->write_queue));
+
+ *obj = XCAR (entry);
+ offset_length = XCDR (entry);
+
+ *len = XINT (XCDR (offset_length));
+ offset = XINT (XCAR (offset_length));
+ *buf = SSDATA (*obj) + offset;
+
+ return 1;
+}
+
/* Send some data to process PROC.
BUF is the beginning of the data; LEN is the number of characters.
OBJECT is the Lisp object that the data comes from. If OBJECT is
static void
send_process (volatile Lisp_Object proc, const char *volatile buf,
- volatile EMACS_INT len, volatile Lisp_Object object)
+ volatile ptrdiff_t len, volatile Lisp_Object object)
{
/* Use volatile to protect variables from being clobbered by longjmp. */
struct Lisp_Process *p = XPROCESS (proc);
ssize_t rv;
struct coding_system *coding;
- struct gcpro gcpro1;
void (*volatile old_sigpipe) (int);
- GCPRO1 (object);
-
if (p->raw_status_new)
update_status (p);
if (! EQ (p->status, Qrun))
&& !NILP (BVAR (XBUFFER (object), enable_multibyte_characters)))
|| EQ (object, Qt))
{
- p->encode_coding_system
- = complement_process_encoding_system (p->encode_coding_system);
+ pset_encode_coding_system
+ (p, complement_process_encoding_system (p->encode_coding_system));
if (!EQ (Vlast_coding_system_used, p->encode_coding_system))
{
/* The coding system for encoding was changed to raw-text
coding->dst_object = Qt;
if (BUFFERP (object))
{
- EMACS_INT from_byte, from, to;
- EMACS_INT save_pt, save_pt_byte;
+ ptrdiff_t from_byte, from, to;
+ ptrdiff_t save_pt, save_pt_byte;
struct buffer *cur = current_buffer;
set_buffer_internal (XBUFFER (object));
if (!setjmp (send_process_frame))
{
p = XPROCESS (proc); /* Repair any setjmp clobbering. */
-
process_sent_to = proc;
- while (len > 0)
+
+ /* If there is already data in the write_queue, put the new data
+ in the back of queue. Otherwise, ignore it. */
+ if (!NILP (p->write_queue))
+ write_queue_push (p, object, buf, len, 0);
+
+ do /* while !NILP (p->write_queue) */
{
- EMACS_INT this = len;
+ ptrdiff_t cur_len = -1;
+ const char *cur_buf;
+ Lisp_Object cur_object;
- /* Send this batch, using one or more write calls. */
- while (this > 0)
+ /* If write_queue is empty, ignore it. */
+ if (!write_queue_pop (p, &cur_object, &cur_buf, &cur_len))
{
- EMACS_INT written = 0;
+ cur_len = len;
+ cur_buf = buf;
+ cur_object = object;
+ }
+
+ while (cur_len > 0)
+ {
+ /* Send this batch, using one or more write calls. */
+ ptrdiff_t written = 0;
int outfd = p->outfd;
old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap);
#ifdef DATAGRAM_SOCKETS
if (DATAGRAM_CHAN_P (outfd))
{
- rv = sendto (outfd, buf, this,
+ rv = sendto (outfd, cur_buf, cur_len,
0, datagram_address[outfd].sa,
datagram_address[outfd].len);
if (0 <= rv)
{
#ifdef HAVE_GNUTLS
if (p->gnutls_p)
- written = emacs_gnutls_write (p, buf, this);
+ written = emacs_gnutls_write (p, cur_buf, cur_len);
else
#endif
- written = emacs_write (outfd, buf, this);
+ written = emacs_write (outfd, cur_buf, cur_len);
rv = (written ? 0 : -1);
#ifdef ADAPTIVE_READ_BUFFERING
if (p->read_output_delay > 0
that may allow the program
to finish doing output and read more. */
{
- EMACS_INT offset = 0;
-
#ifdef BROKEN_PTY_READ_AFTER_EAGAIN
/* A gross hack to work around a bug in FreeBSD.
In the following sequence, read(2) returns
}
#endif /* BROKEN_PTY_READ_AFTER_EAGAIN */
- /* Running filters might relocate buffers or strings.
- Arrange to relocate BUF. */
- if (BUFFERP (object))
- offset = BUF_PTR_BYTE_POS (XBUFFER (object),
- (unsigned char *) buf);
- else if (STRINGP (object))
- offset = buf - SSDATA (object);
-
-#ifdef EMACS_HAS_USECS
- wait_reading_process_output (0, 20000, 0, 0, Qnil, NULL, 0);
-#else
- wait_reading_process_output (1, 0, 0, 0, Qnil, NULL, 0);
-#endif
-
- if (BUFFERP (object))
- buf = (char *) BUF_BYTE_ADDRESS (XBUFFER (object),
- offset);
- else if (STRINGP (object))
- buf = offset + SSDATA (object);
+ /* Put what we should have written in wait_queue. */
+ write_queue_push (p, cur_object, cur_buf, cur_len, 1);
+ wait_reading_process_output (0, 20 * 1000 * 1000,
+ 0, 0, Qnil, NULL, 0);
+ /* Reread queue, to see what is left. */
+ break;
}
else
/* This is a real error. */
report_file_error ("writing to process", Fcons (proc, Qnil));
}
- buf += written;
- len -= written;
- this -= written;
+ cur_buf += written;
+ cur_len -= written;
}
}
+ while (!NILP (p->write_queue));
}
else
{
proc = process_sent_to;
p = XPROCESS (proc);
p->raw_status_new = 0;
- p->status = Fcons (Qexit, Fcons (make_number (256), Qnil));
+ pset_status (p, Fcons (Qexit, Fcons (make_number (256), Qnil)));
p->tick = ++process_tick;
deactivate_process (proc);
error ("SIGPIPE raised on process %s; closed it", SDATA (p->name));
}
-
- UNGCPRO;
}
DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
(Lisp_Object process, Lisp_Object start, Lisp_Object end)
{
Lisp_Object proc;
- EMACS_INT start1, end1;
+ ptrdiff_t start1, end1;
proc = get_process (process);
validate_region (&start, &end);
\f
/* Return the foreground process group for the tty/pty that
the process P uses. */
-static int
+static pid_t
emacs_get_tty_pgrp (struct Lisp_Process *p)
{
- int gid = -1;
+ pid_t gid = -1;
#ifdef TIOCGPGRP
if (ioctl (p->infd, TIOCGPGRP, &gid) == -1 && ! NILP (p->tty_name))
{
/* Initialize in case ioctl doesn't exist or gives an error,
in a way that will cause returning t. */
- int gid;
+ pid_t gid;
Lisp_Object proc;
struct Lisp_Process *p;
{
Lisp_Object proc;
register struct Lisp_Process *p;
- int gid;
+ pid_t gid;
int no_pgrp = 0;
proc = get_process (process);
#ifdef SIGCONT
case SIGCONT:
p->raw_status_new = 0;
- p->status = Qrun;
+ pset_status (p, Qrun);
p->tick = ++process_tick;
if (!nomsg)
{
FD_CLR (p->infd, &input_wait_mask);
FD_CLR (p->infd, &non_keyboard_wait_mask);
}
- p->command = Qt;
+ pset_command (p, Qt);
return process;
}
#ifndef SIGTSTP
tcflush (p->infd, TCIFLUSH);
#endif /* not WINDOWSNT */
}
- p->command = Qnil;
+ pset_command (p, Qnil);
return process;
}
#ifdef SIGCONT
{
pid_t pid;
- if (INTEGERP (process))
- {
- pid = XINT (process);
- goto got_it;
- }
-
- if (FLOATP (process))
- {
- pid = (pid_t) XFLOAT_DATA (process);
- goto got_it;
- }
-
if (STRINGP (process))
{
- Lisp_Object tem;
- if (tem = Fget_process (process), NILP (tem))
+ Lisp_Object tem = Fget_process (process);
+ if (NILP (tem))
{
- pid = XINT (Fstring_to_number (process, make_number (10)));
- if (pid > 0)
- goto got_it;
+ Lisp_Object process_number =
+ string_to_number (SSDATA (process), 10, 1);
+ if (INTEGERP (process_number) || FLOATP (process_number))
+ tem = process_number;
}
process = tem;
}
- else
+ else if (!NUMBERP (process))
process = get_process (process);
if (NILP (process))
return process;
- CHECK_PROCESS (process);
- pid = XPROCESS (process)->pid;
- if (pid <= 0)
- error ("Cannot signal process %s", SDATA (XPROCESS (process)->name));
-
- got_it:
+ if (NUMBERP (process))
+ CONS_TO_INTEGER (process, pid_t, pid);
+ else
+ {
+ CHECK_PROCESS (process);
+ pid = XPROCESS (process)->pid;
+ if (pid <= 0)
+ error ("Cannot signal process %s", SDATA (XPROCESS (process)->name));
+ }
#define parse_signal(NAME, VALUE) \
else if (!xstrcasecmp (name, NAME)) \
XSETINT (sigcode, VALUE)
if (INTEGERP (sigcode))
- ;
+ CHECK_TYPE_RANGED_INTEGER (int, sigcode);
else
{
char *name;
if (!proc_encode_coding_system[new_outfd])
proc_encode_coding_system[new_outfd]
- = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+ = xmalloc (sizeof (struct coding_system));
memcpy (proc_encode_coding_system[new_outfd],
proc_encode_coding_system[old_outfd],
sizeof (struct coding_system));
do
{
errno = 0;
- pid = wait3 (&w, WNOHANG | WUNTRACED, 0);
+ pid = waitpid (-1, &w, WNOHANG | WUNTRACED);
}
while (pid < 0 && errno == EINTR);
for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail))
{
Lisp_Object xpid = XCAR (tail);
- if ((INTEGERP (xpid) && pid == (pid_t) XINT (xpid))
- || (FLOATP (xpid) && pid == (pid_t) XFLOAT_DATA (xpid)))
+ if ((INTEGERP (xpid) && pid == XINT (xpid))
+ || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid)))
{
XSETCAR (tail, Qnil);
goto sigchld_end_of_loop;
/* Tell wait_reading_process_output that it needs to wake up and
look around. */
if (input_available_clear_time)
- EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
+ *input_available_clear_time = make_emacs_time (0, 0);
}
/* There was no asynchronous process found for that pid: we have
/* Report the status of the synchronous process. */
if (WIFEXITED (w))
- synch_process_retcode = WRETCODE (w);
+ synch_process_retcode = WEXITSTATUS (w);
else if (WIFSIGNALED (w))
synch_process_termsig = WTERMSIG (w);
/* Tell wait_reading_process_output that it needs to wake up and
look around. */
if (input_available_clear_time)
- EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
+ *input_available_clear_time = make_emacs_time (0, 0);
}
sigchld_end_of_loop:
static Lisp_Object
exec_sentinel_unwind (Lisp_Object data)
{
- XPROCESS (XCAR (data))->sentinel = XCDR (data);
+ pset_sentinel (XPROCESS (XCAR (data)), XCDR (data));
return Qnil;
}
{
Lisp_Object sentinel, odeactivate;
register struct Lisp_Process *p = XPROCESS (proc);
- int count = SPECPDL_INDEX ();
+ ptrdiff_t count = SPECPDL_INDEX ();
int outer_running_asynch_code = running_asynch_code;
int waiting = waiting_for_user_input_p;
/* There's no good reason to let sentinels change the current
buffer, and many callers of accept-process-output, sit-for, and
friends don't expect current-buffer to be changed from under them. */
- record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
+ record_unwind_current_buffer ();
sentinel = p->sentinel;
if (NILP (sentinel))
/* Zilch the sentinel while it's running, to avoid recursive invocations;
assure that it gets restored no matter how the sentinel exits. */
- p->sentinel = Qnil;
+ pset_sentinel (p, Qnil);
record_unwind_protect (exec_sentinel_unwind, Fcons (proc, sentinel));
/* Inhibit quit so that random quits don't screw up a running filter. */
specbind (Qinhibit_quit, Qt);
{
Lisp_Object tem;
struct buffer *old = current_buffer;
- EMACS_INT opoint, opoint_byte;
- EMACS_INT before, before_byte;
+ ptrdiff_t opoint, opoint_byte;
+ ptrdiff_t before, before_byte;
/* Avoid error if buffer is deleted
(probably that's why the process is dead, too) */
before_byte = PT_BYTE;
tem = BVAR (current_buffer, read_only);
- BVAR (current_buffer, read_only) = Qnil;
+ bset_read_only (current_buffer, Qnil);
insert_string ("\nProcess ");
- Finsert (1, &p->name);
+ { /* FIXME: temporary kludge */
+ Lisp_Object tem2 = p->name; Finsert (1, &tem2); }
insert_string (" ");
Finsert (1, &msg);
- BVAR (current_buffer, read_only) = tem;
+ bset_read_only (current_buffer, tem);
set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
if (opoint >= before)
Fcheck_coding_system (decoding);
Fcheck_coding_system (encoding);
encoding = coding_inherit_eol_type (encoding, Qnil);
- p->decode_coding_system = decoding;
- p->encode_coding_system = encoding;
+ pset_decode_coding_system (p, decoding);
+ pset_encode_coding_system (p, encoding);
setup_process_coding_systems (process);
return Qnil;
CHECK_PROCESS (process);
p = XPROCESS (process);
if (NILP (flag))
- p->decode_coding_system = raw_text_coding_system (p->decode_coding_system);
+ pset_decode_coding_system
+ (p, raw_text_coding_system (p->decode_coding_system));
setup_process_coding_systems (process);
return Qnil;
/* Defined on msdos.c. */
extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
- EMACS_TIME *);
+ EMACS_TIME *, void *);
/* Implementation of wait_reading_process_output, assuming that there
are no subprocesses. Used only by the MS-DOS build.
Wait for timeout to elapse and/or keyboard input to be available.
- time_limit is:
- timeout in seconds, or
- zero for no limit, or
- -1 means gobble data immediately available but don't wait for any.
+ TIME_LIMIT is:
+ timeout in seconds
+ If negative, gobble data immediately available but don't wait for any.
+
+ NSECS is:
+ an additional duration to wait, measured in nanoseconds
+ If TIME_LIMIT is zero, then:
+ If NSECS == 0, there is no limit.
+ If NSECS > 0, the timeout consists of NSECS only.
+ If NSECS < 0, gobble data immediately, as if TIME_LIMIT were negative.
- read_kbd is a Lisp_Object:
+ READ_KBD is:
0 to ignore keyboard input, or
1 to return when input is available, or
-1 means caller will actually read the input, so don't throw to
see full version for other parameters. We know that wait_proc will
always be NULL, since `subprocesses' isn't defined.
- do_display != 0 means redisplay should be done to show subprocess
+ DO_DISPLAY != 0 means redisplay should be done to show subprocess
output that arrives.
Return true if we received input from any process. */
int
-wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
int do_display,
Lisp_Object wait_for_cell,
struct Lisp_Process *wait_proc, int just_wait_proc)
{
register int nfds;
EMACS_TIME end_time, timeout;
- SELECT_TYPE waitchannels;
- int xerrno;
+
+ if (time_limit < 0)
+ {
+ time_limit = 0;
+ nsecs = -1;
+ }
+ else if (TYPE_MAXIMUM (time_t) < time_limit)
+ time_limit = TYPE_MAXIMUM (time_t);
/* What does time_limit really mean? */
- if (time_limit || microsecs)
+ if (time_limit || 0 < nsecs)
{
- EMACS_GET_TIME (end_time);
- EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
- EMACS_ADD_TIME (end_time, end_time, timeout);
+ timeout = make_emacs_time (time_limit, nsecs);
+ end_time = add_emacs_time (current_emacs_time (), timeout);
}
/* Turn off periodic alarms (in case they are in use)
while (1)
{
int timeout_reduced_for_timers = 0;
+ SELECT_TYPE waitchannels;
+ int xerrno;
/* If calling from keyboard input, do not quit
since we want to return C-g as an input character.
/* Compute time from now till when time limit is up */
/* Exit if already run out */
- if (time_limit == -1)
+ if (nsecs < 0)
{
- /* -1 specified for timeout means
+ /* A negative timeout means
gobble output available now
but don't wait at all. */
- EMACS_SET_SECS_USECS (timeout, 0, 0);
+ timeout = make_emacs_time (0, 0);
}
- else if (time_limit || microsecs)
+ else if (time_limit || 0 < nsecs)
{
- EMACS_GET_TIME (timeout);
- EMACS_SUB_TIME (timeout, end_time, timeout);
- if (EMACS_TIME_NEG_P (timeout))
+ EMACS_TIME now = current_emacs_time ();
+ if (EMACS_TIME_LE (end_time, now))
break;
+ timeout = sub_emacs_time (end_time, now);
}
else
{
- EMACS_SET_SECS_USECS (timeout, 100000, 0);
+ timeout = make_emacs_time (100000, 0);
}
/* If our caller will not immediately handle keyboard events,
&& requeued_events_pending_p ())
break;
- if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
+ if (EMACS_TIME_VALID_P (timer_delay) && 0 <= nsecs)
{
- EMACS_TIME difference;
- EMACS_SUB_TIME (difference, timer_delay, timeout);
- if (EMACS_TIME_NEG_P (difference))
+ if (EMACS_TIME_LT (timer_delay, timeout))
{
timeout = timer_delay;
timeout_reduced_for_timers = 1;
if (read_kbd < 0)
set_waiting_for_input (&timeout);
- /* Wait till there is something to do. */
-
- if (! read_kbd && NILP (wait_for_cell))
- FD_ZERO (&waitchannels);
- else
- FD_SET (0, &waitchannels);
-
/* If a frame has been newly mapped and needs updating,
reprocess its display stuff. */
if (frame_garbaged && do_display)
set_waiting_for_input (&timeout);
}
+ /* Wait till there is something to do. */
+ FD_ZERO (&waitchannels);
if (read_kbd && detect_input_pending ())
+ nfds = 0;
+ else
{
- nfds = 0;
- FD_ZERO (&waitchannels);
+ if (read_kbd || !NILP (wait_for_cell))
+ FD_SET (0, &waitchannels);
+ nfds = pselect (1, &waitchannels, NULL, NULL, &timeout, NULL);
}
- else
- nfds = select (1, &waitchannels, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
- &timeout);
xerrno = errno;
/* If we woke up due to SIGWINCH, actually change size now. */
do_pending_window_change (0);
- if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
+ if ((time_limit || nsecs) && nfds == 0 && ! timeout_reduced_for_timers)
/* We waited the full specified time, so return now. */
break;
return;
if (!proc_decode_coding_system[inch])
- proc_decode_coding_system[inch]
- = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+ proc_decode_coding_system[inch] = xmalloc (sizeof (struct coding_system));
coding_system = p->decode_coding_system;
if (! NILP (p->filter))
;
setup_coding_system (coding_system, proc_decode_coding_system[inch]);
if (!proc_encode_coding_system[outch])
- proc_encode_coding_system[outch]
- = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+ proc_encode_coding_system[outch] = xmalloc (sizeof (struct coding_system));
setup_coding_system (p->encode_coding_system,
proc_encode_coding_system[outch]);
#endif
majflt -- number of major page faults (number)
cminflt -- cumulative number of minor page faults (number)
cmajflt -- cumulative number of major page faults (number)
- utime -- user time used by the process, in the (HIGH LOW USEC) format
- stime -- system time used by the process, in the (HIGH LOW USEC) format
- time -- sum of utime and stime, in the (HIGH LOW USEC) format
- cutime -- user time used by the process and its children, (HIGH LOW USEC)
- cstime -- system time used by the process and its children, (HIGH LOW USEC)
- ctime -- sum of cutime and cstime, in the (HIGH LOW USEC) format
+ utime -- user time used by the process, in (current-time) format,
+ which is a list of integers (HIGH LOW USEC PSEC)
+ stime -- system time used by the process (current-time)
+ time -- sum of utime and stime (current-time)
+ cutime -- user time used by the process and its children (current-time)
+ cstime -- system time used by the process and its children (current-time)
+ ctime -- sum of cutime and cstime (current-time)
pri -- priority of the process (number)
nice -- nice value of the process (number)
thcount -- process thread count (number)
- start -- time the process started, in the (HIGH LOW USEC) format
+ start -- time the process started (current-time)
vsize -- virtual memory size of the process in KB's (number)
rss -- resident set size of the process in KB's (number)
- etime -- elapsed time the process is running, in (HIGH LOW USEC) format
+ etime -- elapsed time the process is running, in (HIGH LOW USEC PSEC) format
pcpu -- percents of CPU time used by the process (floating-point number)
pmem -- percents of total physical memory used by process's resident set
(floating-point number)
}
\f
+/* This is not called "init_process" because that is the name of a
+ Mach system call, so it would cause problems on Darwin systems. */
void
-init_process (void)
+init_process_emacs (void)
{
#ifdef subprocesses
register int i;
char const *release = (STRINGP (Voperating_system_release)
? SSDATA (Voperating_system_release)
: 0);
- if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
- && release[1] == '.')) {
+ if (!release || !release[0] || (release[0] < '7' && release[1] == '.')) {
Vprocess_connection_type = Qnil;
}
}