Signal-handler cleanup.
[bpt/emacs.git] / src / process.c
index aaf8693..0cc9bc3 100644 (file)
@@ -20,7 +20,9 @@ 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>
@@ -113,11 +115,20 @@ 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"
+
+#ifndef WNOHANG
+# undef waitpid
+# define waitpid(pid, status, options) wait (status)
+#endif
+#ifndef WUNTRACED
+# define WUNTRACED 0
 #endif
 
 /* Work around GCC 4.7.0 bug with strict overflow checking; see
@@ -161,21 +172,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 (XPROCESS (p)->type, Qnetwork))
-#define NETCONN1_P(p) (EQ ((p)->type, Qnetwork))
+#define NETCONN1_P(p) (EQ (p->type, Qnetwork))
 #define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial))
-#define SERIALCONN1_P(p) (EQ ((p)->type, Qserial))
+#define SERIALCONN1_P(p) (EQ (p->type, Qserial))
 
 #ifndef HAVE_H_ERRNO
 extern int h_errno;
@@ -249,7 +250,6 @@ static int process_output_skip;
 #define process_output_delay_count 0
 #endif
 
-static Lisp_Object Fget_process (Lisp_Object);
 static void create_process (Lisp_Object, char **, Lisp_Object);
 #ifdef SIGIO
 static int keyboard_bit_set (SELECT_TYPE *);
@@ -335,6 +335,88 @@ static struct sockaddr_and_len {
 /* Maximum number of bytes to send to a pty without an eof.  */
 static int pty_max_bytes;
 
+/* These setters are used only in this file, so they can be private.  */
+static inline void
+pset_buffer (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->buffer = val;
+}
+static inline void
+pset_command (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->command = val;
+}
+static inline void
+pset_decode_coding_system (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->decode_coding_system = val;
+}
+static inline void
+pset_decoding_buf (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->decoding_buf = val;
+}
+static inline void
+pset_encode_coding_system (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->encode_coding_system = val;
+}
+static inline void
+pset_encoding_buf (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->encoding_buf = val;
+}
+static inline void
+pset_filter (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->filter = val;
+}
+static inline void
+pset_log (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->log = val;
+}
+static inline void
+pset_mark (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->mark = val;
+}
+static inline void
+pset_name (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->name = val;
+}
+static inline void
+pset_plist (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->plist = val;
+}
+static inline void
+pset_sentinel (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->sentinel = val;
+}
+static inline void
+pset_status (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->status = val;
+}
+static inline void
+pset_tty_name (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->tty_name = val;
+}
+static inline void
+pset_type (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->type = val;
+}
+static inline void
+pset_write_queue (struct Lisp_Process *p, Lisp_Object val)
+{
+  p->write_queue = val;
+}
+
 \f
 
 static struct fd_callback_data
