#include <config.h>
-#include <signal.h>
+
+#define PROCESS_INLINE EXTERN_INLINE
+
#include <stdio.h>
#include <errno.h>
-#include <setjmp.h>
#include <sys/types.h> /* Some typedefs are used in sys/file.h. */
#include <sys/file.h>
#include <sys/stat.h>
-#include <setjmp.h>
-
#include <unistd.h>
#include <fcntl.h>
#include <bsdtty.h>
#endif
+#ifdef USG5_4
+# include <sys/stream.h>
+# include <sys/stropts.h>
+#endif
+
#ifdef HAVE_RES_INIT
#include <netinet/in.h>
#include <arpa/nameser.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"
+
+#ifdef WINDOWSNT
+extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
+ EMACS_TIME *, void *);
+#endif
+
+#ifndef WNOHANG
+# undef waitpid
+# define waitpid(pid, status, options) wait (status)
+#endif
+#ifndef WUNTRACED
+# define WUNTRACED 0
#endif
/* Work around GCC 4.7.0 bug with strict overflow checking; see
static Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
static Lisp_Object QCsentinel, QClog, QCoptions, QCplist;
static Lisp_Object Qlast_nonmenu_event;
-/* QCfamily is declared and initialized in xfaces.c,
- QCfilter in keyboard.c. */
-extern Lisp_Object QCfamily, QCfilter;
-
-/* Qexit is declared and initialized in eval.c. */
-/* QCfamily is defined in xfaces.c. */
-extern Lisp_Object QCfamily;
-/* QCfilter is defined in keyboard.c. */
-extern Lisp_Object QCfilter;
-
-#define NETCONN_P(p) (EQ (PGET (XPROCESS (p), type), Qnetwork))
-#define NETCONN1_P(p) (EQ (PGET (p, type), Qnetwork))
-#define SERIALCONN_P(p) (EQ (PGET (XPROCESS (p), type), Qserial))
-#define SERIALCONN1_P(p) (EQ (PGET (p, type), Qserial))
+#define NETCONN_P(p) (EQ (XPROCESS (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))
#ifndef HAVE_H_ERRNO
extern int h_errno;
#ifndef NON_BLOCKING_CONNECT
#ifdef HAVE_SELECT
#if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX)
-#if defined (O_NONBLOCK) || defined (O_NDELAY)
+#if O_NONBLOCK || O_NDELAY
#if defined (EWOULDBLOCK) || defined (EINPROGRESS)
#define NON_BLOCKING_CONNECT
#endif /* EWOULDBLOCK || EINPROGRESS */
"non-destructive" select. So we require either native select,
or emulation of select using FIONREAD. */
-#ifdef BROKEN_DATAGRAM_SOCKETS
-#undef DATAGRAM_SOCKETS
-#else
-#ifndef DATAGRAM_SOCKETS
-#if defined (HAVE_SELECT) || defined (FIONREAD)
-#if defined (HAVE_SENDTO) && defined (HAVE_RECVFROM) && defined (EMSGSIZE)
-#define DATAGRAM_SOCKETS
-#endif /* HAVE_SENDTO && HAVE_RECVFROM && EMSGSIZE */
-#endif /* HAVE_SELECT || FIONREAD */
-#endif /* DATAGRAM_SOCKETS */
-#endif /* BROKEN_DATAGRAM_SOCKETS */
+#ifndef BROKEN_DATAGRAM_SOCKETS
+# if defined HAVE_SELECT || defined USABLE_FIONREAD
+# if defined HAVE_SENDTO && defined HAVE_RECVFROM && defined EMSGSIZE
+# define DATAGRAM_SOCKETS
+# endif
+# endif
+#endif
#if defined HAVE_LOCAL_SOCKETS && defined DATAGRAM_SOCKETS
# define HAVE_SEQPACKET
#endif
static void create_process (Lisp_Object, char **, Lisp_Object);
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
static int keyboard_bit_set (SELECT_TYPE *);
#endif
static void deactivate_process (Lisp_Object);
static void status_notify (struct Lisp_Process *);
static int read_process_output (Lisp_Object, int);
+static void handle_child_signal (int);
static void create_pty (Lisp_Object);
/* If we support a window system, turn on the code to poll periodically
to detect C-g. It isn't actually used when doing interrupt input. */
-#if defined (HAVE_WINDOW_SYSTEM) && !defined (USE_ASYNC_EVENTS)
+#ifdef HAVE_WINDOW_SYSTEM
#define POLL_FOR_INPUT
#endif
/* 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 void
+pset_buffer (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->buffer = val;
+}
+static void
+pset_command (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->command = val;
+}
+static void
+pset_decode_coding_system (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->decode_coding_system = val;
+}
+static void
+pset_decoding_buf (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->decoding_buf = val;
+}
+static void
+pset_encode_coding_system (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->encode_coding_system = val;
+}
+static void
+pset_encoding_buf (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->encoding_buf = val;
+}
+static void
+pset_filter (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->filter = val;
+}
+static void
+pset_log (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->log = val;
+}
+static void
+pset_mark (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->mark = val;
+}
+static void
+pset_name (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->name = val;
+}
+static void
+pset_plist (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->plist = val;
+}
+static void
+pset_sentinel (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->sentinel = val;
+}
+static void
+pset_status (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->status = val;
+}
+static void
+pset_tty_name (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->tty_name = val;
+}
+static void
+pset_type (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->type = val;
+}
+static void
+pset_write_queue (struct Lisp_Process *p, Lisp_Object val)
+{
+ p->write_queue = val;
+}
+
\f
static struct fd_callback_data
update_status (struct Lisp_Process *p)
{
eassert (p->raw_status_new);
- PSET (p, status, status_convert (p->raw_status));
+ pset_status (p, status_convert (p->raw_status));
p->raw_status_new = 0;
}
static Lisp_Object
status_message (struct Lisp_Process *p)
{
- Lisp_Object status = PGET (p, status);
+ Lisp_Object status = p->status;
Lisp_Object symbol;
int code, coredump;
Lisp_Object string, string2;
if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
{
- char *signame;
+ char const *signame;
synchronize_system_messages_locale ();
signame = strsignal (code);
if (signame == 0)
PTY_OPEN;
#else /* no PTY_OPEN */
{
- { /* Some systems name their pseudoterminals so that there are gaps in
- the usual sequence - for example, on HP9000/S700 systems, there
- are no pseudoterminals with names ending in 'f'. So we wait for
- three failures in a row before deciding that we've reached the
- end of the ptys. */
- int failed_count = 0;
- struct stat stb;
-
- if (stat (pty_name, &stb) < 0)
- {
- failed_count++;
- if (failed_count >= 3)
- return -1;
- }
- else
- failed_count = 0;
- }
-# ifdef O_NONBLOCK
+# if O_NONBLOCK
fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
# else
fd = emacs_open (pty_name, O_RDWR | O_NDELAY, 0);
#else
sprintf (pty_name, "/dev/tty%c%x", c, i);
#endif /* no PTY_TTY_NAME_SPRINTF */
- if (access (pty_name, 6) != 0)
+ if (faccessat (AT_FDCWD, pty_name, R_OK | W_OK, AT_EACCESS) != 0)
{
emacs_close (fd);
# ifndef __sgi
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 (p, status, Qrun);
- PSET (p, mark, Fmake_marker ());
+ 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. */
name1 = concat2 (name, make_formatted_string (suffix, "<%"pMd">", i));
}
name = name1;
- PSET (p, name, name);
+ pset_name (p, name);
XSETPROCESS (val, p);
Vprocess_alist = Fcons (Fcons (name, val), Vprocess_alist);
return val;
#ifdef SIGCHLD
/* Fdelete_process promises to immediately forget about the process, but in
reality, Emacs needs to remember those processes until they have been
- treated by sigchld_handler; otherwise this handler would consider the
+ treated by the SIGCHLD handler; otherwise this handler would consider the
process as being synchronous and say that the synchronous process is
dead. */
static Lisp_Object deleted_pid_list;
p->raw_status_new = 0;
if (NETCONN1_P (p) || SERIALCONN1_P (p))
{
- PSET (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);
/* If the process has already signaled, remove it from the list. */
if (p->raw_status_new)
update_status (p);
- symbol = PGET (p, status);
- if (CONSP (PGET (p, status)))
- symbol = XCAR (PGET (p, status));
+ symbol = p->status;
+ if (CONSP (p->status))
+ symbol = XCAR (p->status);
if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
deleted_pid_list
= Fdelete (make_fixnum_or_float (pid), deleted_pid_list);
#endif
{
Fkill_process (process, Qnil);
- /* Do this now, since remove_process will make sigchld_handler do nothing. */
- PSET (p, status, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil)));
+ /* Do this now, since remove_process will make the
+ SIGCHLD handler do nothing. */
+ pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil)));
p->tick = ++process_tick;
status_notify (p);
redisplay_preserve_echo_area (13);
p = XPROCESS (process);
if (p->raw_status_new)
update_status (p);
- status = PGET (p, status);
+ status = p->status;
if (CONSP (status))
status = XCAR (status);
if (NETCONN1_P (p) || SERIALCONN1_P (p))
{
if (EQ (status, Qexit))
status = Qclosed;
- else if (EQ (PGET (p, command), Qt))
+ else if (EQ (p->command, Qt))
status = Qstop;
else if (EQ (status, Qrun))
status = Qopen;
CHECK_PROCESS (process);
if (XPROCESS (process)->raw_status_new)
update_status (XPROCESS (process));
- if (CONSP (PGET (XPROCESS (process), status)))
- return XCAR (XCDR (PGET (XPROCESS (process), status)));
+ if (CONSP (XPROCESS (process)->status))
+ return XCAR (XCDR (XPROCESS (process)->status));
return make_number (0);
}
(register Lisp_Object process)
{
CHECK_PROCESS (process);
- return PGET (XPROCESS (process), name);
+ return XPROCESS (process)->name;
}
DEFUN ("process-command", Fprocess_command, Sprocess_command, 1, 1, 0,
(register Lisp_Object process)
{
CHECK_PROCESS (process);
- return PGET (XPROCESS (process), command);
+ return XPROCESS (process)->command;
}
DEFUN ("process-tty-name", Fprocess_tty_name, Sprocess_tty_name, 1, 1, 0,
(register Lisp_Object process)
{
CHECK_PROCESS (process);
- return PGET (XPROCESS (process), tty_name);
+ return XPROCESS (process)->tty_name;
}
DEFUN ("set-process-buffer", Fset_process_buffer, Sset_process_buffer,
if (!NILP (buffer))
CHECK_BUFFER (buffer);
p = XPROCESS (process);
- PSET (p, buffer, buffer);
+ pset_buffer (p, buffer);
if (NETCONN1_P (p) || SERIALCONN1_P (p))
- PSET (p, childp, Fplist_put (PGET (p, childp), QCbuffer, buffer));
+ pset_childp (p, Fplist_put (p->childp, QCbuffer, buffer));
setup_process_coding_systems (process);
return buffer;
}
(register Lisp_Object process)
{
CHECK_PROCESS (process);
- return PGET (XPROCESS (process), buffer);
+ return XPROCESS (process)->buffer;
}
DEFUN ("process-mark", Fprocess_mark, Sprocess_mark,
(register Lisp_Object process)
{
CHECK_PROCESS (process);
- return PGET (XPROCESS (process), mark);
+ return XPROCESS (process)->mark;
}
DEFUN ("set-process-filter", Fset_process_filter, Sset_process_filter,
if (p->infd >= 0)
{
- if (EQ (filter, Qt) && !EQ (PGET (p, status), Qlisten))
+ if (EQ (filter, Qt) && !EQ (p->status, Qlisten))
{
FD_CLR (p->infd, &input_wait_mask);
FD_CLR (p->infd, &non_keyboard_wait_mask);
}
- else if (EQ (PGET (p, filter), Qt)
+ else if (EQ (p->filter, Qt)
/* Network or serial process not stopped: */
- && !EQ (PGET (p, command), Qt))
+ && !EQ (p->command, Qt))
{
FD_SET (p->infd, &input_wait_mask);
FD_SET (p->infd, &non_keyboard_wait_mask);
}
}
- PSET (p, filter, filter);
+ pset_filter (p, filter);
if (NETCONN1_P (p) || SERIALCONN1_P (p))
- PSET (p, childp, Fplist_put (PGET (p, childp), QCfilter, filter));
+ pset_childp (p, Fplist_put (p->childp, QCfilter, filter));
setup_process_coding_systems (process);
return filter;
}
(register Lisp_Object process)
{
CHECK_PROCESS (process);
- return PGET (XPROCESS (process), filter);
+ return XPROCESS (process)->filter;
}
DEFUN ("set-process-sentinel", Fset_process_sentinel, Sset_process_sentinel,
CHECK_PROCESS (process);
p = XPROCESS (process);
- PSET (p, sentinel, sentinel);
+ pset_sentinel (p, sentinel);
if (NETCONN1_P (p) || SERIALCONN1_P (p))
- PSET (p, childp, Fplist_put (PGET (p, childp), QCsentinel, sentinel));
+ pset_childp (p, Fplist_put (p->childp, QCsentinel, sentinel));
return sentinel;
}
(register Lisp_Object process)
{
CHECK_PROCESS (process);
- return PGET (XPROCESS (process), sentinel);
+ return XPROCESS (process)->sentinel;
}
DEFUN ("set-process-window-size", Fset_process_window_size,
Lisp_Object contact;
CHECK_PROCESS (process);
- contact = PGET (XPROCESS (process), childp);
+ contact = XPROCESS (process)->childp;
#ifdef DATAGRAM_SOCKETS
if (DATAGRAM_CONN_P (process)
(register Lisp_Object process)
{
CHECK_PROCESS (process);
- return PGET (XPROCESS (process), plist);
+ return XPROCESS (process)->plist;
}
DEFUN ("set-process-plist", Fset_process_plist, Sset_process_plist,
CHECK_PROCESS (process);
CHECK_LIST (plist);
- PSET (XPROCESS (process), plist, plist);
+ pset_plist (XPROCESS (process), plist);
return plist;
}
a socket connection. */)
(Lisp_Object process)
{
- return PGET (XPROCESS (process), type);
+ return XPROCESS (process)->type;
}
#endif
{
Lisp_Object proc;
proc = get_process (process);
- return PGET (XPROCESS (proc), type);
+ return XPROCESS (proc)->type;
}
DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address,
itself; it's all taken care of here. */
record_unwind_protect (start_process_unwind, proc);
- PSET (XPROCESS (proc), childp, Qt);
- PSET (XPROCESS (proc), plist, Qnil);
- PSET (XPROCESS (proc), type, Qreal);
- PSET (XPROCESS (proc), buffer, buffer);
- PSET (XPROCESS (proc), sentinel, Qnil);
- PSET (XPROCESS (proc), filter, Qnil);
- PSET (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;
- PSET (XPROCESS (proc), gnutls_cred_type, Qnil);
+ pset_gnutls_cred_type (XPROCESS (proc), Qnil);
#endif
#ifdef ADAPTIVE_READ_BUFFERING
/* Make the process marker point into the process buffer (if any). */
if (BUFFERP (buffer))
- set_marker_both (PGET (XPROCESS (proc), mark), buffer,
+ set_marker_both (XPROCESS (proc)->mark, buffer,
BUF_ZV (XBUFFER (buffer)),
BUF_ZV_BYTE (XBUFFER (buffer)));
else if (CONSP (Vdefault_process_coding_system))
val = XCAR (Vdefault_process_coding_system);
}
- PSET (XPROCESS (proc), decode_coding_system, val);
+ pset_decode_coding_system (XPROCESS (proc), val);
val = Vcoding_system_for_write;
if (NILP (val))
else if (CONSP (Vdefault_process_coding_system))
val = XCDR (Vdefault_process_coding_system);
}
- PSET (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
}
- PSET (XPROCESS (proc), decoding_buf, empty_unibyte_string);
+ pset_decoding_buf (XPROCESS (proc), empty_unibyte_string);
XPROCESS (proc)->decoding_carryover = 0;
- PSET (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);
{
if (NILP (arg_encoding))
arg_encoding = (complement_process_encoding_system
- (PGET (XPROCESS (proc), encode_coding_system)));
+ (XPROCESS (proc)->encode_coding_system));
XSETCAR (tem,
code_convert_string_norecord
(XCAR (tem), arg_encoding, 1));
start_process_unwind (Lisp_Object proc)
{
if (!PROCESSP (proc))
- abort ();
+ emacs_abort ();
/* Was PROC started successfully?
-2 is used for a pty with no process, eg for gdb. */
#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
int wait_child_setup[2];
#endif
- sigset_t procmask;
+#ifdef SIGCHLD
sigset_t blocked;
- struct sigaction sigint_action;
- struct sigaction sigquit_action;
- struct sigaction sigpipe_action;
-#ifdef AIX
- struct sigaction sighup_action;
#endif
- /* Use volatile to protect variables from being clobbered by longjmp. */
+ /* Use volatile to protect variables from being clobbered by vfork. */
volatile int forkin, forkout;
volatile int pty_flag = 0;
-#ifndef USE_CRT_DLL
- extern char **environ;
+ volatile Lisp_Object lisp_pty_name = Qnil;
+ volatile Lisp_Object encoded_current_dir;
+#if HAVE_WORKING_VFORK
+ char **volatile save_environ;
#endif
inchannel = outchannel = -1;
#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. */
-#ifdef O_NOCTTY
+#if O_NOCTTY
/* Don't let this terminal become our controlling terminal
(in case we don't have one). */
forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
forkin = forkout = -1;
#endif /* not USG, or USG_SUBTTY_WORKS */
pty_flag = 1;
+ lisp_pty_name = build_string (pty_name);
}
else
#endif /* HAVE_PTYS */
}
#endif
-#ifdef O_NONBLOCK
+#if O_NONBLOCK
fcntl (inchannel, F_SETFL, O_NONBLOCK);
fcntl (outchannel, F_SETFL, O_NONBLOCK);
#else
-#ifdef O_NDELAY
+#if O_NDELAY
fcntl (inchannel, F_SETFL, O_NDELAY);
fcntl (outchannel, F_SETFL, O_NDELAY);
#endif
more portable (see USG_SUBTTY_WORKS above). */
XPROCESS (process)->pty_flag = pty_flag;
- PSET (XPROCESS (process), status, Qrun);
-
- /* Delay interrupts until we have a chance to store
- the new fork's pid in its process structure */
- sigemptyset (&blocked);
-#ifdef SIGCHLD
- sigaddset (&blocked, SIGCHLD);
-#endif
-#ifdef HAVE_WORKING_VFORK
- /* On many hosts (e.g. Solaris 2.4), if a vforked child calls `signal',
- this sets the parent's signal handlers as well as the child's.
- So delay all interrupts whose handlers the child might munge,
- and record the current handlers so they can be restored later. */
- sigaddset (&blocked, SIGINT ); sigaction (SIGINT , 0, &sigint_action );
- sigaddset (&blocked, SIGQUIT); sigaction (SIGQUIT, 0, &sigquit_action);
- sigaddset (&blocked, SIGPIPE); sigaction (SIGPIPE, 0, &sigpipe_action);
-#ifdef AIX
- sigaddset (&blocked, SIGHUP ); sigaction (SIGHUP , 0, &sighup_action );
-#endif
-#endif /* HAVE_WORKING_VFORK */
- pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
+ pset_status (XPROCESS (process), Qrun);
FD_SET (inchannel, &input_wait_mask);
FD_SET (inchannel, &non_keyboard_wait_mask);
if (inchannel > max_process_desc)
max_process_desc = inchannel;
- /* Until we store the proper pid, enable sigchld_handler
+ /* Until we store the proper pid, enable the SIGCHLD handler
to recognize an unknown pid as standing for this process.
It is very important not to let this `marker' value stay
in the table after this function has returned; if it does
error. */
setup_process_coding_systems (process);
- BLOCK_INPUT;
+ encoded_current_dir = ENCODE_FILE (current_dir);
- {
- /* child_setup must clobber environ on systems with true vfork.
- Protect it from permanent change. */
- char **save_environ = environ;
- volatile Lisp_Object encoded_current_dir = ENCODE_FILE (current_dir);
+ block_input ();
-#ifndef WINDOWSNT
- pid = vfork ();
- if (pid == 0)
-#endif /* not WINDOWSNT */
- {
- int xforkin = forkin;
- int xforkout = forkout;
+#ifdef SIGCHLD
+ /* Block SIGCHLD until we have a chance to store the new fork's
+ pid in its process structure. */
+ sigemptyset (&blocked);
+ sigaddset (&blocked, SIGCHLD);
+ pthread_sigmask (SIG_BLOCK, &blocked, 0);
+#endif
-#if 0 /* This was probably a mistake--it duplicates code later on,
- but fails to handle all the cases. */
- /* Make sure SIGCHLD is not blocked in the child. */
- sigsetmask (SIGEMPTYMASK);
+#if HAVE_WORKING_VFORK
+ /* child_setup must clobber environ on systems with true vfork.
+ Protect it from permanent change. */
+ save_environ = environ;
#endif
- /* Make the pty be the controlling terminal of the process. */
+#ifndef WINDOWSNT
+ pid = vfork ();
+ if (pid == 0)
+#endif /* not WINDOWSNT */
+ {
+ int xforkin = forkin;
+ int xforkout = forkout;
+
+ /* Make the pty be the controlling terminal of the process. */
#ifdef HAVE_PTYS
- /* First, disconnect its current controlling terminal. */
+ /* First, disconnect its current controlling terminal. */
#ifdef HAVE_SETSID
- /* We tried doing setsid only if pty_flag, but it caused
- process_set_signal to fail on SGI when using a pipe. */
- setsid ();
- /* Make the pty's terminal the controlling terminal. */
- if (pty_flag && xforkin >= 0)
- {
+ /* We tried doing setsid only if pty_flag, but it caused
+ process_set_signal to fail on SGI when using a pipe. */
+ setsid ();
+ /* Make the pty's terminal the controlling terminal. */
+ if (pty_flag && xforkin >= 0)
+ {
#ifdef TIOCSCTTY
- /* We ignore the return value
- because faith@cs.unc.edu says that is necessary on Linux. */
- ioctl (xforkin, TIOCSCTTY, 0);
+ /* We ignore the return value
+ because faith@cs.unc.edu says that is necessary on Linux. */
+ ioctl (xforkin, TIOCSCTTY, 0);
#endif
- }
+ }
#else /* not HAVE_SETSID */
#ifdef USG
- /* It's very important to call setpgrp here and no time
- afterwards. Otherwise, we lose our controlling tty which
- is set when we open the pty. */
- setpgrp ();
+ /* It's very important to call setpgrp here and no time
+ afterwards. Otherwise, we lose our controlling tty which
+ is set when we open the pty. */
+ setpgrp ();
#endif /* USG */
#endif /* not HAVE_SETSID */
#if defined (LDISC1)
- if (pty_flag && xforkin >= 0)
- {
- struct termios t;
- tcgetattr (xforkin, &t);
- t.c_lflag = LDISC1;
- if (tcsetattr (xforkin, TCSANOW, &t) < 0)
- emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
- }
+ if (pty_flag && xforkin >= 0)
+ {
+ struct termios t;
+ tcgetattr (xforkin, &t);
+ t.c_lflag = LDISC1;
+ if (tcsetattr (xforkin, TCSANOW, &t) < 0)
+ emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
+ }
#else
#if defined (NTTYDISC) && defined (TIOCSETD)
- if (pty_flag && xforkin >= 0)
- {
- /* Use new line discipline. */
- int ldisc = NTTYDISC;
- ioctl (xforkin, TIOCSETD, &ldisc);
- }
+ if (pty_flag && xforkin >= 0)
+ {
+ /* Use new line discipline. */
+ int ldisc = NTTYDISC;
+ ioctl (xforkin, TIOCSETD, &ldisc);
+ }
#endif
#endif
#ifdef TIOCNOTTY
- /* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
- can do TIOCSPGRP only to the process's controlling tty. */
- if (pty_flag)
- {
- /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here?
- I can't test it since I don't have 4.3. */
- int j = emacs_open ("/dev/tty", O_RDWR, 0);
- if (j >= 0)
- {
- ioctl (j, TIOCNOTTY, 0);
- emacs_close (j);
- }
+ /* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
+ can do TIOCSPGRP only to the process's controlling tty. */
+ if (pty_flag)
+ {
+ /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here?
+ I can't test it since I don't have 4.3. */
+ int j = emacs_open ("/dev/tty", O_RDWR, 0);
+ if (j >= 0)
+ {
+ ioctl (j, TIOCNOTTY, 0);
+ emacs_close (j);
+ }
#ifndef USG
- /* In order to get a controlling terminal on some versions
- of BSD, it is necessary to put the process in pgrp 0
- before it opens the terminal. */
+ /* In order to get a controlling terminal on some versions
+ of BSD, it is necessary to put the process in pgrp 0
+ before it opens the terminal. */
#ifdef HAVE_SETPGID
- setpgid (0, 0);
+ setpgid (0, 0);
#else
- setpgrp (0, 0);
+ setpgrp (0, 0);
#endif
#endif
- }
+ }
#endif /* TIOCNOTTY */
#if !defined (DONT_REOPEN_PTY)
both HAVE_SETSID and TIOCSCTTY are defined. */
/* Now close the pty (if we had it open) and reopen it.
This makes the pty the controlling terminal of the subprocess. */
- if (pty_flag)
- {
+ if (pty_flag)
+ {
- /* I wonder if emacs_close (emacs_open (pty_name, ...))
- would work? */
- if (xforkin >= 0)
- emacs_close (xforkin);
- xforkout = xforkin = emacs_open (pty_name, O_RDWR, 0);
+ /* I wonder if emacs_close (emacs_open (pty_name, ...))
+ would work? */
+ if (xforkin >= 0)
+ emacs_close (xforkin);
+ xforkout = xforkin = emacs_open (pty_name, O_RDWR, 0);
- if (xforkin < 0)
- {
- emacs_write (1, "Couldn't open the pty terminal ", 31);
- emacs_write (1, pty_name, strlen (pty_name));
- emacs_write (1, "\n", 1);
- _exit (1);
- }
+ if (xforkin < 0)
+ {
+ emacs_write (1, "Couldn't open the pty terminal ", 31);
+ emacs_write (1, pty_name, strlen (pty_name));
+ emacs_write (1, "\n", 1);
+ _exit (1);
+ }
- }
+ }
#endif /* not DONT_REOPEN_PTY */
#ifdef SETUP_SLAVE_PTY
- if (pty_flag)
- {
- SETUP_SLAVE_PTY;
- }
+ if (pty_flag)
+ {
+ SETUP_SLAVE_PTY;
+ }
#endif /* SETUP_SLAVE_PTY */
#ifdef AIX
- /* On AIX, we've disabled SIGHUP above once we start a child on a pty.
- Now reenable it in the child, so it will die when we want it to. */
- if (pty_flag)
- signal (SIGHUP, SIG_DFL);
+ /* On AIX, we've disabled SIGHUP above once we start a child on a pty.
+ Now reenable it in the child, so it will die when we want it to. */
+ if (pty_flag)
+ signal (SIGHUP, SIG_DFL);
#endif
#endif /* HAVE_PTYS */
- signal (SIGINT, SIG_DFL);
- signal (SIGQUIT, SIG_DFL);
- /* GConf causes us to ignore SIGPIPE, make sure it is restored
- in the child. */
- signal (SIGPIPE, SIG_DFL);
+ signal (SIGINT, SIG_DFL);
+ signal (SIGQUIT, SIG_DFL);
+
+ /* Emacs ignores SIGPIPE, but the child should not. */
+ signal (SIGPIPE, SIG_DFL);
+#ifdef SIGCHLD
/* Stop blocking signals in the child. */
- pthread_sigmask (SIG_SETMASK, &procmask, 0);
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+#endif
- if (pty_flag)
- child_setup_tty (xforkout);
+ 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, encoded_current_dir);
#else /* not WINDOWSNT */
#ifdef FD_CLOEXEC
- emacs_close (wait_child_setup[0]);
+ emacs_close (wait_child_setup[0]);
#endif
- child_setup (xforkin, xforkout, xforkout,
- new_argv, 1, encoded_current_dir);
+ child_setup (xforkin, xforkout, xforkout,
+ new_argv, 1, encoded_current_dir);
#endif /* not WINDOWSNT */
- }
- environ = save_environ;
- }
+ }
+
+ /* Back in the parent process. */
+
+#if HAVE_WORKING_VFORK
+ environ = save_environ;
+#endif
+
+ XPROCESS (process)->pid = pid;
- UNBLOCK_INPUT;
+ /* Stop blocking signals in the parent. */
+#ifdef SIGCHLD
+ pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
+#endif
+ unblock_input ();
- /* This runs in the Emacs process. */
if (pid < 0)
{
if (forkin >= 0)
else
{
/* vfork succeeded. */
- XPROCESS (process)->pid = pid;
#ifdef WINDOWSNT
register_child (pid, inchannel);
if (forkin != forkout && forkout >= 0)
emacs_close (forkout);
-#ifdef HAVE_PTYS
- if (pty_flag)
- PSET (XPROCESS (process), tty_name, build_string (pty_name));
- else
-#endif
- PSET (XPROCESS (process), tty_name, Qnil);
+ pset_tty_name (XPROCESS (process), lisp_pty_name);
#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
/* Wait for child_setup to complete in case that vfork is
#endif
}
- /* Restore the signal state whether vfork succeeded or not.
- (We will signal an error, below, if it failed.) */
-#ifdef HAVE_WORKING_VFORK
- /* Restore the parent's signal handlers. */
- sigaction (SIGINT, &sigint_action, 0);
- sigaction (SIGQUIT, &sigquit_action, 0);
- sigaction (SIGPIPE, &sigpipe_action, 0);
-#ifdef AIX
- sigaction (SIGHUP, &sighup_action, 0);
-#endif
-#endif /* HAVE_WORKING_VFORK */
- /* Stop blocking signals in the parent. */
- pthread_sigmask (SIG_SETMASK, &procmask, 0);
-
/* Now generate the error if vfork failed. */
if (pid < 0)
report_file_error ("Doing vfork", Qnil);
#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. */
-#ifdef O_NOCTTY
+#if O_NOCTTY
/* Don't let this terminal become our controlling terminal
(in case we don't have one). */
int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
}
#endif /* HAVE_PTYS */
-#ifdef O_NONBLOCK
+#if O_NONBLOCK
fcntl (inchannel, F_SETFL, O_NONBLOCK);
fcntl (outchannel, F_SETFL, O_NONBLOCK);
#else
-#ifdef O_NDELAY
+#if O_NDELAY
fcntl (inchannel, F_SETFL, O_NDELAY);
fcntl (outchannel, F_SETFL, O_NDELAY);
#endif
more portable (see USG_SUBTTY_WORKS above). */
XPROCESS (process)->pty_flag = pty_flag;
- PSET (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)
- PSET (XPROCESS (process), tty_name, build_string (pty_name));
+ pset_tty_name (XPROCESS (process), build_string (pty_name));
else
#endif
- PSET (XPROCESS (process), tty_name, Qnil);
+ pset_tty_name (XPROCESS (process), Qnil);
}
\f
if (set_socket_option (s, option, value))
{
- PSET (p, childp, Fplist_put (PGET (p, childp), option, value));
+ pset_childp (p, Fplist_put (p->childp, option, value));
return Qt;
}
proc = Fplist_get (contact, QCport);
proc = get_process (proc);
p = XPROCESS (proc);
- if (!EQ (PGET (p, type), Qserial))
+ if (!EQ (p->type, Qserial))
error ("Not a serial process");
- if (NILP (Fplist_get (PGET (p, childp), QCspeed)))
+ if (NILP (Fplist_get (p->childp, QCspeed)))
{
UNGCPRO;
return Qnil;
make_serial_process_unwind (Lisp_Object proc)
{
if (!PROCESSP (proc))
- abort ();
+ emacs_abort ();
remove_process (proc);
return Qnil;
}
if (NILP (buffer))
buffer = name;
buffer = Fget_buffer_create (buffer);
- PSET (p, buffer, buffer);
-
- PSET (p, childp, contact);
- PSET (p, plist, Fcopy_sequence (Fplist_get (contact, QCplist)));
- PSET (p, type, Qserial);
- PSET (p, sentinel, Fplist_get (contact, QCsentinel));
- PSET (p, filter, Fplist_get (contact, QCfilter));
- PSET (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))
- PSET (p, command, Qt);
+ pset_command (p, Qt);
p->pty_flag = 0;
- if (!EQ (PGET (p, command), Qt))
+ if (!EQ (p->command, Qt))
{
FD_SET (fd, &input_wait_mask);
FD_SET (fd, &non_keyboard_wait_mask);
if (BUFFERP (buffer))
{
- set_marker_both (PGET (p, mark), buffer,
+ set_marker_both (p->mark, buffer,
BUF_ZV (XBUFFER (buffer)),
BUF_ZV_BYTE (XBUFFER (buffer)));
}
else if ((!NILP (buffer) && NILP (BVAR (XBUFFER (buffer), enable_multibyte_characters)))
|| (NILP (buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters))))
val = Qnil;
- PSET (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;
- PSET (p, encode_coding_system, val);
+ pset_encode_coding_system (p, val);
setup_process_coding_systems (proc);
- PSET (p, decoding_buf, empty_unibyte_string);
+ pset_decoding_buf (p, empty_unibyte_string);
p->decoding_carryover = 0;
- PSET (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);
{
/* Don't support network sockets when non-blocking mode is
not available, since a blocked Emacs is not useful. */
-#if !defined (O_NONBLOCK) && !defined (O_NDELAY)
+#if !O_NONBLOCK && !O_NDELAY
error ("Network servers not supported");
#else
is_server = 1;
#ifdef NON_BLOCKING_CONNECT
if (is_non_blocking_client)
{
-#ifdef O_NONBLOCK
+#if O_NONBLOCK
ret = fcntl (s, F_SETFL, O_NONBLOCK);
#else
ret = fcntl (s, F_SETFL, O_NDELAY);
if (socktype == SOCK_DGRAM)
{
if (datagram_address[s].sa)
- abort ();
+ emacs_abort ();
datagram_address[s].sa = xmalloc (lres->ai_addrlen);
datagram_address[s].len = lres->ai_addrlen;
if (is_server)
#ifdef HAVE_GETADDRINFO
if (res != &ai)
{
- BLOCK_INPUT;
+ block_input ();
freeaddrinfo (res);
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif
chan_process[inch] = proc;
-#ifdef O_NONBLOCK
+#if O_NONBLOCK
fcntl (inch, F_SETFL, O_NONBLOCK);
#else
-#ifdef O_NDELAY
+#if O_NDELAY
fcntl (inch, F_SETFL, O_NDELAY);
#endif
#endif
p = XPROCESS (proc);
- PSET (p, childp, contact);
- PSET (p, plist, Fcopy_sequence (Fplist_get (contact, QCplist)));
- PSET (p, type, Qnetwork);
+ pset_childp (p, contact);
+ pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist)));
+ pset_type (p, Qnetwork);
- PSET (p, buffer, buffer);
- PSET (p, sentinel, sentinel);
- PSET (p, filter, filter);
- PSET (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)))
- PSET (p, command, Qt);
+ pset_command (p, Qt);
p->pid = 0;
p->infd = inch;
p->outfd = outch;
if (is_server && socktype != SOCK_DGRAM)
- PSET (p, status, Qlisten);
+ pset_status (p, Qlisten);
/* Make the process marker point into the process buffer (if any). */
if (BUFFERP (buffer))
- set_marker_both (PGET (p, mark), buffer,
+ set_marker_both (p->mark, buffer,
BUF_ZV (XBUFFER (buffer)),
BUF_ZV_BYTE (XBUFFER (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. */
- PSET (p, status, Qconnect);
+ pset_status (p, Qconnect);
if (!FD_ISSET (inch, &connect_wait_mask))
{
FD_SET (inch, &connect_wait_mask);
#endif
/* A server may have a client filter setting of Qt, but it must
still listen for incoming connects unless it is stopped. */
- if ((!EQ (PGET (p, filter), Qt) && !EQ (PGET (p, command), Qt))
- || (EQ (PGET (p, status), Qlisten) && NILP (PGET (p, command))))
+ if ((!EQ (p->filter, Qt) && !EQ (p->command, Qt))
+ || (EQ (p->status, Qlisten) && NILP (p->command)))
{
FD_SET (inch, &input_wait_mask);
FD_SET (inch, &non_keyboard_wait_mask);
else
val = Qnil;
}
- PSET (p, decode_coding_system, val);
+ pset_decode_coding_system (p, val);
if (!NILP (tem))
{
else
val = Qnil;
}
- PSET (p, encode_coding_system, val);
+ pset_encode_coding_system (p, val);
}
setup_process_coding_systems (proc);
- PSET (p, decoding_buf, empty_unibyte_string);
+ pset_decoding_buf (p, empty_unibyte_string);
p->decoding_carryover = 0;
- PSET (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);
FD_CLR (inchannel, &connect_wait_mask);
FD_CLR (inchannel, &write_mask);
if (--num_pending_connects < 0)
- abort ();
+ emacs_abort ();
}
#endif
if (inchannel == max_process_desc)
return;
#endif
- if (!NILP (PGET (ps, log)))
- call3 (PGET (ps, log), server, Qnil,
+ if (!NILP (ps->log))
+ call3 (ps->log, server, Qnil,
concat3 (build_string ("accept failed with code"),
Fnumber_to_string (make_number (code)),
build_string ("\n")));
process name of the server process concatenated with the caller
identification. */
- if (!NILP (PGET (ps, filter)) && !EQ (PGET (ps, filter), Qt))
+ if (!NILP (ps->filter) && !EQ (ps->filter, Qt))
buffer = Qnil;
else
{
- buffer = PGET (ps, buffer);
+ buffer = ps->buffer;
if (!NILP (buffer))
buffer = Fbuffer_name (buffer);
else
- buffer = PGET (ps, name);
+ buffer = ps->name;
if (!NILP (buffer))
{
buffer = concat2 (buffer, caller);
/* Generate a unique name for the new server process. Combine the
server process name with the caller identification. */
- name = concat2 (PGET (ps, name), caller);
+ name = concat2 (ps->name, caller);
proc = make_process (name);
chan_process[s] = proc;
-#ifdef O_NONBLOCK
+#if O_NONBLOCK
fcntl (s, F_SETFL, O_NONBLOCK);
#else
-#ifdef O_NDELAY
+#if O_NDELAY
fcntl (s, F_SETFL, O_NDELAY);
#endif
#endif
p = XPROCESS (proc);
/* Build new contact information for this setup. */
- contact = Fcopy_sequence (PGET (ps, childp));
+ contact = Fcopy_sequence (ps->childp);
contact = Fplist_put (contact, QCserver, Qnil);
contact = Fplist_put (contact, QChost, host);
if (!NILP (service))
conv_sockaddr_to_lisp (&saddr.sa, len));
#endif
- PSET (p, childp, contact);
- PSET (p, plist, Fcopy_sequence (PGET (ps, plist)));
- PSET (p, type, Qnetwork);
+ pset_childp (p, contact);
+ pset_plist (p, Fcopy_sequence (ps->plist));
+ pset_type (p, Qnetwork);
- PSET (p, buffer, buffer);
- PSET (p, sentinel, PGET (ps, sentinel));
- PSET (p, filter, PGET (ps, filter));
- PSET (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;
- PSET (p, status, Qrun);
+ pset_status (p, Qrun);
/* Client processes for accepted connections are not stopped initially. */
- if (!EQ (PGET (p, filter), Qt))
+ if (!EQ (p->filter, Qt))
{
FD_SET (s, &input_wait_mask);
FD_SET (s, &non_keyboard_wait_mask);
of the new process should reflect the settings at the time the
server socket was opened; not the current settings. */
- PSET (p, decode_coding_system, PGET (ps, decode_coding_system));
- PSET (p, encode_coding_system, PGET (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);
- PSET (p, decoding_buf, empty_unibyte_string);
+ pset_decoding_buf (p, empty_unibyte_string);
p->decoding_carryover = 0;
- PSET (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);
- if (!NILP (PGET (ps, log)))
- call3 (PGET (ps, log), server, proc,
+ if (!NILP (ps->log))
+ call3 (ps->log, server, proc,
concat3 (build_string ("accept from "),
(STRINGP (host) ? host : build_string ("-")),
build_string ("\n")));
- if (!NILP (PGET (p, sentinel)))
+ if (!NILP (p->sentinel))
exec_sentinel (proc,
concat3 (build_string ("open from "),
(STRINGP (host) ? host : build_string ("-")),
-1 meaning caller will actually read the input, so don't throw to
the quit handler, or
- DO_DISPLAY != 0 means redisplay should be done to show subprocess
+ DO_DISPLAY means redisplay should be done to show subprocess
output that arrives.
If WAIT_FOR_CELL is a cons cell, wait until its car is non-nil
int
wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
- int do_display,
+ bool do_display,
Lisp_Object wait_for_cell,
struct Lisp_Process *wait_proc, int just_wait_proc)
{
FD_ZERO (&Writeok);
if (time_limit == 0 && nsecs == 0 && wait_proc && !NILP (Vinhibit_quit)
- && !(CONSP (PGET (wait_proc, status))
- && EQ (XCAR (PGET (wait_proc, status)), Qexit)))
+ && !(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. */
Otherwise, do pending quit if requested. */
if (read_kbd >= 0)
QUIT;
-#ifdef SYNC_INPUT
- else
+ else if (pending_signals)
process_pending_signals ();
-#endif
/* Exit now if the cell we're waiting for became non-nil. */
if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
do
{
- int old_timers_run = timers_run;
+ unsigned old_timers_run = timers_run;
struct buffer *old_buffer = current_buffer;
Lisp_Object old_window = selected_window;
if (wait_proc && wait_proc->raw_status_new)
update_status (wait_proc);
if (wait_proc
- && ! EQ (PGET (wait_proc, status), Qrun)
- && ! EQ (PGET (wait_proc, status), Qconnect))
+ && ! EQ (wait_proc->status, Qrun)
+ && ! EQ (wait_proc->status, Qconnect))
{
int nread, total_nread = 0;
process_output_skip = 0;
}
#endif
+
#if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS)
nfds = xg_select
#elif defined (HAVE_NS)
Cleanup occurs c/o status_notify after SIGCLD. */
no_avail = 1; /* Cannot depend on values returned */
#else
- abort ();
+ emacs_abort ();
#endif
}
else
check_write = 0;
}
-#if 0 /* When polling is used, interrupt_input is 0,
- so get_input_pending should read the input.
- So this should not be needed. */
- /* If we are using polling for input,
- and we see input available, make it get read now.
- Otherwise it might not actually get read for a second.
- And on hpux, since we turn off polling in wait_reading_process_output,
- it might never get read at all if we don't spend much time
- outside of wait_reading_process_output. */
- if (read_kbd && interrupt_input
- && keyboard_bit_set (&Available)
- && input_polling_used ())
- kill (getpid (), SIGALRM);
-#endif
-
/* Check for keyboard input */
/* If there is any, return immediately
to give it higher priority than subprocesses */
if (read_kbd != 0)
{
- int old_timers_run = timers_run;
+ unsigned old_timers_run = timers_run;
struct buffer *old_buffer = current_buffer;
Lisp_Object old_window = selected_window;
int leave = 0;
if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
break;
-#ifdef SIGIO
+#ifdef USABLE_SIGIO
/* If we think we have keyboard input waiting, but didn't get SIGIO,
go read it. This can happen with X on BSD after logging out.
In that case, there really is no input and no SIGIO,
if (read_kbd && interrupt_input
&& keyboard_bit_set (&Available) && ! noninteractive)
- kill (getpid (), SIGIO);
+ handle_input_available_signal (SIGIO);
#endif
if (! wait_proc)
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++)
{
continue;
/* If this is a server stream socket, accept connection. */
- if (EQ (PGET (XPROCESS (proc), status), Qlisten))
+ if (EQ (XPROCESS (proc)->status, Qlisten))
{
server_accept_connection (proc, channel);
continue;
#endif
/* ISC 4.1 defines both EWOULDBLOCK and O_NONBLOCK,
and Emacs uses O_NONBLOCK, so what we get is EAGAIN. */
-#ifdef O_NONBLOCK
+#if O_NONBLOCK
else if (nread == -1 && errno == EAGAIN)
;
#else
-#ifdef O_NDELAY
+#if O_NDELAY
else if (nread == -1 && errno == EAGAIN)
;
/* Note that we cannot distinguish between no input
if (p->pid == -2)
{
- /* If the EIO occurs on a pty, sigchld_handler's
- waitpid() will not find the process object to
+ /* If the EIO occurs on a pty, the SIGCHLD handler's
+ waitpid call will not find the process object to
delete. Do it here. */
p->tick = ++process_tick;
- PSET (p, status, Qfailed);
+ pset_status (p, Qfailed);
}
else
- kill (getpid (), SIGCHLD);
+ handle_child_signal (SIGCHLD);
}
#endif /* HAVE_PTYS */
/* If we can detect process termination, don't consider the
deactivate_process (proc);
if (XPROCESS (proc)->raw_status_new)
update_status (XPROCESS (proc));
- if (EQ (PGET (XPROCESS (proc), status), Qrun))
- PSET (XPROCESS (proc), status,
- Fcons (Qexit, Fcons (make_number (256), Qnil)));
+ if (EQ (XPROCESS (proc)->status, Qrun))
+ pset_status (XPROCESS (proc),
+ list2 (Qexit, make_number (256)));
}
}
#ifdef NON_BLOCKING_CONNECT
FD_CLR (channel, &connect_wait_mask);
FD_CLR (channel, &write_mask);
if (--num_pending_connects < 0)
- abort ();
+ emacs_abort ();
proc = chan_process[channel];
if (NILP (proc))
if (xerrno)
{
p->tick = ++process_tick;
- PSET (p, status,
- Fcons (Qfailed, Fcons (make_number (xerrno), Qnil)));
+ pset_status (p, list2 (Qfailed, make_number (xerrno)));
deactivate_process (proc);
}
else
{
- PSET (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. */
exec_sentinel (proc, build_string ("open\n"));
- if (!EQ (PGET (p, filter), Qt) && !EQ (PGET (p, command), Qt))
+ if (!EQ (p->filter, Qt) && !EQ (p->command, Qt))
{
FD_SET (p->infd, &input_wait_mask);
FD_SET (p->infd, &non_keyboard_wait_mask);
chars = alloca (carryover + readmax);
if (carryover)
/* See the comment above. */
- memcpy (chars, SDATA (PGET (p, decoding_buf)), carryover);
+ memcpy (chars, SDATA (p->decoding_buf), carryover);
#ifdef DATAGRAM_SOCKETS
/* We have a working select, so proc_buffered_char is always -1. */
/* 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 = PGET (p, filter);
+ outstream = p->filter;
if (!NILP (outstream))
{
Lisp_Object text;
- int outer_running_asynch_code = running_asynch_code;
+ bool outer_running_asynch_code = running_asynch_code;
int waiting = waiting_for_user_input_p;
/* No need to gcpro these, because all we do with them later
text = coding->dst_object;
Vlast_coding_system_used = CODING_ID_NAME (coding->id);
/* A new coding system might be found. */
- if (!EQ (PGET (p, decode_coding_system), Vlast_coding_system_used))
+ if (!EQ (p->decode_coding_system, Vlast_coding_system_used))
{
- PSET (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
proc_encode_coding_system[p->outfd] surely points to a
valid memory because p->outfd will be changed once EOF is
sent to the process. */
- if (NILP (PGET (p, encode_coding_system))
+ if (NILP (p->encode_coding_system)
&& proc_encode_coding_system[p->outfd])
{
- PSET (p, encode_coding_system,
- coding_inherit_eol_type (Vlast_coding_system_used, Qnil));
- setup_coding_system (PGET (p, encode_coding_system),
+ 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 (PGET (p, decoding_buf)) < coding->carryover_bytes)
- PSET (p, decoding_buf, make_uninit_string (coding->carryover_bytes));
- memcpy (SDATA (PGET (p, decoding_buf)), coding->carryover,
+ if (SCHARS (p->decoding_buf) < 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;
}
}
/* If no filter, write into buffer if it isn't dead. */
- else if (!NILP (PGET (p, buffer)) && !NILP (BVAR (XBUFFER (PGET (p, buffer)), name)))
+ else if (!NILP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
{
Lisp_Object old_read_only;
ptrdiff_t old_begv, old_zv;
Lisp_Object text;
struct buffer *b;
- Fset_buffer (PGET (p, buffer));
+ Fset_buffer (p->buffer);
opoint = PT;
opoint_byte = PT_BYTE;
old_read_only = BVAR (current_buffer, read_only);
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 (PGET (p, mark))->buffer)
+ if (XMARKER (p->mark)->buffer)
SET_PT_BOTH (clip_to_bounds (BEGV,
- marker_position (PGET (p, mark)), ZV),
+ marker_position (p->mark), ZV),
clip_to_bounds (BEGV_BYTE,
- marker_byte_position (PGET (p, mark)),
+ marker_byte_position (p->mark),
ZV_BYTE));
else
SET_PT_BOTH (ZV, ZV_BYTE);
Vlast_coding_system_used = CODING_ID_NAME (coding->id);
/* A new coding system might be found. See the comment in the
similar code in the previous `if' block. */
- if (!EQ (PGET (p, decode_coding_system), Vlast_coding_system_used))
+ if (!EQ (p->decode_coding_system, Vlast_coding_system_used))
{
- PSET (p, decode_coding_system, Vlast_coding_system_used);
- if (NILP (PGET (p, encode_coding_system))
+ pset_decode_coding_system (p, Vlast_coding_system_used);
+ if (NILP (p->encode_coding_system)
&& proc_encode_coding_system[p->outfd])
{
- PSET (p, encode_coding_system,
- coding_inherit_eol_type (Vlast_coding_system_used, Qnil));
- setup_coding_system (PGET (p, encode_coding_system),
+ 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 (PGET (p, decoding_buf)) < coding->carryover_bytes)
- PSET (p, decoding_buf, make_uninit_string (coding->carryover_bytes));
- memcpy (SDATA (PGET (p, decoding_buf)), coding->carryover,
+ if (SCHARS (p->decoding_buf) < 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;
}
/* Make sure the process marker's position is valid when the
process buffer is changed in the signal_after_change above.
W3 is known to do that. */
- if (BUFFERP (PGET (p, buffer))
- && (b = XBUFFER (PGET (p, buffer)), b != current_buffer))
- set_marker_both (PGET (p, mark), PGET (p, buffer), BUF_PT (b), BUF_PT_BYTE (b));
+ if (BUFFERP (p->buffer)
+ && (b = XBUFFER (p->buffer), b != current_buffer))
+ set_marker_both (p->mark, p->buffer, BUF_PT (b), BUF_PT_BYTE (b));
else
- set_marker_both (PGET (p, mark), PGET (p, buffer), PT, PT_BYTE);
+ set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
update_mode_lines++;
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. */
\f
/* Sending data to subprocess */
-static jmp_buf send_process_frame;
-static Lisp_Object process_sent_to;
-
-#ifndef FORWARD_SIGNAL_TO_MAIN_THREAD
-static _Noreturn void send_process_trap (int);
-#endif
-
-static void
-send_process_trap (int ignore)
-{
- SIGNAL_THREAD_CHECK (SIGPIPE);
- sigunblock (sigmask (SIGPIPE));
- 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.
entry = Fcons (obj, Fcons (make_number (offset), make_number (len)));
if (front)
- PSET (p, write_queue, Fcons (entry, PGET (p, write_queue)));
+ pset_write_queue (p, Fcons (entry, p->write_queue));
else
- PSET (p, write_queue, nconc2 (PGET (p, write_queue), Fcons (entry, Qnil)));
+ pset_write_queue (p, nconc2 (p->write_queue, Fcons (entry, Qnil)));
}
/* Remove the first element in the write_queue of process P, put its
Lisp_Object entry, offset_length;
ptrdiff_t offset;
- if (NILP (PGET (p, write_queue)))
+ if (NILP (p->write_queue))
return 0;
- entry = XCAR (PGET (p, write_queue));
- PSET (p, write_queue, XCDR (PGET (p, write_queue)));
+ entry = XCAR (p->write_queue);
+ pset_write_queue (p, XCDR (p->write_queue));
*obj = XCAR (entry);
offset_length = XCDR (entry);
This function can evaluate Lisp code and can garbage collect. */
static void
-send_process (volatile Lisp_Object proc, const char *volatile buf,
- volatile ptrdiff_t len, volatile Lisp_Object object)
+send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
+ 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;
- void (*volatile old_sigpipe) (int);
if (p->raw_status_new)
update_status (p);
- if (! EQ (PGET (p, status), Qrun))
- error ("Process %s not running", SDATA (PGET (p, name)));
+ if (! EQ (p->status, Qrun))
+ error ("Process %s not running", SDATA (p->name));
if (p->outfd < 0)
- error ("Output file descriptor of %s is closed", SDATA (PGET (p, name)));
+ error ("Output file descriptor of %s is closed", SDATA (p->name));
coding = proc_encode_coding_system[p->outfd];
Vlast_coding_system_used = CODING_ID_NAME (coding->id);
&& !NILP (BVAR (XBUFFER (object), enable_multibyte_characters)))
|| EQ (object, Qt))
{
- PSET (p, encode_coding_system,
- complement_process_encoding_system (PGET (p, encode_coding_system)));
- if (!EQ (Vlast_coding_system_used, PGET (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
because we sent a unibyte text previously. Now we are
Another reason we come here is that the coding system
was just complemented and a new one was returned by
complement_process_encoding_system. */
- setup_coding_system (PGET (p, encode_coding_system), coding);
- Vlast_coding_system_used = PGET (p, encode_coding_system);
+ setup_coding_system (p->encode_coding_system, coding);
+ Vlast_coding_system_used = p->encode_coding_system;
}
coding->src_multibyte = 1;
}
pty_max_bytes--;
}
- /* 2000-09-21: Emacs 20.7, sparc-sun-solaris-2.6, GCC 2.95.2,
- CFLAGS="-g -O": The value of the parameter `proc' is clobbered
- when returning with longjmp despite being declared volatile. */
- if (!setjmp (send_process_frame))
- {
- p = XPROCESS (proc); /* Repair any setjmp clobbering. */
- process_sent_to = proc;
+ /* 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);
- /* If there is already data in the write_queue, put the new data
- in the back of queue. Otherwise, ignore it. */
- if (!NILP (PGET (p, write_queue)))
- write_queue_push (p, object, buf, len, 0);
+ do /* while !NILP (p->write_queue) */
+ {
+ ptrdiff_t cur_len = -1;
+ const char *cur_buf;
+ Lisp_Object cur_object;
- do /* while !NILP (p->write_queue) */
+ /* If write_queue is empty, ignore it. */
+ if (!write_queue_pop (p, &cur_object, &cur_buf, &cur_len))
{
- ptrdiff_t cur_len = -1;
- const char *cur_buf;
- Lisp_Object cur_object;
+ cur_len = len;
+ cur_buf = buf;
+ cur_object = object;
+ }
- /* If write_queue is empty, ignore it. */
- if (!write_queue_pop (p, &cur_object, &cur_buf, &cur_len))
+ while (cur_len > 0)
+ {
+ /* Send this batch, using one or more write calls. */
+ ptrdiff_t written = 0;
+ int outfd = p->outfd;
+#ifdef DATAGRAM_SOCKETS
+ if (DATAGRAM_CHAN_P (outfd))
{
- cur_len = len;
- cur_buf = buf;
- cur_object = object;
+ rv = sendto (outfd, cur_buf, cur_len,
+ 0, datagram_address[outfd].sa,
+ datagram_address[outfd].len);
+ if (0 <= rv)
+ written = rv;
+ else if (errno == EMSGSIZE)
+ report_file_error ("sending datagram", Fcons (proc, Qnil));
}
-
- 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, cur_buf, cur_len,
- 0, datagram_address[outfd].sa,
- datagram_address[outfd].len);
- if (0 <= rv)
- written = rv;
- else if (errno == EMSGSIZE)
- {
- signal (SIGPIPE, old_sigpipe);
- report_file_error ("sending datagram",
- Fcons (proc, Qnil));
- }
- }
- else
+ else
#endif
- {
+ {
#ifdef HAVE_GNUTLS
- if (p->gnutls_p)
- written = emacs_gnutls_write (p, cur_buf, cur_len);
- else
+ if (p->gnutls_p)
+ written = emacs_gnutls_write (p, cur_buf, cur_len);
+ else
#endif
- written = emacs_write (outfd, cur_buf, cur_len);
- rv = (written ? 0 : -1);
+ written = emacs_write (outfd, cur_buf, cur_len);
+ rv = (written ? 0 : -1);
#ifdef ADAPTIVE_READ_BUFFERING
- if (p->read_output_delay > 0
- && p->adaptive_read_buffering == 1)
- {
- p->read_output_delay = 0;
- process_output_delay_count--;
- p->read_output_skip = 0;
- }
-#endif
+ if (p->read_output_delay > 0
+ && p->adaptive_read_buffering == 1)
+ {
+ p->read_output_delay = 0;
+ process_output_delay_count--;
+ p->read_output_skip = 0;
}
- signal (SIGPIPE, old_sigpipe);
+#endif
+ }
- if (rv < 0)
- {
- if (0
+ if (rv < 0)
+ {
+ if (0
#ifdef EWOULDBLOCK
- || errno == EWOULDBLOCK
+ || errno == EWOULDBLOCK
#endif
#ifdef EAGAIN
- || errno == EAGAIN
+ || errno == EAGAIN
#endif
- )
- /* Buffer is full. Wait, accepting input;
- that may allow the program
- to finish doing output and read more. */
- {
+ )
+ /* Buffer is full. Wait, accepting input;
+ that may allow the program
+ to finish doing output and read more. */
+ {
#ifdef BROKEN_PTY_READ_AFTER_EAGAIN
- /* A gross hack to work around a bug in FreeBSD.
- In the following sequence, read(2) returns
- bogus data:
-
- write(2) 1022 bytes
- write(2) 954 bytes, get EAGAIN
- read(2) 1024 bytes in process_read_output
- read(2) 11 bytes in process_read_output
-
- That is, read(2) returns more bytes than have
- ever been written successfully. The 1033 bytes
- read are the 1022 bytes written successfully
- after processing (for example with CRs added if
- the terminal is set up that way which it is
- here). The same bytes will be seen again in a
- later read(2), without the CRs. */
-
- if (errno == EAGAIN)
- {
- int flags = FWRITE;
- ioctl (p->outfd, TIOCFLUSH, &flags);
- }
+ /* A gross hack to work around a bug in FreeBSD.
+ In the following sequence, read(2) returns
+ bogus data:
+
+ write(2) 1022 bytes
+ write(2) 954 bytes, get EAGAIN
+ read(2) 1024 bytes in process_read_output
+ read(2) 11 bytes in process_read_output
+
+ That is, read(2) returns more bytes than have
+ ever been written successfully. The 1033 bytes
+ read are the 1022 bytes written successfully
+ after processing (for example with CRs added if
+ the terminal is set up that way which it is
+ here). The same bytes will be seen again in a
+ later read(2), without the CRs. */
+
+ if (errno == EAGAIN)
+ {
+ int flags = FWRITE;
+ ioctl (p->outfd, TIOCFLUSH, &flags);
+ }
#endif /* BROKEN_PTY_READ_AFTER_EAGAIN */
- /* 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));
+ /* 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 if (errno == EPIPE)
+ {
+ p->raw_status_new = 0;
+ pset_status (p, list2 (Qexit, make_number (256)));
+ p->tick = ++process_tick;
+ deactivate_process (proc);
+ error ("process %s no longer connected to pipe; closed it",
+ SDATA (p->name));
}
- cur_buf += written;
- cur_len -= written;
+ else
+ /* This is a real error. */
+ report_file_error ("writing to process", Fcons (proc, Qnil));
}
+ cur_buf += written;
+ cur_len -= written;
}
- while (!NILP (PGET (p, write_queue)));
- }
- else
- {
- signal (SIGPIPE, old_sigpipe);
- proc = process_sent_to;
- p = XPROCESS (proc);
- p->raw_status_new = 0;
- PSET (p, status, Fcons (Qexit, Fcons (make_number (256), Qnil)));
- p->tick = ++process_tick;
- deactivate_process (proc);
- error ("SIGPIPE raised on process %s; closed it", SDATA (PGET (p, name)));
}
+ while (!NILP (p->write_queue));
}
DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
pid_t gid = -1;
#ifdef TIOCGPGRP
- if (ioctl (p->infd, TIOCGPGRP, &gid) == -1 && ! NILP (PGET (p, tty_name)))
+ if (ioctl (p->infd, TIOCGPGRP, &gid) == -1 && ! NILP (p->tty_name))
{
int fd;
/* Some OS:es (Solaris 8/9) does not allow TIOCGPGRP from the
master side. Try the slave side. */
- fd = emacs_open (SSDATA (PGET (p, tty_name)), O_RDONLY, 0);
+ fd = emacs_open (SSDATA (p->tty_name), O_RDONLY, 0);
if (fd != -1)
{
proc = get_process (process);
p = XPROCESS (proc);
- if (!EQ (PGET (p, type), Qreal))
+ if (!EQ (p->type, Qreal))
error ("Process %s is not a subprocess",
- SDATA (PGET (p, name)));
+ SDATA (p->name));
if (p->infd < 0)
error ("Process %s is not active",
- SDATA (PGET (p, name)));
+ SDATA (p->name));
gid = emacs_get_tty_pgrp (p);
proc = get_process (process);
p = XPROCESS (proc);
- if (!EQ (PGET (p, type), Qreal))
+ if (!EQ (p->type, Qreal))
error ("Process %s is not a subprocess",
- SDATA (PGET (p, name)));
+ SDATA (p->name));
if (p->infd < 0)
error ("Process %s is not active",
- SDATA (PGET (p, name)));
+ SDATA (p->name));
if (!p->pty_flag)
current_group = Qnil;
#ifdef SIGCONT
case SIGCONT:
p->raw_status_new = 0;
- PSET (p, status, Qrun);
+ pset_status (p, Qrun);
p->tick = ++process_tick;
if (!nomsg)
{
struct Lisp_Process *p;
p = XPROCESS (process);
- if (NILP (PGET (p, command))
+ if (NILP (p->command)
&& p->infd >= 0)
{
FD_CLR (p->infd, &input_wait_mask);
FD_CLR (p->infd, &non_keyboard_wait_mask);
}
- PSET (p, command, Qt);
+ pset_command (p, Qt);
return process;
}
#ifndef SIGTSTP
struct Lisp_Process *p;
p = XPROCESS (process);
- if (EQ (PGET (p, command), Qt)
+ if (EQ (p->command, Qt)
&& p->infd >= 0
- && (!EQ (PGET (p, filter), Qt) || EQ (PGET (p, status), Qlisten)))
+ && (!EQ (p->filter, Qt) || EQ (p->status, Qlisten)))
{
FD_SET (p->infd, &input_wait_mask);
FD_SET (p->infd, &non_keyboard_wait_mask);
tcflush (p->infd, TCIFLUSH);
#endif /* not WINDOWSNT */
}
- PSET (p, command, Qnil);
+ pset_command (p, Qnil);
return process;
}
#ifdef SIGCONT
CHECK_PROCESS (process);
pid = XPROCESS (process)->pid;
if (pid <= 0)
- error ("Cannot signal process %s",
- SDATA (PGET (XPROCESS (process), name)));
+ error ("Cannot signal process %s", SDATA (XPROCESS (process)->name));
}
#define parse_signal(NAME, VALUE) \
#ifdef SIGUSR2
parse_signal ("usr2", SIGUSR2);
#endif
-#ifdef SIGTERM
parse_signal ("term", SIGTERM);
-#endif
#ifdef SIGHUP
parse_signal ("hup", SIGHUP);
#endif
-#ifdef SIGINT
parse_signal ("int", SIGINT);
-#endif
#ifdef SIGQUIT
parse_signal ("quit", SIGQUIT);
#endif
-#ifdef SIGILL
parse_signal ("ill", SIGILL);
-#endif
-#ifdef SIGABRT
parse_signal ("abrt", SIGABRT);
-#endif
#ifdef SIGEMT
parse_signal ("emt", SIGEMT);
#endif
#ifdef SIGKILL
parse_signal ("kill", SIGKILL);
#endif
-#ifdef SIGFPE
parse_signal ("fpe", SIGFPE);
-#endif
#ifdef SIGBUS
parse_signal ("bus", SIGBUS);
#endif
-#ifdef SIGSEGV
parse_signal ("segv", SIGSEGV);
-#endif
#ifdef SIGSYS
parse_signal ("sys", SIGSYS);
#endif
/* Make sure the process is really alive. */
if (XPROCESS (proc)->raw_status_new)
update_status (XPROCESS (proc));
- if (! EQ (PGET (XPROCESS (proc), status), Qrun))
- error ("Process %s not running", SDATA (PGET (XPROCESS (proc), name)));
+ if (! EQ (XPROCESS (proc)->status, Qrun))
+ error ("Process %s not running", SDATA (XPROCESS (proc)->name));
if (CODING_REQUIRE_FLUSHING (coding))
{
if (XPROCESS (proc)->pty_flag)
send_process (proc, "\004", 1, Qnil);
- else if (EQ (PGET (XPROCESS (proc), type), Qserial))
+ else if (EQ (XPROCESS (proc)->type, Qserial))
{
#ifndef WINDOWSNT
if (tcdrain (XPROCESS (proc)->outfd) != 0)
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 (PGET (XPROCESS (proc), type), Qnetwork)
+ 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. */
#endif /* not HAVE_SHUTDOWN */
new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0);
if (new_outfd < 0)
- abort ();
+ emacs_abort ();
old_outfd = XPROCESS (proc)->outfd;
if (!proc_encode_coding_system[new_outfd])
proc_encode_coding_system[new_outfd]
= xmalloc (sizeof (struct coding_system));
- memcpy (proc_encode_coding_system[new_outfd],
- proc_encode_coding_system[old_outfd],
- 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));
** Malloc WARNING: This should never call malloc either directly or
indirectly; if it does, that is a bug */
-#ifdef SIGCHLD
-static void
-sigchld_handler (int signo)
+/* Record the changed status of the child process PID with wait status W. */
+void
+record_child_status_change (pid_t pid, int w)
{
- int old_errno = errno;
+#ifdef SIGCHLD
Lisp_Object proc;
struct Lisp_Process *p;
+ Lisp_Object tail;
- SIGNAL_THREAD_CHECK (signo);
+ /* Find the process that signaled us, and record its status. */
- while (1)
+ /* The process can have been deleted by Fdelete_process. */
+ for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail))
{
- pid_t pid;
- int w;
- Lisp_Object tail;
-
-#ifdef WNOHANG
-#ifndef WUNTRACED
-#define WUNTRACED 0
-#endif /* no WUNTRACED */
- /* Keep trying to get a status until we get a definitive result. */
- do
- {
- errno = 0;
- pid = waitpid (-1, &w, WNOHANG | WUNTRACED);
- }
- while (pid < 0 && errno == EINTR);
-
- if (pid <= 0)
+ Lisp_Object xpid = XCAR (tail);
+ if ((INTEGERP (xpid) && pid == XINT (xpid))
+ || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid)))
{
- /* PID == 0 means no processes found, PID == -1 means a real
- failure. We have done all our job, so return. */
-
- errno = old_errno;
+ XSETCAR (tail, Qnil);
return;
}
-#else
- pid = wait (&w);
-#endif /* no WNOHANG */
-
- /* Find the process that signaled us, and record its status. */
-
- /* The process can have been deleted by Fdelete_process. */
- for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail))
- {
- Lisp_Object xpid = XCAR (tail);
- if ((INTEGERP (xpid) && pid == XINT (xpid))
- || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid)))
- {
- XSETCAR (tail, Qnil);
- goto sigchld_end_of_loop;
- }
- }
+ }
- /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */
+ /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */
+ p = 0;
+ for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+ {
+ proc = XCDR (XCAR (tail));
+ p = XPROCESS (proc);
+ if (EQ (p->type, Qreal) && p->pid == pid)
+ break;
p = 0;
- for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
- {
- proc = XCDR (XCAR (tail));
- p = XPROCESS (proc);
- if (EQ (PGET (p, type), Qreal) && p->pid == pid)
- break;
- p = 0;
- }
-
- /* Look for an asynchronous process whose pid hasn't been filled
- in yet. */
- if (p == 0)
- for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
- {
- proc = XCDR (XCAR (tail));
- p = XPROCESS (proc);
- if (p->pid == -1)
- break;
- p = 0;
- }
-
- /* Change the status of the process that was found. */
- if (p != 0)
- {
- int clear_desc_flag = 0;
+ }
- p->tick = ++process_tick;
- p->raw_status = w;
- p->raw_status_new = 1;
+ /* Look for an asynchronous process whose pid hasn't been filled
+ in yet. */
+ if (! p)
+ for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+ {
+ proc = XCDR (XCAR (tail));
+ p = XPROCESS (proc);
+ if (p->pid == -1)
+ break;
+ p = 0;
+ }
- /* If process has terminated, stop waiting for its output. */
- if ((WIFSIGNALED (w) || WIFEXITED (w))
- && p->infd >= 0)
- clear_desc_flag = 1;
+ /* Change the status of the process that was found. */
+ if (p)
+ {
+ int clear_desc_flag = 0;
- /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */
- if (clear_desc_flag)
- {
- FD_CLR (p->infd, &input_wait_mask);
- FD_CLR (p->infd, &non_keyboard_wait_mask);
- }
+ p->tick = ++process_tick;
+ p->raw_status = w;
+ p->raw_status_new = 1;
- /* Tell wait_reading_process_output that it needs to wake up and
- look around. */
- if (input_available_clear_time)
- *input_available_clear_time = make_emacs_time (0, 0);
- }
+ /* If process has terminated, stop waiting for its output. */
+ if ((WIFSIGNALED (w) || WIFEXITED (w))
+ && p->infd >= 0)
+ clear_desc_flag = 1;
- /* There was no asynchronous process found for that pid: we have
- a synchronous process. */
- else
+ /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */
+ if (clear_desc_flag)
{
- synch_process_alive = 0;
-
- /* Report the status of the synchronous process. */
- if (WIFEXITED (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)
- *input_available_clear_time = make_emacs_time (0, 0);
+ FD_CLR (p->infd, &input_wait_mask);
+ FD_CLR (p->infd, &non_keyboard_wait_mask);
}
- sigchld_end_of_loop:
- ;
+ /* Tell wait_reading_process_output that it needs to wake up and
+ look around. */
+ if (input_available_clear_time)
+ *input_available_clear_time = make_emacs_time (0, 0);
+ }
+ /* There was no asynchronous process found for that pid: we have
+ a synchronous process. */
+ else
+ {
+ synch_process_alive = 0;
+
+ /* Report the status of the synchronous process. */
+ if (WIFEXITED (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)
+ *input_available_clear_time = make_emacs_time (0, 0);
+ }
+#endif
+}
- /* On some systems, we must return right away.
- If any more processes want to signal us, we will
- get another signal.
- Otherwise (on systems that have WNOHANG), loop around
- to use up all the processes that have something to tell us. */
+#ifdef SIGCHLD
+
+/* On some systems, the SIGCHLD handler must return right away. If
+ any more processes want to signal us, we will get another signal.
+ Otherwise, loop around to use up all the processes that have
+ something to tell us. */
#if (defined WINDOWSNT \
|| (defined USG && !defined GNU_LINUX \
&& !(defined HPUX && defined WNOHANG)))
- errno = old_errno;
- return;
-#endif /* USG, but not HPUX with WNOHANG */
+enum { CAN_HANDLE_MULTIPLE_CHILDREN = 0 };
+#else
+enum { CAN_HANDLE_MULTIPLE_CHILDREN = 1 };
+#endif
+
+static void
+handle_child_signal (int sig)
+{
+ do
+ {
+ pid_t pid;
+ int status;
+
+ do
+ pid = waitpid (-1, &status, WNOHANG | WUNTRACED);
+ while (pid < 0 && errno == EINTR);
+
+ /* PID == 0 means no processes found, PID == -1 means a real failure.
+ Either way, we have done all our job. */
+ if (pid <= 0)
+ break;
+
+ record_child_status_change (pid, status);
}
+ while (CAN_HANDLE_MULTIPLE_CHILDREN);
}
+
+static void
+deliver_child_signal (int sig)
+{
+ deliver_process_signal (sig, handle_child_signal);
+}
+
#endif /* SIGCHLD */
\f
static Lisp_Object
exec_sentinel_unwind (Lisp_Object data)
{
- PSET (XPROCESS (XCAR (data)), sentinel, XCDR (data));
+ pset_sentinel (XPROCESS (XCAR (data)), XCDR (data));
return Qnil;
}
exec_sentinel (Lisp_Object proc, Lisp_Object reason)
{
Lisp_Object sentinel, odeactivate;
- register struct Lisp_Process *p = XPROCESS (proc);
+ struct Lisp_Process *p = XPROCESS (proc);
ptrdiff_t count = SPECPDL_INDEX ();
- int outer_running_asynch_code = running_asynch_code;
+ bool outer_running_asynch_code = running_asynch_code;
int waiting = waiting_for_user_input_p;
if (inhibit_sentinels)
/* 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 = PGET (p, sentinel);
+ sentinel = p->sentinel;
if (NILP (sentinel))
return;
/* Zilch the sentinel while it's running, to avoid recursive invocations;
assure that it gets restored no matter how the sentinel exits. */
- PSET (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);
p->update_tick = p->tick;
/* If process is still active, read any output that remains. */
- while (! EQ (PGET (p, filter), Qt)
- && ! EQ (PGET (p, status), Qconnect)
- && ! EQ (PGET (p, status), Qlisten)
+ while (! EQ (p->filter, Qt)
+ && ! EQ (p->status, Qconnect)
+ && ! EQ (p->status, Qlisten)
/* Network or serial process not stopped: */
- && ! EQ (PGET (p, command), Qt)
+ && ! EQ (p->command, Qt)
&& p->infd >= 0
&& p != deleting_process
&& read_process_output (proc, p->infd) > 0);
- buffer = PGET (p, buffer);
+ buffer = p->buffer;
/* Get the text to use for the message. */
if (p->raw_status_new)
msg = status_message (p);
/* If process is terminated, deactivate it or delete it. */
- symbol = PGET (p, status);
- if (CONSP (PGET (p, status)))
- symbol = XCAR (PGET (p, status));
+ symbol = p->status;
+ if (CONSP (p->status))
+ symbol = XCAR (p->status);
if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
|| EQ (symbol, Qclosed))
this code to be run again. */
p->update_tick = p->tick;
/* Now output the message suitably. */
- if (!NILP (PGET (p, sentinel)))
+ if (!NILP (p->sentinel))
exec_sentinel (proc, msg);
/* Don't bother with a message in the buffer
when a process becomes runnable. */
/* Avoid error if buffer is deleted
(probably that's why the process is dead, too) */
- if (NILP (BVAR (XBUFFER (buffer), name)))
+ if (!BUFFER_LIVE_P (XBUFFER (buffer)))
continue;
Fset_buffer (buffer);
/* Insert new output into buffer
at the current end-of-output marker,
thus preserving logical ordering of input and output. */
- if (XMARKER (PGET (p, mark))->buffer)
- Fgoto_char (PGET (p, mark));
+ if (XMARKER (p->mark)->buffer)
+ Fgoto_char (p->mark);
else
SET_PT_BOTH (ZV, ZV_BYTE);
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 ");
{ /* FIXME: temporary kludge */
- Lisp_Object tem2 = PGET (p, name); Finsert (1, &tem2); }
+ Lisp_Object tem2 = p->name; Finsert (1, &tem2); }
insert_string (" ");
Finsert (1, &msg);
- BVAR (current_buffer, read_only) = tem;
- set_marker_both (PGET (p, mark), PGET (p, buffer), PT, PT_BYTE);
+ bset_read_only (current_buffer, tem);
+ set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
if (opoint >= before)
SET_PT_BOTH (opoint + (PT - before),
CHECK_PROCESS (process);
p = XPROCESS (process);
if (p->infd < 0)
- error ("Input file descriptor of %s closed", SDATA (PGET (p, name)));
+ error ("Input file descriptor of %s closed", SDATA (p->name));
if (p->outfd < 0)
- error ("Output file descriptor of %s closed", SDATA (PGET (p, name)));
+ error ("Output file descriptor of %s closed", SDATA (p->name));
Fcheck_coding_system (decoding);
Fcheck_coding_system (encoding);
encoding = coding_inherit_eol_type (encoding, Qnil);
- PSET (p, decode_coding_system, decoding);
- PSET (p, encode_coding_system, encoding);
+ pset_decode_coding_system (p, decoding);
+ pset_encode_coding_system (p, encoding);
setup_process_coding_systems (process);
return Qnil;
(register Lisp_Object process)
{
CHECK_PROCESS (process);
- return Fcons (PGET (XPROCESS (process), decode_coding_system),
- PGET (XPROCESS (process), encode_coding_system));
+ return Fcons (XPROCESS (process)->decode_coding_system,
+ XPROCESS (process)->encode_coding_system);
}
DEFUN ("set-process-filter-multibyte", Fset_process_filter_multibyte,
CHECK_PROCESS (process);
p = XPROCESS (process);
if (NILP (flag))
- PSET (p, decode_coding_system,
- raw_text_coding_system (PGET (p, decode_coding_system)));
+ pset_decode_coding_system
+ (p, raw_text_coding_system (p->decode_coding_system));
setup_process_coding_systems (process);
return Qnil;
# endif
-# ifdef SIGIO
+# ifdef USABLE_SIGIO
/* Return nonzero if *MASK has a bit set
that corresponds to one of the keyboard input descriptors. */
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 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 (intmax_t time_limit, int nsecs, int read_kbd,
- int do_display,
+ bool do_display,
Lisp_Object wait_for_cell,
struct Lisp_Process *wait_proc, int just_wait_proc)
{
do
{
- int old_timers_run = timers_run;
+ unsigned old_timers_run = timers_run;
timer_delay = timer_check ();
if (timers_run != old_timers_run && do_display)
/* We must retry, since a timer may have requeued itself
if (!proc_decode_coding_system[inch])
proc_decode_coding_system[inch] = xmalloc (sizeof (struct coding_system));
- coding_system = PGET (p, decode_coding_system);
- if (! NILP (PGET (p, filter)))
+ coding_system = p->decode_coding_system;
+ if (! NILP (p->filter))
;
- else if (BUFFERP (PGET (p, buffer)))
+ else if (BUFFERP (p->buffer))
{
- if (NILP (BVAR (XBUFFER (PGET (p, buffer)), enable_multibyte_characters)))
+ if (NILP (BVAR (XBUFFER (p->buffer), enable_multibyte_characters)))
coding_system = raw_text_coding_system (coding_system);
}
setup_coding_system (coding_system, proc_decode_coding_system[inch]);
if (!proc_encode_coding_system[outch])
proc_encode_coding_system[outch] = xmalloc (sizeof (struct coding_system));
- setup_coding_system (PGET (p, encode_coding_system),
+ setup_coding_system (p->encode_coding_system,
proc_encode_coding_system[outch]);
#endif
}
for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
{
proc = Fcdr (XCAR (tail));
- if (PROCESSP (proc) && EQ (PGET (XPROCESS (proc), buffer), buf))
+ if (PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf))
return proc;
}
#endif /* subprocesses */
{
proc = XCDR (XCAR (tail));
if (PROCESSP (proc)
- && (NILP (buffer) || EQ (PGET (XPROCESS (proc), buffer), buffer)))
+ && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
{
if (NETCONN_P (proc) || SERIALCONN_P (proc))
Fdelete_process (proc);
#ifndef CANNOT_DUMP
if (! noninteractive || initialized)
#endif
- signal (SIGCHLD, sigchld_handler);
+ {
+ struct sigaction action;
+ emacs_sigaction_init (&action, deliver_child_signal);
+ sigaction (SIGCHLD, &action, 0);
+ }
#endif
FD_ZERO (&input_wait_mask);
#ifdef HAVE_GETSOCKNAME
ADD_SUBFEATURE (QCservice, Qt);
#endif
-#if defined (O_NONBLOCK) || defined (O_NDELAY)
+#if O_NONBLOCK || O_NDELAY
ADD_SUBFEATURE (QCserver, Qt);
#endif