Assume POSIX 1003.1-1988 or later for errno.h.
[bpt/emacs.git] / src / process.c
index fbc0349..b23f06f 100644 (file)
@@ -20,15 +20,14 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 #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>
 
@@ -73,6 +72,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #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>
@@ -113,11 +117,17 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #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
 
 /* Work around GCC 4.7.0 bug with strict overflow checking; see
@@ -161,21 +171,11 @@ static Lisp_Object QClocal, QCremote, QCcoding;
 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;
@@ -196,11 +196,9 @@ static EMACS_INT update_tick;
 #ifndef NON_BLOCKING_CONNECT
 #ifdef HAVE_SELECT
 #if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX)
-#if defined (O_NONBLOCK) || defined (O_NDELAY)
 #if defined (EWOULDBLOCK) || defined (EINPROGRESS)
 #define NON_BLOCKING_CONNECT
 #endif /* EWOULDBLOCK || EINPROGRESS */
-#endif /* O_NONBLOCK || O_NDELAY */
 #endif /* HAVE_GETPEERNAME || GNU_LINUX */
 #endif /* HAVE_SELECT */
 #endif /* NON_BLOCKING_CONNECT */
@@ -211,17 +209,13 @@ static EMACS_INT update_tick;
    "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
@@ -250,17 +244,18 @@ static int process_output_skip;
 #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
 
@@ -331,8 +326,87 @@ static struct sockaddr_and_len {
 #define DATAGRAM_CONN_P(proc)  (0)
 #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
 
@@ -428,7 +502,7 @@ static void
 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;
 }
 
@@ -479,7 +553,7 @@ decode_status (Lisp_Object l, Lisp_Object *symbol, int *code, int *coredump)
 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;
@@ -488,7 +562,7 @@ status_message (struct Lisp_Process *p)
 
   if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
     {
-      char *signame;
+      char const *signame;
       synchronize_system_messages_locale ();
       signame = strsignal (code);
       if (signame == 0)
@@ -563,30 +637,7 @@ allocate_pty (void)
 #ifdef PTY_OPEN
        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
-         fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
-#  else
-         fd = emacs_open (pty_name, O_RDWR | O_NDELAY, 0);
-#  endif
-       }
+       fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
 #endif /* no PTY_OPEN */
 
        if (fd >= 0)
@@ -598,7 +649,7 @@ allocate_pty (void)
 #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
@@ -626,8 +677,8 @@ make_process (Lisp_Object name)
   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.  */
@@ -648,7 +699,7 @@ make_process (Lisp_Object name)
       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;
@@ -725,9 +776,8 @@ get_process (register Lisp_Object name)
 #ifdef SIGCHLD
 /* Fdelete_process promises to immediately forget about the process, but in
    reality, Emacs needs to remember those processes until they have been
-   treated by sigchld_handler; otherwise this handler would consider the
-   process as being synchronous and say that the synchronous process is
-   dead.  */
+   treated by the SIGCHLD handler and waitpid has been invoked on them;
+   otherwise they might fill up the kernel's process table.  */
 static Lisp_Object deleted_pid_list;
 #endif
 
@@ -745,7 +795,7 @@ nil, indicating the current buffer's process.  */)
   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);
@@ -763,9 +813,9 @@ nil, indicating the current buffer's process.  */)
       /* 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);
@@ -773,8 +823,9 @@ nil, indicating the current buffer's process.  */)
 #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);
@@ -815,14 +866,14 @@ nil, indicating the current buffer's process.  */)
   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;
@@ -839,8 +890,8 @@ If PROCESS has not yet exited or died, return 0.  */)
   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);
 }
 
@@ -864,7 +915,7 @@ possibly modified to make it unique among process names.  */)
   (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,
@@ -876,7 +927,7 @@ For a network or serial process, this is nil (process is running) or t
   (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,
@@ -886,7 +937,7 @@ not the name of the pty that Emacs uses to talk with that terminal.  */)
   (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,
@@ -901,9 +952,9 @@ Return 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;
 }
@@ -915,7 +966,7 @@ Output from PROCESS is inserted in this buffer unless PROCESS has a filter.  */)
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
-  return PGET (XPROCESS (process), buffer);
+  return XPROCESS (process)->buffer;
 }
 
 DEFUN ("process-mark", Fprocess_mark, Sprocess_mark,
@@ -924,7 +975,7 @@ 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,
@@ -960,23 +1011,23 @@ The string argument is normally a multibyte string, except:
 
   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;
 }