@@ -353,7 +435,7 @@ static struct fd_callback_data
 void
 add_read_fd (int fd, fd_callback func, void *data)
 {
-  xassert (fd < MAXDESC);
+  eassert (fd < MAXDESC);
   add_keyboard_wait_descriptor (fd);
 
   fd_callback_info[fd].func = func;
@@ -366,7 +448,7 @@ add_read_fd (int fd, fd_callback func, void *data)
 void
 delete_read_fd (int fd)
 {
-  xassert (fd < MAXDESC);
+  eassert (fd < MAXDESC);
   delete_keyboard_wait_descriptor (fd);
 
   fd_callback_info[fd].condition &= ~FOR_READ;
@@ -383,7 +465,7 @@ delete_read_fd (int fd)
 void
 add_write_fd (int fd, fd_callback func, void *data)
 {
-  xassert (fd < MAXDESC);
+  eassert (fd < MAXDESC);
   FD_SET (fd, &write_mask);
   if (fd > max_input_desc)
     max_input_desc = fd;
@@ -400,7 +482,7 @@ delete_write_fd (int fd)
 {
   int lim = max_input_desc;
 
-  xassert (fd < MAXDESC);
+  eassert (fd < MAXDESC);
   FD_CLR (fd, &write_mask);
   fd_callback_info[fd].condition &= ~FOR_WRITE;
   if (fd_callback_info[fd].condition == 0)
@@ -429,7 +511,7 @@ static void
 update_status (struct Lisp_Process *p)
 {
   eassert (p->raw_status_new);
-  p->status = status_convert (p->raw_status);
+  pset_status (p, status_convert (p->raw_status));
   p->raw_status_new = 0;
 }
 
@@ -442,7 +524,7 @@ status_convert (int w)
   if (WIFSTOPPED (w))
     return Fcons (Qstop, Fcons (make_number (WSTOPSIG (w)), Qnil));
   else if (WIFEXITED (w))
-    return Fcons (Qexit, Fcons (make_number (WRETCODE (w)),
+    return Fcons (Qexit, Fcons (make_number (WEXITSTATUS (w)),
                                WCOREDUMP (w) ? Qt : Qnil));
   else if (WIFSIGNALED (w))
     return Fcons (Qsignal, Fcons (make_number (WTERMSIG (w)),
@@ -498,7 +580,7 @@ status_message (struct Lisp_Process *p)
        {
          int c1, c2;
 
-         string = make_unibyte_string (signame, strlen (signame));
+         string = build_unibyte_string (signame);
          if (! NILP (Vlocale_coding_system))
            string = (code_convert_string_norecord
                      (string, Vlocale_coding_system, 0));
@@ -625,35 +707,18 @@ make_process (Lisp_Object name)
   printmax_t i;
 
   p = allocate_process ();
+  /* Initialize Lisp data.  Note that allocate_process initializes all
+     Lisp data to nil, so do it only for slots which should not be nil.  */
+  pset_status (p, Qrun);
+  pset_mark (p, Fmake_marker ());
 
+  /* Initialize non-Lisp data.  Note that allocate_process zeroes out all
+     non-Lisp data, so do it only for slots which should not be zero.  */
   p->infd = -1;
   p->outfd = -1;
-  p->tick = 0;
-  p->update_tick = 0;
-  p->pid = 0;
-  p->pty_flag = 0;
-  p->raw_status_new = 0;
-  p->status = Qrun;
-  p->mark = Fmake_marker ();
-  p->kill_without_query = 0;
-  p->write_queue = Qnil;
-
-#ifdef ADAPTIVE_READ_BUFFERING
-  p->adaptive_read_buffering = 0;
-  p->read_output_delay = 0;
-  p->read_output_skip = 0;
-#endif
 
 #ifdef HAVE_GNUTLS
   p->gnutls_initstage = GNUTLS_STAGE_EMPTY;
-  /* Default log level.  */
-  p->gnutls_log_level = 0;
-  /* GnuTLS handshakes attempted for this connection.  */
-  p->gnutls_handshakes_tried = 0;
-  p->gnutls_p = 0;
-  p->gnutls_state = NULL;
-  p->gnutls_x509_cred = NULL;
-  p->gnutls_anon_cred = NULL;
 #endif
 
   /* If name is already in use, modify it until it is unused.  */
@@ -663,11 +728,10 @@ make_process (Lisp_Object name)
     {
       tem = Fget_process (name1);
       if (NILP (tem)) break;
-      sprintf (suffix, "<%"pMd">", i);
-      name1 = concat2 (name, build_string (suffix));
+      name1 = concat2 (name, make_formatted_string (suffix, "<%"pMd">", i));
     }
   name = name1;
-  p->name = name;
+  pset_name (p, name);
   XSETPROCESS (val, p);
   Vprocess_alist = Fcons (Fcons (name, val), Vprocess_alist);
   return val;
@@ -744,7 +808,7 @@ 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
+   treated by the SIGCHLD handler; otherwise this handler would consider the
    process as being synchronous and say that the synchronous process is
    dead.  */
 static Lisp_Object deleted_pid_list;
@@ -764,7 +828,7 @@ nil, indicating the current buffer's process.  */)
   p->raw_status_new = 0;
   if (NETCONN1_P (p) || SERIALCONN1_P (p))
     {
-      p->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
+      pset_status (p, Fcons (Qexit, Fcons (make_number (0), Qnil)));
       p->tick = ++process_tick;
       status_notify (p);
       redisplay_preserve_echo_area (13);
@@ -792,9 +856,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.  */
-         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);
@@ -921,9 +985,9 @@ Return BUFFER.  */)
   if (!NILP (buffer))
     CHECK_BUFFER (buffer);
   p = XPROCESS (process);
-  p->buffer = buffer;
+  pset_buffer (p, buffer);
   if (NETCONN1_P (p) || SERIALCONN1_P (p))
-    p->childp = Fplist_put (p->childp, QCbuffer, buffer);
+    pset_childp (p, Fplist_put (p->childp, QCbuffer, buffer));
   setup_process_coding_systems (process);
   return buffer;
 }
@@ -994,9 +1058,9 @@ The string argument is normally a multibyte string, except:
        }
     }
 
-  p->filter = filter;
+  pset_filter (p, filter);
   if (NETCONN1_P (p) || SERIALCONN1_P (p))
-    p->childp = Fplist_put (p->childp, QCfilter, filter);
+    pset_childp (p, Fplist_put (p->childp, QCfilter, filter));
   setup_process_coding_systems (process);
   return filter;
 }
@@ -1023,9 +1087,9 @@ It gets two arguments: the process, and a string describing the change.  */)
   CHECK_PROCESS (process);
   p = XPROCESS (process);
 
-  p->sentinel = sentinel;
+  pset_sentinel (p, sentinel);
   if (NETCONN1_P (p) || SERIALCONN1_P (p))
-    p->childp = Fplist_put (p->childp, QCsentinel, sentinel);
+    pset_childp (p, Fplist_put (p->childp, QCsentinel, sentinel));
   return sentinel;
 }
 
@@ -1045,8 +1109,8 @@ DEFUN ("set-process-window-size", Fset_process_window_size,
   (register Lisp_Object process, Lisp_Object height, Lisp_Object width)
 {
   CHECK_PROCESS (process);
-  CHECK_RANGED_INTEGER (0, height, INT_MAX);
-  CHECK_RANGED_INTEGER (0, width, INT_MAX);
+  CHECK_RANGED_INTEGER (height, 0, INT_MAX);
+  CHECK_RANGED_INTEGER (width, 0, INT_MAX);
 
   if (XPROCESS (process)->infd < 0
       || set_window_size (XPROCESS (process)->infd,
@@ -1106,10 +1170,6 @@ DEFUN ("process-query-on-exit-flag",
   return (XPROCESS (process)->kill_without_query ? Qnil : Qt);
 }
 
-#ifdef DATAGRAM_SOCKETS
-static Lisp_Object Fprocess_datagram_address (Lisp_Object);
-#endif
-
 DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
        1, 2, 0,
        doc: /* Return the contact info of PROCESS; t for a real child.
@@ -1162,7 +1222,7 @@ DEFUN ("set-process-plist", Fset_process_plist, Sset_process_plist,
   CHECK_PROCESS (process);
   CHECK_LIST (plist);
 
-  XPROCESS (process)->plist = plist;
+  pset_plist (XPROCESS (process), plist);
   return plist;
 }
 
@@ -1348,18 +1408,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);
 
-  XPROCESS (proc)->childp = Qt;
-  XPROCESS (proc)->plist = Qnil;
-  XPROCESS (proc)->type = Qreal;
-  XPROCESS (proc)->buffer = buffer;
-  XPROCESS (proc)->sentinel = Qnil;
-  XPROCESS (proc)->filter = Qnil;
-  XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
+  pset_childp (XPROCESS (proc), Qt);
+  pset_plist (XPROCESS (proc), Qnil);
+  pset_type (XPROCESS (proc), Qreal);
+  pset_buffer (XPROCESS (proc), buffer);
+  pset_sentinel (XPROCESS (proc), Qnil);
+  pset_filter (XPROCESS (proc), Qnil);
+  pset_command (XPROCESS (proc), Flist (nargs - 2, args + 2));
 
 #ifdef HAVE_GNUTLS
   /* AKA GNUTLS_INITSTAGE(proc).  */
   XPROCESS (proc)->gnutls_initstage = GNUTLS_STAGE_EMPTY;
-  XPROCESS (proc)->gnutls_cred_type = Qnil;
+  pset_gnutls_cred_type (XPROCESS (proc), Qnil);
 #endif
 
 #ifdef ADAPTIVE_READ_BUFFERING
@@ -1387,7 +1447,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
     val = Vcoding_system_for_read;
     if (NILP (val))
       {
-       args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+       args2 = alloca ((nargs + 1) * sizeof *args2);
        args2[0] = Qstart_process;
        for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
        GCPRO2 (proc, current_dir);
@@ -1399,14 +1459,14 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
        else if (CONSP (Vdefault_process_coding_system))
          val = XCAR (Vdefault_process_coding_system);
       }
-    XPROCESS (proc)->decode_coding_system = val;
+    pset_decode_coding_system (XPROCESS (proc), val);
 
     val = Vcoding_system_for_write;
     if (NILP (val))
       {
        if (EQ (coding_systems, Qt))
          {
-           args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+           args2 = alloca ((nargs + 1) * sizeof *args2);
            args2[0] = Qstart_process;
            for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
            GCPRO2 (proc, current_dir);
@@ -1419,7 +1479,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
        else if (CONSP (Vdefault_process_coding_system))
          val = XCDR (Vdefault_process_coding_system);
       }
-    XPROCESS (proc)->encode_coding_system = val;
+    pset_encode_coding_system (XPROCESS (proc), val);
     /* Note: At this moment, the above coding system may leave
        text-conversion or eol-conversion unspecified.  They will be
        decided after we read output from the process and decode it by
@@ -1428,9 +1488,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
   }
 
 
-  XPROCESS (proc)->decoding_buf = empty_unibyte_string;
+  pset_decoding_buf (XPROCESS (proc), empty_unibyte_string);
   XPROCESS (proc)->decoding_carryover = 0;
-  XPROCESS (proc)->encoding_buf = empty_unibyte_string;
+  pset_encoding_buf (XPROCESS (proc), empty_unibyte_string);
 
   XPROCESS (proc)->inherit_coding_system_flag
     = !(NILP (buffer) || !inherit_process_coding_system);
@@ -1500,7 +1560,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
 
       /* Now that everything is encoded we can collect the strings into
         NEW_ARGV.  */
-      new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
+      new_argv = alloca ((nargs - 1) * sizeof *new_argv);
       new_argv[nargs - 2] = 0;
 
       for (i = nargs - 2; i-- != 0; )
@@ -1525,7 +1585,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.  */
@@ -1551,8 +1611,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 #if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
   int wait_child_setup[2];
 #endif
-  sigset_t procmask;
-  sigset_t blocked;
+  sigset_t blocked, procmask;
   struct sigaction sigint_action;
   struct sigaction sigquit_action;
   struct sigaction sigpipe_action;
@@ -1562,9 +1621,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
   /* Use volatile to protect variables from being clobbered by longjmp.  */
   volatile int forkin, forkout;
   volatile int pty_flag = 0;
-#ifndef USE_CRT_DLL
-  extern char **environ;
-#endif
 
   inchannel = outchannel = -1;
 
@@ -1652,7 +1708,7 @@ 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;
-  XPROCESS (process)->status = Qrun;
+  pset_status (XPROCESS (process), Qrun);
 
   /* Delay interrupts until we have a chance to store
      the new fork's pid in its process structure */
@@ -1679,7 +1735,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
   if (inchannel > max_process_desc)
     max_process_desc = inchannel;
 
-  /* Until we store the proper pid, enable sigchld_handler
+  /* Until we store the proper pid, enable the SIGCHLD handler
      to recognize an unknown pid as standing for this process.
      It is very important not to let this `marker' value stay
      in the table after this function has returned; if it does
@@ -1707,12 +1763,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
        int xforkin = forkin;
        int xforkout = forkout;
 
-#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);
-#endif
-
        /* Make the pty be the controlling terminal of the process.  */
 #ifdef HAVE_PTYS
        /* First, disconnect its current controlling terminal.  */
@@ -1874,10 +1924,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
         So have an interrupt jar it loose.  */
       {
        struct atimer *timer;
-       EMACS_TIME offset;
+       EMACS_TIME offset = make_emacs_time (1, 0);
 
        stop_polling ();
-       EMACS_SET_SECS_USECS (offset, 1, 0);
        timer = start_atimer (ATIMER_RELATIVE, offset, create_process_1, 0);
 
        if (forkin >= 0)
@@ -1892,10 +1941,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 
 #ifdef HAVE_PTYS
       if (pty_flag)
-       XPROCESS (process)->tty_name = build_string (pty_name);
+       pset_tty_name (XPROCESS (process), build_string (pty_name));
       else
 #endif
-       XPROCESS (process)->tty_name = Qnil;
+       pset_tty_name (XPROCESS (process), Qnil);
 
 #if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
       /* Wait for child_setup to complete in case that vfork is
@@ -1990,7 +2039,7 @@ create_pty (Lisp_Object process)
      more portable (see USG_SUBTTY_WORKS above).  */
 
   XPROCESS (process)->pty_flag = pty_flag;
-  XPROCESS (process)->status = Qrun;
+  pset_status (XPROCESS (process), Qrun);
   setup_process_coding_systems (process);
 
   FD_SET (inchannel, &input_wait_mask);
@@ -2001,10 +2050,10 @@ create_pty (Lisp_Object process)
   XPROCESS (process)->pid = -2;
 #ifdef HAVE_PTYS
   if (pty_flag)
-    XPROCESS (process)->tty_name = build_string (pty_name);
+    pset_tty_name (XPROCESS (process), build_string (pty_name));
   else
 #endif
-    XPROCESS (process)->tty_name = Qnil;
+    pset_tty_name (XPROCESS (process), Qnil);
 }
 
 \f
@@ -2393,7 +2442,7 @@ OPTION is not a supported option, return nil instead; otherwise return t.  */)
 
   if (set_socket_option (s, option, value))
     {
-      p->childp = Fplist_put (p->childp, option, value);
+      pset_childp (p, Fplist_put (p->childp, option, value));
       return Qt;
     }
 
@@ -2502,7 +2551,7 @@ static Lisp_Object
 make_serial_process_unwind (Lisp_Object proc)
 {
   if (!PROCESSP (proc))
-    abort ();
+    emacs_abort ();
   remove_process (proc);
   return Qnil;
 }
@@ -2626,18 +2675,18 @@ usage:  (make-serial-process &rest ARGS)  */)
   if (NILP (buffer))
     buffer = name;
   buffer = Fget_buffer_create (buffer);
-  p->buffer = buffer;
-
-  p->childp = contact;
-  p->plist = Fcopy_sequence (Fplist_get (contact, QCplist));
-  p->type = Qserial;
-  p->sentinel = Fplist_get (contact, QCsentinel);
-  p->filter = Fplist_get (contact, QCfilter);
-  p->log = Qnil;
+  pset_buffer (p, buffer);
+
+  pset_childp (p, contact);
+  pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist)));
+  pset_type (p, Qserial);
+  pset_sentinel (p, Fplist_get (contact, QCsentinel));
+  pset_filter (p, Fplist_get (contact, QCfilter));
+  pset_log (p, Qnil);
   if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
     p->kill_without_query = 1;
   if (tem = Fplist_get (contact, QCstop), !NILP (tem))
-    p->command = Qt;
+    pset_command (p, Qt);
   p->pty_flag = 0;
 
   if (!EQ (p->command, Qt))
@@ -2669,7 +2718,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;
-  p->decode_coding_system = val;
+  pset_decode_coding_system (p, val);
 
   val = Qnil;
   if (!NILP (tem))
@@ -2683,12 +2732,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;
-  p->encode_coding_system = val;
+  pset_encode_coding_system (p, val);
 
   setup_process_coding_systems (proc);
-  p->decoding_buf = empty_unibyte_string;
+  pset_decoding_buf (p, empty_unibyte_string);
   p->decoding_carryover = 0;
-  p->encoding_buf = empty_unibyte_string;
+  pset_encoding_buf (p, empty_unibyte_string);
   p->inherit_coding_system_flag
     = !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system);
 
@@ -3036,7 +3085,9 @@ usage: (make-network-process &rest ARGS)  */)
       CHECK_STRING (service);
       memset (&address_un, 0, sizeof address_un);
       address_un.sun_family = AF_LOCAL;