@@ -988,7 +1039,7 @@ See `set-process-filter' for more info on filter functions.  */)
   (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,
@@ -1003,9 +1054,9 @@ It gets two arguments: the process, and a string describing the change.  */)
   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;
 }
 
@@ -1016,7 +1067,7 @@ See `set-process-sentinel' for more info on sentinels.  */)
   (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,
@@ -1101,7 +1152,7 @@ list of keywords.  */)
   Lisp_Object contact;
 
   CHECK_PROCESS (process);
-  contact = PGET (XPROCESS (process), childp);
+  contact = XPROCESS (process)->childp;
 
 #ifdef DATAGRAM_SOCKETS
   if (DATAGRAM_CONN_P (process)
@@ -1127,7 +1178,7 @@ DEFUN ("process-plist", Fprocess_plist, Sprocess_plist,
   (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,
@@ -1138,7 +1189,7 @@ 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;
 }
 
@@ -1150,7 +1201,7 @@ The value is nil for a pipe, t or `pty' for a pty, or `stream' for
 a socket connection.  */)
   (Lisp_Object process)
 {
-  return PGET (XPROCESS (process), type);
+  return XPROCESS (process)->type;
 }
 #endif
 
@@ -1163,7 +1214,7 @@ nil, indicating the current buffer's process.  */)
 {
   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,
@@ -1324,18 +1375,18 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
      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
@@ -1346,7 +1397,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
 
   /* 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)));
 
@@ -1375,7 +1426,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
        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))
@@ -1395,7 +1446,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
        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
@@ -1404,9 +1455,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
   }
 
 
-  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);
@@ -1464,7 +1515,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
              {
                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));
@@ -1501,7 +1552,7 @@ static Lisp_Object
 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.  */
@@ -1524,22 +1575,19 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
   int inchannel, outchannel;
   pid_t pid;
   int sv[2];
-#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+#ifndef WINDOWSNT
   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;
@@ -1553,19 +1601,16 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 #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
       /* 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);
-#else
-      forkout = forkin = emacs_open (pty_name, O_RDWR, 0);
-#endif
       if (forkin < 0)
        report_file_error ("Opening pty", Qnil);
 #else
       forkin = forkout = -1;
 #endif /* not USG, or USG_SUBTTY_WORKS */
       pty_flag = 1;
+      lisp_pty_name = build_string (pty_name);
     }
   else
 #endif /* HAVE_PTYS */
@@ -1587,7 +1632,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
       forkin = sv[0];
     }
 
-#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+#ifndef WINDOWSNT
     {
       int tem;
 
@@ -1606,15 +1651,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
     }
 #endif
 
-#ifdef O_NONBLOCK
   fcntl (inchannel, F_SETFL, O_NONBLOCK);
   fcntl (outchannel, F_SETFL, O_NONBLOCK);
-#else
-#ifdef O_NDELAY
-  fcntl (inchannel, F_SETFL, O_NDELAY);
-  fcntl (outchannel, F_SETFL, O_NDELAY);
-#endif
-#endif
 
   /* Record this as an active process, with its channels.
      As a result, child_setup will close Emacs's side of the pipes.  */
@@ -1628,207 +1666,173 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
      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
-     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
-     it might cause call-process to hang and subsequent asynchronous
-     processes to get their return values scrambled.  */
-  XPROCESS (process)->pid = -1;
-
-  /* This must be called after the above line because it may signal an
-     error. */
+  /* This may signal an 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.  */
-#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)
-         {
+      /* First, disconnect its current controlling terminal.  */
+      /* 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 ();
-#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);
-             }
-#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.  */
-#ifdef HAVE_SETPGID
-           setpgid (0, 0);
-#else
-           setpgrp (0, 0);
-#endif
-#endif
-         }
+      /* 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);
+           }
+       }
 #endif /* TIOCNOTTY */
 
 #if !defined (DONT_REOPEN_PTY)
 /*** There is a suggestion that this ought to be a
-     conditional on TIOCSPGRP,
-     or !(defined (HAVE_SETSID) && defined (TIOCSCTTY)).
+     conditional on TIOCSPGRP, or !defined TIOCSCTTY.
      Trying the latter gave the wrong results on Debian GNU/Linux 1.1;
      that system does seem to need this code, even though
-     both HAVE_SETSID and TIOCSCTTY are defined.  */
+     both TIOCSCTTY is 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]);
-#endif
-       child_setup (xforkin, xforkout, xforkout,
-                    new_argv, 1, encoded_current_dir);
+      emacs_close (wait_child_setup[0]);
+      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;
+  if (0 <= pid)
+    XPROCESS (process)->alive = 1;
 