-      strncpy (address_un.sun_path, SSDATA (service), sizeof address_un.sun_path);
+      if (sizeof address_un.sun_path <= SBYTES (service))
+       error ("Service name too long");
+      strcpy (address_un.sun_path, SSDATA (service));
       ai.ai_addr = (struct sockaddr *) &address_un;
       ai.ai_addrlen = sizeof address_un;
       goto open_socket;
@@ -3337,8 +3388,8 @@ usage: (make-network-process &rest ARGS)  */)
       if (socktype == SOCK_DGRAM)
        {
          if (datagram_address[s].sa)
-           abort ();
-         datagram_address[s].sa = (struct sockaddr *) xmalloc (lres->ai_addrlen);
+           emacs_abort ();
+         datagram_address[s].sa = xmalloc (lres->ai_addrlen);
          datagram_address[s].len = lres->ai_addrlen;
          if (is_server)
            {
@@ -3423,23 +3474,23 @@ usage: (make-network-process &rest ARGS)  */)
 
   p = XPROCESS (proc);
 
-  p->childp = contact;
-  p->plist = Fcopy_sequence (Fplist_get (contact, QCplist));
-  p->type = Qnetwork;
+  pset_childp (p, contact);
+  pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist)));
+  pset_type (p, Qnetwork);
 