-  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)
@@ -1839,7 +1843,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
   else
     {
       /* vfork succeeded.  */
-      XPROCESS (process)->pid = pid;
 
 #ifdef WINDOWSNT
       register_child (pid, inchannel);
@@ -1865,14 +1868,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
       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)
+#ifndef WINDOWSNT
       /* Wait for child_setup to complete in case that vfork is
         actually defined as fork.  The descriptor wait_child_setup[1]
         of a pipe is closed at the child side either by close-on-exec
@@ -1887,20 +1885,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 #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);
@@ -1923,13 +1907,9 @@ create_pty (Lisp_Object process)
 #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
       /* 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);
-#else
-      int forkout = emacs_open (pty_name, O_RDWR, 0);
-#endif
       if (forkout < 0)
        report_file_error ("Opening pty", Qnil);
 #if defined (DONT_REOPEN_PTY)
@@ -1943,15 +1923,8 @@ create_pty (Lisp_Object process)
     }
 #endif /* HAVE_PTYS */
 
-#ifdef O_NONBLOCK
   fcntl (inchannel, F_SETFL, O_NONBLOCK);
   fcntl (outchannel, F_SETFL, O_NONBLOCK);
-#else
-#ifdef O_NDELAY
-  fcntl (inchannel, F_SETFL, O_NDELAY);
-  fcntl (outchannel, F_SETFL, O_NDELAY);
-#endif
-#endif
 
   /* Record this as an active process, with its channels.
      As a result, child_setup will close Emacs's side of the pipes.  */
@@ -1965,7 +1938,7 @@ create_pty (Lisp_Object process)
      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);
@@ -1976,10 +1949,10 @@ create_pty (Lisp_Object process)
   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
@@ -2368,7 +2341,7 @@ OPTION is not a supported option, return nil instead; otherwise return t.  */)
 
   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;
     }
 
@@ -2457,10 +2430,10 @@ usage: (serial-process-configure &rest ARGS)  */)
     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;
@@ -2477,7 +2450,7 @@ static Lisp_Object
 make_serial_process_unwind (Lisp_Object proc)
 {
   if (!PROCESSP (proc))
-    abort ();
+    emacs_abort ();
   remove_process (proc);
   return Qnil;
 }
@@ -2601,21 +2574,21 @@ usage:  (make-serial-process &rest ARGS)  */)
   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);
@@ -2623,7 +2596,7 @@ usage:  (make-serial-process &rest ARGS)  */)
 
   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)));
     }
@@ -2644,7 +2617,7 @@ usage:  (make-serial-process &rest ARGS)  */)
   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))
@@ -2658,12 +2631,12 @@ usage:  (make-serial-process &rest ARGS)  */)
   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);
 
@@ -2907,13 +2880,9 @@ usage: (make-network-process &rest ARGS)  */)
     {
       /* 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)
-      error ("Network servers not supported");
-#else
       is_server = 1;
       if (TYPE_RANGED_INTEGERP (int, tem))
        backlog = XINT (tem);
-#endif
     }
 
   /* Make QCaddress an alias for :local (server) or :remote (client).  */
@@ -3173,11 +3142,7 @@ usage: (make-network-process &rest ARGS)  */)
 #ifdef NON_BLOCKING_CONNECT
       if (is_non_blocking_client)
        {
-#ifdef O_NONBLOCK
          ret = fcntl (s, F_SETFL, O_NONBLOCK);
-#else
-         ret = fcntl (s, F_SETFL, O_NDELAY);
-#endif
          if (ret < 0)
            {
              xerrno = errno;
@@ -3314,7 +3279,7 @@ usage: (make-network-process &rest ARGS)  */)
       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)
@@ -3353,9 +3318,9 @@ usage: (make-network-process &rest ARGS)  */)
 #ifdef HAVE_GETADDRINFO
   if (res != &ai)
     {
-      BLOCK_INPUT;
+      block_input ();
       freeaddrinfo (res);
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 #endif
 
@@ -3390,37 +3355,31 @@ usage: (make-network-process &rest ARGS)  */)
 
   chan_process[inch] = proc;
 
-#ifdef O_NONBLOCK
   fcntl (inch, F_SETFL, O_NONBLOCK);
-#else
-#ifdef 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)));
 
@@ -3430,7 +3389,7 @@ usage: (make-network-process &rest ARGS)  */)
       /* 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);
@@ -3442,8 +3401,8 @@ usage: (make-network-process &rest ARGS)  */)
 #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);
@@ -3497,7 +3456,7 @@ usage: (make-network-process &rest ARGS)  */)
        else
          val = Qnil;
       }
-    PSET (p, decode_coding_system, val);
+    pset_decode_coding_system (p, val);
 
     if (!NILP (tem))
       {
@@ -3531,13 +3490,13 @@ usage: (make-network-process &rest ARGS)  */)
        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);
@@ -3900,7 +3859,7 @@ deactivate_process (Lisp_Object proc)
          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)
@@ -4030,8 +3989,8 @@ server_accept_connection (Lisp_Object server, int channel)
        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")));
@@ -4101,15 +4060,15 @@ server_accept_connection (Lisp_Object server, int channel)
      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);
@@ -4120,23 +4079,17 @@ server_accept_connection (Lisp_Object server, int channel)
   /* 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
   fcntl (s, F_SETFL, O_NONBLOCK);
-#else
-#ifdef 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))
@@ -4150,21 +4103,21 @@ server_accept_connection (Lisp_Object server, int channel)
                          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);
@@ -4178,24 +4131,24 @@ server_accept_connection (Lisp_Object server, int channel)
      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 ("-")),
@@ -4246,7 +4199,7 @@ wait_reading_process_output_1 (void)
      -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
@@ -4266,7 +4219,7 @@ wait_reading_process_output_1 (void)
 
 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)
 {
@@ -4286,8 +4239,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
   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.  */
@@ -4323,10 +4276,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
         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)))
@@ -4365,7 +4316,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
          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;
 
@@ -4401,7 +4352,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                  if (EMACS_TIME_LT (timer_delay, timeout))
                    {
                      timeout = timer_delay;
-                     timeout_reduced_for_timers = 1;
+                     timeout_reduced_for_timers = 1;
                    }
                }
              else
@@ -4460,8 +4411,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       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;
 
@@ -4481,14 +4432,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                  total_nread += nread;
                  got_some_input = 1;
                }
-#ifdef EIO
-             else if (nread == -1 && EIO == errno)
-               break;
-#endif
-#ifdef EAGAIN
-             else if (nread == -1 && EAGAIN == errno)
+             else if (nread == -1 && (errno == EIO || errno == EAGAIN))
                break;
-#endif
 #ifdef EWOULDBLOCK
              else if (nread == -1 && EWOULDBLOCK == errno)
                break;
@@ -4592,6 +4537,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
              process_output_skip = 0;
            }
 #endif
+
 #if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS)
           nfds = xg_select
 #elif defined (HAVE_NS)
@@ -4679,7 +4625,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                 Cleanup occurs c/o status_notify after SIGCLD. */
              no_avail = 1; /* Cannot depend on values returned */
 #else
-             abort ();
+             emacs_abort ();
 #endif
            }
          else
@@ -4692,28 +4638,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
          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;
@@ -4762,7 +4693,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       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,
@@ -4770,7 +4701,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
       if (read_kbd && interrupt_input
          && keyboard_bit_set (&Available) && ! noninteractive)
-       kill (getpid (), SIGIO);
+       handle_input_available_signal (SIGIO);
 #endif
 
       if (! wait_proc)