-  p->buffer = buffer;
-  p->sentinel = sentinel;
-  p->filter = filter;
-  p->log = Fplist_get (contact, QClog);
+  pset_buffer (p, buffer);
+  pset_sentinel (p, sentinel);
+  pset_filter (p, filter);
+  pset_log (p, Fplist_get (contact, QClog));
   if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
     p->kill_without_query = 1;
   if ((tem = Fplist_get (contact, QCstop), !NILP (tem)))
-    p->command = Qt;
+    pset_command (p, Qt);
   p->pid = 0;
   p->infd  = inch;
   p->outfd = outch;
   if (is_server && socktype != SOCK_DGRAM)
-    p->status = Qlisten;
+    pset_status (p, Qlisten);
 
   /* Make the process marker point into the process buffer (if any).  */
   if (BUFFERP (buffer))
@@ -3453,7 +3504,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.  */
-      p->status = Qconnect;
+      pset_status (p, Qconnect);
       if (!FD_ISSET (inch, &connect_wait_mask))
        {
          FD_SET (inch, &connect_wait_mask);
@@ -3520,7 +3571,7 @@ usage: (make-network-process &rest ARGS)  */)
        else
          val = Qnil;
       }
-    p->decode_coding_system = val;
+    pset_decode_coding_system (p, val);
 
     if (!NILP (tem))
       {
@@ -3554,13 +3605,13 @@ usage: (make-network-process &rest ARGS)  */)
        else
          val = Qnil;
       }
-    p->encode_coding_system = val;
+    pset_encode_coding_system (p, val);
   }
   setup_process_coding_systems (proc);
 
-  p->decoding_buf = empty_unibyte_string;
+  pset_decoding_buf (p, empty_unibyte_string);
   p->decoding_carryover = 0;
-  p->encoding_buf = empty_unibyte_string;
+  pset_encoding_buf (p, empty_unibyte_string);
 
   p->inherit_coding_system_flag
     = !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system);
@@ -3740,8 +3791,9 @@ FLAGS is the current flags of the interface.  */)
 
   CHECK_STRING (ifname);
 
-  memset (rq.ifr_name, 0, sizeof rq.ifr_name);
-  strncpy (rq.ifr_name, SSDATA (ifname), sizeof (rq.ifr_name));
+  if (sizeof rq.ifr_name <= SBYTES (ifname))
+    error ("interface name too long");
+  strcpy (rq.ifr_name, SSDATA (ifname));
 
   s = socket (AF_INET, SOCK_STREAM, 0);
   if (s < 0)
@@ -3922,7 +3974,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)
@@ -4172,18 +4224,18 @@ server_accept_connection (Lisp_Object server, int channel)
                          conv_sockaddr_to_lisp (&saddr.sa, len));
 #endif
 
-  p->childp = contact;
-  p->plist = Fcopy_sequence (ps->plist);
-  p->type = Qnetwork;
+  pset_childp (p, contact);
+  pset_plist (p, Fcopy_sequence (ps->plist));
+  pset_type (p, Qnetwork);
 
-  p->buffer = buffer;
-  p->sentinel = ps->sentinel;
-  p->filter = ps->filter;
-  p->command = Qnil;
+  pset_buffer (p, buffer);
+  pset_sentinel (p, ps->sentinel);
+  pset_filter (p, ps->filter);
+  pset_command (p, Qnil);
   p->pid = 0;
   p->infd  = s;
   p->outfd = s;
-  p->status = Qrun;
+  pset_status (p, Qrun);
 
   /* Client processes for accepted connections are not stopped initially.  */
   if (!EQ (p->filter, Qt))
@@ -4200,13 +4252,13 @@ 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. */
 
-  p->decode_coding_system = ps->decode_coding_system;
-  p->encode_coding_system = ps->encode_coding_system;
+  pset_decode_coding_system (p, ps->decode_coding_system);
+  pset_encode_coding_system (p, ps->encode_coding_system);
   setup_process_coding_systems (proc);
 
-  p->decoding_buf = empty_unibyte_string;
+  pset_decoding_buf (p, empty_unibyte_string);
   p->decoding_carryover = 0;
-  p->encoding_buf = empty_unibyte_string;
+  pset_encoding_buf (p, empty_unibyte_string);
 
   p->inherit_coding_system_flag
     = (NILP (buffer) ? 0 : ps->inherit_coding_system_flag);
@@ -4259,10 +4311,10 @@ wait_reading_process_output_1 (void)
      an additional duration to wait, measured in nanoseconds
      If TIME_LIMIT is zero, then:
        If NSECS == 0, there is no limit.
-       If NSECS > 0, the timeout consists of NSEC only.
+       If NSECS > 0, the timeout consists of NSECS only.
        If NSECS < 0, gobble data immediately, as if TIME_LIMIT were negative.
 
-   READ_KBD is a lisp value:
+   READ_KBD is:
      0 to ignore keyboard input, or
      1 to return when input is available, or
      -1 meaning caller will actually read the input, so don't throw to