@@ -4788,15 +4719,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       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++)
        {
@@ -4820,7 +4749,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                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;
@@ -4845,23 +4774,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
              else if (nread == -1 && errno == EWOULDBLOCK)
                ;
 #endif
-             /* ISC 4.1 defines both EWOULDBLOCK and O_NONBLOCK,
-                and Emacs uses O_NONBLOCK, so what we get is EAGAIN.  */
-#ifdef O_NONBLOCK
-             else if (nread == -1 && errno == EAGAIN)
-               ;
-#else
-#ifdef O_NDELAY
              else if (nread == -1 && errno == EAGAIN)
                ;
+#ifdef WINDOWSNT
+             /* FIXME: Is this special case still needed?  */
              /* Note that we cannot distinguish between no input
                 available now and a closed pipe.
                 With luck, a closed pipe will be accompanied by
                 subprocess termination and SIGCHLD.  */
              else if (nread == 0 && !NETCONN_P (proc) && !SERIALCONN_P (proc))
                ;
-#endif /* O_NDELAY */
-#endif /* O_NONBLOCK */
+#endif
 #ifdef HAVE_PTYS
              /* On some OSs with ptys, when the process on one end of
                 a pty exits, the other end gets an error reading with
@@ -4885,14 +4808,14 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
                  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
@@ -4908,9 +4831,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                  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
@@ -4922,7 +4845,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
              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))
@@ -4958,18 +4881,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
              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);
@@ -5041,7 +4963,7 @@ read_process_output (Lisp_Object proc, register int channel)
   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.  */
@@ -5117,14 +5039,14 @@ read_process_output (Lisp_Object proc, register int channel)
   /* 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
@@ -5162,9 +5084,9 @@ read_process_output (Lisp_Object proc, register int channel)
       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
@@ -5177,21 +5099,21 @@ read_process_output (Lisp_Object proc, register int channel)
             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;
        }
@@ -5227,7 +5149,7 @@ read_process_output (Lisp_Object proc, register int channel)
     }
 
   /* 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;
@@ -5237,7 +5159,7 @@ read_process_output (Lisp_Object proc, register int channel)
       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);
@@ -5246,16 +5168,16 @@ read_process_output (Lisp_Object proc, register int channel)
       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);
@@ -5272,23 +5194,23 @@ read_process_output (Lisp_Object proc, register int channel)
       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;
        }
@@ -5306,11 +5228,11 @@ read_process_output (Lisp_Object proc, register int channel)
       /* 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++;
 
@@ -5337,7 +5259,7 @@ read_process_output (Lisp_Object proc, register int channel)
        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.  */
@@ -5349,21 +5271,6 @@ read_process_output (Lisp_Object proc, register int channel)
 \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.
@@ -5404,9 +5311,9 @@ write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj,
   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
@@ -5420,11 +5327,11 @@ write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj,
   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);
@@ -5447,21 +5354,19 @@ write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj,
    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);
@@ -5471,9 +5376,9 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
          && !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
@@ -5483,8 +5388,8 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
             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;
     }
@@ -5548,156 +5453,123 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
       buf = SSDATA (object);
     }
 
-  if (pty_max_bytes == 0)
-    {
-#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
-      pty_max_bytes = fpathconf (p->outfd, _PC_MAX_CANON);
-      if (pty_max_bytes < 0)
-       pty_max_bytes = 250;
-#else
-      pty_max_bytes = 250;
-#endif
-      /* Deduct one, to leave space for the eof.  */
-      pty_max_bytes--;
-    }
+  /* 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);
 
-  /* 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))
+  do   /* while !NILP (p->write_queue) */
     {
-      p = XPROCESS (proc);  /* Repair any setjmp clobbering.  */
-      process_sent_to = proc;
+      ptrdiff_t cur_len = -1;
+      const char *cur_buf;
+      Lisp_Object cur_object;
 
-      /* 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) */
+      /* 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 (errno == EAGAIN
 #ifdef EWOULDBLOCK
-                     || errno == EWOULDBLOCK
-#endif
-#ifdef EAGAIN
-                     || errno == EAGAIN
+                 || errno == EWOULDBLOCK
 #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,
@@ -5754,12 +5626,12 @@ emacs_get_tty_pgrp (struct Lisp_Process *p)
   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)
        {
@@ -5788,12 +5660,12 @@ return t unconditionally.  */)
   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);
 
@@ -5828,12 +5700,12 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
   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;
@@ -5922,7 +5794,7 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
 #ifdef SIGCONT
     case SIGCONT:
       p->raw_status_new = 0;
-      PSET (p, status, Qrun);
+      pset_status (p, Qrun);
       p->tick = ++process_tick;
       if (!nomsg)
        {
@@ -6012,13 +5884,13 @@ traffic.  */)
       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
@@ -6041,9 +5913,9 @@ traffic.  */)
       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);
@@ -6054,7 +5926,7 @@ traffic.  */)
          tcflush (p->infd, TCIFLUSH);
 #endif /* not WINDOWSNT */
        }
-      PSET (p, command, Qnil);
+      pset_command (p, Qnil);
       return process;
     }
 #ifdef SIGCONT
@@ -6101,8 +5973,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
       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)              \
@@ -6129,39 +6000,27 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
 #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