@@ -4308,7 +4360,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 (wait_proc->status) && EQ (XCAR (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.  */
@@ -4329,11 +4382,10 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
   /* Since we may need to wait several times,
      compute the absolute time to return at.  */
-  if (time_limit || nsecs) /* FIXME neither should be negative, no? */
+  if (time_limit || 0 < nsecs)
     {
-      EMACS_GET_TIME (end_time);
-      EMACS_SET_SECS_NSECS (timeout, time_limit, nsecs);
-      EMACS_ADD_TIME (end_time, end_time, timeout);
+      timeout = make_emacs_time (time_limit, nsecs);
+      end_time = add_emacs_time (current_emacs_time (), timeout);
     }
 
   while (1)
@@ -4358,22 +4410,22 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       /* Exit if already run out */
       if (nsecs < 0)
        {
-         /* -1 specified for timeout means
+         /* A negative timeout means
             gobble output available now
             but don't wait at all. */
 
-         EMACS_SET_SECS_USECS (timeout, 0, 0);
+         timeout = make_emacs_time (0, 0);
        }
-      else if (time_limit || nsecs)
+      else if (time_limit || 0 < nsecs)
        {
-         EMACS_GET_TIME (timeout);
-         if (EMACS_TIME_LE (end_time, timeout))
+         EMACS_TIME now = current_emacs_time ();
+         if (EMACS_TIME_LE (end_time, now))
            break;
-         EMACS_SUB_TIME (timeout, end_time, timeout);
+         timeout = sub_emacs_time (end_time, now);
        }
       else
        {
-         EMACS_SET_SECS_USECS (timeout, 100000, 0);
+         timeout = make_emacs_time (100000, 0);
        }
 
       /* Normally we run timers here.
@@ -4415,7 +4467,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
              && requeued_events_pending_p ())
            break;
 
-         /* If time_limit is negative, we are not going to wait at all.  */
+         /* A negative timeout means do not wait at all.  */
          if (0 <= nsecs)
            {
              if (EMACS_TIME_VALID_P (timer_delay))
@@ -4458,7 +4510,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
             Atemp = input_wait_mask;
          Ctemp = write_mask;
 
-         EMACS_SET_SECS_USECS (timeout, 0, 0);
+         timeout = make_emacs_time (0, 0);
          if ((pselect (max (max_process_desc, max_input_desc) + 1,
                        &Atemp,
 #ifdef NON_BLOCKING_CONNECT
@@ -4610,7 +4662,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                        nsecs = XPROCESS (proc)->read_output_delay;
                    }
                }
-             EMACS_SET_SECS_NSECS (timeout, 0, nsecs);
+             timeout = make_emacs_time (0, nsecs);
              process_output_skip = 0;
            }
 #endif
@@ -4683,7 +4735,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       do_pending_window_change (0);
 
       if ((time_limit || nsecs) && nfds == 0 && ! timeout_reduced_for_timers)
-       /* We wanted the full specified time, so return now.  */
+       /* We waited the full specified time, so return now.  */
        break;
       if (nfds < 0)
        {
@@ -4701,7 +4753,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
@@ -4810,15 +4862,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++)
        {
@@ -4907,11 +4957,11 @@ 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
-                        wait3() 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;
-                     p->status = Qfailed;
+                     pset_status (p, Qfailed);
                    }
                   else
                    kill (getpid (), SIGCHLD);
@@ -4931,8 +4981,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                  if (XPROCESS (proc)->raw_status_new)
                    update_status (XPROCESS (proc));
                  if (EQ (XPROCESS (proc)->status, Qrun))
-                   XPROCESS (proc)->status
-                     = Fcons (Qexit, Fcons (make_number (256), Qnil));
+                   pset_status (XPROCESS (proc),
+                                list2 (Qexit, make_number (256)));
                }
            }
 #ifdef NON_BLOCKING_CONNECT
@@ -4944,7 +4994,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))
@@ -4980,12 +5030,12 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
              if (xerrno)
                {
                  p->tick = ++process_tick;
-                 p->status = Fcons (Qfailed, Fcons (make_number (xerrno), Qnil));
+                 pset_status (p, list2 (Qfailed, make_number (xerrno)));
                  deactivate_process (proc);
                }
              else
                {
-                 p->status = Qrun;
+                 pset_status (p, Qrun);
                  /* Execute the sentinel here.  If we had relied on
                     status_notify to do it later, it will read input
                     from the process before calling the sentinel.  */
@@ -5059,7 +5109,7 @@ read_process_output (Lisp_Object proc, register int channel)
   ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object odeactivate;
 
-  chars = (char *) alloca (carryover + readmax);
+  chars = alloca (carryover + readmax);
   if (carryover)
     /* See the comment above.  */
     memcpy (chars, SDATA (p->decoding_buf), carryover);
@@ -5138,14 +5188,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 = 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
@@ -5185,7 +5235,7 @@ read_process_output (Lisp_Object proc, register int channel)
       /* A new coding system might be found.  */
       if (!EQ (p->decode_coding_system, Vlast_coding_system_used))
        {
-         p->decode_coding_system = Vlast_coding_system_used;
+         pset_decode_coding_system (p, Vlast_coding_system_used);
 
          /* Don't call setup_coding_system for
             proc_decode_coding_system[channel] here.  It is done in
@@ -5201,8 +5251,8 @@ read_process_output (Lisp_Object proc, register int channel)
          if (NILP (p->encode_coding_system)
              && proc_encode_coding_system[p->outfd])
            {
-             p->encode_coding_system
-               = coding_inherit_eol_type (Vlast_coding_system_used, Qnil);
+             pset_encode_coding_system
+               (p, coding_inherit_eol_type (Vlast_coding_system_used, Qnil));
              setup_coding_system (p->encode_coding_system,
                                   proc_encode_coding_system[p->outfd]);
            }
@@ -5211,7 +5261,7 @@ read_process_output (Lisp_Object proc, register int channel)
       if (coding->carryover_bytes > 0)
        {
          if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
-           p->decoding_buf = make_uninit_string (coding->carryover_bytes);
+           pset_decoding_buf (p, make_uninit_string (coding->carryover_bytes));
          memcpy (SDATA (p->decoding_buf), coding->carryover,
                  coding->carryover_bytes);
          p->decoding_carryover = coding->carryover_bytes;
@@ -5267,14 +5317,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 (p->mark)->buffer)
-       SET_PT_BOTH (clip_to_bounds (BEGV, marker_position (p->mark), ZV),
-                    clip_to_bounds (BEGV_BYTE, marker_byte_position (p->mark),
+       SET_PT_BOTH (clip_to_bounds (BEGV,
+                                    marker_position (p->mark), ZV),
+                    clip_to_bounds (BEGV_BYTE,
+                                    marker_byte_position (p->mark),
                                     ZV_BYTE));
       else
        SET_PT_BOTH (ZV, ZV_BYTE);
@@ -5293,12 +5345,12 @@ read_process_output (Lisp_Object proc, register int channel)
         similar code in the previous `if' block.  */
       if (!EQ (p->decode_coding_system, Vlast_coding_system_used))
        {
-         p->decode_coding_system = Vlast_coding_system_used;
+         pset_decode_coding_system (p, Vlast_coding_system_used);
          if (NILP (p->encode_coding_system)
              && proc_encode_coding_system[p->outfd])
            {
-             p->encode_coding_system
-               = coding_inherit_eol_type (Vlast_coding_system_used, Qnil);
+             pset_encode_coding_system
+               (p, coding_inherit_eol_type (Vlast_coding_system_used, Qnil));
              setup_coding_system (p->encode_coding_system,
                                   proc_encode_coding_system[p->outfd]);
            }
@@ -5306,7 +5358,7 @@ read_process_output (Lisp_Object proc, register int channel)
       if (coding->carryover_bytes > 0)
        {
          if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
-           p->decoding_buf = make_uninit_string (coding->carryover_bytes);
+           pset_decoding_buf (p, make_uninit_string (coding->carryover_bytes));
          memcpy (SDATA (p->decoding_buf), coding->carryover,
                  coding->carryover_bytes);
          p->decoding_carryover = coding->carryover_bytes;
@@ -5356,7 +5408,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.  */
@@ -5371,16 +5423,20 @@ read_process_output (Lisp_Object proc, register int channel)
 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 _Noreturn void
+handle_pipe_signal (int sig)
+{
+  sigset_t unblocked;
+  sigemptyset (&unblocked);
+  sigaddset (&unblocked, SIGPIPE);
+  pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
+  _longjmp (send_process_frame, 1);
+}
 
 static void
-send_process_trap (int ignore)
+deliver_pipe_signal (int sig)
 {
-  SIGNAL_THREAD_CHECK (SIGPIPE);
-  sigunblock (sigmask (SIGPIPE));
-  longjmp (send_process_frame, 1);
+  handle_on_main_thread (sig, handle_pipe_signal);
 }
 
 /* In send_process, when a write fails temporarily,
@@ -5423,9 +5479,9 @@ write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj,
   entry = Fcons (obj, Fcons (make_number (offset), make_number (len)));
 
   if (front)
-    p->write_queue = Fcons (entry, p->write_queue);
+    pset_write_queue (p, Fcons (entry, p->write_queue));
   else
-    p->write_queue = nconc2 (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
@@ -5443,7 +5499,7 @@ write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj,
     return 0;
 
   entry = XCAR (p->write_queue);
-  p->write_queue = XCDR (p->write_queue);
+  pset_write_queue (p, XCDR (p->write_queue));
 
   *obj = XCAR (entry);
   offset_length = XCDR (entry);
@@ -5473,7 +5529,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
   struct Lisp_Process *p = XPROCESS (proc);
   ssize_t rv;
   struct coding_system *coding;
-  void (*volatile old_sigpipe) (int);
+  struct sigaction old_sigpipe_action;
 
   if (p->raw_status_new)
     update_status (p);
@@ -5490,8 +5546,8 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
          && !NILP (BVAR (XBUFFER (object), enable_multibyte_characters)))
       || EQ (object, Qt))
     {
-      p->encode_coding_system
-       = complement_process_encoding_system (p->encode_coding_system);
+      pset_encode_coding_system
+       (p, complement_process_encoding_system (p->encode_coding_system));
       if (!EQ (Vlast_coding_system_used, p->encode_coding_system))
        {
          /* The coding system for encoding was changed to raw-text
@@ -5583,7 +5639,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
   /* 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))
+  if (!_setjmp (send_process_frame))
     {
       p = XPROCESS (proc);  /* Repair any setjmp clobbering.  */
       process_sent_to = proc;
@@ -5612,7 +5668,9 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
              /* 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);
+             struct sigaction action;
+             emacs_sigaction_init (&action, deliver_pipe_signal);
+             sigaction (SIGPIPE, &action, &old_sigpipe_action);
 #ifdef DATAGRAM_SOCKETS
              if (DATAGRAM_CHAN_P (outfd))
                {
@@ -5623,7 +5681,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
                    written = rv;
                  else if (errno == EMSGSIZE)
                    {
-                     signal (SIGPIPE, old_sigpipe);
+                     sigaction (SIGPIPE, &old_sigpipe_action, 0);
                      report_file_error ("sending datagram",
                                         Fcons (proc, Qnil));
                    }
@@ -5648,7 +5706,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
                    }
 #endif
                }
-             signal (SIGPIPE, old_sigpipe);
+             sigaction (SIGPIPE, &old_sigpipe_action, 0);
 
              if (rv < 0)
                {
@@ -5708,11 +5766,11 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
     }
   else
     {
-      signal (SIGPIPE, old_sigpipe);
+      sigaction (SIGPIPE, &old_sigpipe_action, 0);
       proc = process_sent_to;
       p = XPROCESS (proc);
       p->raw_status_new = 0;
-      p->status = Fcons (Qexit, Fcons (make_number (256), Qnil));
+      pset_status (p, Fcons (Qexit, Fcons (make_number (256), Qnil)));
       p->tick = ++process_tick;
       deactivate_process (proc);
       error ("SIGPIPE raised on process %s; closed it", SDATA (p->name));
@@ -5941,7 +5999,7 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
 #ifdef SIGCONT
     case SIGCONT:
       p->raw_status_new = 0;
-      p->status = Qrun;
+      pset_status (p, Qrun);
       p->tick = ++process_tick;
       if (!nomsg)
        {
@@ -6037,7 +6095,7 @@ traffic.  */)
          FD_CLR (p->infd, &input_wait_mask);
          FD_CLR (p->infd, &non_keyboard_wait_mask);
        }
-      p->command = Qt;
+      pset_command (p, Qt);
       return process;
     }
 #ifndef SIGTSTP
@@ -6073,7 +6131,7 @@ traffic.  */)
          tcflush (p->infd, TCIFLUSH);
 #endif /* not WINDOWSNT */
        }
-      p->command = Qnil;
+      pset_command (p, Qnil);
       return process;
     }
 #ifdef SIGCONT
@@ -6303,12 +6361,12 @@ 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]
-         = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+         = xmalloc (sizeof (struct coding_system));
       memcpy (proc_encode_coding_system[new_outfd],
              proc_encode_coding_system[old_outfd],
              sizeof (struct coding_system));
@@ -6346,150 +6404,142 @@ process has been transmitted to the serial port.  */)
    indirectly; if it does, that is a bug  */
 
 #ifdef SIGCHLD
-static void
-sigchld_handler (int signo)
+
+/* Record one child's changed status.  Return true if a child was found.  */
+static bool
+record_child_status_change (void)
 {
-  int old_errno = errno;
   Lisp_Object proc;
   struct Lisp_Process *p;
+  pid_t pid;
+  int w;
+  Lisp_Object tail;
 
-  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 = wait3 (&w, WNOHANG | WUNTRACED, 0);
-       }
-      while (pid < 0 && errno == EINTR);
-
-      if (pid <= 0)
-       {
-         /* PID == 0 means no processes found, PID == -1 means a real
-            failure.  We have done all our job, so return.  */
+  do
+    pid = waitpid (-1, &w, WNOHANG | WUNTRACED);
+  while (pid < 0 && errno == EINTR);
 
-         errno = old_errno;
-         return;
-       }
-#else
-      pid = wait (&w);
-#endif /* no WNOHANG */
+  /* PID == 0 means no processes found, PID == -1 means a real failure.
+     Either way, we have done all our job.  */
+  if (pid <= 0)
+    return false;
 