@@ -6246,8 +6105,8 @@ process has been transmitted to the serial port.  */)
   /* 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))
     {
@@ -6257,7 +6116,7 @@ process has been transmitted to the serial port.  */)
 
   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)
@@ -6274,7 +6133,7 @@ process has been transmitted to the serial port.  */)
         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.  */
@@ -6285,15 +6144,14 @@ process has been transmitted to the serial port.  */)
 #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));
 
@@ -6302,9 +6160,35 @@ process has been transmitted to the serial port.  */)
   return process;
 }
 \f
-/* On receipt of a signal that a child status has changed, loop asking
-   about children with changed statuses until the system says there
-   are no more.
+/* If the status of the process DESIRED has changed, return true and
+   set *STATUS to its exit status; otherwise, return false.
+   If HAVE is nonnegative, assume that HAVE = waitpid (HAVE, STATUS, ...)
+   has already been invoked, and do not invoke waitpid again.  */
+
+static bool
+process_status_retrieved (pid_t desired, pid_t have, int *status)
+{
+  if (have < 0)
+    {
+      /* Invoke waitpid only with a known process ID; do not invoke
+        waitpid with a nonpositive argument.  Otherwise, Emacs might
+        reap an unwanted process by mistake.  For example, invoking
+        waitpid (-1, ...) can mess up glib by reaping glib's subprocesses,
+        so that another thread running glib won't find them.  */
+      do
+       have = waitpid (desired, status, WNOHANG | WUNTRACED);
+      while (have < 0 && errno == EINTR);
+    }
+
+  return have == desired;
+}
+
+/* If PID is nonnegative, the child process PID with wait status W has
+   changed its status; record this and return true.
+
+   If PID is negative, ignore W, and look for known child processes
+   of Emacs whose status have changed.  For each one found, record its new
+   status.
 
    All we do is change the status; we do not run sentinels or print
    notifications.  That is saved for the next time keyboard input is
@@ -6327,151 +6211,122 @@ process has been transmitted to the serial port.  */)
    ** 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)
+void
+record_child_status_change (pid_t pid, int w)
 {
-  int old_errno = errno;
-  Lisp_Object proc;
-  struct Lisp_Process *p;
-
-  SIGNAL_THREAD_CHECK (signo);
-
-  while (1)
-    {
-      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);
+#ifdef SIGCHLD
 
-      if (pid <= 0)
-       {
-         /* PID == 0 means no processes found, PID == -1 means a real
-            failure.  We have done all our job, so return.  */
+  /* Record at most one child only if we already know one child that
+     has exited.  */
+  bool record_at_most_one_child = 0 <= pid;
 
-         errno = old_errno;
-         return;
-       }
-#else
-      pid = wait (&w);
-#endif /* no WNOHANG */
+  Lisp_Object tail;
 
-      /* Find the process that signaled us, and record its status.  */
+  /* 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))
+  /* The process can have been deleted by Fdelete_process.  */
+  for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail))
+    {
+      bool all_pids_are_fixnums
+       = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t)
+          && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM);
+      Lisp_Object xpid = XCAR (tail);
+      if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid))
        {
-         Lisp_Object xpid = XCAR (tail);
-         if ((INTEGERP (xpid) && pid == XINT (xpid))
-             || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid)))
+         pid_t deleted_pid;
+         if (INTEGERP (xpid))
+           deleted_pid = XINT (xpid);
+         else
+           deleted_pid = XFLOAT_DATA (xpid);
+         if (process_status_retrieved (deleted_pid, pid, &w))
            {
              XSETCAR (tail, Qnil);
-             goto sigchld_end_of_loop;
+             if (record_at_most_one_child)
+               return;
            }
        }
+    }
 