-      /* 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))
+    {
+      Lisp_Object xpid = XCAR (tail);
+      if ((INTEGERP (xpid) && pid == XINT (xpid))
+         || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid)))
        {
-         Lisp_Object xpid = XCAR (tail);
-         if ((INTEGERP (xpid) && pid == XINT (xpid))
-             || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid)))
-           {
-             XSETCAR (tail, Qnil);
-             goto sigchld_end_of_loop;
-           }
+         XSETCAR (tail, Qnil);
+         return true;
        }
+    }
 
-      /* Otherwise, if it is asynchronous, it is in Vprocess_alist.  */
+  /* Otherwise, if it is asynchronous, it is in Vprocess_alist.  */
+  p = 0;
+  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+    {
+      proc = XCDR (XCAR (tail));
+      p = XPROCESS (proc);
+      if (EQ (p->type, Qreal) && p->pid == pid)
+       break;
       p = 0;
-      for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
-       {
-         proc = XCDR (XCAR (tail));
-         p = XPROCESS (proc);
-         if (EQ (p->type, Qreal) && p->pid == pid)
-           break;
-         p = 0;
-       }
-
-      /* Look for an asynchronous process whose pid hasn't been filled
-        in yet.  */
-      if (p == 0)
-       for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
-         {
-           proc = XCDR (XCAR (tail));
-           p = XPROCESS (proc);
-           if (p->pid == -1)
-             break;
-           p = 0;
-         }
-
-      /* Change the status of the process that was found.  */
-      if (p != 0)
-       {
-         int clear_desc_flag = 0;
+    }
 
-         p->tick = ++process_tick;
-         p->raw_status = w;
-         p->raw_status_new = 1;
+  /* Look for an asynchronous process whose pid hasn't been filled
+     in yet.  */
+  if (! p)
+    for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+      {
+       proc = XCDR (XCAR (tail));
+       p = XPROCESS (proc);
+       if (p->pid == -1)
+         break;
+       p = 0;
+      }
 
-         /* If process has terminated, stop waiting for its output.  */
-         if ((WIFSIGNALED (w) || WIFEXITED (w))
-             && p->infd >= 0)
-           clear_desc_flag = 1;
+  /* Change the status of the process that was found.  */
+  if (p)
+    {
+      int clear_desc_flag = 0;
 
-         /* We use clear_desc_flag to avoid a compiler bug in Microsoft C.  */
-         if (clear_desc_flag)
-           {
-             FD_CLR (p->infd, &input_wait_mask);
-             FD_CLR (p->infd, &non_keyboard_wait_mask);
-           }
+      p->tick = ++process_tick;
+      p->raw_status = w;
+      p->raw_status_new = 1;
 
-         /* Tell wait_reading_process_output that it needs to wake up and
-            look around.  */
-         if (input_available_clear_time)
-           EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
-       }
+      /* If process has terminated, stop waiting for its output.  */
+      if ((WIFSIGNALED (w) || WIFEXITED (w))
+         && p->infd >= 0)
+       clear_desc_flag = 1;
 
-      /* There was no asynchronous process found for that pid: we have
-        a synchronous process.  */
-      else
+      /* We use clear_desc_flag to avoid a compiler bug in Microsoft C.  */
+      if (clear_desc_flag)
        {
-         synch_process_alive = 0;
-
-         /* Report the status of the synchronous process.  */
-         if (WIFEXITED (w))
-           synch_process_retcode = WRETCODE (w);
-         else if (WIFSIGNALED (w))
-           synch_process_termsig = WTERMSIG (w);
-
-         /* Tell wait_reading_process_output that it needs to wake up and
-            look around.  */
-         if (input_available_clear_time)
-           EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
+         FD_CLR (p->infd, &input_wait_mask);
+         FD_CLR (p->infd, &non_keyboard_wait_mask);
        }
 
-    sigchld_end_of_loop:
-      ;
+      /* Tell wait_reading_process_output that it needs to wake up and
+        look around.  */
+      if (input_available_clear_time)
+       *input_available_clear_time = make_emacs_time (0, 0);
+    }
+  /* There was no asynchronous process found for that pid: we have
+     a synchronous process.  */
+  else
+    {
+      synch_process_alive = 0;
+
+      /* Report the status of the synchronous process.  */
+      if (WIFEXITED (w))
+       synch_process_retcode = WEXITSTATUS (w);
+      else if (WIFSIGNALED (w))
+       synch_process_termsig = WTERMSIG (w);
+
+      /* Tell wait_reading_process_output that it needs to wake up and
+        look around.  */
+      if (input_available_clear_time)
+       *input_available_clear_time = make_emacs_time (0, 0);
+    }
+
+  return true;
+}
 
-      /* 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.  */
+/* On some systems, the SIGCHLD handler must return right away.  If
+   any more processes want to signal us, we will get another signal.
+   Otherwise, loop around to use up all the processes that have
+   something to tell us.  */
 #if (defined WINDOWSNT \
      || (defined USG && !defined GNU_LINUX \
         && !(defined HPUX && defined WNOHANG)))
-      errno = old_errno;
-      return;
-#endif /* USG, but not HPUX with WNOHANG */
-    }
+enum { CAN_HANDLE_MULTIPLE_CHILDREN = 0 };
+#else
+enum { CAN_HANDLE_MULTIPLE_CHILDREN = 1 };
+#endif
+
+static void
+handle_child_signal (int sig)
+{
+  while (record_child_status_change () && CAN_HANDLE_MULTIPLE_CHILDREN)
+    continue;
+}
+
+static void
+deliver_child_signal (int sig)
+{
+  handle_on_main_thread (sig, handle_child_signal);
 }
+
 #endif /* SIGCHLD */
 \f
 
 static Lisp_Object
 exec_sentinel_unwind (Lisp_Object data)
 {
-  XPROCESS (XCAR (data))->sentinel = XCDR (data);
+  pset_sentinel (XPROCESS (XCAR (data)), XCDR (data));
   return Qnil;
 }
 
@@ -6507,9 +6557,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)
@@ -6527,7 +6577,7 @@ 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 = p->sentinel;
   if (NILP (sentinel))
@@ -6535,7 +6585,7 @@ exec_sentinel (Lisp_Object proc, Lisp_Object reason)
 
   /* Zilch the sentinel while it's running, to avoid recursive invocations;
      assure that it gets restored no matter how the sentinel exits.  */
-  p->sentinel = Qnil;
+  pset_sentinel (p, Qnil);
   record_unwind_protect (exec_sentinel_unwind, Fcons (proc, sentinel));
   /* Inhibit quit so that random quits don't screw up a running filter.  */
   specbind (Qinhibit_quit, Qt);
@@ -6690,12 +6740,13 @@ 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 ");
-             Finsert (1, &p->name);
+             { /* FIXME: temporary kludge */
+               Lisp_Object tem2 = p->name; Finsert (1, &tem2); }
              insert_string (" ");
              Finsert (1, &msg);
-             BVAR (current_buffer, read_only) = tem;
+             bset_read_only (current_buffer, tem);
              set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
 
              if (opoint >= before)
@@ -6732,8 +6783,8 @@ encode subprocess input.  */)
   Fcheck_coding_system (decoding);
   Fcheck_coding_system (encoding);
   encoding = coding_inherit_eol_type (encoding, Qnil);
-  p->decode_coding_system = decoding;
-  p->encode_coding_system = encoding;
+  pset_decode_coding_system (p, decoding);
+  pset_encode_coding_system (p, encoding);
   setup_process_coding_systems (process);
 
   return Qnil;
@@ -6763,7 +6814,8 @@ suppressed.  */)
   CHECK_PROCESS (process);
   p = XPROCESS (process);
   if (NILP (flag))
-    p->decode_coding_system = raw_text_coding_system (p->decode_coding_system);
+    pset_decode_coding_system
+      (p, raw_text_coding_system (p->decode_coding_system));
   setup_process_coding_systems (process);
 
   return Qnil;
@@ -6825,25 +6877,25 @@ keyboard_bit_set (fd_set *mask)
 
 /* Defined on msdos.c.  */
 extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
-                      EMACS_TIME *);
+                      EMACS_TIME *, void *);
 
 /* Implementation of wait_reading_process_output, assuming that there
    are no subprocesses.  Used only by the MS-DOS build.
 
    Wait for timeout to elapse and/or keyboard input to be available.
 
-   time_limit is:
+   TIME_LIMIT is:
      timeout in seconds
      If negative, gobble data immediately available but don't wait for any.
 
-   nsec is:
+   NSECS is:
      an additional duration to wait, measured in nanoseconds
      If TIME_LIMIT is zero, then:
-       If NSEC == 0, there is no limit.
-       If NSEC > 0, the timeout consists of NSEC only.
+       If NSECS == 0, there is no limit.
+       If NSECS > 0, the timeout consists of NSECS only.
        If NSECS < 0, gobble data immediately, as if TIME_LIMIT were negative.
 
-   read_kbd is a Lisp_Object:
+   READ_KBD is:
      0 to ignore keyboard input, or
      1 to return when input is available, or
      -1 means caller will actually read the input, so don't throw to
@@ -6852,7 +6904,7 @@ 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 != 0 means redisplay should be done to show subprocess
    output that arrives.
 
    Return true if we received input from any process.  */
@@ -6865,8 +6917,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 {
   register int nfds;
   EMACS_TIME end_time, timeout;
-  SELECT_TYPE waitchannels;
-  int xerrno;
 
   if (time_limit < 0)
     {
@@ -6877,11 +6927,10 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
     time_limit = TYPE_MAXIMUM (time_t);
 
   /* What does time_limit really mean?  */
-  if (time_limit || nsecs) /* FIXME: what if negative? */
+  if (time_limit || 0 < nsecs)
     {
-      EMACS_GET_TIME (end_time);
-      EMACS_SET_SECS_NSECS (timeout, time_limit, nsecs);
-      EMACS_ADD_TIME (end_time, end_time, timeout);
+      timeout = make_emacs_time (time_limit, nsecs);
+      end_time = add_emacs_time (current_emacs_time (), timeout);
     }
 
   /* Turn off periodic alarms (in case they are in use)
@@ -6893,6 +6942,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
   while (1)
     {
       int timeout_reduced_for_timers = 0;
+      SELECT_TYPE waitchannels;
+      int xerrno;
 
       /* If calling from keyboard input, do not quit
         since we want to return C-g as an input character.
@@ -6908,22 +6959,22 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       /* Exit if already run out */
       if (nsecs < 0)
        {
-         /* -1 specified for timeout means
+         /* A negative timeout means
             gobble output available now
             but don't wait at all. */
 
-         EMACS_SET_SECS_USECS (timeout, 0, 0);
+         timeout = make_emacs_time (0, 0);
        }
-      else if (time_limit || nsecs)
+      else if (time_limit || 0 < nsecs)
        {
-         EMACS_GET_TIME (timeout);
-         if (EMACS_TIME_LE (end_time, timeout))
+         EMACS_TIME now = current_emacs_time ();
+         if (EMACS_TIME_LE (end_time, now))
            break;
-         EMACS_SUB_TIME (timeout, end_time, timeout);
+         timeout = sub_emacs_time (end_time, now);
        }
       else
        {
-         EMACS_SET_SECS_USECS (timeout, 100000, 0);
+         timeout = make_emacs_time (100000, 0);
        }
 
       /* If our caller will not immediately handle keyboard events,
@@ -6967,13 +7018,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       if (read_kbd < 0)
        set_waiting_for_input (&timeout);
 
-      /* Wait till there is something to do.  */
-
-      if (! read_kbd && NILP (wait_for_cell))
-       FD_ZERO (&waitchannels);
-      else
-       FD_SET (0, &waitchannels);
-
       /* If a frame has been newly mapped and needs updating,
         reprocess its display stuff.  */
       if (frame_garbaged && do_display)
@@ -6984,13 +7028,16 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
            set_waiting_for_input (&timeout);
        }
 
+      /* Wait till there is something to do.  */
+      FD_ZERO (&waitchannels);
       if (read_kbd && detect_input_pending ())
+       nfds = 0;
+      else
        {
-         nfds = 0;
-         FD_ZERO (&waitchannels);
+         if (read_kbd || !NILP (wait_for_cell))
+           FD_SET (0, &waitchannels);
+         nfds = pselect (1, &waitchannels, NULL, NULL, &timeout, NULL);
        }
-      else
-       nfds = pselect (1, &waitchannels, NULL, NULL, &timeout, NULL);
 
       xerrno = errno;
 
@@ -7105,8 +7152,7 @@ setup_process_coding_systems (Lisp_Object process)
     return;
 
   if (!proc_decode_coding_system[inch])
-    proc_decode_coding_system[inch]
-      = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+    proc_decode_coding_system[inch] = xmalloc (sizeof (struct coding_system));
   coding_system = p->decode_coding_system;
   if (! NILP (p->filter))
     ;
@@ -7118,8 +7164,7 @@ setup_process_coding_systems (Lisp_Object process)
   setup_coding_system (coding_system, proc_decode_coding_system[inch]);
 
   if (!proc_encode_coding_system[outch])
-    proc_encode_coding_system[outch]
-      = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+    proc_encode_coding_system[outch] = xmalloc (sizeof (struct coding_system));
   setup_coding_system (p->encode_coding_system,
                       proc_encode_coding_system[outch]);
 #endif
@@ -7327,8 +7372,10 @@ integer or floating point values.
 }
 
 \f
+/* This is not called "init_process" because that is the name of a
+   Mach system call, so it would cause problems on Darwin systems.  */
 void
-init_process (void)
+init_process_emacs (void)
 {
 #ifdef subprocesses
   register int i;
@@ -7339,7 +7386,11 @@ init_process (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);
@@ -7425,8 +7476,7 @@ init_process (void)
     char const *release = (STRINGP (Voperating_system_release)
                           ? SSDATA (Voperating_system_release)
                           : 0);
-    if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
-                                   && release[1] == '.')) {
+    if (!release || !release[0] || (release[0] < '7' && release[1] == '.')) {
       Vprocess_connection_type = Qnil;
     }
   }