-      /* 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 (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)
+  /* Otherwise, if it is asynchronous, it is in Vprocess_alist.  */
+  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+    {
+      Lisp_Object proc = XCDR (XCAR (tail));
+      struct Lisp_Process *p = XPROCESS (proc);
+      if (p->alive && process_status_retrieved (p->pid, pid, &w))
        {
-         int clear_desc_flag = 0;
-
+         /* Change the status of the process that was found.  */
          p->tick = ++process_tick;
          p->raw_status = w;
          p->raw_status_new = 1;
 
          /* If process has terminated, stop waiting for its output.  */
-         if ((WIFSIGNALED (w) || WIFEXITED (w))
-             && p->infd >= 0)
-           clear_desc_flag = 1;
-
-         /* We use clear_desc_flag to avoid a compiler bug in Microsoft C.  */
-         if (clear_desc_flag)
+         if (WIFSIGNALED (w) || WIFEXITED (w))
            {
-             FD_CLR (p->infd, &input_wait_mask);
-             FD_CLR (p->infd, &non_keyboard_wait_mask);
+             int clear_desc_flag = 0;
+             p->alive = 0;
+             if (p->infd >= 0)
+               clear_desc_flag = 1;
+
+             /* clear_desc_flag avoids 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);
+               }
            }
 
          /* 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 (record_at_most_one_child)
+           return;
        }
+    }
 
-      /* There was no asynchronous process found for that pid: we have
-        a synchronous process.  */
-      else
-       {
-         synch_process_alive = 0;
+  if (0 <= pid)
+    {
+      /* The caller successfully waited for a pid but no asynchronous
+        process was found for it, so this is a synchronous process.  */
 
-         /* Report the status of the synchronous process.  */
-         if (WIFEXITED (w))
-           synch_process_retcode = WEXITSTATUS (w);
-         else if (WIFSIGNALED (w))
-           synch_process_termsig = WTERMSIG (w);
+      synch_process_alive = 0;
 
-         /* 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);
-       }
+      /* Report the status of the synchronous process.  */
+      if (WIFEXITED (w))
+       synch_process_retcode = WEXITSTATUS (w);
+      else if (WIFSIGNALED (w))
+       synch_process_termsig = WTERMSIG (w);
 
-    sigchld_end_of_loop:
-      ;
-
-      /* On some systems, we must return right away.
-        If any more processes want to signal us, we will
-        get another signal.
-        Otherwise (on systems that have WNOHANG), 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 */
+      /* 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
+}
+
+#ifdef SIGCHLD
+
+static void
+handle_child_signal (int sig)
+{
+  record_child_status_change (-1, 0);
 }
+
+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;
 }
 
@@ -6489,9 +6344,9 @@ static void
 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)
@@ -6509,15 +6364,15 @@ exec_sentinel (Lisp_Object proc, Lisp_Object reason)
   /* 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);
@@ -6605,16 +6460,16 @@ status_notify (struct Lisp_Process *deleting_process)
          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)
@@ -6622,9 +6477,9 @@ status_notify (struct Lisp_Process *deleting_process)
          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))
@@ -6641,7 +6496,7 @@ status_notify (struct Lisp_Process *deleting_process)
             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.  */
@@ -6654,7 +6509,7 @@ status_notify (struct Lisp_Process *deleting_process)
 
              /* 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);
 
@@ -6663,8 +6518,8 @@ status_notify (struct Lisp_Process *deleting_process)
              /* 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);
 
@@ -6672,14 +6527,14 @@ status_notify (struct Lisp_Process *deleting_process)
              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),
@@ -6709,14 +6564,14 @@ encode subprocess input.  */)
   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;
@@ -6728,8 +6583,8 @@ DEFUN ("process-coding-system",
   (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,
@@ -6746,8 +6601,8 @@ suppressed.  */)
   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;
@@ -6786,7 +6641,7 @@ delete_gpm_wait_descriptor (int desc)
 
 # endif
 
-# ifdef SIGIO
+# ifdef USABLE_SIGIO
 
 /* Return nonzero if *MASK has a bit set
    that corresponds to one of the keyboard input descriptors.  */
@@ -6836,14 +6691,14 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
    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)
 {
@@ -6919,7 +6774,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
          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
@@ -7085,19 +6940,19 @@ setup_process_coding_systems (Lisp_Object process)
 
   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
 }
@@ -7143,7 +6998,7 @@ BUFFER may be a buffer or the name of one.  */)
   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 */
@@ -7182,7 +7037,7 @@ kill_buffer_processes (Lisp_Object buffer)
     {
       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);
@@ -7318,7 +7173,11 @@ init_process_emacs (void)
 #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);
@@ -7386,9 +7245,7 @@ init_process_emacs (void)
 #ifdef HAVE_GETSOCKNAME
    ADD_SUBFEATURE (QCservice, Qt);
 #endif
-#if defined (O_NONBLOCK) || defined (O_NDELAY)
    ADD_SUBFEATURE (QCserver, Qt);
-#endif
 
    for (sopt = socket_options; sopt->name; sopt++)
      subfeatures = pure_cons (intern_c_string (sopt->name), subfeatures);